Skip to content

Phase 7.3: LLMService facade — извлечь generate/stream из оркестратора #644

@ShaerWare

Description

@ShaerWare

Parent

Sub-issue of #641 (Phase 7: Service facade migration)

Зависит от

Цель

Извлечь логику LLM-генерации из orchestrator.py в LLMService фасад, соответствующий Protocol из modules/llm/protocols.py.

Текущее состояние

Генерация размазана между:

  • orchestrator.py (_process_llm_request, ~200 строк) — сборка промпта, RAG-контекст, FAQ, history, вызов провайдера, token accounting
  • cloud_llm_service.pyBaseLLMProvider ABC + конкретные провайдеры (Gemini, OpenAI, Claude, DeepSeek), generate_response(), generate_response_stream()
  • modules/llm/service.pyCloudProviderService (CRUD провайдеров в БД)

Ключевая логика в оркестраторе:

  1. Resolve backend (vllm / cloud:provider-id)
  2. Собрать system prompt (persona + custom)
  3. Получить RAG-контекст из wiki_rag_service
  4. Получить FAQ-ответ
  5. Собрать messages (system + history + user)
  6. Вызвать провайдер (generate / stream)
  7. Token accounting

Что сделать

  1. Создать LLMServiceImpl в modules/llm/facade.py, реализующий Protocol
  2. generate() / stream() инкапсулируют всю цепочку (промпт, RAG, FAQ, вызов, accounting)
  3. resolve_backend() делегирует к CloudProviderService
  4. list_providers() делегирует к CloudProviderService
  5. Зависимость от KnowledgeService (для RAG-контекста) — через конструктор
  6. Возвраты типизированы через TypedDict из modules/llm/schemas.py
  7. Зарегистрировать в ServiceContainer
  8. Мигрировать оркестратор: заменить inline-логику на вызов llm_service.generate() / stream()

Нюансы

  • Самый большой blast radius — оркестратор, chat endpoint, widget endpoint, telegram bot, whatsapp bot — все используют LLM-генерацию
  • BaseLLMProvider остаётся — это internal implementation, не Protocol boundary
  • Streaminggenerate_response_stream() возвращает sync Generator, нужен async wrapper
  • Config resolution — сейчас хардкожен порядок (action button → segment → bot default → global), нужно сохранить
  • Dependency на KnowledgeService — для RAG. Если 7.2 ещё не сделан, можно временно зависеть от wiki_rag_service напрямую

Критерии готовности

  • LLMServiceImpl реализует Protocol
  • Вся логика генерации извлечена из orchestrator.py
  • Оркестратор вызывает llm_service.generate() / stream() вместо inline-кода
  • Streaming работает корректно (SSE, widget, telegram)
  • Тесты, CI зелёный

Риск: высокий

Затрагивает ядро системы. Требует тщательного тестирования всех каналов (admin chat, widget, telegram, whatsapp).

Оценка: L-XL (1-2 PR)

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low priority / Backlogphase:5-techdebtPhase 5: Technical DebtrefactoringArchitectural refactoring

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions