sync: migrate ai-operator to Gitea (2026-08-10)
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
# Conversation State Machine
|
||||
|
||||
## Purpose
|
||||
|
||||
The conversation state machine enforces the safe order of an AI Operator call. The assistant cannot answer business questions, search a knowledge base, or execute business tools until both language and region are selected in code.
|
||||
|
||||
## States
|
||||
|
||||
```text
|
||||
CALL_STARTED
|
||||
-> GREETING
|
||||
-> LANGUAGE_SELECTION
|
||||
-> REGION_SELECTION
|
||||
-> READY_TO_HELP
|
||||
-> QUESTION_ANSWERING
|
||||
-> READY_TO_HELP
|
||||
-> CLOSING
|
||||
-> ENDED
|
||||
```
|
||||
|
||||
`HANDOFF` can be entered from any non-ended state. `CLOSING` and `ENDED` can also be entered from any non-ended state. `ENDED` is immutable.
|
||||
|
||||
## Transition Table
|
||||
|
||||
| From | Event | To | Requirement |
|
||||
| --- | --- | --- | --- |
|
||||
| CALL_STARTED | call.started | GREETING | call session exists |
|
||||
| GREETING | greeting.played | LANGUAGE_SELECTION | bilingual greeting prepared |
|
||||
| LANGUAGE_SELECTION | language.selected | REGION_SELECTION | language is `ru` or `kk` |
|
||||
| REGION_SELECTION | region.selected | READY_TO_HELP | normalized region code is selected |
|
||||
| READY_TO_HELP | question.received | QUESTION_ANSWERING | language and region selected |
|
||||
| QUESTION_ANSWERING | answer.completed | READY_TO_HELP | answer flow completed |
|
||||
| any non-ended | handoff.requested | HANDOFF | none |
|
||||
| any non-ended | closing.requested | CLOSING | none |
|
||||
| any non-ended | call.ended | ENDED | none |
|
||||
|
||||
Invalid transitions return errors and do not mutate state. Denied actions are recorded in session history.
|
||||
|
||||
## Tool Permission Matrix
|
||||
|
||||
| State | Allowed Tools |
|
||||
| --- | --- |
|
||||
| CALL_STARTED | none |
|
||||
| GREETING | none |
|
||||
| LANGUAGE_SELECTION | `set_language`, `request_human_handoff`, `end_call` |
|
||||
| REGION_SELECTION | `set_region`, `set_language`, `request_human_handoff`, `end_call` |
|
||||
| READY_TO_HELP | `search_knowledge_base`, `set_language`, `set_region`, `request_human_handoff`, `end_call` |
|
||||
| QUESTION_ANSWERING | `search_knowledge_base`, `request_human_handoff`, `end_call`, `set_language`, `set_region` |
|
||||
| HANDOFF | `end_call` |
|
||||
| CLOSING | `end_call` |
|
||||
| ENDED | none |
|
||||
|
||||
## Hard Guardrail
|
||||
|
||||
`search_knowledge_base` is denied unless all of these are true:
|
||||
|
||||
- language is `ru` or `kk`;
|
||||
- region status is `selected`;
|
||||
- region code is not empty;
|
||||
- state is `READY_TO_HELP` or `QUESTION_ANSWERING`.
|
||||
|
||||
This is enforced in Go code by `internal/dialogue/policy`, independently of prompts.
|
||||
|
||||
## Messages
|
||||
|
||||
The message catalog has bilingual initial greeting plus Russian and Kazakh fragments for language, region, ready, denial, handoff, and closing states.
|
||||
|
||||
Initial greeting:
|
||||
|
||||
```text
|
||||
Здравствуйте! Это AI-оператор. Выберите язык обслуживания: русский или қазақша.
|
||||
Сәлеметсіз бе! Бұл AI-оператор. Қызмет көрсету тілін таңдаңыз: қазақша немесе русский.
|
||||
```
|
||||
|
||||
## Prompt Fragments
|
||||
|
||||
`internal/dialogue/prompt` builds state-aware prompt fragments that include current state, language, region, next action, and forbidden actions. Prompt fragments are secondary; policy enforcement remains in Go code.
|
||||
|
||||
## CLI Usage
|
||||
|
||||
```bash
|
||||
./bin/ai-operator doctor --env /etc/ai-operator/ai-operator.env --check-dialogue
|
||||
./bin/ai-operator dialogue-self-test --env /etc/ai-operator/ai-operator.env
|
||||
./bin/ai-operator dialogue-self-test --env /etc/ai-operator/ai-operator.env --json
|
||||
```
|
||||
|
||||
The self-test runs without Asterisk calls, OpenAI, database, or external services.
|
||||
|
||||
## Integration
|
||||
|
||||
For the test route only, Call Manager creates a Dialogue Orchestrator session before starting the voice provider. The provider receives a state-aware system prompt. On hangup, Call Manager ends and cleans the dialogue session.
|
||||
|
||||
Production Kazakhtelecom routes remain disabled.
|
||||
|
||||
## Not Implemented Yet
|
||||
|
||||
- language detection from speech;
|
||||
- region resolver;
|
||||
- Knowledge Base/RAG;
|
||||
- final agent prompt;
|
||||
- real business tools;
|
||||
- production route switch.
|
||||
|
||||
## TZ-07 Language Detector
|
||||
|
||||
Language selection is now handled by `internal/dialogue/language`. The state machine still stores strict `ru` or `kk`, while detector input can be natural text such as `русский`, `қазақша`, `russian`, or `kazakh`.
|
||||
|
||||
## TZ-08 Region Resolver Update
|
||||
|
||||
TZ-08 adds an offline Kazakhstan Region Resolver with 20 enabled regions, stable `region_code` values, Almaty city/region clarification, false-positive protection, and explicit region-change policy. Production routing remains disabled; OpenAI, PostgreSQL, and Knowledge Base/RAG are still not used at this stage.
|
||||
|
||||
## TZ-09 Knowledge Base Update
|
||||
|
||||
TZ-09 adds PostgreSQL + pgvector, KGA JSONL ingestion, fake embeddings, hybrid KB search, cross-language fallback for KK queries, citations, and `search_knowledge_base` integration behind the existing language/region guardrail. OpenAI is not called automatically and production routing remains disabled.
|
||||
## TZ-10 Agent Integration
|
||||
|
||||
The state machine remains the hard gate for business answers. Agent prompt instructions are secondary; `search_knowledge_base` is still denied before language and region are selected. ToolCall results now flow back to the VoiceProvider.
|
||||
## TZ-11 Handoff
|
||||
|
||||
`request_human_handoff` moves active conversations to `HANDOFF`. Repeated handoff requests are idempotent. `ENDED` remains immutable.
|
||||
Reference in New Issue
Block a user