app-hotline — Hotline AVAXIS (call & voice support monitoring)¶
Status: draft v0.3 (schema rewrite — screenplay model) Aktualizováno: 2026-05-30 Vendor: AVAXIS.CZ (publisher) Repo:
git.avaxis.cz/avax-apps/app-hotline-appSlug:app-hotline(schemaapp_hotline, bucketapp-hotline, port 8106) Související:ai-helper.md,app-ai-helper.md,voice-video-call.md,apps-gateway.md
0. Zásadní rozhodnutí¶
v0.3 — F3 schema rewrite (2026-05-30)¶
- Application
hotline-transcribev app-ai-helper přebírá celou STT+strukturalizaci. Aplikace registrovaná druhým Claude na app-ai-helper s 2-step pipeline (speech.to_text.diarized→chatAya 32B screenplay formatting). App-hotline backend volá 1× endpoint a dostane hotový screenplay + turns + AI topic/usefulness/summary. - Schema = screenplay model (ne turn-by-turn segments). Tabulky:
hotline_call,hotline_turn,billing_entries,self_service_queries,audit_log. Per F3 commit40a245d. - AI/human mirror columns —
hotline_call.ai_*(návrh od AI) vshotline_call.human_*(operatorův přepis při approval). Vždy oba sloupce per pole (screenplay/topic/summary/usefulness) — pro audit trail původního AI návrhu i lidsky validovaného výstupu. - Customer consent gate — GDPR Article 6(1)(a) compliance.
customer_consent BOOLEAN NOT NULL DEFAULT FALSE+ dialog před recording. Bez consent recording nepoběží. - Customer phone hashing — SHA256(phone + company_salt). Plain phone NIKDY není uložené.
v0.2 (zachované)¶
- Batch only. Žádný live streaming — WAV se uploaduje až po ukončení hovoru. Live transcription je P3 roadmap.
- GDPR retention 30 dní audio (auto-delete cron), transkripty + screenplay zachovány déle (anonymizace per retention policy v audit_log).
1. Cíl¶
Hotline AVAXIS monitoruje hlasové hovory (telefon / VoIP / face-to-face s mic záznamem), automaticky je přepisuje, identifikuje účastníky a extrahuje dotazy + odpovědi. Z extrahovaných Q&A buduje RAG knowledge base, kterou uživatelé používají self-service místo dalšího volání. Souběžně generuje fakturační podklady (kdo volal, jak dlouho, jaká témata).
Use case scénář¶
- Klient (Jiří Novák) zavolá na hotline kvůli problému s migrací DB.
- Operátor (Petra) zvedne, hovor začne — Hotline app monitoruje mic (operátorův PC) + line-in (klientský audio stream přes VoIP bridge).
- Hovor trvá 12 min. Hotline:
- Live STT (Whisper Small, lokální worker)
- Speaker diarization (Petra vs. Jiří)
- Q&A turn detection: extrahuje páry
(otázka klienta, odpověď operátora) - Po hovoru:
- Audio uloženo do S3 (
app-hotline/recordings/<call_id>.wav) - Transcript do DB (
app_hotline.transcripts) - Q&A indexováno do RAG korpusu
app-hotline-qa - Billing entry:
call_id, klient, operator, duration=12min, topics=[DB migrace] - Příští klient (Marie) má stejný dotaz — místo volání otevře Tk klienta
Hotline → Hledat, zadámigrace databáze. RAG vrátí odpověď Petry z minulého hovoru. - Admin (Michal) v měsíčním reportu vidí: 47 hovorů, 9.3 hodin support time, top topic „DB migrace" (12 hovorů → vznikl RAG entry → vidí jak poklesl follow-up volume).
2. Architecture overview¶
┌──────────────────────────────────────────┐
│ launcher2 (operátor / admin / klient) │
│ - login + IPC session token │
└──────────────────┬───────────────────────┘
│ apps-gateway routing
▼
┌──────────────────────────────────────────────────┐
│ app-hotline kontejner (FastAPI + Celery worker) │
│ port 8106 → :: /apps/app-hotline/* │
│ │
│ ├─ Audio pipeline (v0.1 just capture+store) │
│ │ ├─ mic capture → local WAV (operátor disk) │
│ │ ├─ post-call upload → S3 mirror (volitelný) │
│ │ └─ job submit → ai-helper │
│ │ `_AI.speech.transcribe_structured()` │
│ │ (až bude capability ready — v0.2) │
│ ├─ Transcript ingest (callback z ai-helper) │
│ │ └─ parse segments + Q/A pairs → DB │
│ ├─ RAG indexer (po approve) │
│ │ └─ Q&A pairs → ai-helper `_AI.rag.index()` │
│ ├─ Billing report generator │
│ └─ Q&A search UI (Tk panel) │
└─────────────────┬────────────────────────────────┘
│ M2M (AVAX_AUTH_TOKEN)
▼
┌─────────────────────────────────────┐
│ app-ai-helper (existing service) │
│ - LM Studio worker pool │
│ - Whisper STT worker │
│ - RAG corpus `app-hotline-qa` │
│ - Embedding bge-m3 (1024d) │
└─────────────────────────────────────┘
3. Persony a role¶
| Persona | Co vidí v Tk klientu |
|---|---|
| Operátor (zaměstnanec AVAXIS support team) | Live hovor tab (mic monitor), historie hovorů (filter podle data/klienta), Q&A draft editor |
| Klient (jakýkoli end-user s subscription) | Q&A search („zeptat se hotliny bez hovoru"), historie vlastních dotazů |
| Billing manager (AVAXIS účetní) | Billing report tab (export CSV/PDF), hodinový sazebník, fakturační statusy |
| Super_admin (Michal) | Vše + admin tab (operátoři, sazby, RAG corpora správa, retention policy, GDPR ops) |
UI: 12 tabs, dynamicky skryté podle role z JWT (system_role, company_id).
4. UI tabs (Tk customtkinter)¶
| # | Tab | Persony | Popis |
|---|---|---|---|
| 1 | 🔴 Live hovor | operator | Mic capture aktivní + transcript live ▼. Klik „Konec" → uložit audio + spustit STT job. |
| 2 | 📞 Historie hovorů | operator, admin | Tabulka: datum, klient, operátor, délka, status. Klik = detail (transcript, audio playback, Q&A draft). |
| 3 | ❓ Q&A hledat | client, operator | Search box + RAG retrieval. „Jak migrovat DB?" → vrátí top 3 hits z minulých hovorů. |
| 4 | 📚 Q&A knowledge base | operator, admin | Browse all extracted Q&A pairs. Edit, schválit do public, smazat. |
| 5 | 💰 Billing report | billing, admin | Filter podle období / klienta. Export CSV/PDF. Hodinová sazba. |
| 6 | 📊 Statistiky | admin | Top topics, hovor volume, average duration, RAG hit rate (= kolik dotazů odpovědělo bez hovoru). |
| 7 | ⚙️ Nastavení | operator | Mic input device, sample rate, retention period, auto-RAG indexing on/off. |
| 8 | 👥 Operátoři | admin | Správa speaker profiles (kdo je operátor, hodinová sazba per operátor). |
| 9 | 🗄️ Retention | admin | GDPR: per-klient retention period, anonymizace, smazání. |
| 10 | 🧠 RAG correctness | admin | Review Q&A pairs s nízkou confidence — odsouhlasit / přepsat / smazat. |
| 11 | 🤖 AI workers | admin | Status workers (STT, embedding, chat) — link na app-ai-helper. |
| 12 | 📋 Audit log | admin | Kdo přepisoval Q&A, kdy, co změnil. |
5. Datový model (PostgreSQL app_hotline schema) — v0.3 screenplay model¶
Změny vs v0.2:
- calls → hotline_call (široký, AI/human mirror columns, consent gate)
- transcript_segments → hotline_turn (z screenplay turns, ne raw STT segments)
- qa_pairs ❌ odstraněno — Q&A extraction nahrazené screenplay+topic+usefulness
metadata na hotline_call (1 řádek per hovor, ne sekundární tabulka)
- audit_log nově — kompliance pro 3y retention regulatory tracking
-- 5.1 hotline_call — primary entity, široká tabulka s AI/human mirror columns
CREATE TABLE app_hotline.hotline_call (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Časování
call_started_at TIMESTAMPTZ NOT NULL,
call_ended_at TIMESTAMPTZ,
call_duration_s INTEGER GENERATED ALWAYS AS
(EXTRACT(EPOCH FROM (call_ended_at - call_started_at))::int) STORED,
-- Identifikace (operatorův user.id, zákazník hashed kvůli GDPR)
operator_id UUID NOT NULL, -- public.users(id) (cross-schema, ne FK)
customer_user_id UUID, -- pokud registered + souhlas, jinak NULL
customer_phone_hash VARCHAR(64), -- SHA256(phone + company_salt). NIKDY plain.
customer_consent BOOLEAN NOT NULL DEFAULT FALSE, -- GDPR Article 6(1)(a) gate
consent_recorded_at TIMESTAMPTZ,
-- Audio storage
audio_s3_key TEXT,
audio_local_path TEXT,
audio_deleted_at TIMESTAMPTZ, -- retention cron timestamp
retention_until TIMESTAMPTZ, -- default = call_started_at + 30 days
-- AI Helper Application interaction (hotline-transcribe)
ai_instance_id UUID, -- ai_helper.application_instances.id
transcribe_job_id TEXT, -- async job tracking
-- Status state machine
status TEXT NOT NULL DEFAULT 'recording'
CHECK (status IN ('recording', 'stored', 'transcribing', 'pending_review',
'approved', 'rejected', 'archived', 'failed')),
-- AI návrh (přímý výstup z hotline-transcribe Application)
ai_screenplay TEXT, -- formátovaný screenplay text (Aya 32B step 2)
ai_topic_primary TEXT, -- enum: billing|technical|account|complaint|inquiry|cancellation|other
ai_topic_detail TEXT, -- max 80 chars upřesnění
ai_usefulness SMALLINT, -- 1-5 (RAG push gate: ≤ 2 auto-skip)
ai_usefulness_reasoning TEXT, -- model's justification
ai_summary TEXT, -- 3-5 vět summary
-- Human přepis při approval (mirror sloupce, NULL pokud neupravoval)
human_screenplay TEXT,
human_topic_primary TEXT,
human_topic_detail TEXT,
human_usefulness SMALLINT,
human_summary TEXT,
-- Approval workflow
approved_by_user_id UUID,
approved_at TIMESTAMPTZ,
rejected_at TIMESTAMPTZ,
rejected_reason TEXT,
-- RAG push tracking (po approve)
pushed_to_rag_at TIMESTAMPTZ,
rag_document_id UUID, -- ai_helper.documents.id
-- Billing
billing_status TEXT NOT NULL DEFAULT 'pending'
CHECK (billing_status IN ('pending', 'invoiced', 'paid', 'waived')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CHECK (ai_usefulness IS NULL OR (ai_usefulness BETWEEN 1 AND 5)),
CHECK (human_usefulness IS NULL OR (human_usefulness BETWEEN 1 AND 5))
);
CREATE INDEX ix_hotline_call_started ON app_hotline.hotline_call(call_started_at DESC);
CREATE INDEX ix_hotline_call_operator ON app_hotline.hotline_call(operator_id, call_started_at DESC);
CREATE INDEX ix_hotline_call_status ON app_hotline.hotline_call(status, call_started_at DESC);
CREATE INDEX ix_hotline_call_pending ON app_hotline.hotline_call(status) WHERE status = 'pending_review';
CREATE INDEX ix_hotline_call_retention ON app_hotline.hotline_call(retention_until) WHERE audio_deleted_at IS NULL;
CREATE INDEX ix_hotline_call_customer ON app_hotline.hotline_call(customer_phone_hash);
-- 5.2 hotline_turn — jednotlivé turny z hotline-transcribe screenplay
CREATE TABLE app_hotline.hotline_turn (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
call_id UUID NOT NULL REFERENCES app_hotline.hotline_call(id) ON DELETE CASCADE,
order_index INTEGER NOT NULL, -- pořadí v hovoru (od 0)
speaker_raw TEXT NOT NULL, -- SPEAKER_00 / SPEAKER_01 (z pyannote)
speaker_role TEXT, -- 'support' | 'customer' (z Aya step 2)
speaker_user_id UUID, -- public.users(id) pokud identifikováno
start_ms INTEGER NOT NULL, -- offset z call_started_at
end_ms INTEGER NOT NULL,
text_raw TEXT NOT NULL, -- raw Whisper output
text_corrected TEXT, -- po Aya post-process (ASR fix)
confidence REAL, -- 0-1 STT confidence
was_edited BOOLEAN NOT NULL DEFAULT FALSE, -- operator přepsal v approval UI
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX ix_hotline_turn_call ON app_hotline.hotline_turn(call_id, order_index);
-- 5.3 billing_entries — beze změny z v0.2 (jen FK target name)
CREATE TABLE app_hotline.billing_entries (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
call_id UUID NOT NULL REFERENCES app_hotline.hotline_call(id),
client_company UUID,
duration_min NUMERIC(8,2) NOT NULL,
rate_per_hour NUMERIC(10,2) NOT NULL,
amount NUMERIC(10,2) NOT NULL,
invoice_id UUID,
status TEXT NOT NULL DEFAULT 'draft'
CHECK (status IN ('draft', 'sent', 'paid', 'cancelled')),
period_start DATE NOT NULL,
period_end DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- 5.4 fakturační záznamy
-- 5.4 self_service_queries — Q&A search analytika
CREATE TABLE app_hotline.self_service_queries (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL, -- public.users(id)
query_text TEXT NOT NULL,
rag_hits JSONB, -- top N retrieval results
user_satisfied BOOLEAN, -- 👍/👎 feedback
fallback_to_call BOOLEAN NOT NULL DEFAULT FALSE, -- klient přesto zavolal
fallback_call_id UUID REFERENCES app_hotline.hotline_call(id), -- jaký hovor následoval
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX ix_self_queries_user ON app_hotline.self_service_queries(user_id, created_at DESC);
-- 5.5 audit_log — compliance tracking (3y retention)
CREATE TABLE app_hotline.audit_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
call_id UUID REFERENCES app_hotline.hotline_call(id) ON DELETE SET NULL,
user_id UUID NOT NULL,
action TEXT NOT NULL
CHECK (action IN ('viewed', 'edited', 'approved', 'rejected',
'deleted', 'exported')),
field TEXT, -- který sloupec se měnil
old_value TEXT,
new_value TEXT,
reason TEXT, -- např. "GDPR retention cron"
ip_address INET,
user_agent TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- ON DELETE SET NULL: call CASCADE smaže hotline_call, audit_log řádek
-- zůstává (3y retention pro compliance audity).
CREATE INDEX ix_audit_call ON app_hotline.audit_log(call_id, created_at DESC);
CREATE INDEX ix_audit_user ON app_hotline.audit_log(user_id, created_at DESC);
CREATE INDEX ix_audit_action ON app_hotline.audit_log(action, created_at DESC);
Status state machine (hotline_call.status)¶
recording ← UI start (po consent dialog)
│ Konec hovoru
▼
stored ← WAV uložený lokálně + S3 mirror (volitelné)
│ submit hotline-transcribe
▼
transcribing ← async job v ai-helper Application
│ ingest screenplay + turns
▼
pending_review ← operator může otevřít approval dialog
│ approve │ reject
▼ ▼
approved rejected
│ │
│ push do RAG │
▼ ▼
(rag_document_id) ─────► archived (po retention cleanup)
failed ← terminal po STT/upload/M2M error (fail-soft retry)
Per-app DB user GRANTs¶
Alembic vytvoří schema přes avaxis superuser, ale runtime kontejner
běží jako avax_app_app_hotline (low-priv per-app user). Po prvním
alembic upgrade head doplnit:
GRANT USAGE, CREATE ON SCHEMA app_hotline TO avax_app_app_hotline;
GRANT ALL ON ALL TABLES IN SCHEMA app_hotline TO avax_app_app_hotline;
ALTER DEFAULT PRIVILEGES IN SCHEMA app_hotline
GRANT ALL ON TABLES TO avax_app_app_hotline;
Per memory reference_alembic_deploy_gotchas + reference_per_app_db_grant_step.
6. Audio pipeline¶
6.1 Capture & storage (v0.1)¶
Reuse sounddevice patterny z voice-video-call.md:
- Live mic input → ring buffer (memory) v Tk klientu
- Stream do local WAV na disku operátora (audio_local_path)
v C:\Avaxis\hotline\recordings\<call_id>.wav (default; override v
Nastavení tab)
- Po Konec hovoru klik:
1. Finalize WAV (close write, integrity check)
2. UPSERT calls row s status='stored', audio_local_path
3. Volitelný S3 mirror (Nastavení → „Zálohovat audio na S3") —
async upload do app-hotline/recordings/<call_id>.wav přes
APPDIST credentials. Pokud zapnutý, set audio_s3_key.
6.2 Transcribe → ai-helper capability¶
App-hotline nevolá STT přímo. Po status='stored' submitne job na
app-ai-helper přes plánovanou capability:
from avaxis_sdk import AVAX
avax = AVAX.from_m2m(...)
job = avax._AI.speech.transcribe_structured_async(
audio_source=audio_local_path or f"s3://app-hotline/recordings/{call_id}.wav",
language="cs",
speakers=2, # known počet — operátor + klient
extract_qa=True, # vrátí i (otázka, odpověď) páry
callback_url=f"https://api.avaxis.cz/apps/app-hotline/_internal/transcribe-done",
)
# job.id se uloží do calls.transcribe_job_id
speech.transcribe_structured() neexistuje v app-ai-helper v dnešní
verzi (2026-05-28). Musí být doplněna — viz §13.1. App-hotline v0.1
ji jen volá optimisticky; pokud HTTP 501 (not implemented), status
zůstává stored s badge „čeká na STT capability".
Návrh capability response (synchronní polling nebo callback):
{
"job_id": "...",
"status": "completed",
"segments": [
{"start_ms": 0, "end_ms": 3200, "speaker": "SPEAKER_00", "text": "Dobrý den…"},
{"start_ms": 3300, "end_ms": 8100, "speaker": "SPEAKER_01", "text": "Dobrý, mám problém…"}
],
"qa_pairs": [
{"question": "Jak migrovat databázi?", "answer": "…", "topic": "DB migrace", "confidence": 0.92}
],
"model": "whisper-medium",
"duration_ms": 12340
}
6.3 Speaker mapping¶
speech.transcribe_structured vrací anonymní SPEAKER_00/SPEAKER_01.
App-hotline backend mapuje na konkrétní users:
- Operátor: heuristika „kdo začíná hovor pozdravem" + cross-check
s operator_id z calls row
- Klient: druhý speaker (pokud jen 2 účastníci)
- Pokud > 2 speakers: ručně přiřadit v Historie hovorů tab
Per-operator voice fingerprint (P3, ne v0.1): až ai-helper bude umět voice embedding, mapování operátora bude automatické bez heuristik.
6.4 RAG indexing¶
Pro každý approved Q&A pair:
doc = avax._AI.rag.index_document(
corpus="app-hotline-qa",
content=f"Otázka: {qa.question}\n\nOdpověď: {qa.answer}",
metadata={
"call_id": str(qa.call_id),
"topic": qa.topic,
"operator": qa.operator_name,
"date": qa.created_at.isoformat(),
},
)
qa.rag_doc_id = doc.id
qa.rag_indexed = True
Corpus app-hotline-qa musí existovat v app-ai-helper (admin tab "RAG
corpora" → vytvořit s embedding_model=bge-m3, chunk_size=512).
7. RAG retrieval (Q&A search tab)¶
hits = avax._AI.rag.search(
corpus="app-hotline-qa",
query="jak migrovat databázi",
top_k=5,
threshold=0.7,
)
# hits = [{"text": "...", "score": 0.87, "metadata": {...}}, ...]
UI: ukázat top 3, klik = expand full Q&A + odkaz na původní hovor (přepis playable).
Self-service feedback loop: user klikne 👍 → self_service_queries.user_satisfied=true.
Pokud 👎 nebo „fallback to call" — log → admin tab "Q&A correctness" review.
8. M2M auth + AI Helper integrace¶
App-hotline backend volá app-ai-helper přes M2M JWT z AVAX_AUTH_TOKEN
(per vendor-onboarding §3 a apps-gateway §7):
# backend/app/services/ai_client.py
import os
from avaxis_sdk import AVAX
# M2M mode — JWT issuer = core-api /auth/token client_credentials grant
ai = AVAX.from_m2m(
client_id=os.environ["AVAX_M2M_CLIENT_ID"],
client_secret=os.environ["AVAX_M2M_CLIENT_SECRET"],
api_url=os.environ["AVAX_API_URL"],
)
M2M client musí být vytvořen v UI Launcher2 (admin → M2M Clients →
Vytvořit pro app-hotline). Po vytvoření Michal zapíše client_id +
client_secret jako Gitea secrets AVAX_M2M_CLIENT_ID / AVAX_M2M_CLIENT_SECRET
(per-repo, ne org level — secrety jsou unikátní per app).
Scopes potřebné pro app-hotline M2M client:
- ai:chat (volitelné — pro post-processing Q&A párů, např. topic normalize)
- ai:rag:read (search RAG corpus z self-service hledání)
- ai:rag:write (index Q&A pairs po approve)
- ai:speech:transcribe_structured (čeká na implementaci capability, viz §13.1)
9. Capabilities deklarace¶
V manifest.json:
{
"slug": "app-hotline",
"name": "Hotline AVAXIS",
"version": "0.1.0",
"description": "Voice/call monitoring + Q&A extraction + RAG knowledge base",
"ai_consumer": {
"capabilities": ["chat", "rag.search", "rag.index_document", "speech.stt"],
"preferred_models": {
"chat": "qwen2.5-14b",
"embedding": "bge-m3",
"stt": "whisper-small"
}
},
"permissions": {
"microphone": true,
"filesystem": ["recordings/"],
"s3_buckets": ["app-hotline"]
}
}
Launcher2 manifest check při instalaci → zobrazí dialog „Tato app požaduje přístup k mikrofonu a hovoru AI workerům. Schválit?".
10. Migrations roadmap¶
| Migrace | Co |
|---|---|
0001_init.py |
app_hotline schema create + 5 tabulek z §5 |
0002_indexes.py |
Performance indexy (top topics, billing periods) |
0003_operator_profiles.py |
P2 voice fingerprint (pgvector 192d) |
0004_audit_log.py |
Audit log (kdo přepisoval Q&A) |
11. CI/CD¶
publish.yml(z skeleton): Wine cross-build → S3app-hotline/channels/alpha.jsonbackend.yml(z skeleton): docker build → push to Gitea registry → SSH deploy na avaxdev →docker run avax-app-hotline -p 127.0.0.1:8106:8000- Alembic upgrade head jako post-deploy step (per
reference-alembic-deploy-gotchas—--sqlworkaround pokud online no-op)
12. Open questions (status k v0.2)¶
| # | Otázka | Status |
|---|---|---|
| 1 | STT engine | ✅ VYŘEŠENO — řeší app-ai-helper (nová capability speech.transcribe_structured), app-hotline jen volá |
| 2 | Diarization placement | ✅ VYŘEŠENO — součást speech.transcribe_structured capability v app-ai-helper |
| 3 | GDPR retention | ✅ VYŘEŠENO — 30 dní audio (auto-delete cron), transkripty napořád (s anonymizací jmen po retention) |
| 4 | Live vs batch STT | ✅ VYŘEŠENO — batch only v0.1, live v P3 roadmap |
| 5 | Multi-channel audio (VoIP bridge) | ⏳ OTEVŘENÉ — v0.1 jen mic operátora; VoIP bridge (Asterisk?) P2+ |
| 6 | Q&A approval flow | ✅ VYŘEŠENO — strict approve gate: Q&A pairs jsou invisible (a NOT v RAG corpus) dokud operator/admin neaprove. Lepší kvalita, slower propagace. |
12.1 Strict approval flow detail¶
ai-helper vrátí qa_pairs
│
▼
INSERT INTO qa_pairs (..., is_approved=false, rag_indexed=false)
│
▼
UI „Historie hovorů" → call detail → „Q&A pairs k schválení (N)"
│
▼ operator klik „✓ Schválit" pro každý pair
│
INSERT INTO RAG corpus (POST _AI.rag.index_document)
UPDATE qa_pairs SET is_approved=true, approved_by=user_id, approved_at=now(),
rag_doc_id=..., rag_indexed=true
│
▼ teď viditelné v Q&A search tabu pro klienty
Operator může i editovat text otázky/odpovědi PŘED approve (typo fix, přepsat osobní data, atd). Po approve text immutable (audit log zachycuje edits).
Bulk approve: tlačítko „Schválit všechny s confidence > 0.85" pro rychlou review session.
13. Roadmap¶
13.1 Co BLOKUJE app-hotline v0.1 deployment¶
Předpokládá novou capability v app-ai-helper:
POST /v1/call/speech.transcribe_structured_async
audio_source: str # file:// nebo s3://
language: "cs" | "en" | ...
speakers: int | "auto"
extract_qa: bool # vrátí i Q&A pairs (LLM post-process)
callback_url: str | None
→ 202 Accepted + job_id
GET /v1/jobs/{job_id}
→ 200 OK status=completed|running|failed
result.segments: [...]
result.qa_pairs: [...]
App-hotline POC může běžet i bez této capability — UI bude fungovat, transcripty zůstanou prázdné. Druhý Claude na app-ai-helper repu musí capability implementovat (pravděpodobně přes Whisper worker + chained LLM call na Q&A extraction).
13.2 Phases¶
| Phase | Co | Závisí na |
|---|---|---|
| P0 | DB schema + REST API + Tk capture/storage + Historie hovorů UI | — |
| P1 | speech.transcribe_structured napojení + Q&A approval UI |
app-ai-helper capability |
| P2 | RAG indexing + Q&A search self-service UI | P1 + corpus app-hotline-qa v app-ai-helper |
| P3 | Billing report + statistiky + audit log | P0 |
| P4 | GDPR retention cron (audio 30d delete) + anonymizace | P0 |
| P5 | Multi-channel audio + VoIP bridge | infra (Asterisk?) |
| P6 | Live streaming STT + voice fingerprint operátorů | app-ai-helper extended capabilities |
Související¶
- Service:
ai-helper.md— co poskytuje - Sister client app:
app-ai-helper.md— vzor 12-tab role-based UI - Audio capture:
voice-video-call.md— aiortc patterny - Vendor onboarding:
vendor-onboarding.md - Apps-gateway routing:
apps-gateway.md§7 M2M flow