From ae91334479404839cbc55e09a4a5f72f614fbad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB=20=D0=9A=D1=83=D1=82?= =?UTF-8?q?=D0=BB=D0=B0=D1=85=D0=BC=D0=B5=D1=82=D0=BE=D0=B2?= Date: Tue, 26 May 2026 12:23:31 +0000 Subject: [PATCH] add main.py --- main.py | 130 ++++++++++---------------------------------------------- 1 file changed, 22 insertions(+), 108 deletions(-) diff --git a/main.py b/main.py index 5c4cd78..f32e8e5 100644 --- a/main.py +++ b/main.py @@ -1,130 +1,44 @@ -""" -Парсер задания: сырой текст → плоская карточка TaskCard. - -Пример: - python main.py - python main.py "Сдайте до понедельника презентацию по RAG: 10 слайдов. Оценка: за полноту и визуализацию." -""" - -import json import os -import sys -from typing import Optional - -from dotenv import load_dotenv -from langchain_core.output_parsers import PydanticOutputParser +from pydantic import BaseModel, Field from langchain_core.prompts import PromptTemplate from langchain_openai import ChatOpenAI -from pydantic import BaseModel, Field - -load_dotenv() - -# --------------------------------------------------------------------------- -# Pydantic-модель карточки задания -# --------------------------------------------------------------------------- - +from langchain_core.output_parsers import PydanticOutputParser class TaskCard(BaseModel): - """Плоская карточка задания — все поля одного уровня вложенности.""" - - title: str = Field( - ..., - description="Краткое название задачи (2–6 слов)", - ) - subject: str = Field( - ..., - description="Область знаний или технология (LangChain, Python, ML и т.п.)", - ) - deadline_hint: str = Field( - ..., - description="Срок сдачи в свободной форме, пустая строка если не указан", - ) - deliverable_type: str = Field( - ..., - description="Что нужно сдать: отчёт, код, презентация, видео, ссылка и т.п.", - ) - grading_hints: list[str] = Field( - default_factory=list, - description="Список критериев оценки, упомянутых в тексте задания", - ) - notes: Optional[str] = Field( - default=None, - description="Любые дополнительные заметки или уточнения из текста", - ) - - -# --------------------------------------------------------------------------- -# LLM — BroJS -# --------------------------------------------------------------------------- + title: str = Field(..., description="Краткое название задачи") + subject: str = Field(..., description="Предмет или область") + deadline_hint: str = Field(..., description="Краткая подсказка о сроке") + deliverable_type: str = Field(..., description="Тип сдачи: отчёт, код, презентация и т.д.") + grading_hints: list[str] = Field(..., description="Список критериев оценки") +# 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.3, + temperature=0.5, ) -# --------------------------------------------------------------------------- -# Цепочка: PromptTemplate → LLM → PydanticOutputParser -# --------------------------------------------------------------------------- - parser = PydanticOutputParser(pydantic_object=TaskCard) -_TEMPLATE = """Ты — ассистент, который извлекает структурированную информацию из описания учебного задания. -Верни ответ строго в формате JSON согласно инструкции ниже — без лишних пояснений. - -{format_instructions} - -Описание задания: -{task_text} -""" +prompt_template = """\nНиже приведена формулировка задания от преподавателя.\nВаша задача – вернуть данные в формате JSON, соответствующем модели TaskCard.\n{format_instructions}\n\nФормулировка: {input_text}\n""" prompt = PromptTemplate( - template=_TEMPLATE, - input_variables=["task_text"], + template=prompt_template, + input_variables=["input_text"], partial_variables={"format_instructions": parser.get_format_instructions()}, ) chain = prompt | llm | parser - -# --------------------------------------------------------------------------- -# Публичный интерфейс -# --------------------------------------------------------------------------- - - -def parse_task(task_text: str) -> TaskCard: - """Парсит текст задания и возвращает валидированный объект TaskCard.""" - return chain.invoke({"task_text": task_text}) - - -def print_card(card: TaskCard) -> None: - """Выводит карточку в двух форматах: JSON-объект и читаемая сводка.""" - print("\n─── Валидированный объект (model_dump) ─────────────────────") - print(json.dumps(card.model_dump(), ensure_ascii=False, indent=2)) - - print("\n─── Человекочитаемая сводка ─────────────────────────────────") - print(f" Задача: {card.title}") - print(f" Тема: {card.subject}") - print(f" Срок: {card.deadline_hint or '—'}") - print(f" Тип сдачи: {card.deliverable_type}") - if card.grading_hints: - print(f" Критерии: {', '.join(card.grading_hints)}") - if card.notes: - print(f" Заметки: {card.notes}") - - -# --------------------------------------------------------------------------- -# CLI -# --------------------------------------------------------------------------- - -_EXAMPLE = ( - "Сдайте к пятнице мини-отчёт по LangChain: 2 страницы, упор на агентов. " - "Оценка: за полноту и за пример кода." -) - if __name__ == "__main__": - text = " ".join(sys.argv[1:]) if len(sys.argv) > 1 else _EXAMPLE - print(f"Вход:\n {text}") - card = parse_task(text) - print_card(card) + example = "Сдайте к пятнице мини-отчёт по LangChain: 2 страницы, упор на агентов. Оценка: за полноту и за пример кода." + result = chain.invoke({"input_text": example}) + print("\n--- Parsed Result ---") + print(result.model_dump()) + 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)}")