"""Task parser for raw assignment text. This module demonstrates how to convert a free‑form assignment description into a structured data object using LangChain and Pydantic. The main entry point is :func:`parse_task` which accepts a string and returns a validated :class:`TaskCard` instance. Example usage: >>> from main import parse_task >>> text = "Сдайте к пятнице мини-отчёт по LangChain: 2 страницы, упор на агентов. Оценка: за полноту и за пример кода." >>> card = parse_task(text) >>> print(card.model_dump()) {"title": "мини-отчёт по LangChain", "subject": "LangChain", "deadline_hint": "к пятнице", "deliverable_type": "отчёт", "grading_hints": ["полнота", "пример кода"]} """ from __future__ import annotations 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 class TaskCard(BaseModel): """Structured representation of an assignment description.""" title: str = Field(..., description="Short title of the assignment") subject: str = Field(..., description="Subject or topic of the assignment") deadline_hint: str = Field(..., description="Free‑form deadline hint") deliverable_type: str = Field(..., description="What is expected to be submitted") grading_hints: List[str] = Field(..., description="List of grading criteria mentioned in the text") # Prompt template – we ask the model to output JSON that matches TaskCard. prompt_template = ( "You are an assistant that extracts structured information from a short assignment description." " Return a JSON object with the following fields: title, subject, deadline_hint, deliverable_type, grading_hints." " Do not add any extra keys or text." " Example input: {input_text}\n" " {format_instructions}" ) parser = PydanticOutputParser(pydantic_object=TaskCard) prompt = PromptTemplate( template=prompt_template, input_variables=["input_text"], partial_variables={"format_instructions": parser.get_format_instructions()}, ) # Use the default OpenAI model; the user can set OPENAI_API_KEY. llm = ChatOpenAI(temperature=0) # Chain: prompt -> LLM -> parser chain = prompt | llm | parser def parse_task(text: str) -> TaskCard: """Parse raw assignment text into a :class:`TaskCard`. Parameters ---------- text: Raw assignment description. Returns ------- TaskCard Validated structured data. """ return chain.invoke({"input_text": text}) if __name__ == "__main__": import sys if len(sys.argv) < 2: print("Usage: python main.py ''") sys.exit(1) raw = sys.argv[1] card = parse_task(raw) print("Parsed card:\n", card.model_dump(indent=2)) print("\nHuman‑readable summary:\n") print(f"Title: {card.title}") print(f"Subject: {card.subject}") print(f"Deadline hint: {card.deadline_hint}") print(f"Deliverable type: {card.deliverable_type}") print("Grading hints:") for hint in card.grading_hints: print(f"- {hint}")