From 889499ec936cccc24e3625760ca95932d54005ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=B8=D1=8F=20=D0=91=D0=B5=D1=80=D0=B4?= =?UTF-8?q?=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=D0=B0?= Date: Thu, 28 May 2026 16:46:01 +0000 Subject: [PATCH] =?UTF-8?q?=D0=AD=D0=BA=D0=B7=D0=B0=D0=BC=D0=B5=D0=BD:=20?= =?UTF-8?q?=D0=A1=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83=D1=80=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B=D0=B9=20=D0=B2=D1=8B=D0=B2?= =?UTF-8?q?=D0=BE=D0=B4=20(Pydantic):=20solution.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- solution.py | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 solution.py diff --git a/solution.py b/solution.py new file mode 100644 index 0000000..a6114a7 --- /dev/null +++ b/solution.py @@ -0,0 +1,149 @@ +import os +import sys +from typing import List, Optional + +from langchain_core.output_parsers import PydanticOutputParser +from langchain_core.prompts import PromptTemplate +from langchain_openai import ChatOpenAI +from pydantic import BaseModel, Field + +# ------------------------------------------------------------------ +# 1. Pydantic модели +# ------------------------------------------------------------------ + + +class PersonInfo(BaseModel): + name: str = Field(..., description="Имя человека") + age: Optional[int] = Field(None, description="Возраст (если известен)") + profession: str = Field(..., description="Профессия или должность") + skills: List[str] = Field(..., description="Список навыков") + + +class MeetingNotes(BaseModel): + date: str = Field(..., description="Дата встречи в формате YYYY-MM-DD") + participants: List[str] = Field( + ..., description="Имена участников встречи" + ) + topics: List[str] = Field(..., description="Темы обсуждения") + decisions: List[str] = Field( + ..., description="Принятые решения и выводы" + ) + next_steps: List[str] = Field( + ..., + description="Следующие шаги после встречи", + ) + + +# ------------------------------------------------------------------ +# 2. Создание парсера +# ------------------------------------------------------------------ + + +def get_parser(model_cls): + return PydanticOutputParser(pydantic_object=model_cls) + + +person_parser = get_parser(PersonInfo) +meeting_parser = get_parser(MeetingNotes) + +# ------------------------------------------------------------------ +# 3. Prompt шаблоны (один общий, но с разными инструкциями) +# ------------------------------------------------------------------ + + +prompt_template = """ +{format_instructions} + +Входной текст: +"{text}" +""" + +prompt = PromptTemplate( + input_variables=["text", "format_instructions"], + template=prompt_template, +) + +# ------------------------------------------------------------------ +# 4. LLM +# ------------------------------------------------------------------ +# Для работы нужен API‑ключ OpenAI в переменной окружения OPENAI_API_KEY +llm = ChatOpenAI(temperature=0, model_name="gpt-3.5-turbo") + +# ------------------------------------------------------------------ +# 5. Функция выбора схемы и выполнения цепочки +# ------------------------------------------------------------------ + + +def extract_structured(text: str): + """ + Определяем тип текста (person vs meeting) по эвристике + и возвращаем валидированный объект Pydantic. + """ + # простая эвристика: наличие слова "встреча" или "meeting" + if any(word in text.lower() for word in ["встреча", "meeting"]): + parser = meeting_parser + else: + parser = person_parser + + chain = prompt | llm | parser + result = chain.invoke( + { + "text": text, + "format_instructions": parser.get_format_instructions(), + } + ) + return result + + +# ------------------------------------------------------------------ +# 6. CLI +# ------------------------------------------------------------------ + + +def main(): + examples = [ + ( + "Анна, 28 лет, Python-разработчик. Навыки: FastAPI, Docker.", + PersonInfo, + ), + ( + """Встреча 2023-08-15 + +Участники: +- Иванов И.И. +- Петров П.П. + +Темы: +1. Обновление проекта +2. Распределение задач + +Решения: +- Завершить модуль X к 01/09 +- Назначить ответственных за Y + +Следующие шаги: +- Подготовить презентацию +- Отправить отчёт команде""", + MeetingNotes, + ), + ] + + if len(sys.argv) > 1 and sys.argv[1] == "--example": + for idx, (txt, model_cls) in enumerate(examples, start=1): + print(f"\n=== Пример {idx} ===") + obj = extract_structured(txt) + print(obj.model_dump(indent=2)) + else: + # пользовательский ввод + print("Введите текст (Ctrl-D/Enter для завершения):") + user_text = sys.stdin.read().strip() + if not user_text: + print("Пустой ввод.") + return + obj = extract_structured(user_text) + print("\nРезультат:") + print(obj.model_dump(indent=2)) + + +if __name__ == "__main__": + main() \ No newline at end of file