202 lines
6.9 KiB
Markdown
202 lines
6.9 KiB
Markdown
# Intent Router Specification (MVP) — v1.1
|
|
Version: 1.1
|
|
Scope: Routing + query normalization + anchor extraction for layered RAG (CODE + DOCS)
|
|
|
|
---
|
|
|
|
## 1) Цель
|
|
|
|
Intent Router принимает:
|
|
- `user_query: string`
|
|
- `conversation_state: object`
|
|
- `repo_context: object` (язык/структура репо/доступные слои)
|
|
|
|
И возвращает:
|
|
- `intent`
|
|
- `graph_id`
|
|
- `conversation_mode`
|
|
- `query_plan` (нормализация + якоря)
|
|
- `retrieval_spec` (запрос по слоям RAG)
|
|
- `evidence_policy`
|
|
|
|
Router **не делает** retrieval и **не генерирует** ответ.
|
|
|
|
---
|
|
|
|
## 2) MVP интенты (строго 4)
|
|
|
|
- `CODE_QA` — объяснение/поиск по коду
|
|
- `DOCS_QA` — объяснение/поиск по документации
|
|
- `GENERATE_DOCS_FROM_CODE` — генерация документации по коду
|
|
- `PROJECT_MISC` — прочие вопросы по проекту
|
|
|
|
---
|
|
|
|
## 3) Диалоговый режим (контекст темы)
|
|
|
|
### 3.1 Политика
|
|
Router обязан сохранять intent в рамках темы.
|
|
|
|
- Если `conversation_state.active_intent` задан
|
|
- и нет явного сигнала смены темы
|
|
- то `intent = conversation_state.active_intent` и `conversation_mode = CONTINUE`
|
|
|
|
Смена intent допускается только если:
|
|
- есть явный сигнал смены домена/задачи, или
|
|
- новый запрос явно не соответствует текущему intent (жёсткое несоответствие)
|
|
|
|
---
|
|
|
|
## 4) Обязательная нормализация запроса и извлечение якорей
|
|
|
|
Router обязан выполнять:
|
|
|
|
### 4.1 Query normalization
|
|
Выход должен содержать:
|
|
- `raw` — исходный запрос
|
|
- `normalized` — каноническая, детерминированная и meaning-preserving форма `raw`
|
|
- `expansions[]` — добавочные токены для retrieval/rerank
|
|
- `keyword_hints[]` — компактные ключевые токены (символы/пути/доменные термины)
|
|
|
|
Требования:
|
|
- `raw` хранит исходную строку пользователя без изменений
|
|
- `normalized` строится **только** из `raw` и безопасных правил форматирования
|
|
- `normalized` не должен включать appended expansions, синонимы и догаданные keywords
|
|
- все enrichment должны жить только в `expansions[]`, `keyword_hints[]`, `anchors[]`
|
|
|
|
### 4.2 RU→EN mapping (минимальный словарь)
|
|
Router обязан поддерживать RU→EN mapping терминов только как `expansions`:
|
|
|
|
- `класс` → `class`
|
|
- `метод` → `method`
|
|
- `функция` → `function`, `def`
|
|
- `модуль` → `module`
|
|
- `пакет` → `package`
|
|
- `файл` → `file`
|
|
- `тест`, `юнит-тест` → `test`, `unit test`
|
|
|
|
Словарь должен быть расширяемым, но эти ключи обязательны.
|
|
|
|
### 4.3 Anchor extraction (якоря)
|
|
Router обязан извлекать **явные якоря** из user_query и conversation_state:
|
|
|
|
Типы якорей:
|
|
- `FILE_PATH` — путь/часть пути (`src/...`, `package/module.py`, `README.md`)
|
|
- `SYMBOL` — идентификатор (CamelCase, snake_case, dotted path)
|
|
- `DOC_REF` — ссылка на doc file/section (если есть явные маркеры)
|
|
- `KEY_TERM` — важные термины, влияющие на retrieval (класс/метод/функция и т.п.)
|
|
|
|
Каждый якорь должен возвращаться структурировано.
|
|
|
|
---
|
|
|
|
## 5) Контракт выхода Router
|
|
|
|
Top-level:
|
|
|
|
```json
|
|
{
|
|
"schema_version": "1.1",
|
|
"intent": "CODE_QA",
|
|
"graph_id": "CodeQAGraph",
|
|
"conversation_mode": "CONTINUE",
|
|
"query_plan": {
|
|
"raw": "",
|
|
"normalized": "",
|
|
"expansions": [],
|
|
"keyword_hints": [],
|
|
"anchors": []
|
|
},
|
|
"retrieval_spec": {
|
|
"domains": [],
|
|
"layer_queries": [],
|
|
"filters": {},
|
|
"rerank_profile": ""
|
|
},
|
|
"evidence_policy": {
|
|
"require_def": false,
|
|
"require_flow": false,
|
|
"require_spec": false,
|
|
"allow_answer_without_evidence": false
|
|
}
|
|
}
|
|
|
|
|
|
## 6) query_plan.anchors контракт
|
|
|
|
{
|
|
"type": "FILE_PATH | SYMBOL | DOC_REF | KEY_TERM",
|
|
"value": "string",
|
|
"subtype": "optional string",
|
|
"span": { "start": 0, "end": 0 },
|
|
"confidence": 0.0
|
|
}
|
|
|
|
Требования:
|
|
- FILE_PATH.value хранит путь как в запросе (без попытки “исправить”)
|
|
- SYMBOL.value хранит символ как в запросе (с сохранением регистра)
|
|
- KEY_TERM используется для выставления expected evidence и выбора слоёв
|
|
- anchors может быть пустым, но router должен пытаться извлечь их всегда
|
|
|
|
|
|
## 7) retrieval_spec контракт (слои + фильтры)
|
|
|
|
### 7.1 Структура
|
|
|
|
{
|
|
"domains": ["CODE", "DOCS"],
|
|
"layer_queries": [
|
|
{ "layer_id": "C1", "top_k": 30 },
|
|
{ "layer_id": "C3", "top_k": 15 }
|
|
],
|
|
"filters": {
|
|
"test_policy": "EXCLUDE",
|
|
"path_scope": [],
|
|
"language": []
|
|
},
|
|
"rerank_profile": "code"
|
|
}
|
|
|
|
## 7.2 Требования по intent
|
|
|
|
- CODE_QA → domains = ["CODE"], rerank_profile="code"
|
|
- DOCS_QA → domains = ["DOCS"], rerank_profile="docs"
|
|
- GENERATE_DOCS_FROM_CODE → domains = ["CODE"], rerank_profile="generate"
|
|
- PROJECT_MISC → domains = ["CODE","DOCS"], rerank_profile="project"
|
|
|
|
## 7.3 Требования по якорям
|
|
|
|
- Если найден FILE_PATH → router обязан добавить filters.path_scope (минимум: этот путь/директория)
|
|
- Если найден SYMBOL → router обязан добавить SYMBOL в query_plan.keyword_hints и query_plan.expansions (при необходимости)
|
|
- Если найден KEY_TERM (например "класс") → router обязан добавить RU→EN expansions
|
|
|
|
## 8) evidence_policy (минимальные требования)
|
|
{
|
|
"require_def": true,
|
|
"require_flow": true,
|
|
"require_spec": false,
|
|
"allow_answer_without_evidence": false
|
|
}
|
|
|
|
Требования:
|
|
- CODE_QA: require_def=true; require_flow=true
|
|
- DOCS_QA: require_spec=true
|
|
- GENERATE_DOCS_FROM_CODE: require_def=true
|
|
- PROJECT_MISC: allow_answer_without_evidence=true
|
|
|
|
## 9) Минимально обязательные поля (строго)
|
|
|
|
Router обязан всегда возвращать:
|
|
- intent
|
|
- graph_id
|
|
- conversation_mode
|
|
- query_plan.raw
|
|
- query_plan.normalized
|
|
- query_plan.expansions
|
|
- query_plan.anchors
|
|
- retrieval_spec.domains
|
|
- retrieval_spec.layer_queries
|
|
- retrieval_spec.filters.test_policy
|
|
- retrieval_spec.rerank_profile
|
|
- evidence_policy.*
|