Initial import NDC_1C

This commit is contained in:
2026-03-26 10:38:25 +03:00
commit a162d77ef7
2943 changed files with 3615871 additions and 0 deletions
@@ -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).