# task.py import os from typing import List, Optional 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): """ Карточка задания, получаемая из неформального описания. """ title: str = Field(..., description="Краткое название задачи") subject: Optional[str] = Field( None, description="Предмет/тема, к которой относится задание (если указано)" ) deadline_hint: Optional[str] = Field( None, description="Указание срока сдачи в свободной форме" ) deliverable_type: str = Field(..., description="Тип сдаваемого материала") grading_hints: List[str] = Field( default_factory=list, description="Ключевые критерии оценки (если упомянуты)" ) # Создаём парсер для Pydantic модели parser = PydanticOutputParser(pydantic_object=TaskCard) # Шаблон промпта. Модель должна вернуть JSON, соответствующий TaskCard. prompt_template = PromptTemplate( template=""" Вы — помощник по анализу учебных заданий. Вам дано неформальное описание задания от преподавателя. Нужно извлечь из него следующую информацию и вернуть в формате JSON, соответствующем модели TaskCard: {format_instructions} Пример входа: {input_text} """, input_variables=["input_text"], partial_variables={"format_instructions": parser.get_format_instructions()}, ) # Инициализируем LLM. Ключ берётся из переменной окружения OPENAI_API_KEY. llm = ChatOpenAI( model="gpt-4o-mini", # можно заменить на нужную модель temperature=0, max_retries=2, ) # Строим цепочку: промпт → LLM → парсер chain = prompt_template | llm | parser def main(): """ Пример использования. Вводится строка задания, выводятся: 1) валидированный объект TaskCard (dump) 2) человекочитаемая сводка """ # Для примера берём ввод из переменной окружения или stdin input_text = os.getenv( "TASK_TEXT", "Сдайте к пятнице мини-отчёт по LangChain: 2 страницы, упор на агентов. Оценка: за полноту и за пример кода." ) # Запускаем цепочку result: TaskCard = chain.invoke({"input_text": input_text}) # Выводим результат print("\n=== Валидированный объект ===") print(result.model_dump(indent=2)) print("\n=== Краткая сводка ===") summary_parts = [ f"Задача: {result.title}", f"Тема: {result.subject or 'не указана'}", f"Срок сдачи: {result.deadline_hint or 'не указан'}", f"Тип сдаваемого материала: {result.deliverable_type}", ] if result.grading_hints: summary_parts.append( "Критерии оценки: " + ", ".join(result.grading_hints) ) print("; ".join(summary_parts)) if __name__ == "__main__": main()