Initial import NDC_1C
This commit is contained in:
@@ -0,0 +1,444 @@
|
||||
# 5 - Assistant Mode Architecture Report (2026-03-24)
|
||||
|
||||
## 1. Статус этапа
|
||||
|
||||
Дата фиксации: **24 марта 2026**.
|
||||
|
||||
На текущем этапе реализован рабочий `Assistant Mode` поверх существующего `Decomposition` контура:
|
||||
|
||||
- decomposition/debug режим сохранен и не удален;
|
||||
- добавлен отдельный backend endpoint для assistant-loop;
|
||||
- добавлен слой `answer_composer` (human-readable ответ);
|
||||
- добавлена session-scoped история диалога (in-memory);
|
||||
- добавлен debug drawer в GUI по каждому assistant ответу;
|
||||
- единый pipeline нормализации/маршрутизации используется для обоих режимов.
|
||||
|
||||
---
|
||||
|
||||
## 2. Что входит в текущую архитектуру
|
||||
|
||||
## 2.1 Backend
|
||||
|
||||
Ключевые узлы:
|
||||
|
||||
- `llm_normalizer/backend/src/routes/assistant.ts`
|
||||
- `llm_normalizer/backend/src/services/assistantService.ts`
|
||||
- `llm_normalizer/backend/src/services/answerComposer.ts`
|
||||
- `llm_normalizer/backend/src/services/assistantSessionStore.ts`
|
||||
- `llm_normalizer/backend/src/types/assistant.ts`
|
||||
- `llm_normalizer/backend/src/services/routeHintAdapter.ts` (общий deterministic routing)
|
||||
- `llm_normalizer/backend/src/services/normalizerService.ts` (общий normalizer pipeline)
|
||||
|
||||
Подключение в сервер:
|
||||
|
||||
- `llm_normalizer/backend/src/server.ts`
|
||||
- `llm_normalizer/backend/src/serverContext.ts`
|
||||
|
||||
## 2.2 Frontend
|
||||
|
||||
Ключевые узлы:
|
||||
|
||||
- `llm_normalizer/frontend/src/App.tsx` (mode switch + orchestration)
|
||||
- `llm_normalizer/frontend/src/components/AssistantPanel.tsx`
|
||||
- `llm_normalizer/frontend/src/api/client.ts` (assistant API methods)
|
||||
- `llm_normalizer/frontend/src/state/types.ts` (assistant типы состояния)
|
||||
- `llm_normalizer/frontend/src/styles.css` (assistant/mode switch UI стиль)
|
||||
|
||||
---
|
||||
|
||||
## 3. Backend: функциональная архитектура
|
||||
|
||||
## 3.1 Endpoint’ы
|
||||
|
||||
### 3.1.1 POST `/api/assistant/message`
|
||||
|
||||
Назначение:
|
||||
|
||||
- принять user message;
|
||||
- прогнать через normalizer pipeline;
|
||||
- определить route/fallback;
|
||||
- собрать human-readable assistant reply;
|
||||
- вернуть reply + debug + session conversation snapshot.
|
||||
|
||||
Проверки:
|
||||
|
||||
- `user_message` обязателен;
|
||||
- при пустом сообщении возвращается `INVALID_ASSISTANT_MESSAGE` (HTTP 400).
|
||||
|
||||
### 3.1.2 GET `/api/assistant/session/:session_id`
|
||||
|
||||
Назначение:
|
||||
|
||||
- вернуть текущую историю сессии из in-memory store.
|
||||
|
||||
Поведение:
|
||||
|
||||
- если сессия отсутствует: `ASSISTANT_SESSION_NOT_FOUND` (HTTP 404).
|
||||
|
||||
---
|
||||
|
||||
## 3.2 Контракт данных Assistant Mode
|
||||
|
||||
Типы заданы в:
|
||||
|
||||
- `llm_normalizer/backend/src/types/assistant.ts`
|
||||
|
||||
Ключевые сущности:
|
||||
|
||||
- `AssistantMessageRequestPayload`
|
||||
- `AssistantDebugPayload`
|
||||
- `AssistantConversationItem`
|
||||
- `AssistantMessageResponsePayload`
|
||||
|
||||
`fallback_type` (жестко зафиксированный набор):
|
||||
|
||||
- `none`
|
||||
- `out_of_scope`
|
||||
- `clarification`
|
||||
- `partial`
|
||||
- `unknown`
|
||||
|
||||
---
|
||||
|
||||
## 3.3 Session memory
|
||||
|
||||
Реализовано в:
|
||||
|
||||
- `llm_normalizer/backend/src/services/assistantSessionStore.ts`
|
||||
|
||||
Характеристики:
|
||||
|
||||
- хранилище: in-memory `Map<session_id, session_state>`;
|
||||
- auto-create сессии при первом сообщении;
|
||||
- ограничение длины: `MAX_ITEMS_PER_SESSION = 200`;
|
||||
- хранение только в рамках текущего backend процесса;
|
||||
- при рестарте backend память очищается.
|
||||
|
||||
Это deliberate решение текущего этапа (sandbox/stage), без persistent storage.
|
||||
|
||||
---
|
||||
|
||||
## 3.4 Assistant pipeline (внутренний flow)
|
||||
|
||||
Реализовано в:
|
||||
|
||||
- `llm_normalizer/backend/src/services/assistantService.ts`
|
||||
|
||||
Порядок выполнения:
|
||||
|
||||
1. `ensureSession` -> получаем/создаем `session_id`.
|
||||
2. Сохраняем user message как conversation item (`role=user`).
|
||||
3. Формируем `NormalizeRequestPayload` с:
|
||||
- `promptVersion` по умолчанию `normalizer_v2_0_2`,
|
||||
- connection/prompt/context/useMock из запроса.
|
||||
4. Вызываем `normalizerService.normalize(...)`.
|
||||
5. По `route_hint_summary` строим retrieval plan (`buildRetrievalPlan`).
|
||||
6. Передаем данные в `composeAssistantAnswer(...)`.
|
||||
7. Формируем `debug` payload:
|
||||
- `trace_id`,
|
||||
- `route_summary`,
|
||||
- `fragments`,
|
||||
- `retrieval`,
|
||||
- `normalized`.
|
||||
8. Сохраняем assistant message как conversation item (`role=assistant`).
|
||||
9. Логируем structured event `assistant_message_processed`.
|
||||
10. Возвращаем:
|
||||
- `assistant_reply`,
|
||||
- `conversation_item`,
|
||||
- `debug`,
|
||||
- `conversation`.
|
||||
|
||||
---
|
||||
|
||||
## 3.5 Routing rules (общий deterministic v2 engine)
|
||||
|
||||
Основные правила маршрутизации берутся из:
|
||||
|
||||
- `llm_normalizer/backend/src/services/routeHintAdapter.ts`
|
||||
|
||||
Правила выбора маршрута:
|
||||
|
||||
1. `live_mcp_drilldown`
|
||||
- если `asks_for_exact_object_trace = true`.
|
||||
2. `batch_refresh_then_store`
|
||||
- если `asks_for_ranking_or_top = true` **или** `asks_for_period_summary = true`.
|
||||
3. `hybrid_store_plus_live`
|
||||
- если `has_multi_entity_scope = true` и `asks_for_chain_explanation = true`.
|
||||
4. `store_feature_risk`
|
||||
- если `asks_for_rule_check = true` и не chain;
|
||||
- также anomaly path: `asks_for_anomaly_scan = true` без ranking и без multi-entity chain.
|
||||
5. `store_canonical`
|
||||
- default routed путь для in-scope, если нет более сильного сигнала.
|
||||
6. `no_route`
|
||||
- если fragment out-of-scope / insufficient specificity / missing mapping / unsupported fragment type.
|
||||
|
||||
Fallback type в summary:
|
||||
|
||||
- `out_of_scope` — сообщение вне контура;
|
||||
- `clarification` — нет routable in-scope fragment’ов из-за недоспецификации;
|
||||
- `partial` — часть in-scope/routed, часть no-route/out-of-scope;
|
||||
- `none` — все ок для текущего контура.
|
||||
|
||||
---
|
||||
|
||||
## 3.6 Answer composer rules
|
||||
|
||||
Реализовано в:
|
||||
|
||||
- `llm_normalizer/backend/src/services/answerComposer.ts`
|
||||
|
||||
Логика:
|
||||
|
||||
1. `out_of_scope`
|
||||
- вежливый boundary response (работа только по company-specific accounting contour).
|
||||
2. `clarification`
|
||||
- конкретный уточняющий ответ: период/счет/документ/контрагент.
|
||||
3. `partial`
|
||||
- сообщает, что обработана только часть запроса;
|
||||
- выводит routed части;
|
||||
- явно фиксирует sandbox retrieval mode.
|
||||
4. `none`
|
||||
- human-readable summary с перечислением planned routes.
|
||||
5. `unknown`
|
||||
- защитный fallback, если routed items не сформированы.
|
||||
|
||||
Важно:
|
||||
|
||||
- на этом этапе composer формирует **человеко-читаемый operational ответ**;
|
||||
- это не финальный production-grade semantic answer over full live retrieval.
|
||||
|
||||
---
|
||||
|
||||
## 3.7 Retrieval слой (текущий статус)
|
||||
|
||||
Текущее состояние: **stubbed / sandbox retrieval plan**.
|
||||
|
||||
Что есть:
|
||||
|
||||
- генерация плана “что и по какому route исполнять”;
|
||||
- диагностический payload по fragment’ам.
|
||||
|
||||
Чего пока нет:
|
||||
|
||||
- боевой deep retrieval из 1С по всем route;
|
||||
- гарантированного factual grounding для каждого ответа assistant mode.
|
||||
|
||||
---
|
||||
|
||||
## 3.8 Логирование и трассировка
|
||||
|
||||
В `assistantService` пишется structured log c событием:
|
||||
|
||||
- `assistant_message_processed`
|
||||
|
||||
Поля:
|
||||
|
||||
- `session_id`
|
||||
- `message_id`
|
||||
- `user_message`
|
||||
- `normalizer_output`
|
||||
- `resolved_execution_state`
|
||||
- `routes`
|
||||
- `fallback_type`
|
||||
- `retrieval_payloads`
|
||||
- `assistant_reply`
|
||||
- `trace_id`
|
||||
|
||||
Это дает базу для будущего field-eval hardening.
|
||||
|
||||
---
|
||||
|
||||
## 4. Frontend: функциональная архитектура
|
||||
|
||||
## 4.1 Режимы UI
|
||||
|
||||
Реализовано в:
|
||||
|
||||
- `llm_normalizer/frontend/src/App.tsx`
|
||||
|
||||
Есть явный переключатель:
|
||||
|
||||
- `Assistant`
|
||||
- `Decomposition`
|
||||
|
||||
Поведение:
|
||||
|
||||
- backend pipeline общий;
|
||||
- UI-представление разное;
|
||||
- decomposition stack не ломается и остается доступным.
|
||||
|
||||
---
|
||||
|
||||
## 4.2 Assistant Mode UI состав
|
||||
|
||||
Реализовано в:
|
||||
|
||||
- `llm_normalizer/frontend/src/components/AssistantPanel.tsx`
|
||||
|
||||
Элементы:
|
||||
|
||||
1. Chat timeline:
|
||||
- user/assistant messages,
|
||||
- timestamp,
|
||||
- trace id для assistant сообщений.
|
||||
2. Input зона:
|
||||
- поле сообщения,
|
||||
- send,
|
||||
- reset session.
|
||||
3. Контекст:
|
||||
- `periodHint`
|
||||
- `businessContext`
|
||||
4. Toggle:
|
||||
- `useMock`.
|
||||
5. Debug drawer:
|
||||
- раскрывается per assistant message,
|
||||
- показывает raw debug JSON (`trace/fragments/routes/fallback/retrieval/normalized`).
|
||||
|
||||
---
|
||||
|
||||
## 4.3 Pipeline progress UX
|
||||
|
||||
Во время обработки показывается этапный status ticker:
|
||||
|
||||
1. `Razbirayu zapros`
|
||||
2. `Proveryayu kontur`
|
||||
3. `Opredelyayu marshrut`
|
||||
4. `Ishchu dannye`
|
||||
5. `Sobirayu otvet`
|
||||
|
||||
Цель: убрать ощущение “зависло” и визуализировать pipeline.
|
||||
|
||||
---
|
||||
|
||||
## 4.4 Frontend state flow
|
||||
|
||||
Ключевые state переменные:
|
||||
|
||||
- `uiMode`
|
||||
- `assistantSessionId`
|
||||
- `assistantConversation`
|
||||
- `assistantInput`
|
||||
- `assistantBusy`
|
||||
- `assistantStatus`
|
||||
- `assistantError`
|
||||
|
||||
Flow отправки:
|
||||
|
||||
1. optimistic append user message в chat;
|
||||
2. запуск status ticker;
|
||||
3. вызов `apiClient.sendAssistantMessage(...)`;
|
||||
4. обновление `session_id` и полной conversation с backend;
|
||||
5. остановка ticker + финальный статус.
|
||||
|
||||
---
|
||||
|
||||
## 4.5 API client для Assistant
|
||||
|
||||
Реализовано в:
|
||||
|
||||
- `llm_normalizer/frontend/src/api/client.ts`
|
||||
|
||||
Добавлены методы:
|
||||
|
||||
- `sendAssistantMessage(...)` -> `POST /api/assistant/message`
|
||||
- `loadAssistantSession(sessionId)` -> `GET /api/assistant/session/:id`
|
||||
|
||||
---
|
||||
|
||||
## 5. Что сделано по требованиям ТЗ (mapping)
|
||||
|
||||
1. `docs/assistant_mode_spec.md` — выполнено
|
||||
2. GUI с переключателем `Assistant` / `Decomposition` — выполнено
|
||||
3. backend endpoint assistant loop — выполнено
|
||||
4. `answer_composer` слой — выполнено
|
||||
5. session-based chat history — выполнено (in-memory)
|
||||
6. debug drawer/expandable technical view — выполнено
|
||||
7. `docs/assistant_mode_flow.md` — выполнено
|
||||
8. `docs/known_limits_before_field_eval.md` — выполнено
|
||||
|
||||
---
|
||||
|
||||
## 6. Критические ограничения текущей реализации
|
||||
|
||||
1. **retrieval sandbox/stubbed**
|
||||
- assistant выдает план/маршрут, не full factual extraction по всем route.
|
||||
2. **session memory volatile**
|
||||
- хранится только в памяти backend процесса.
|
||||
3. **нет production hardening**
|
||||
- auth/tenancy/persistence/SLO не включены.
|
||||
4. **composer базовый**
|
||||
- достаточен для MVP loop, но не финальный policy-grade layer.
|
||||
|
||||
---
|
||||
|
||||
## 7. Запуск и проверка на новой машине (текущий этап)
|
||||
|
||||
## 7.1 Backend
|
||||
|
||||
```powershell
|
||||
cd X:\1C\NDC_1C\llm_normalizer\backend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## 7.2 Frontend
|
||||
|
||||
```powershell
|
||||
cd X:\1C\NDC_1C\llm_normalizer\frontend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## 7.3 Открыть GUI
|
||||
|
||||
- `http://localhost:5174`
|
||||
|
||||
## 7.4 Smoke test Assistant Mode
|
||||
|
||||
1. Переключить mode -> `Assistant`.
|
||||
2. Ввести сообщение в чат.
|
||||
3. Нажать `Send`.
|
||||
4. Проверить:
|
||||
- появился assistant reply;
|
||||
- появился trace id;
|
||||
- открывается debug drawer;
|
||||
- session сохраняет историю.
|
||||
|
||||
---
|
||||
|
||||
## 8. Тестовый статус к моменту фиксации
|
||||
|
||||
Проверки выполнены 24.03.2026:
|
||||
|
||||
- backend tests: `npm test` -> **21 passed**
|
||||
- backend build: `npm run build` -> **OK**
|
||||
- frontend build: `npm run build` -> **OK**
|
||||
|
||||
Также добавлен endpoint test:
|
||||
|
||||
- `llm_normalizer/backend/tests/assistantEndpoint.test.ts`
|
||||
|
||||
Покрывает:
|
||||
|
||||
- успешный `POST /api/assistant/message`;
|
||||
- session continuity;
|
||||
- `GET /api/assistant/session/:session_id`.
|
||||
|
||||
---
|
||||
|
||||
## 9. Архитектурный итог этапа
|
||||
|
||||
Текущий Assistant Mode — это уже **usable dialog loop**:
|
||||
|
||||
- user-friendly вход (чат),
|
||||
- deterministic decomposition/routing ядро,
|
||||
- единый backend pipeline,
|
||||
- прозрачная debug-плоскость для инженерной диагностики,
|
||||
- session-based continuity в рамках процесса.
|
||||
|
||||
Для перехода в следующий уровень (field-hardened assistant) нужен следующий блок:
|
||||
|
||||
- подключение route-specific factual retrieval,
|
||||
- сбор 30–40 реальных полевых запросов,
|
||||
- policy hardening по traces (clarification/no-route/partial quality).
|
||||
|
||||
Reference in New Issue
Block a user