Files
task-6a1484a292f7bbc573321443/main.py
T
2026-05-27 13:32:34 +00:00

112 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Main entry point for the "сырой текст задания → плоская карточка" task.
The script demonstrates how to convert a freeform description of an assignment into a structured data object using LangChain and Pydantic.
Usage examples are provided in the ``__main__`` section three different raw texts are parsed and printed.
"""
from __future__ import annotations
import os
from typing import List
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field
# ---------------------------------------------------------------------------
# 1. Define the data model that represents a task card.
# ---------------------------------------------------------------------------
class TaskCard(BaseModel):
"""Structured representation of an assignment description.
The fields are intentionally generic they capture the most common pieces of information
that appear in the course tasks:
* ``title`` short name of the task.
* ``subject`` subject or topic area.
* ``deadline_hint`` freeform hint about when the task should be finished.
* ``deliverable_type`` what is expected to be submitted (report, code, presentation…).
* ``grading_hints`` list of items that influence grading.
"""
title: str = Field(..., description="Short name of the task")
subject: str | None = Field(None, description="Subject or topic area")
deadline_hint: str | None = Field(
None,
description="Freeform hint about when the task should be finished",
)
deliverable_type: str | None = Field(
None,
description="What is expected to be submitted (report, code, presentation…)",
)
grading_hints: List[str] = Field(
default_factory=list,
description="List of items that influence grading",
)
# ---------------------------------------------------------------------------
# 2. Build the prompt and parser.
# ---------------------------------------------------------------------------
parser = PydanticOutputParser(pydantic_object=TaskCard)
prompt_template = PromptTemplate(
template=(
"You are an assistant that extracts structured information from a freeform task description."
" Return only the data in JSON format that matches the following schema:\n{format_instructions}\n"
"Input: {text}"
),
input_variables=["text"],
partial_variables={"format_instructions": parser.get_format_instructions()},
)
# ---------------------------------------------------------------------------
# 3. Create the LLM instance.
# ---------------------------------------------------------------------------
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,
)
# ---------------------------------------------------------------------------
# 4. Helper that runs the chain and returns a TaskCard.
# ---------------------------------------------------------------------------
async def parse_task(text: str) -> TaskCard:
"""Parse *text* into a :class:`TaskCard` using LangChain.
The function is asynchronous because ``ChatOpenAI`` uses an async API. It can be called from
synchronous code via ``asyncio.run``.
"""
chain = prompt_template | llm | parser
result = await chain.ainvoke({"text": text})
return result
# ---------------------------------------------------------------------------
# 5. Demo three example texts.
# ---------------------------------------------------------------------------
if __name__ == "__main__":
import asyncio
examples = [
"Сдайте к пятнице мини‑отчёт по LangChain: 2 страницы, упор на агентов. Оценка: за полноту и за пример кода.",
"На следующей неделе подготовьте презентацию о Qdrant. Должно быть 10 слайдов, включать примеры кода. Оценка по содержанию и дизайну.",
"Разработайте скрипт на Python, который генерирует случайный пароль длиной 12 символов. Сдача – код в репозитории. Оценка: корректность и безопасность.",
]
async def demo():
for i, txt in enumerate(examples, start=1):
card = await parse_task(txt)
print(f"\nExample {i}:")
print("Raw text:")
print(txt)
print("\nParsed card: ")
# Prettyprint the model using ``model_dump`` it returns a dict.
print(card.model_dump(indent=2, sort_keys=False))
asyncio.run(demo())