""" Задание 2: Сырой текст задания → плоская карточка Скрипт с LangChain + Pydantic, который из неструктурированного текста задания извлекает структурированную карточку: title, subject, deadline_hint, deliverable_type, grading_hints. """ import os from pydantic import BaseModel, Field from langchain.output_parsers import PydanticOutputParser from langchain.prompts import PromptTemplate from langchain_openai import ChatOpenAI # ─── Pydantic-модель карточки ─────────────────────────────────────────────── class TaskCard(BaseModel): """Структурированная карточка задания, извлечённая из сырого текста.""" title: str = Field( description="Краткое название задания (1–10 слов)" ) subject: str = Field( description="Предмет / область знаний, к которой относится задание" ) deadline_hint: str = Field( description="Указание на дедлайн, если есть в тексте; иначе — «не указан»" ) deliverable_type: str = Field( description="Тип результата: например «код», «эссе», «презентация», «отчёт», «тест» и т.д." ) grading_hints: str = Field( description="Подсказки по оцениванию: что будет проверяться, критерии, баллы — кратко" ) # ─── Настройка парсера и промпта ─────────────────────────────────────────── parser = PydanticOutputParser(pydantic_object=TaskCard) prompt = PromptTemplate( template=( "Ты — ассистент, который превращает неструктурированный текст учебного задания " "в структурированную карточку.\n\n" "Извлеки из текста ниже пять полей:\n" "- title — краткое название задания\n" "- subject — предмет / область\n" "- deadline_hint — дедлайн (если указан, иначе «не указан»)\n" "- deliverable_type — тип результата (код, эссе, презентация, отчёт, тест…)\n" "- grading_hints — краткие критерии оценивания\n\n" "Текст задания:\n" "{raw_text}\n\n" "{format_instructions}" ), input_variables=["raw_text"], partial_variables={"format_instructions": parser.get_format_instructions()}, ) # ─── Инициализация LLM ────────────────────────────────────────────────────── # Переменные окружения (можно задать через .env или export): # OPENAI_API_BASE — URL API (по умолчанию https://api.openai.com/v1) # OPENAI_API_KEY — ключ API # OPENAI_MODEL — модель (по умолчанию gpt-4o-mini) api_base = os.environ.get("OPENAI_API_BASE", "https://api.openai.com/v1") api_key = os.environ.get("OPENAI_API_KEY", "") model_name = os.environ.get("OPENAI_MODEL", "gpt-4o-mini") llm = ChatOpenAI( model=model_name, openai_api_base=api_base, openai_api_key=api_key, temperature=0, ) # ─── Цепочка (один проход) ────────────────────────────────────────────────── chain = prompt | llm | parser # ─── Пример использования ─────────────────────────────────────────────────── SAMPLE_TASK = ( "Напишите Python-скрипт, который парсит CSV-файл с данными о продажах " "и строит сводный отчёт по месяцам. Код должен быть покрыт тестами (pytest). " "Дедлайн — 15 марта 2025 года. Оценивается: корректность парсинга (30%), " "качество тестов (30%), читаемость кода (20%), оформление README (20%). " "Предмет: Программирование на Python." ) def extract_card(raw_text: str) -> TaskCard: """Извлечь структурированную карточку из сырого текста задания.""" result = chain.invoke({"raw_text": raw_text}) return result def print_card(card: TaskCard) -> None: """Красивый вывод карточки.""" print("=" * 60) print(" СТРУКТУРИРОВАННАЯ КАРТОЧКА ЗАДАНИЯ") print("=" * 60) for key, value in card.model_dump().items(): print(f" {key:20s}: {value}") print("=" * 60) print() print("model_dump():") print(card.model_dump()) print() print("── Краткая сводка ──") print(f" 📌 Задание : {card.title}") print(f" 📚 Предмет : {card.subject}") print(f" ⏰ Дедлайн : {card.deadline_hint}") print(f" 📦 Результат: {card.deliverable_type}") print(f" ✅ Критерии : {card.grading_hints}") if __name__ == "__main__": print("Образец входного текста:") print(f' "{SAMPLE_TASK}"') print() card = extract_card(SAMPLE_TASK) print_card(card)