diff --git a/solutions/69dd4221f309a98be0006b2e_сырой_текст_задания___плоская_карточка/solution.py b/solutions/69dd4221f309a98be0006b2e_сырой_текст_задания___плоская_карточка/solution.py index 6a0a0a0..3c906dd 100644 --- a/solutions/69dd4221f309a98be0006b2e_сырой_текст_задания___плоская_карточка/solution.py +++ b/solutions/69dd4221f309a98be0006b2e_сырой_текст_задания___плоская_карточка/solution.py @@ -1,101 +1,68 @@ -from __future__ import annotations - import os 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 -from pydantic import BaseModel, Field class AssignmentCard(BaseModel): - """Структурированная карточка задания.""" + """Структурированная карточка учебного задания.""" - title: str = Field(..., description="Краткое название задачи") - subject: str = Field(..., description="Область знаний или предмет") + title: str = Field(..., description="Название задания одной фразой") + subject: str = Field(..., description="Учебная дисциплина или тема") deadline_hint: str | None = Field( None, - description=( - "Указание срока сдачи в свободной форме (например, «к пятнице»). " - "Если не найдено – None" - ), + description="Срок выполнения в произвольной форме, если упомянут", ) - deliverable_type: str = Field(..., description="Тип сдаваемого материала") - grading_hints: List[str] = Field( + deliverable_type: str = Field( + ..., + description="Что нужно сдать: отчёт, код, презентация и т.п.", + ) + grading_hints: List[str] | None = Field( default_factory=list, - description=( - "Ключевые критерии оценки, перечисленные в тексте. " - "Если не найдено – пустой список" + description="Критерии оценки, которые явно названы в тексте", + ) + + +def run(raw_text: str) -> None: + output_parser = PydanticOutputParser(pydantic_object=AssignmentCard) + + template = PromptTemplate( + template=( + "Прочитай описание учебного задания и заполни все поля карточки.\n\n" + "Описание:\n{raw_text}\n\n" + "Верни ответ строго в JSON без лишних пояснений.\n" + "{format_instructions}" ), + input_variables=["raw_text"], + partial_variables={ + "format_instructions": output_parser.get_format_instructions() + }, ) + model = ChatOpenAI(model="gpt-4o-mini", temperature=0) -def build_chain() -> PromptTemplate: - """Создаёт цепочку Prompt → LLM → Pydantic парсер.""" - parser = PydanticOutputParser(pydantic_object=AssignmentCard) + chain = template | model | output_parser - prompt_template = ( - "Ниже приведено описание задания от преподавателя. " - "Ваша задача – извлечь из него следующую информацию:\n" - "- title: название задачи\n" - "- subject: предмет/область знаний\n" - "- deadline_hint: указание срока сдачи (если есть)\n" - "- deliverable_type: что сдать (отчёт, код, презентация и т.д.)\n" - "- grading_hints: список критериев оценки\n\n" - "Ответ должен быть строго в формате JSON, соответствующем модели " - f"{AssignmentCard.__name__}.\n" - "{format_instructions}\n\n" - "Текст задания:\n{assignment_text}" + card: AssignmentCard = chain.invoke({"raw_text": raw_text}) + + print("Валидированный объект:") + print(card.model_dump()) + + print("\nСводка:") + print( + f"Задание «{card.title}» по теме «{card.subject}». " + f"Сдать: {card.deliverable_type}. " + f"Дедлайн: {card.deadline_hint or 'не указан'}. " + f"Оценивается: {', '.join(card.grading_hints) if card.grading_hints else 'критерии не указаны'}." ) - prompt = PromptTemplate( - template=prompt_template, - input_variables=["assignment_text"], - partial_variables={"format_instructions": parser.get_format_instructions()}, - ) - return prompt - - -def main() -> None: - """Пример использования цепочки.""" - # Получаем ключ API из переменной окружения - api_key = os.getenv("OPENAI_API_KEY") - if not api_key: - raise RuntimeError( - "Переменная окружения OPENAI_API_KEY не установлена. " - "Установите её перед запуском." - ) - - llm = ChatOpenAI(api_key=api_key, temperature=0) - - prompt = build_chain() - parser = PydanticOutputParser(pydantic_object=AssignmentCard) - chain = prompt | llm | parser - - # Пример входного текста - assignment_text = ( - "Сдайте к пятнице мини-отчёт по LangChain: 2 страницы, упор на агентов. " - "Оценка: за полноту и за пример кода." - ) - - result = chain.invoke({"assignment_text": assignment_text}) - - # Выводим валидированный объект - print("=== Валидированная карточка ===") - print(result.model_dump()) - - # Краткая человекочитаемая сводка - summary = ( - f"Задача: {result.title}\n" - f"Предмет: {result.subject}\n" - f"Срок сдачи: {result.deadline_hint or 'не указан'}\n" - f"Тип сдаваемого материала: {result.deliverable_type}\n" - f"Критерии оценки: {', '.join(result.grading_hints) if result.grading_hints else 'нет'}" - ) - print("\n=== Сводка ===") - print(summary) - if __name__ == "__main__": - main() \ No newline at end of file + sample = ( + "Сдайте к пятнице мини-отчёт по LangChain: 2 страницы, упор на агентов. " + "Оценка: за полноту и за пример кода." + ) + run(sample) \ No newline at end of file