Structured Output Union событий API

📖 Описание

solution.py – практическое задание, в котором из сырого лога (несколько строк разного формата) извлекаются типизированные события через Pydantic v2 и LangChain ≥1.0.
Задача закрепляет работу с Union + Enums + StructuredOutput: одна входная лента, разные схемы, явный type/kind для маршрутизации.

Цель – получить список типизированных событий ApiEvent из произвольного текста, а затем вывести их в табличном виде.


📦 Установка зависимостей

# Создайте и активируйте виртуальное окружение (необязательно)
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. Запуск по умолчанию (пример лога)

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. Передача собственного текста

python solution.py --text "GET /api/v1/products 200 45ms\nPOST /api/v1/cart 500 Internal Server Error"

Скрипт разбивает входной текст на строки, отправляет каждую в LLM, получает типизированный объект и выводит таблицу.

3. Использование собственного файла лога

python solution.py --file path/to/your.log

Внутри solution.py реализована простая логика: если указан --file, то читается содержимое файла и используется в качестве входного текста.


📦 Структура проекта

.
├── solution.py          # Основной скрипт
├── .env                 # Переменные окружения (OPENAI_API_KEY)
└── README.md            # Это файл

🔧 Как это работает

  1. Модели

    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

    ApiEvent = Annotated[
        Union[HttpOkEvent, HttpErrorEvent],
        Field(discriminator="kind")
    ]
    
  3. Парсинг

    • Для каждой строки лога создаётся промпт, который задаёт задачу LLM: «Преобразуй строку в JSON, соответствующий ApiEvent».
    • Используется PydanticOutputParser (или with_structured_output) для строгой валидации.
  4. Вывод

    • Список ApiEvent сериализуется через model_dump() и печатается в табличном формате (можно заменить на tabulate или pandas).

📌 Пример использования в коде

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


S
Description
Решения домашних заданий
Readme 30 KiB
Languages
Python 100%