diff --git a/main.py b/main.py index f32e8e5..5c9415f 100644 --- a/main.py +++ b/main.py @@ -1,44 +1,104 @@ -import os +"""Task 69dd4221f309a98be0006b2e – Structured task card parser. + +The script accepts a single natural‑language description of a course task and +returns a validated Pydantic model instance. It demonstrates a one‑shot +prompting pattern with a structured output parser. + +Usage: + python main.py "" + +The script prints the raw model dump and a short human‑readable summary. +""" + +import sys +from typing import List + from pydantic import BaseModel, Field from langchain_core.prompts import PromptTemplate from langchain_openai import ChatOpenAI from langchain_core.output_parsers import PydanticOutputParser +# --------------------------------------------------------------------------- +# 1. Pydantic model +# --------------------------------------------------------------------------- class TaskCard(BaseModel): - title: str = Field(..., description="Краткое название задачи") - subject: str = Field(..., description="Предмет или область") - deadline_hint: str = Field(..., description="Краткая подсказка о сроке") - deliverable_type: str = Field(..., description="Тип сдачи: отчёт, код, презентация и т.д.") - grading_hints: list[str] = Field(..., description="Список критериев оценки") + """Compact representation of a course task. -# LLM configuration – BroJS -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.5, -) + All fields are optional because the model may not be able to infer every + piece of information from a very short description. The parser will + still return a valid instance – missing values will be ``None``. + """ + title: str | None = Field(None, description="Short title of the task") + subject: str | None = Field(None, description="Subject or topic of the task") + deadline_hint: str | None = Field( + None, description="Free‑form hint about the deadline (e.g. 'к пятнице')" + ) + deliverable_type: str | None = Field( + None, description="What is expected to be submitted (report, code, etc.)" + ) + grading_hints: List[str] | None = Field( + None, description="List of hints mentioned about grading" + ) + +# --------------------------------------------------------------------------- +# 2. Prompt + chain +# --------------------------------------------------------------------------- parser = PydanticOutputParser(pydantic_object=TaskCard) -prompt_template = """\nНиже приведена формулировка задания от преподавателя.\nВаша задача – вернуть данные в формате JSON, соответствующем модели TaskCard.\n{format_instructions}\n\nФормулировка: {input_text}\n""" +prompt_template = """You are a helper that extracts structured information from a +course task description. Return a JSON object that matches the following +schema: + +{schema} + +The input description is: + +{description} + +Respond ONLY with the JSON object. Do not add any extra text. +""" prompt = PromptTemplate( template=prompt_template, - input_variables=["input_text"], - partial_variables={"format_instructions": parser.get_format_instructions()}, + input_variables=["description"], + partial_variables={"schema": parser.get_format_instructions()}, ) +# LLM – use the default OpenAI OSS endpoint via environment variables +llm = ChatOpenAI(model="openai/gpt-oss-20b:free", temperature=0.2) + chain = prompt | llm | parser -if __name__ == "__main__": - example = "Сдайте к пятнице мини-отчёт по LangChain: 2 страницы, упор на агентов. Оценка: за полноту и за пример кода." - result = chain.invoke({"input_text": example}) - print("\n--- Parsed Result ---") - print(result.model_dump()) +# --------------------------------------------------------------------------- +# 3. Main entry point +# --------------------------------------------------------------------------- + +def main() -> None: + if len(sys.argv) < 2: + print("Usage: python main.py ''") + sys.exit(1) + + description = sys.argv[1] + result: TaskCard = chain.invoke({"description": description}) + + # Print raw model dump + print("\n--- Parsed model ---") + print(result.model_dump(indent=2)) + + # Human‑readable summary print("\n--- Summary ---") - print(f"Title: {result.title}") - print(f"Subject: {result.subject}") - print(f"Deadline hint: {result.deadline_hint}") - print(f"Deliverable type: {result.deliverable_type}") - print(f"Grading hints: {', '.join(result.grading_hints)}") + print(f"Title: {result.title or 'N/A'}") + print(f"Subject: {result.subject or 'N/A'}") + print(f"Deadline hint: {result.deadline_hint or 'N/A'}") + print(f"Deliverable: {result.deliverable_type or 'N/A'}") + if result.grading_hints: + print("Grading hints:") + for hint in result.grading_hints: + print(f"- {hint}") + else: + print("Grading hints: N/A") + + +if __name__ == "__main__": + main()