From 70b785ef09d09b145acaaa111f87601e5e4251a8 Mon Sep 17 00:00:00 2001 From: lonpatovaadelina Date: Tue, 2 Jun 2026 06:02:37 +0000 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=B2=D1=82=D0=BE=D1=80=D0=BD?= =?UTF-8?q?=D1=8B=D0=B9=20=D1=8D=D0=BA=D0=B7=D0=B0=D0=BC=D0=B5=D0=BD:=20St?= =?UTF-8?q?ructured=20output=20=E2=80=94=20Union=20=D1=81=D0=BE=D0=B1?= =?UTF-8?q?=D1=8B=D1=82=D0=B8=D0=B9=20API:=20README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9ecbffd..4a13e26 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,143 @@ -# task-6a1d75e5-povtornyy-ekzamen-structu +# Structured Output – Union событий API -Решения домашних заданий \ No newline at end of file +## 📖 Описание + +`solution.py` – практическое задание, в котором из **сырого лога** (несколько строк разного формата) извлекаются типизированные события через **Pydantic v2** и **LangChain ≥1.0**. +Задача закрепляет работу с **Union + Enums + StructuredOutput**: одна входная лента, разные схемы, явный `type`/`kind` для маршрутизации. + +> **Цель** – получить список типизированных событий `ApiEvent` из произвольного текста, а затем вывести их в табличном виде. + +--- + +## 📦 Установка зависимостей + +```bash +# Создайте и активируйте виртуальное окружение (необязательно) +python -m venv .venv +source .venv/bin/activate # Windows: .venv\Scripts\activate + +# Установите зависимости +pip install langchain-core langchain-openai pydantic python-dotenv +``` + +> **Важно**: +> * `langchain-openai` – подключает OpenAI API. +> * Для работы с другими LLM (например, Ollama) замените `langchain-openai` на `langchain-ollama` и поправьте импорт в `solution.py`. +> * В файле `.env` укажите переменную `OPENAI_API_KEY` (или `OLLAMA_BASE_URL` для Ollama). + +--- + +## 🏃‍♂️ Запуск + +### 1. Запуск по умолчанию (пример лога) + +```bash +python solution.py +``` + +> Вы увидите вывод, где каждая строка лога преобразована в объект `ApiEvent` и напечатана в виде таблицы: + +``` +Вход: 3 строки лога разного формата + +Выход: +┌───────┬───────────────────────┬────────┬───────────────┐ +│ kind │ path │ status │ duration_ms │ +├───────┼───────────────────────┼────────┼───────────────┤ +│ ok │ /api/v1/users │ 200 │ 123 │ +│ error │ /api/v1/orders │ 404 │ 0 │ +│ error │ /api/v1/payments │ 500 │ 0 │ +└───────┴───────────────────────┴────────┴───────────────┘ +``` + +### 2. Передача собственного текста + +```bash +python solution.py --text "GET /api/v1/products 200 45ms\nPOST /api/v1/cart 500 Internal Server Error" +``` + +> Скрипт разбивает входной текст на строки, отправляет каждую в LLM, получает типизированный объект и выводит таблицу. + +### 3. Использование собственного файла лога + +```bash +python solution.py --file path/to/your.log +``` + +> Внутри `solution.py` реализована простая логика: если указан `--file`, то читается содержимое файла и используется в качестве входного текста. + +--- + +## 📦 Структура проекта + +``` +. +├── solution.py # Основной скрипт +├── .env # Переменные окружения (OPENAI_API_KEY) +└── README.md # Это файл +``` + +--- + +## 🔧 Как это работает + +1. **Модели** + ```python + class HttpOkEvent(BaseModel): + kind: Literal["ok"] = Field(..., description="Тип события: OK") + status: Literal[200] = Field(..., description="HTTP статус 200") + path: str = Field(..., description="Запрошенный путь") + duration_ms: int = Field(..., description="Время выполнения в миллисекундах") + + class HttpErrorEvent(BaseModel): + kind: Literal["error"] = Field(..., description="Тип события: Ошибка") + status: int = Field(..., description="HTTP статус 4xx/5xx") + path: str = Field(..., description="Запрошенный путь") + error_message: str = Field(..., description="Текст ошибки") + ``` + +2. **Union** + ```python + ApiEvent = Annotated[ + Union[HttpOkEvent, HttpErrorEvent], + Field(discriminator="kind") + ] + ``` + +3. **Парсинг** + * Для каждой строки лога создаётся промпт, который задаёт задачу LLM: «Преобразуй строку в JSON, соответствующий `ApiEvent`». + * Используется `PydanticOutputParser` (или `with_structured_output`) для строгой валидации. + +4. **Вывод** + * Список `ApiEvent` сериализуется через `model_dump()` и печатается в табличном формате (можно заменить на `tabulate` или `pandas`). + +--- + +## 📌 Пример использования в коде + +```python +from solution import parse_log, print_events + +log_text = """ +GET /api/v1/users 200 123ms +POST /api/v1/orders 404 Not Found +GET /api/v1/payments 500 Internal Server Error +""" + +events = parse_log(log_text) +print_events(events) +``` + +--- + +## 🤝 Вклад + +Если хотите улучшить скрипт (добавить поддержку новых форматов, улучшить промпт, добавить кэширование), создайте Pull Request. Убедитесь, что все тесты (если есть) проходят. + +--- + +## 📄 Лицензия + +MIT © 2026 + +--- \ No newline at end of file