Files

124 lines
5.7 KiB
Python
Raw Permalink 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.
"""
Задание: Сырой текст задания → плоская карточка
Скрипт с LangChain + Pydantic, который из неструктурированного текста задания
извлекает структурированную карточку: title, subject, deadline_hint,
deliverable_type, grading_hints (list[str]).
"""
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: list[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 ──────────────────────────────────────────────────────
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" ✅ Критерии : {', '.join(card.grading_hints)}")
if __name__ == "__main__":
print("Образец входного текста:")
print(f' "{SAMPLE_TASK}"')
print()
card = extract_card(SAMPLE_TASK)
print_card(card)