llm: провайдер за протоколом, фабрика, mock #17

Closed
opened 2026-10-12 19:35:00 +03:00 by Eleboba · 0 comments
Owner

Описание

ADR-008: модель не выбрана — код не должен от неё зависеть.

Желаемый результат

  • LLMProvider Protocol: complete(messages, json_schema=None) -> LLMResult (текст/JSON + токены).
  • openai_compat (base_url, model, api_key, timeout) и mock (детерминированные ответы для тестов).
  • Выбор — LLM_PROVIDER в .env.

Подзадачи

  • app/llm/provider.py — протокол, LLMResult
  • app/llm/openai_compat.py на httpx
  • app/llm/mock.py
  • app/llm/factory.py
  • LLMSettings в конфиге
  • Тесты на respx

Анализ

Затрагиваемые файлы

Файл Что меняется
app/llm/ новый пакет
app/config.py LLMSettings

Ограничения и риски

Ключ — секрет. Таймаут и ретраи на 429/5xx. Учёт токенов — в ответе.

Как проверить

make test; с реальным ключом: python -m app.llm.cli 'привет'.


Лог выполнения

Перенесено из SourceCraft: https://sourcecraft.dev/rogachevegorushka/tgit/issues/17

2026-10-14

  • app/llm/provider.py — протокол LLMProvider.complete(messages, schema=None) -> LLMResult (текст, data — разобранный JSON при запросе схемы, токены). data — только «синтаксически JSON»: форму проверяет вызывающий код (#18).
  • openai_compat.py — /chat/completions, structured output через response_format: json_schema (strict), JSON вынимается и из ```-обёртки; ретраи 408/409/429/5xx и сетевые ошибки (1→2→… с), прочие 4xx — LLMError сразу; тело запроса (текст пользователя) в ошибки не попадает.
  • mock.py — правила «подстрока → ответ» для тестов и демо без сети; factory.py, LLMSettings (LLM_*), CLI python -m app.llm.cli.
  • Тесты: 14 (respx + подменённый sleep), покрытие проекта 92 %.
  • Не проверено вживую: модель не выбрана, ключа нет. Нужна модель с поддержкой response_format: json_schema (у OpenAI-совместимого API YandexGPT — уточнить); если не поддерживает — fallback на «JSON в тексте» уже работает через разбор ответа.
## Описание ADR-008: модель не выбрана — код не должен от неё зависеть. ## Желаемый результат - `LLMProvider` Protocol: `complete(messages, json_schema=None) -> LLMResult` (текст/JSON + токены). - `openai_compat` (base_url, model, api_key, timeout) и `mock` (детерминированные ответы для тестов). - Выбор — `LLM_PROVIDER` в `.env`. ## Подзадачи - [x] `app/llm/provider.py` — протокол, `LLMResult` - [x] `app/llm/openai_compat.py` на httpx - [x] `app/llm/mock.py` - [x] `app/llm/factory.py` - [x] `LLMSettings` в конфиге - [x] Тесты на respx ## Анализ ### Затрагиваемые файлы | Файл | Что меняется | |------|--------------| | `app/llm/` | новый пакет | | `app/config.py` | LLMSettings | ### Ограничения и риски Ключ — секрет. Таймаут и ретраи на 429/5xx. Учёт токенов — в ответе. ## Как проверить `make test`; с реальным ключом: `python -m app.llm.cli 'привет'`. --- ## Лог выполнения > Перенесено из SourceCraft: https://sourcecraft.dev/rogachevegorushka/tgit/issues/17 ### 2026-10-14 - `app/llm/provider.py` — протокол `LLMProvider.complete(messages, schema=None) -> LLMResult` (текст, `data` — разобранный JSON при запросе схемы, токены). `data` — только «синтаксически JSON»: форму проверяет вызывающий код (#18). - `openai_compat.py` — `/chat/completions`, structured output через `response_format: json_schema (strict)`, JSON вынимается и из ```-обёртки; ретраи 408/409/429/5xx и сетевые ошибки (1→2→… с), прочие 4xx — `LLMError` сразу; тело запроса (текст пользователя) в ошибки не попадает. - `mock.py` — правила «подстрока → ответ» для тестов и демо без сети; `factory.py`, `LLMSettings` (`LLM_*`), CLI `python -m app.llm.cli`. - Тесты: 14 (respx + подменённый `sleep`), покрытие проекта 92 %. - **Не проверено вживую:** модель не выбрана, ключа нет. Нужна модель с поддержкой `response_format: json_schema` (у OpenAI-совместимого API YandexGPT — уточнить); если не поддерживает — fallback на «JSON в тексте» уже работает через разбор ответа.
Eleboba added this to the M3 · LLM-ассистент по логам milestone 2026-10-12 19:35:00 +03:00
Eleboba added the llmfeaturesize/0.5 labels 2026-10-12 19:35:00 +03:00
Eleboba self-assigned this 2026-10-12 19:35:00 +03:00
Sign in to join this conversation.