From c7dd41fb690459db0ded6ab5bdc1661d9f6af45e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB=20=D0=9A=D1=83=D1=82?= =?UTF-8?q?=D0=BB=D0=B0=D1=85=D0=BC=D0=B5=D1=82=D0=BE=D0=B2?= Date: Tue, 26 May 2026 13:02:41 +0000 Subject: [PATCH] add parser.py --- parser.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 parser.py diff --git a/parser.py b/parser.py new file mode 100644 index 0000000..36e3ece --- /dev/null +++ b/parser.py @@ -0,0 +1,50 @@ +import os +import json +from typing import List +from langchain_openai import ChatOpenAI +from langchain_core.output_parsers import JsonOutputParser +from langchain_core.prompts import PromptTemplate +from pydantic import BaseModel + +from models import TaskCard + +class TaskParser: + """Parser that converts raw task descriptions into TaskCard objects using a LLM.""" + + def __init__(self) -> None: + self.llm = ChatOpenAI( + model="openai/gpt-oss-20b:free", + base_url="https://platform.brojs.ru/jrnl-bh/api/inference/v1", + api_key=os.getenv("JOURNAL_MCP_PAT"), + temperature=0.1, + ) + self.parser = JsonOutputParser(pydantic_object=TaskCard) + self.prompt = PromptTemplate( + input_variables=["raw_text"], + template=""" +Parse the following raw task description into a JSON object matching the TaskCard schema. +The output must be valid JSON and contain all required fields. +If a field cannot be determined, use null for optional fields or an empty list for lists. + +Raw text: +{raw_text} + +JSON output: +""", + ) + + def _run_llm(self, raw_text: str) -> TaskCard: + chain = self.prompt | self.llm | self.parser + return chain.invoke({"raw_text": raw_text}) + + def parse(self, raw_text: str) -> TaskCard: + return self._run_llm(raw_text) + + def batch_parse(self, texts: List[str]) -> List[TaskCard]: + return [self.parse(t) for t in texts] + + def save_to_file(self, card: TaskCard, filename: str) -> None: + with open(filename, "w", encoding="utf-8") as f: + json.dump(card.dict(), f, ensure_ascii=False, indent=2) + +# End of parser.py