94 lines
3.2 KiB
Python
94 lines
3.2 KiB
Python
"""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 '<assignment text>'")
|
||
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}")
|