Files
agent/_process/05. MVP - process_v2.md
T

221 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MVP: процесс v2
## 1. Общее описание
Процесс v2 в текущем MVP ориентирован в первую очередь на **документацию проекта**, но роутер также поддерживает `GENERAL / GENERAL_QA / SUMMARY` для общих обзорных вопросов. Для документных веток нужна активная RAG-сессия с проиндексированными документами.
Это **узкий MVP**, а не полная target architecture. Поддерживаются три маршрута:
- `GENERAL`
- `GENERAL_QA`
- `SUMMARY`
- `DOCS`
- `DOC_EXPLAIN`
- `SUMMARY`
- `FIND_FILES`
Запрос проходит следующие смысловые этапы:
1. проверка готовности сессии;
2. intent routing;
3. формирование retrieval-параметров;
4. retrieval из `DOCS RAG`;
5. минимальная сборка evidence;
6. запуск task-focused workflow нужной ветки;
7. формирование ответа.
```mermaid
flowchart TB
subgraph api [API]
RS[RequestService]
end
subgraph runtime [Agent runtime]
AR[AgentRuntime]
PR[ProcessRunner]
end
subgraph v2 [Процесс v2]
P2[V2Process]
IR[V2IntentRouter]
POL[V2RetrievalPolicyResolver]
AD[V2RagRetrievalAdapter]
RSR[RagSessionRetriever]
ASM[DocsEvidenceAssembler]
end
subgraph rag [Пакет rag]
RR[RagRepository]
end
subgraph wf [Workflow]
SUM[DocsExplainSummaryGraph]
FF[DocsExplainFindFilesGraph]
end
LLM[AgentLlmService]
RS --> AR --> PR --> P2
P2 --> IR --> POL --> AD --> RSR --> RR
AD --> ASM
ASM --> SUM
ASM --> FF
SUM --> LLM
```
Клиент указывает `process_version: v2`. Без `active_rag_session_id` в сессии процесс возвращает сообщение об ошибке. Иначе выполняется цепочка:
маршрутизация → `RetrievalPlan` → retrieval строк из `DOCS RAG` → минимальная сборка evidence → ветвление по `subintent` → запуск workflow.
### Реализованные домены, интенты и сабинтенты
В коде заданы константы `V2Domain`, `V2Intent`, `V2Subintent`. Сейчас процесс intentionally ограничен одной рабочей областью.
| Уровень | Значение (строка) | Реализация |
|--------|-------------------|------------|
| **Домен (routing_domain)** | `DOCS` | Единственный поддерживаемый домен: документация проекта. |
| **Интент** | `DOC_EXPLAIN` | Единственный интент: объяснение по документации. |
| **Сабинтент** | `SUMMARY` | Объяснение темы по SUMMARY-блокам документации. |
| **Сабинтент** | `FIND_FILES` | Поиск путей к документам, где описана нужная сущность или тема. |
Итого в текущем MVP реализована **одна** рабочая тройка домен×интент: `DOCS` + `DOC_EXPLAIN`, с **двумя** ветками по сабинтенту.
---
## 2. Этапы вне workflow (внутри `V2Process.run`)
### 2.1. `V2IntentRouter.route`
| | |
|--|--|
| **Название** | Маршрутизация запроса (v2) |
| **Задача** | Определить домен, интент, subintent и извлечь якоря из текста. |
| **Вход** | `user_query: str` (текст сообщения пользователя). |
| **Выход** | `V2RouteResult`: `routing_domain`, `intent`, `subintent`, `user_query`, `normalized_query`, `target_terms`, `anchors` (`V2RouteAnchors`), `confidence`. |
| **Как работает** | Router реализован по схеме **LLM-first**: `normalization``target_terms`/`anchors extraction``LLM router``deterministic validator``fallback`. LLM является **основным селектором маршрута**. Deterministic-слой больше не выбирает маршрут по умолчанию: он отвечает только за extraction, валидацию enum/комбинаций и fallback при сломанном или невалидном ответе LLM. В trace пишется событие `intent_routed`. |
Код: `src/app/core/agent/processes/v2/intent_router/router.py`, `modules/normalizer.py`, `modules/target_terms.py`, `modules/anchors.py`, `routers/llm.py`, `routers/validator.py`, `routers/fallback.py`.
---
### 2.2. `V2RetrievalPolicyResolver.resolve`
| | |
|--|--|
| **Название** | Политика retrieval для v2 |
| **Задача** | По результату роутинга выбрать профиль, список слоёв RAG и лимит строк выдачи. |
| **Вход** | `V2RouteResult`. |
| **Выход** | `RetrievalPlan`: `profile`, `layers`, `limit`, опционально `filters`. |
| **Как работает** | Это отдельный смысловой шаг между routing и retrieval. Он не ходит в БД и не извлекает данные, а только подготавливает параметры поиска. Для `FIND_FILES` выбирается один профиль слоёв и лимит, для `SUMMARY` — другой. Лог: `retrieval_plan_resolved`. |
Код: `src/app/core/agent/processes/v2/retrieval/policy_resolver.py`.
---
### 2.3. `V2RagRetrievalAdapter` → `RagSessionRetriever.retrieve`
| | |
|--|--|
| **Название** | Загрузка сырых строк из RAG по плану |
| **Задача** | Делегировать поиск в единственную реализацию retrieval в пакете `rag`. |
| **Вход** | `rag_session_id`, `query_text` (нормализованный запрос), `RetrievalPlan`. |
| **Выход** | `list[dict]` — строки чанков в формате `RagRepository.retrieve` (поля `path`, `layer`, `metadata`, и т.д.). |
| **Как работает** | Выполняется retrieval по уже сформированному плану: профиль, список слоёв и лимит. На этом шаге происходит только извлечение сырых строк из `DOCS RAG`. Лог: `rag_rows_fetched`. |
Код адаптера: `src/app/core/agent/processes/v2/retrieval/v2_rag_adapter.py`.
Код API: `src/app/core/rag/retrieval/session_retriever.py`.
---
### 2.4. `DocsEvidenceAssembler`
| | |
|--|--|
| **Название** | Сборка evidence для задачи |
| **Задача** | Превратить сырые строки retrieval в списки summary или кандидатов файлов с дедупом и скорингом. |
| **Вход** | Список строк `rows`, `V2RouteResult` (для `target_terms`). |
| **Выход** | `list[RetrievedSummary]` или `list[RetrievedFile]`. |
| **Как работает** | Это **минимальная evidence-проверка**, достаточная для MVP. Для `SUMMARY` отбрасываются записи без summary-текста и summary-like секции, затем применяется дедуп и простой скоринг по терминам. Для `FIND_FILES` остаются только релевантные пути документов, также с дедупом и простым скорингом. Здесь нет сложной многоступенчатой валидации: задача шага — отфильтровать очевидный шум и передать в workflow компактное evidence. Лог: `evidence_assembled`. |
Код: `src/app/core/agent/processes/v2/evidence/assembler.py`.
---
## 3. Шаги workflow
Текущие workflow являются **task-focused**: каждая ветка решает одну узкую прикладную задачу и не содержит общей универсальной логики для всех типов вопросов.
### 3.1. Ветка `SUMMARY`: `GenerateSummaryAnswerStep`
| | |
|--|--|
| **Название** | Сборка ответа по summary |
| **Задача** | Сформировать ответ пользователю по найденным SUMMARY-блокам или сообщить об отсутствии. |
| **Вход** | `DocsExplainSummaryContext`: `runtime`, `route`, `rag_session_id`, `prompt_name`, `documents` (список `RetrievedSummary`). |
| **Выход** | Контекст с `answer: str`, `prompt_input` при успешном вызове LLM. |
| **Как работает** | Workflow получает уже отобранные summary-документы. Если документов нет — возвращает честный fallback-ответ. Иначе собирает prompt input из запроса пользователя и найденных summary-блоков и вызывает LLM. Workflow не занимается retrieval и не строит retrieval-план: он решает только задачу генерации ответа по уже подготовленному evidence. |
Код: `src/app/core/agent/processes/v2/workflows/docs_explain_summary/steps/generate_summary_answer_step.py`.
Граф: `DocsExplainSummaryGraph` (`V2WorkflowGraph`).
---
### 3.2. Ветка `FIND_FILES`: `FinalizeFindFilesAnswerStep`
| | |
|--|--|
| **Название** | Сборка списка файлов |
| **Задача** | Вывести пользователю markdown-список путей к файлам документации. |
| **Вход** | `DocsExplainFindFilesContext`: `runtime`, `route`, `rag_session_id`, `files` (`RetrievedFile`). |
| **Выход** | Контекст с `answer: str`. |
| **Как работает** | Workflow получает уже собранный список файлов и формирует финальный ответ. Если файлов нет — возвращает fallback. Если файлы есть — отдает детерминированный список путей. Эта ветка intentionally не использует LLM, потому что задача сводится к выдаче путей, а не к генерации объяснения. |
Код: `src/app/core/agent/processes/v2/workflows/docs_explain_find_files/steps/finalize_find_files_answer_step.py`.
Граф: `DocsExplainFindFilesGraph` (`V2WorkflowGraph`).
---
### 3.3. Транспорт: `V2WorkflowGraph`
| | |
|--|--|
| **Название** | Workflow v2 с буфером trace |
| **Задача** | Выполнить шаги без пошаговых `step_started`/`step_completed` в trace; один раз сбросить сводку. |
| **Вход** | Контекст workflow (`DocsExplainSummaryContext` или `DocsExplainFindFilesContext`). |
| **Выход** | Обновлённый контекст. |
| **Как работает** | Для каждого шага: `trace_input` до `run`, затем `run`, затем `trace_output`; записи копятся в список. В trace уходят `workflow_started`, затем `workflow_trace_flushed` с массивом шагов, затем `workflow_completed`. Статусы пользователю публикуются через `publisher` как и раньше. |
Код: `src/app/core/agent/processes/v2/workflows/v2_workflow_graph.py`.
---
## 4. Сборка в приложении
В `ModularApplication` создаются `RagSessionRetriever`, `V2RagRetrievalAdapter`, `V2RetrievalPolicyResolver`, `DocsEvidenceAssembler` и передаются в `V2Process` (см. `src/app/core/application.py`).
---
## 5. Итоговая концептуальная схема текущего MVP
В концептуальном виде текущий `v2` работает так:
1. **Session check**
Проверка, что есть активная RAG-сессия проекта.
2. **LLM-first intent routing**
Нормализация, extraction (`target_terms`, `anchors`), затем основной выбор маршрута через LLM.
3. **Deterministic validation + fallback**
Проверка enum/комбинации маршрута и fallback только если LLM не ответил или вернул невалидный маршрут.
4. **Retrieval parameter planning**
Формирование профиля поиска, слоёв и лимитов.
5. **RAG retrieval**
Загрузка сырых строк из `DOCS RAG`.
6. **Minimal evidence assembly**
Дедуп, базовый скоринг, отбор полезных summary или файлов.
7. **Task-focused workflow**
Узкая ветка `SUMMARY` или `FIND_FILES`.
8. **Final response**
Либо explanation через LLM, либо детерминированный список файлов.
Это и есть актуальная архитектура **узкого MVP**, синхронизированная с текущей реализацией.