diff --git a/main.py b/main.py new file mode 100644 index 0000000..0e58933 --- /dev/null +++ b/main.py @@ -0,0 +1,93 @@ +"""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}")