Přeskočit obsah

Core-API AI Decommission — runbook

Stav: PLÁN (schváleno 2026-06-03). Žádné code edity zatím — tohle je execution-ready handoff. Cíl: core-api přestane být AI provider; veškerá komunikace s lokálním LLM jde přes app-ai-helper (async chat-jobs). Worker registry v core-api se ruší. Historie chatu archivovat → dropnout.

0. Rozhodnutí (locked)

Otázka Rozhodnutí
Rozsah Celý decommission, fázovaně (Fáze 1–5)
Historie 719 konverzací / 1443 zpráv Archivovat (pg_dump → S3) → dropnout tabulky
Legacy /ai/chat + /ai/conversations Retire (ne proxy shim)
Worker registry /ai/servers + AiServer Odstranit — registr je výhradně app_ai_helper.worker

1. Současný stav (ověřeno na avaxdev 2026-06-03)

  • app-ai-helper LIVE a funkční: gerry worker (LM Studio, 192.168.1.188:1234, qwen3.6-27b) online, /jobs async routes existují, broker avax-redis:6379/2 (+ backend /3) na avax_default. Vlastní schema app_ai_helper (chat_conversation, chat_message, rag_corpus/document/chunk, worker, ai_capability).
  • core-api /ai/* LIVE-but-BROKEN: jediný ai_servers row míří na 192.168.1.167:1234 = mrtvá IP (gerry se přesunul na .188). Každý nový chat přes core-api → 502/connection refused. Tj. legacy chat je už teď nefunkční, jen formálně mountovaný.
  • Data v core-api (public schema): ai_conversations=719, ai_messages=1443, ai_documents=23, ai_chunks=125, ai_assistants=3 (1 s aktivním API klíčem: legal-asistent), ai_servers=1 (stale).
  • core-api alembic head: 030connectors.
  • app-legal už jede M2M → app-ai-helper (NE legacy LEGAL_AI_KEY); ověřeno E2E smoke {'vysledek':4}.

2. Inventář — kde core-api sahá na lokální LLM

Vše přes backend/app/services/ai.py (přímý LM Studio klient) nad AiServer:

Soubor / místo Co Lokální LLM
backend/app/routers/ai.py /ai/servers/* worker registry CRUD + ping + models proxy ano
backend/app/routers/ai.py /ai/assistants/* asistenti + per-assistant API klíče
backend/app/routers/ai.py /ai/conversations/* user SSE chat ano (chat_completion_stream)
backend/app/routers/ai.py /ai/chat M2M chat (api-key) ano (chat_completion)
backend/app/routers/ai.py /ai/documents/* + retrieve_context RAG upload/index + embed ano (embed)
backend/app/services/ai.py LM Studio klient (ping/embed/list_models/chat/stream + RAG retrieval) ano
backend/app/workers/ai_rag.py Celery ai.index_document ano (embed)
backend/app/main.py:93-94 include_router(ai_router) mount
backend/tests/test_ai_chat.py testy legacy AI
launcher2 desktop/launcher2/api.py ai_admin_* (servery/asistenti/klíče) + ai_create_conversation + ai_send_message_stream volá core-api
launcher2 desktop/launcher2/screens/core.py admin UI „AI servery / asistenti" (~ř. 6149+) volá core-api
launcher2 desktop/launcher2/screens/support.py vestavěný chat (ř. 91, _ai_send, ~418/554) volá core-api

FK graf (pořadí dropů = děti první)

ai_conversation_documents → ai_conversations, ai_documents   (oboje CASCADE)
ai_messages               → ai_conversations                 (CASCADE)
ai_chunks                 → ai_documents                     (CASCADE) + vector(1024/768) HNSW
ai_documents              → users, companies, apps, ai_servers(embedding_server_id SET NULL)
ai_conversations          → users, ai_assistants(SET NULL), ai_servers(server_id RESTRICT), apps
ai_assistants             → apps(CASCADE), ai_servers(default_server_id SET NULL)
ai_servers                → (kořen)
Drop order: ai_conversation_documentsai_messagesai_chunksai_documentsai_conversationsai_assistantsai_servers.


3. Fáze

Princip pořadí: napřed deploy code (zastaví zápisy a volání na LLM), teprve POTOM archiv (konzistentní snapshot) a drop. Code fáze 1–4 jsou reverzibilní přes git. Fáze 5 (drop dat) je jednosměrná — až po ověřeném archivu.

Fáze 0 — async cutover prerequisite — ✅ HOTOVO (2026-06-03)

app-ai-helper shipnul async chat-job (cesta A: Celery, ne in-process). E2E ověřeno reálným app-legal M2M tokenem ({'vysledek':4} přes strict json_schema).

Async kontrakt (pro app-legal avax_client): 1. Token: POST {AVAX_API_URL}/auth/token — ⚠️ JSON body (NE form-encoded!): {"grant_type":"client_credentials","client_id":…,"client_secret":…,"scope":"ai-chat-async"}{access_token, scope:"ai-chat-async"}. (Scope ai-chat-async přidán do m2m_clients.allowed_scopes app-legal — gated UPDATE hotový.) 2. Submit: POST {AVAX_GATEWAY_URL}/apps/app-ai-helper/v1/call/chat.job (Bearer), body = stejný chat payload jako sync (messages, temperature, response_format strict json_schema projde verbatim, chat_template_kwargs). → 202 {job_id, status:"queued", poll:"/jobs/{id}"}. 3. Poll: GET {AVAX_GATEWAY_URL}/apps/app-ai-helper/jobs/{job_id} (Bearer). status: queued → done | failed | error. Job keys: id,type,status,priority, assigned_worker_id,progress,result_s3_keys,error,…. Na done: result_s3_keys.result.choices[0].message.content. 4. Poll interval ~4s, timeout velkoryse (gerry cold-load = první volání po idle může failed → resubmit). Latency warm ~8s.

Pozn.: AVAX_GATEWAY_URL=http://core-api:80 (nginx→apps-gateway), AVAX_API_URL=http://core-api:8000 (bare backend). connector ai-chat-async v0.1.0 (provider app-ai-helper).

Fáze 1 — Worker registry pryč (AiServer)

Backend (backend/): - Odebrat /ai/servers/* endpointy z routers/ai.py (list/create/get/update/ delete/models/ping). - Odebrat ping(), list_models() ze services/ai.py (server-bound). - AiServer model nechat dokud nepadnou FK (Fáze 5) — jen přestat exponovat.

Launcher2 (desktop/launcher2/): - api.py: odebrat ai_admin_list_servers/create/update/delete/server_models/ping_server. - screens/core.py: odebrat admin sekci „AI servery".

Reverzibilní (kód).

Fáze 2 — Legacy chat retire

Backend: - Odebrat /ai/conversations/*, /ai/chat (+ _m2m_stream_response, _resolve_m2m_assistant), /ai/assistants/* (+ api-key endpointy). - Ze services/ai.py odebrat chat_completion, chat_completion_stream, _build_messages.

Launcher2: - screens/support.py: vestavěný chat → nahradit tlačítkem „Otevřít AI Pomocníka" (spustí app-ai-helper z katalogu přes IPC) NEBO odebrat. - api.py: odebrat ai_create_conversation, ai_send_message_stream, ai_list_assistants/conversations a asistent-admin helpery. - screens/core.py: odebrat admin sekci „Asistenti" + API-key UI.

Koordinace app-legal: zrušit legacy LEGAL_AI_KEY fallback (už jede M2M); revokovat asistenta legal-asistent API klíč (před dropem dat).

Fáze 3 — RAG/embed + platform_docs korpus

Backend: - Odebrat /ai/documents/*, retrieve_context, format_rag_context, _resolve_doc_ids, embed, _build_site_url ze services/ai.py. - Smazat workers/ai_rag.py + odregistrovat task ai.index_document z workers/celery_app.py. - Tím je services/ai.py prázdný → smazat celý soubor + models/ai.py import v main.py.

Korpus (21 platform_docs / 125 chunků): - Re-index do app-ai-helper RAG přes /v1/rag/corpora + /v1/batch/rag/index (koordinace app-ai-helper Claude). - Ověřit, jestli běží docs-corpus sync timer (systemd na avaxdev, sync_docs_corpus) — přepojit na ai-helper, nebo retire.

Fáze 4 — Launcher2 finalize + testy

  • Odebrat backend/tests/test_ai_chat.py.
  • Odebrat zbylé danglingy v api.py / core.py.
  • Bump launcher verze + publish (vendor publish.yml flow).
  • core-api: odebrat include_router(ai_router) z main.py + smazat routers/ai.py.

Fáze 5 — Archiv + drop (gated, destruktivní)

Pořadí: až po deployi Fází 1–4 (žádné nové zápisy).

  1. Archiv (pg_dump dotčených tabulek → gzip → S3):
    sudo docker exec avax-postgres pg_dump -U avaxis -d avaxis_dev \
      -t public.ai_conversation_documents -t public.ai_messages \
      -t public.ai_chunks -t public.ai_documents -t public.ai_conversations \
      -t public.ai_assistants -t public.ai_servers \
      --no-owner | gzip > /tmp/legacy_ai_archive_2026-06-03.sql.gz
    # → upload do S3 (bucket claudeai, key archive/legacy-ai/legacy_ai_2026-06-03.sql.gz)
    # → OVĚŘIT restore do scratch DB PŘED dropem.
    
  2. Drop migrace 031_drop_legacy_ai (down_revision 030connectors):
  3. drop v FK pořadí (viz §2). op.drop_table() × 7.
  4. ai_chunks HNSW indexy + vector sloupce padnou s tabulkou.
  5. pgvector extension: nechat (low cost; potvrdit, že v public schema ji nepoužívá nic jiného než ai_chunks).
  6. Projít /review-migration před commitem.
  7. Deploy migrace (bare backend alembic upgrade head).

4. Koordinace (cross-Claude)

Komu Co potřebuju / dodám
app-ai-helper Claude (a) jaký scope kontroluje /jobs submit; (b) převzít platform_docs korpus k re-indexu; (c) potvrdit, že historii chatu NEmigrujeme (archiv+drop)
app-legal Claude (a) přepnout na async /apps/app-ai-helper/jobs; (b) zrušit LEGAL_AI_KEY; (c) potvrdit, že legacy legal-asistent klíč můžu revokovat
launcher2 UI změny Fáze 1–4 + bump/publish

5. Rollback & data-safety

  • Fáze 1–4 = jen kód → git revert / redeploy starého image.
  • Fáze 5 archiv MUSÍ projít restore-verifikací do scratch DB před dropem.
  • Archiv držet ≥ 90 dní (S3) i po dropu.
  • Drop NIKDY před deployem code fází (jinak živé endpointy zapisují do mizejících tabulek).

6. Související

  • docs/spec/ai-helper.md — cílový AI provider (worker/scheduler/jobs)
  • docs/spec/ai-chat.md — legacy kontrakt (po decommissi historický)
  • app-legal/.tmp/PLATFORM_ASYNC_INFRA_HANDOFF.md — async infra (Fáze 0)
  • apps-gateway/src/apps_gateway/routing.py — generický proxy (jobs pokryté)