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,/jobsasync routes existují, brokeravax-redis:6379/2(+ backend/3) naavax_default. Vlastní schemaapp_ai_helper(chat_conversation,chat_message,rag_corpus/document/chunk,worker,ai_capability). - core-api
/ai/*LIVE-but-BROKEN: jedinýai_serversrow míří na192.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)
ai_conversation_documents → ai_messages → ai_chunks →
ai_documents → ai_conversations → ai_assistants → ai_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)zmain.py+ smazatrouters/ai.py.
Fáze 5 — Archiv + drop (gated, destruktivní)¶
Pořadí: až po deployi Fází 1–4 (žádné nové zápisy).
- 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. - Drop migrace
031_drop_legacy_ai(down_revision030connectors): - drop v FK pořadí (viz §2).
op.drop_table()× 7. ai_chunksHNSW indexy + vector sloupce padnou s tabulkou.- pgvector extension: nechat (low cost; potvrdit, že v public schema ji
nepoužívá nic jiného než
ai_chunks). - Projít
/review-migrationpřed commitem. - 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é)