import os from langchain_openai import ChatOpenAI from langchain_core.prompts import PromptTemplate from langchain.output_parsers import PydanticOutputParser from models import TaskCard from typing import List class TaskParser: """Converts raw task text into a TaskCard using LangChain.""" 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.0, ) self.output_parser = PydanticOutputParser(pydantic_object=TaskCard) self.prompt = PromptTemplate( template=( "Parse the following raw task description into a structured card.\n" "{format_instructions}\n\nRaw text:\n{raw_text}\n\nJSON:" ), input_variables=["raw_text"], partial_variables={"format_instructions": self.output_parser.get_format_instructions()}, ) self.chain = self.prompt | self.llm | self.output_parser def parse(self, raw_text: str) -> TaskCard: """Parse a single raw task description.""" return self.chain.invoke({"raw_text": raw_text}) def batch_parse(self, texts: List[str]) -> List[TaskCard]: """Parse multiple raw task descriptions.""" return [self.parse(t) for t in texts]