Initial import NDC_1C
This commit is contained in:
@@ -0,0 +1,252 @@
|
||||
# Bootstrap Runbook: Полный пайплайн запуска с нуля (новая машина)
|
||||
|
||||
Дата: 2026-03-23
|
||||
Статус: рабочий контур подтвержден (`adopt with restrictions`)
|
||||
Цель: поднять наш текущий live read-only bridge к 1С с нуля на новой Windows-машине.
|
||||
|
||||
## 1. Что в итоге должно работать
|
||||
|
||||
После выполнения шагов должны одновременно работать:
|
||||
|
||||
1. Python proxy (`onec_mcp_toolkit_proxy`) на `http://127.0.0.1:6003`
|
||||
2. 1С:Предприятие с открытой обработкой `MCP_Toolkit.epf` в режиме `Прокси`
|
||||
3. Успешные read-only вызовы:
|
||||
- `get_metadata`
|
||||
- `execute_query`
|
||||
- `get_link_of_object`
|
||||
- `get_object_by_link`
|
||||
|
||||
Важно: это live request/response мост, не оффлайн-реплика.
|
||||
|
||||
## 2. Архитектура (минимум)
|
||||
|
||||
```text
|
||||
Клиент/ассистент -> HTTP -> Python Proxy (6003) -> /1c/poll,/1c/result -> MCP_Toolkit.epf -> База 1С
|
||||
```
|
||||
|
||||
## 3. Что нужно на новой машине
|
||||
|
||||
1. Windows (рекомендуемо 64-bit).
|
||||
2. Установленная платформа 1С (в нашем контуре: `8.3.27.1936`).
|
||||
3. Тестовая база 1С (БП 2.0) и рабочий пользователь с read-only правами.
|
||||
4. Git.
|
||||
5. Miniconda.
|
||||
6. Доступ к репозиторию `ROCTUP/1c-mcp-toolkit`.
|
||||
|
||||
## 4. Рекомендованная структура папок
|
||||
|
||||
```text
|
||||
X:\1C\
|
||||
NDC_1C\
|
||||
docs\
|
||||
external\
|
||||
1c-mcp-toolkit\
|
||||
```
|
||||
|
||||
Если диска `X:` нет, можно использовать любой путь, но держать единую структуру.
|
||||
|
||||
## 5. Установка и подготовка окружения
|
||||
|
||||
### 5.1 Клонировать toolkit
|
||||
|
||||
```powershell
|
||||
git clone https://github.com/ROCTUP/1c-mcp-toolkit X:\1C\NDC_1C\external\1c-mcp-toolkit
|
||||
```
|
||||
|
||||
### 5.2 Проверить `.epf` артефакты
|
||||
|
||||
```powershell
|
||||
Get-ChildItem X:\1C\NDC_1C\external\1c-mcp-toolkit\build
|
||||
```
|
||||
|
||||
Ожидаемые файлы:
|
||||
|
||||
- `MCP_Toolkit.epf` (x64)
|
||||
- `MCP_Toolkit_x86.epf` (x86 fallback)
|
||||
|
||||
### 5.3 Создать изолированную conda-среду
|
||||
|
||||
```powershell
|
||||
& 'C:\Users\<USER>\miniconda3\Scripts\conda.exe' create -y -n ndc_1c_toolkit python=3.11
|
||||
```
|
||||
|
||||
### 5.4 Установить зависимости proxy
|
||||
|
||||
```powershell
|
||||
& 'C:\Users\<USER>\miniconda3\envs\ndc_1c_toolkit\python.exe' -m pip install --upgrade pip
|
||||
& 'C:\Users\<USER>\miniconda3\envs\ndc_1c_toolkit\python.exe' -m pip install -r X:\1C\NDC_1C\external\1c-mcp-toolkit\requirements.txt
|
||||
```
|
||||
|
||||
## 6. Запуск proxy (read-only профиль)
|
||||
|
||||
Запускать из PowerShell:
|
||||
|
||||
```powershell
|
||||
$env:PORT='6003'
|
||||
$env:TIMEOUT='180'
|
||||
$env:ALLOW_DANGEROUS_WITH_APPROVAL='false'
|
||||
$env:ANONYMIZATION_ENABLED='false'
|
||||
$env:RESPONSE_FORMAT='json'
|
||||
$env:LOG_LEVEL='INFO'
|
||||
& 'C:\Users\<USER>\miniconda3\envs\ndc_1c_toolkit\python.exe' -m onec_mcp_toolkit_proxy
|
||||
```
|
||||
|
||||
Проверка:
|
||||
|
||||
```powershell
|
||||
Invoke-WebRequest http://127.0.0.1:6003/health -UseBasicParsing
|
||||
```
|
||||
|
||||
Ожидаемо: HTTP 200 и `status=healthy`.
|
||||
|
||||
## 7. Запуск 1С и обработчика
|
||||
|
||||
### 7.1 Открыть 1С:Предприятие
|
||||
|
||||
Открывать в **режиме Предприятия** (не Конфигуратор).
|
||||
Если UI обработки не появляется в обычном режиме, запускать в управляемом приложении.
|
||||
|
||||
### 7.2 Открыть внешнюю обработку
|
||||
|
||||
`Файл -> Открыть -> X:\1C\NDC_1C\external\1c-mcp-toolkit\build\MCP_Toolkit.epf`
|
||||
|
||||
### 7.3 Настроить форму MCP Toolkit
|
||||
|
||||
1. Режим: `Прокси`
|
||||
2. Адрес сервера: `http://127.0.0.1:6003`
|
||||
3. Идентификатор канала: `default` (или ваш фиксированный channel)
|
||||
4. Нажать `Подключиться`
|
||||
|
||||
Ожидаемо в логе формы:
|
||||
|
||||
- `Подключение к серверу: http://127.0.0.1:6003`
|
||||
- `Успешное подключение к серверу`
|
||||
|
||||
## 8. Smoke-проверка после подключения
|
||||
|
||||
### 8.1 Metadata
|
||||
|
||||
```powershell
|
||||
Invoke-WebRequest "http://127.0.0.1:6003/api/get_metadata?channel=default&meta_type=Документ&limit=20" -UseBasicParsing
|
||||
```
|
||||
|
||||
Ожидаемо: `success=true`.
|
||||
|
||||
### 8.2 Query
|
||||
|
||||
```powershell
|
||||
$body = @{ query = "ВЫБРАТЬ ПЕРВЫЕ 1 1 КАК Test"; limit = 1 } | ConvertTo-Json
|
||||
Invoke-WebRequest "http://127.0.0.1:6003/api/execute_query?channel=default" `
|
||||
-Method POST -ContentType "application/json; charset=utf-8" -Body $body -UseBasicParsing
|
||||
```
|
||||
|
||||
Ожидаемо: `success=true`, `Test=1`.
|
||||
|
||||
### 8.3 Object link flow
|
||||
|
||||
1. Получить `object_description` (например, из `execute_query`).
|
||||
2. Вызвать `get_link_of_object`.
|
||||
3. Передать ссылку в `get_object_by_link`.
|
||||
|
||||
Ожидаемо: объект документа читается.
|
||||
|
||||
## 9. Ежедневный рабочий цикл (операторский)
|
||||
|
||||
### Старт дня
|
||||
|
||||
1. Запустить proxy.
|
||||
2. Проверить `/health`.
|
||||
3. Запустить 1С и открыть `MCP_Toolkit.epf`.
|
||||
4. Проверить статус `Подключено`.
|
||||
5. Выполнить быстрый test query.
|
||||
|
||||
### Стоп дня
|
||||
|
||||
1. Отключиться в форме MCP Toolkit.
|
||||
2. Закрыть 1С.
|
||||
3. Остановить proxy (Ctrl+C/Stop-Process).
|
||||
|
||||
## 10. Траблшутинг (частые проблемы)
|
||||
|
||||
### 10.1 Ошибка `Не могу установить соединение` в форме 1С
|
||||
|
||||
Причина: proxy не запущен или не слушает `6003`.
|
||||
Проверка:
|
||||
|
||||
```powershell
|
||||
Invoke-WebRequest http://127.0.0.1:6003/health -UseBasicParsing
|
||||
```
|
||||
|
||||
### 10.2 `timeout waiting for 1C response` на API
|
||||
|
||||
Причина: нет активного `.epf` в том же `channel`, форма закрыта, либо канал не совпадает.
|
||||
|
||||
### 10.3 `UI не показывается` при открытии `.epf`
|
||||
|
||||
Обработка имеет управляемые формы.
|
||||
Запускать в 1С:Предприятии (управляемый режим), не в Конфигураторе для рабочего контура.
|
||||
|
||||
### 10.4 Кодировка ссылки из `get_link_of_object` выглядит “кракозябрами”
|
||||
|
||||
Нюанс текущего ответа proxy; вызов рабочий, ссылку можно нормализовать при постобработке.
|
||||
|
||||
## 11. Жёсткие правила безопасности
|
||||
|
||||
1. Только read-only операции.
|
||||
2. Не использовать `execute_code`.
|
||||
3. Не выставлять `6003` во внешний интернет.
|
||||
4. Держать `ALLOW_DANGEROUS_WITH_APPROVAL=false`.
|
||||
5. Работать под отдельным техпользователем с минимальными правами чтения.
|
||||
|
||||
## 12. Что это даёт и чего не даёт
|
||||
|
||||
### Даёт
|
||||
|
||||
- Живой доступ к текущим данным 1С по запросу.
|
||||
- Runtime metadata + deep read semantics (документы, проводки, субконто, сальдо).
|
||||
|
||||
### Не даёт
|
||||
|
||||
- Мгновенный “весь срез компании” в одном запросе для тяжёлой аналитики.
|
||||
- Автоматическую фоновой репликацию без отдельного слоя витрин/снэпшотов.
|
||||
|
||||
## 13. Рекомендованный next step после bootstrap
|
||||
|
||||
1. Добавить one-click старт скрипт (`Start-NDC1CBridge.ps1`).
|
||||
2. Добавить one-click smoke скрипт (`Test-NDC1CBridge.ps1`).
|
||||
3. Поднять плановую аналитическую витрину (например, 15/60 минут) для тяжёлых задач.
|
||||
|
||||
---
|
||||
|
||||
Итог bootstrap: на новой машине поднимаем контур за последовательность
|
||||
`Proxy -> MCP_Toolkit.epf -> Подключение -> Smoke`
|
||||
и получаем рабочий live read-only мост к 1С на текущем этапе проекта.
|
||||
|
||||
_________________________________________________
|
||||
|
||||
ЗАПУСК ПРКСИ ПЕРЕД ПОДКЛЮЮЧЕНИЕМ К ТУЛКИТ 1С
|
||||
|
||||
_________________________________________________
|
||||
Запускай так в PowerShell:
|
||||
|
||||
$env:PORT='6003'
|
||||
$env:TIMEOUT='180'
|
||||
$env:ALLOW_DANGEROUS_WITH_APPROVAL='false'
|
||||
$env:ANONYMIZATION_ENABLED='false'
|
||||
$env:RESPONSE_FORMAT='json'
|
||||
$env:LOG_LEVEL='INFO'
|
||||
& 'C:\Users\DCTOUCH\miniconda3\envs\ndc_1c_toolkit\python.exe' -m onec_mcp_toolkit_proxy
|
||||
|
||||
|
||||
Проверка, что поднялся:
|
||||
|
||||
Invoke-WebRequest http://127.0.0.1:6003/health -UseBasicParsing
|
||||
|
||||
Должен вернуть status":"healthy".
|
||||
|
||||
Остановить:
|
||||
|
||||
в том же окне Ctrl + C.
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
# Архитектурный Stage Report (AS-IS)
|
||||
|
||||
Дата фиксации: 2026-03-23
|
||||
Проект: NDC 1C analytics bridge
|
||||
Контур: локальный стенд (Windows, тестовая база 1С)
|
||||
|
||||
## 1. Резюме этапа
|
||||
|
||||
На текущем этапе подтверждён рабочий **read-only runtime мост** к живой 1С через `1c-mcp-toolkit` в proxy-режиме.
|
||||
Три критические бухгалтерские проверки закрыты как `PROVEN`:
|
||||
|
||||
1. `document -> posting -> debit/credit account`
|
||||
2. `posting -> subconto[1..3] -> counterparty / contract / item`
|
||||
3. Объяснение реального сальдо через агрегат движений (`delta = 0.0`)
|
||||
|
||||
Официальный статус решения: `adopt with restrictions`.
|
||||
|
||||
## 2. Цель этапа (что фиксируем)
|
||||
|
||||
Зафиксировать не идею, а фактическое состояние архитектуры:
|
||||
|
||||
- как реально ходят данные;
|
||||
- что именно работает в live режиме;
|
||||
- что является ограничением;
|
||||
- какие артефакты подтверждают результаты;
|
||||
- что берём в следующий этап.
|
||||
|
||||
## 3. Текущая архитектура (AS-IS)
|
||||
|
||||
```text
|
||||
AI/клиент аналитики
|
||||
|
|
||||
| HTTP (read-only API calls)
|
||||
v
|
||||
Local Proxy: onec_mcp_toolkit_proxy (FastAPI) [127.0.0.1:6003]
|
||||
|\
|
||||
| \-- /health, /api/get_metadata, /api/execute_query, /api/get_object_by_link, ...
|
||||
|
|
||||
| Long polling bridge
|
||||
| GET /1c/poll
|
||||
| POST /1c/result
|
||||
v
|
||||
1C External Processing MCP_Toolkit.epf (управляемая форма, режим "Прокси")
|
||||
|
|
||||
v
|
||||
Тестовая база 1С: Бухгалтерия предприятия 2.0 (2.0.67.20), платформа 8.3.27.1936
|
||||
```
|
||||
|
||||
Дополнительно параллельно существует OData read-only слой (базовый широкий вход), но в этом stage фиксируется именно runtime-mост toolkit.
|
||||
|
||||
## 4. Компоненты и роль
|
||||
|
||||
1. `MCP_Toolkit.epf`
|
||||
- Путь: `X:\1C\NDC_1C\external\1c-mcp-toolkit\build\MCP_Toolkit.epf`
|
||||
- Роль: 1С-сторона моста, выполнение read-запросов в контексте базы и возврат результатов в proxy.
|
||||
- Важно: форма управляемая; в обычном режиме UI может не открываться.
|
||||
|
||||
2. `onec_mcp_toolkit_proxy` (Python/FastAPI)
|
||||
- Путь: `X:\1C\NDC_1C\external\1c-mcp-toolkit\onec_mcp_toolkit_proxy`
|
||||
- Роль: единая HTTP/MCP точка входа для аналитики.
|
||||
- Runtime: Miniconda env `ndc_1c_toolkit`.
|
||||
- Базовый endpoint: `http://127.0.0.1:6003`.
|
||||
|
||||
3. 1С тестовая база
|
||||
- Платформа: `8.3.27.1936`
|
||||
- Конфигурация: `БП 2.0 (2.0.67.20)`
|
||||
- Роль: source of truth для всех live чтений.
|
||||
|
||||
4. Артефактный слой (доказательства)
|
||||
- Путь: `X:\1C\NDC_1C\docs\snapshots\toolkit`
|
||||
- Роль: хранение фактических ответов/логов проверки этапа.
|
||||
|
||||
## 5. Семантика доступа к данным (очень важно)
|
||||
|
||||
### 5.1 Что это сейчас
|
||||
|
||||
Это **live request/response bridge**:
|
||||
|
||||
- каждый запрос читается из текущего состояния 1С на момент вызова;
|
||||
- данные не берутся из локальной копии/реплики;
|
||||
- нет постоянного stream-пайплайна “само обновляется”.
|
||||
|
||||
### 5.2 Что это не сейчас
|
||||
|
||||
- это не полноценная витрина данных по всей компании;
|
||||
- это не always-on snapshot pipeline;
|
||||
- это не CDC/стриминг изменений в фоновом режиме.
|
||||
|
||||
### 5.3 Практический вывод
|
||||
|
||||
Для точечных и средних аналитических задач мост подходит в near real-time режиме.
|
||||
Для очень широких срезов (вся компания, тяжёлые многомерные отчёты) потребуется отдельный слой агрегаций/снэпшотов.
|
||||
|
||||
## 6. API-поверхность, которую используем в проекте
|
||||
|
||||
Разрешённый operational набор:
|
||||
|
||||
- `get_metadata`
|
||||
- `execute_query`
|
||||
- `get_object_by_link`
|
||||
- `get_link_of_object`
|
||||
- при необходимости другие read-only методы
|
||||
|
||||
Запрещено в operational контуре:
|
||||
|
||||
- `execute_code`
|
||||
- любые write/mutation операции.
|
||||
|
||||
## 7. Ограничения и guardrails
|
||||
|
||||
Обязательные ограничения на текущем этапе:
|
||||
|
||||
1. Только read-only вызовы.
|
||||
2. `ALLOW_DANGEROUS_WITH_APPROVAL=false`.
|
||||
3. Endpoint не публиковать наружу.
|
||||
4. Использовать отдельного техпользователя 1С с правами чтения.
|
||||
5. Все спорные/рисковые действия маркировать как `manual required`.
|
||||
|
||||
## 8. Подтверждённые доказательства этапа
|
||||
|
||||
### 8.1 Проверка 1: document -> posting -> debit/credit
|
||||
|
||||
- Есть реальная проводка:
|
||||
- документ: `Счет-фактура полученный 00000000001 от 03.08.2030 12:00:00`
|
||||
- Дт: `68.02`
|
||||
- Кт: `19.04`
|
||||
- сумма: `500`
|
||||
- Документ прочитан по ссылке через `get_object_by_link`.
|
||||
|
||||
### 8.2 Проверка 2: posting -> subconto[1..3]
|
||||
|
||||
Есть реальные примеры:
|
||||
|
||||
- `Контрагент + Договор`:
|
||||
- `СубконтоКт1 (Контрагенты)` = `Ассоциация "СРО"СОВЕТ ПРОЕКТИРОВЩИКОВ"`
|
||||
- `СубконтоКт2 (Договоры)` = `дело А40-201628/21`
|
||||
- `Номенклатура/склад`:
|
||||
- `СубконтоКт1 (Номенклатура)` = `Портьерные шторы Garden kolor`
|
||||
- `СубконтоКт3 (Склады)` = `Основной склад`
|
||||
|
||||
### 8.3 Проверка 3: объяснение сальдо движениями
|
||||
|
||||
По счёту `68.02`:
|
||||
|
||||
- `СальдоИтого (Остатки) = 28363.8`
|
||||
- `ОборотДт - ОборотКт = 49600886.74 - 49572522.94 = 28363.8`
|
||||
- `delta = 0.0`
|
||||
|
||||
## 9. Риски и технический долг
|
||||
|
||||
1. Heavy analytics latency
|
||||
- На очень широких задачах модель вынуждена собирать картину по частям.
|
||||
|
||||
2. Отсутствие материализованной витрины
|
||||
- Нет быстрого “единый срез по компании” без серии запросов.
|
||||
|
||||
3. Нюанс кодировки
|
||||
- В отдельных ответах (`get_link_of_object`) требуется нормализация строки ссылки.
|
||||
|
||||
4. Риск регресса через опасные инструменты
|
||||
- `execute_code` существует в toolkit и должен быть процедурно/технически заблокирован в operational потоке.
|
||||
|
||||
## 10. Решения, принятые по итогу этапа
|
||||
|
||||
1. Оставляем `OData` как базовый read-only широкий слой.
|
||||
2. `1c-mcp-toolkit` фиксируем как рабочий runtime/deeper слой для семантических проверок и интерактивной аналитики.
|
||||
3. Статус внедрения: `adopt with restrictions`.
|
||||
|
||||
## 11. Что делаем следующим этапом
|
||||
|
||||
Этап 2 (production-hardening):
|
||||
|
||||
1. Ввести жёсткие технические guardrails на запрет `execute_code`.
|
||||
2. Формализовать query-профили (шаблоны безопасных read-only запросов).
|
||||
3. Добавить слой агрегатов/плановых снэпшотов для тяжёлой аналитики.
|
||||
4. Настроить эксплуатационный регламент:
|
||||
- health-check;
|
||||
- контроль channel;
|
||||
- таймауты;
|
||||
- логирование и аудит вызовов.
|
||||
|
||||
## 12. Список ключевых артефактов этапа
|
||||
|
||||
- `X:\1C\NDC_1C\docs\toolkit_inventory.md`
|
||||
- `X:\1C\NDC_1C\docs\toolkit_install_runbook.md`
|
||||
- `X:\1C\NDC_1C\docs\toolkit_smoke_test_report.md`
|
||||
- `X:\1C\NDC_1C\docs\toolkit_semantic_probe_report.md`
|
||||
- `X:\1C\NDC_1C\docs\toolkit_decision_note.md`
|
||||
- `X:\1C\NDC_1C\docs\snapshots\toolkit\semantic_probe_live_summary.json`
|
||||
|
||||
---
|
||||
|
||||
Stage считаем зафиксированным на дату `2026-03-23`:
|
||||
**Live read-only bridge подтверждён, критические бухгалтерские цепочки доказаны, архитектурный статус — `adopt with restrictions`.**
|
||||
@@ -0,0 +1,26 @@
|
||||
# 2020 экспорт: состав выгрузки
|
||||
|
||||
Папка собрана автоматически для ручного анализа текущего состояния.
|
||||
|
||||
## Файлы
|
||||
|
||||
1. `01_ontology_mapping_layer.md` — текущая онтология/мэппинг и метрики среза.
|
||||
2. `02_canonical_relation_rules.md` — правила построения canonical relations.
|
||||
3. `03_snapshot_fragment_problem_cases.json` — проблемный фрагмент snapshot июня 2020.
|
||||
4. `04_samples_SpisanieSRaschetnogoScheta.json` — реальные записи по `СписаниеСРасчетногоСчета`.
|
||||
5. `05_samples_RealizaciyaTovarovUslug.json` — реальные записи по `РеализацияТоваровУслуг`.
|
||||
6. `06_samples_PostuplenieTovarovUslug.json` — реальные записи по `ПоступлениеТоваровУслуг`.
|
||||
7. `07_samples_DocumentJournals.json` — реальные записи по журналам документов.
|
||||
8. `08_samples_NDS_registers.json` — реальные записи по НДС-регистрам.
|
||||
9. `09_samples_key_fields_Recorder_Ref_Supplier_Buyer_Responsible.json` — записи с ключевыми полями.
|
||||
|
||||
## Ключевые поля: фактическая встречаемость в snapshot
|
||||
|
||||
| field | count |
|
||||
| --- | --- |
|
||||
| Ответственный_Key | 187 |
|
||||
| Ref | 168 |
|
||||
| Recorder | 147 |
|
||||
| Ref_Key | 93 |
|
||||
| Поставщик_Key | 78 |
|
||||
| Покупатель_Key | 46 |
|
||||
@@ -0,0 +1,96 @@
|
||||
# Текущая онтология / mapping-слой
|
||||
|
||||
Дата экспорта: 2026-03-23T10:23:29.088258+00:00
|
||||
Источник snapshot: `X:\1C\NDC_1C\logs\pre_report_snapshot_2020_2020-06_semantic_v2.json`
|
||||
|
||||
## Что считается сущностями сейчас
|
||||
|
||||
Базовая модель (canonical classes):
|
||||
- `CanonicalEntity`
|
||||
- `Organization`
|
||||
- `Counterparty`
|
||||
- `Contract`
|
||||
- `Account`
|
||||
- `Subconto`
|
||||
- `ResponsiblePerson`
|
||||
- `Currency`
|
||||
- `Warehouse`
|
||||
- `CashflowArticle`
|
||||
- `Department`
|
||||
- `Individual`
|
||||
- `Item`
|
||||
- `BankAccount`
|
||||
- `Document`
|
||||
- `InvoiceDocument`
|
||||
- `Posting`
|
||||
- `RegisterMovement`
|
||||
- `RegisterRecord`
|
||||
- `Period`
|
||||
|
||||
## Срез июня 2020: покрытие сущностей
|
||||
|
||||
- Отобранный период: `2020-06`
|
||||
- Диапазон: `2020-06-01T00:00:00+00:00 -> 2020-07-01T00:00:00+00:00`
|
||||
- Записей в slice: `409`
|
||||
- Связей в slice: `2011`
|
||||
- Entity sets: `42`
|
||||
- Записей с `source_id=unknown`: `0`
|
||||
|
||||
### Распределение entity sets по canonical-классам
|
||||
|
||||
| Canonical class | Entity set count |
|
||||
| --- | --- |
|
||||
| Account | 3 |
|
||||
| Document | 28 |
|
||||
| Individual | 1 |
|
||||
| InvoiceDocument | 2 |
|
||||
| RegisterRecord | 8 |
|
||||
|
||||
### Топ target_entity в links
|
||||
|
||||
| target_entity | count |
|
||||
| --- | --- |
|
||||
| Document | 458 |
|
||||
| Counterparty | 440 |
|
||||
| Organization | 434 |
|
||||
| Account | 217 |
|
||||
| Currency | 158 |
|
||||
| ResponsiblePerson | 112 |
|
||||
| Unknown | 102 |
|
||||
| BankAccount | 30 |
|
||||
| Individual | 22 |
|
||||
| Department | 18 |
|
||||
| Warehouse | 12 |
|
||||
| Contract | 7 |
|
||||
| Item | 1 |
|
||||
|
||||
### Топ relation в links
|
||||
|
||||
| relation | count |
|
||||
| --- | --- |
|
||||
| journal_refers_to_document | 168 |
|
||||
| journal_organization | 168 |
|
||||
| reference | 165 |
|
||||
| register_relates_to_organization | 148 |
|
||||
| register_recorded_by_document | 147 |
|
||||
| document_has_counterparty | 139 |
|
||||
| document_line_has_account | 136 |
|
||||
| journal_counterparty | 133 |
|
||||
| register_relates_to_invoice | 124 |
|
||||
| document_belongs_to_organization | 118 |
|
||||
| journal_has_currency | 95 |
|
||||
| register_relates_to_supplier | 78 |
|
||||
| register_relates_to_account | 77 |
|
||||
| document_has_currency | 63 |
|
||||
| document_has_responsible | 57 |
|
||||
| journal_responsible | 55 |
|
||||
| register_relates_to_buyer | 46 |
|
||||
| journal_bank_account | 30 |
|
||||
| register_relates_to_individual | 21 |
|
||||
| register_relates_to_department | 18 |
|
||||
|
||||
### Качество типизации связей
|
||||
|
||||
- Всего связей: `2011`
|
||||
- Связей с `target_entity=Unknown`: `102`
|
||||
- Доля unknown: `5.07%`
|
||||
@@ -0,0 +1,32 @@
|
||||
# Текущие canonical relation rules
|
||||
|
||||
Источник: `canonical_layer/mappers.py`
|
||||
|
||||
## Текущий каталог semantic relations
|
||||
|
||||
| Context | Field role | Relation |
|
||||
| --- | --- | --- |
|
||||
| register | recorder | register_recorded_by_document |
|
||||
| journal | ref | journal_refers_to_document |
|
||||
| document | counterparty | document_has_counterparty |
|
||||
| document | contract | document_has_contract |
|
||||
| document | organization | document_belongs_to_organization |
|
||||
| document | responsible | document_has_responsible |
|
||||
| document | currency | document_has_currency |
|
||||
| document | warehouse | document_has_warehouse |
|
||||
| document | cashflow_article | document_has_cashflow_article |
|
||||
| document | bank_account | document_has_bank_account |
|
||||
| register | supplier | register_relates_to_supplier |
|
||||
| register | buyer | register_relates_to_buyer |
|
||||
| register | invoice | register_relates_to_invoice |
|
||||
| register | contract | register_relates_to_contract |
|
||||
| register | organization | register_relates_to_organization |
|
||||
| register | account | register_relates_to_account |
|
||||
| register | item | register_relates_to_item |
|
||||
|
||||
## Базовые правила извлечения ссылок
|
||||
|
||||
1. Поле попадает в link, если это `_Key`, `*ref`, GUID или semantic-поле (например `Recorder`, `СчетФактура`).
|
||||
2. `*_Type` используется как приоритетная подсказка типа target-сущности.
|
||||
3. Нулевые GUID (`00000000-...`) отфильтровываются из canonical links.
|
||||
4. Если `source_id` отсутствует, строится составной `cmp:<sha1>` ключ.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+8753
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,435 @@
|
||||
# MVP PROD ARCH Report #3: Stage 1-7 (AS-IS + Runbook)
|
||||
|
||||
Дата фиксации: 2026-03-23
|
||||
Проект: NDC 1C analytics bridge
|
||||
Контур: локальный стенд Windows + 1С + Miniconda
|
||||
Статус: **MVP контур Stage 1-7 поднят, Stage 7 частично (спецификация + API-роуты, без полного orchestration-сервиса в прод-режиме)**
|
||||
|
||||
---
|
||||
|
||||
## 1. Executive summary
|
||||
|
||||
На текущем этапе мы имеем рабочую многоуровневую read-only архитектуру:
|
||||
|
||||
`1C Source -> Runtime Bridge -> Refresh/Canonical Store -> Feature/Anomaly -> Risk -> API Layer`
|
||||
|
||||
Что подтверждено фактически:
|
||||
|
||||
1. Runtime bridge к живой 1С доказан и стабилен в read-only режиме.
|
||||
2. Три жесткие бухгалтерские проверки закрыты как `PROVEN`.
|
||||
3. Реализован и протестирован Layer 3/4: refresh + canonical store.
|
||||
4. Реализован и протестирован Layer 5: feature/anomaly engine.
|
||||
5. Реализован и протестирован Layer 6: risk engine.
|
||||
6. По Layer 7 есть orchestration-spec и техническая поверхность API, но полноценный production-orchestrator (планировщик/роутер/политики исполнения) еще в roadmap.
|
||||
|
||||
---
|
||||
|
||||
## 2. Архитектура на текущем этапе
|
||||
|
||||
### 2.1 High-level
|
||||
|
||||
```text
|
||||
1С (source of truth, read-only)
|
||||
-> toolkit bridge / OData read
|
||||
-> Refresh Engine (historical/incremental/targeted)
|
||||
-> Canonical Store (entities + links + checkpoints + run logs)
|
||||
-> Feature Engine (derived metrics + anomaly signals)
|
||||
-> Risk Engine (domain patterns + global risk score)
|
||||
-> FastAPI endpoints for integration with assistant/orchestrator
|
||||
```
|
||||
|
||||
### 2.2 Runtime bridge (live)
|
||||
|
||||
Базовая связка:
|
||||
|
||||
- Proxy: `onec_mcp_toolkit_proxy` (`http://127.0.0.1:6003`)
|
||||
- 1С обработка: `MCP_Toolkit.epf` в режиме `Прокси`
|
||||
- Канал: long polling (`/1c/poll`, `/1c/result`)
|
||||
|
||||
Важно:
|
||||
|
||||
- Это **live request/response**, не snapshot-реплика.
|
||||
- Для тяжелой аналитики используется выделенный store-слой, а не прямой проход LLM по всей базе 1С.
|
||||
|
||||
---
|
||||
|
||||
## 3. Stage-by-stage статус (1-7)
|
||||
|
||||
## Stage 1. Runtime bridge + guardrails
|
||||
|
||||
Статус: **DONE (MVP)**
|
||||
Артефакты:
|
||||
|
||||
- `docs/ARCH/2 - architecture_stage_report_2026-03-23.md`
|
||||
- `docs/toolkit_install_runbook.md`
|
||||
- `docs/toolkit_smoke_test_report.md`
|
||||
- `docs/toolkit_semantic_probe_report.md`
|
||||
|
||||
Ключевой результат:
|
||||
|
||||
- Подтвержден live read-only мост через `1c-mcp-toolkit`.
|
||||
- Статус принятия: `adopt with restrictions`.
|
||||
|
||||
## Stage 2. Canonical schema
|
||||
|
||||
Статус: **DONE (MVP)**
|
||||
Артефакт:
|
||||
|
||||
- `docs/accounting_canonical_schema.md`
|
||||
|
||||
Реализация:
|
||||
|
||||
- `canonical_entities`
|
||||
- `canonical_links`
|
||||
- JSON-атрибуты + нормализованные связи.
|
||||
|
||||
## Stage 3. Historical loader
|
||||
|
||||
Статус: **DONE (MVP)**
|
||||
Артефакт:
|
||||
|
||||
- `docs/historical_load_plan.md`
|
||||
|
||||
Реализация:
|
||||
|
||||
- режим `historical` в `scripts/run_refresh.py`.
|
||||
|
||||
## Stage 4. Incremental refresh
|
||||
|
||||
Статус: **DONE (MVP)**
|
||||
Артефакты:
|
||||
|
||||
- `docs/refresh_strategy.md`
|
||||
- `docs/incremental_refresh_plan.md`
|
||||
|
||||
Реализация:
|
||||
|
||||
- режимы `incremental`, `targeted`
|
||||
- таблицы `refresh_runs`, `refresh_checkpoints`
|
||||
- run-status: `success/partial_success/failed`
|
||||
|
||||
## Stage 5. Feature / anomaly engine
|
||||
|
||||
Статус: **DONE (MVP)**
|
||||
Артефакты:
|
||||
|
||||
- `docs/analytics_store_design.md`
|
||||
- `docs/anomaly_engine_spec.md`
|
||||
|
||||
Реализация:
|
||||
|
||||
- `feature_runs`
|
||||
- `feature_metrics`
|
||||
- `anomaly_signals`
|
||||
- API: `/features/*`
|
||||
|
||||
## Stage 6. Risk engine
|
||||
|
||||
Статус: **DONE (MVP)**
|
||||
Артефакт:
|
||||
|
||||
- `docs/risk_engine_spec.md`
|
||||
|
||||
Реализация:
|
||||
|
||||
- `risk_runs`
|
||||
- `risk_patterns`
|
||||
- domain-level risk patterns
|
||||
- `global_risk_summary`
|
||||
- API: `/risk/*`
|
||||
|
||||
## Stage 7. Assistant orchestration
|
||||
|
||||
Статус: **PARTIAL (spec + API-ready surface)**
|
||||
Артефакты:
|
||||
|
||||
- `docs/assistant_orchestration_spec.md`
|
||||
- `docs/security_guardrails_readonly.md`
|
||||
|
||||
Состояние:
|
||||
|
||||
- спецификация маршрутизации готова;
|
||||
- runtime endpoints для refresh/features/risk готовы;
|
||||
- полноценный orchestration-service с scheduler/policy execution — **еще не реализован как отдельный прод-компонент**.
|
||||
|
||||
---
|
||||
|
||||
## 4. Deliverables check (архитектурный комплект)
|
||||
|
||||
На дату 2026-03-23 все 8 целевых deliverables присутствуют в `docs/`:
|
||||
|
||||
1. `accounting_canonical_schema.md`
|
||||
2. `analytics_store_design.md`
|
||||
3. `refresh_strategy.md`
|
||||
4. `historical_load_plan.md`
|
||||
5. `incremental_refresh_plan.md`
|
||||
6. `anomaly_engine_spec.md`
|
||||
7. `assistant_orchestration_spec.md`
|
||||
8. `security_guardrails_readonly.md`
|
||||
|
||||
---
|
||||
|
||||
## 5. Текущее окружение и зависимости
|
||||
|
||||
## 5.1 ОС и инструменты
|
||||
|
||||
- Windows (локальный стенд)
|
||||
- 1С платформа: `8.3.27.1936`
|
||||
- База: Бухгалтерия предприятия 2.0 (лабораторный контур)
|
||||
- Python: `3.12.10` (технический интерпретатор машины)
|
||||
- Miniconda env проекта: `ndc_1c_mvp`
|
||||
- Miniconda env toolkit proxy: `ndc_1c_toolkit` (для bridge-контура)
|
||||
|
||||
## 5.2 Python зависимости проекта
|
||||
|
||||
`requirements.txt`:
|
||||
|
||||
- `fastapi>=0.116.0`
|
||||
- `odata1cw>=0.0.4`
|
||||
- `pydantic>=2.11.0`
|
||||
- `pytest>=8.3.5`
|
||||
- `python-dotenv>=1.1.0`
|
||||
- `requests>=2.32.0`
|
||||
- `SQLAlchemy>=2.0.38`
|
||||
- `uvicorn>=0.35.0`
|
||||
|
||||
## 5.3 Ключевые env-параметры
|
||||
|
||||
Из `.env.example`:
|
||||
|
||||
- `CANONICAL_DB_URL=sqlite:///X:/1C/NDC_1C/data/canonical_store.db`
|
||||
- `REFRESH_DEFAULT_LIMIT_PER_SET=200`
|
||||
- `FEATURE_BASELINE_WINDOW_HOURS=24`
|
||||
- `ANOMALY_STALE_REFRESH_THRESHOLD_HOURS=6`
|
||||
- `FEATURE_ENTITY_SCAN_LIMIT=200000`
|
||||
- `RISK_MEDIUM_THRESHOLD=0.45`
|
||||
- `RISK_HIGH_THRESHOLD=0.75`
|
||||
- `RISK_ANOMALY_SCAN_LIMIT=5000`
|
||||
|
||||
---
|
||||
|
||||
## 6. Полный запуск системы с нуля (на новой машине)
|
||||
|
||||
## 6.1 Bootstrap bridge-контура (1С + proxy)
|
||||
|
||||
1. Установить 1С платформу и подготовить тестовую базу (read-only пользователь).
|
||||
2. Установить Miniconda и Git.
|
||||
3. Подготовить toolkit и env:
|
||||
|
||||
```powershell
|
||||
git clone https://github.com/ROCTUP/1c-mcp-toolkit X:\1C\NDC_1C\external\1c-mcp-toolkit
|
||||
& 'C:\Users\<USER>\miniconda3\Scripts\conda.exe' create -y -n ndc_1c_toolkit python=3.11
|
||||
& 'C:\Users\<USER>\miniconda3\envs\ndc_1c_toolkit\python.exe' -m pip install -r X:\1C\NDC_1C\external\1c-mcp-toolkit\requirements.txt
|
||||
```
|
||||
|
||||
4. Запустить proxy:
|
||||
|
||||
```powershell
|
||||
$env:PORT='6003'
|
||||
$env:TIMEOUT='180'
|
||||
$env:ALLOW_DANGEROUS_WITH_APPROVAL='false'
|
||||
$env:ANONYMIZATION_ENABLED='false'
|
||||
$env:RESPONSE_FORMAT='json'
|
||||
$env:LOG_LEVEL='INFO'
|
||||
& 'C:\Users\<USER>\miniconda3\envs\ndc_1c_toolkit\python.exe' -m onec_mcp_toolkit_proxy
|
||||
```
|
||||
|
||||
5. Проверить health:
|
||||
|
||||
```powershell
|
||||
Invoke-WebRequest http://127.0.0.1:6003/health -UseBasicParsing
|
||||
```
|
||||
|
||||
6. В 1С:Предприятии открыть:
|
||||
|
||||
`X:\1C\NDC_1C\external\1c-mcp-toolkit\build\MCP_Toolkit.epf`
|
||||
|
||||
7. В форме выставить:
|
||||
|
||||
- режим: `Прокси`
|
||||
- сервер: `http://127.0.0.1:6003`
|
||||
- channel: `default`
|
||||
- нажать `Подключиться`
|
||||
|
||||
## 6.2 Bootstrap аналитического контура (NDC_1C)
|
||||
|
||||
1. Подготовить проектную среду:
|
||||
|
||||
```powershell
|
||||
cd X:\1C\NDC_1C
|
||||
& 'C:\Users\<USER>\miniconda3\Scripts\conda.exe' create -y -n ndc_1c_mvp python=3.11
|
||||
& 'C:\Users\<USER>\miniconda3\envs\ndc_1c_mvp\python.exe' -m pip install -r requirements.txt
|
||||
copy .env.example .env
|
||||
```
|
||||
|
||||
2. Настроить `.env` (минимум: `ONEC_INFOBASE`, `ONEC_USERNAME`, `ONEC_PASSWORD`).
|
||||
|
||||
3. Запустить API:
|
||||
|
||||
```powershell
|
||||
& 'C:\Users\<USER>\miniconda3\envs\ndc_1c_mvp\python.exe' -m uvicorn canonical_layer.app:app --host 127.0.0.1 --port 8000 --reload
|
||||
```
|
||||
|
||||
4. Запустить data-pipeline:
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File .\scripts\run_refresh.ps1 -Mode incremental
|
||||
powershell -ExecutionPolicy Bypass -File .\scripts\run_features.ps1 -Strict
|
||||
powershell -ExecutionPolicy Bypass -File .\scripts\run_risk.ps1 -Strict
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Операционный runbook (ежедневный цикл)
|
||||
|
||||
Старт:
|
||||
|
||||
1. Поднять bridge proxy и проверить `/health`.
|
||||
2. Подключить `MCP_Toolkit.epf` в 1С.
|
||||
3. Выполнить refresh -> features -> risk.
|
||||
4. Проверить API/хранилища:
|
||||
- `/store/stats`
|
||||
- `/features/stats`
|
||||
- `/risk/stats`
|
||||
|
||||
Стоп:
|
||||
|
||||
1. Отключить toolkit в 1С.
|
||||
2. Закрыть 1С.
|
||||
3. Остановить proxy/API (Ctrl+C).
|
||||
|
||||
---
|
||||
|
||||
## 8. Реально полученные результаты (фактические прогоны)
|
||||
|
||||
Ниже — выдержки из последних реальных прогонов (`logs/*.json`) на дату отчета.
|
||||
|
||||
## 8.1 Refresh (incremental)
|
||||
|
||||
Источник: `logs/refresh_last_run.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"run_id": "7414d9b93c964b589bb863952a027f5e",
|
||||
"mode": "incremental",
|
||||
"status": "success",
|
||||
"records_read": 4,
|
||||
"entities_written": 4,
|
||||
"links_written": 10,
|
||||
"checkpoints_updated": 2
|
||||
}
|
||||
```
|
||||
|
||||
## 8.2 Feature engine
|
||||
|
||||
Источник: `logs/features_last_run.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"run_id": "8c311e26916146579e97e110b2243a34",
|
||||
"status": "success",
|
||||
"entities_total": 2,
|
||||
"metrics_written": 19,
|
||||
"anomalies_written": 0
|
||||
}
|
||||
```
|
||||
|
||||
## 8.3 Risk engine
|
||||
|
||||
Источник: `logs/risk_last_run.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"run_id": "fbad845fdfd64de8a73e35d4da6274e4",
|
||||
"status": "success",
|
||||
"patterns_written": 1,
|
||||
"global_score": 0.05,
|
||||
"risk_patterns": [
|
||||
{
|
||||
"pattern_key": "global_risk_summary",
|
||||
"severity": "low"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 8.4 Текущее состояние SQLite store (факт)
|
||||
|
||||
Снимок на момент отчета:
|
||||
|
||||
- `canonical_store.db` существует, размер `86016` байт
|
||||
- `canonical_entities=2`
|
||||
- `canonical_links=10`
|
||||
- `refresh_runs=3`
|
||||
- `refresh_checkpoints=2`
|
||||
- `feature_runs=3`
|
||||
- `feature_metrics=61`
|
||||
- `anomaly_signals=0`
|
||||
- `risk_runs=1`
|
||||
- `risk_patterns=1`
|
||||
|
||||
## 8.5 Тестовый статус
|
||||
|
||||
Фактический запуск:
|
||||
|
||||
```text
|
||||
python -m pytest -q
|
||||
....... [100%]
|
||||
7 passed in 1.86s
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. API-поверхность на текущем этапе
|
||||
|
||||
Реализованные endpoints:
|
||||
|
||||
- `GET /health`
|
||||
- `GET /metadata/entity-sets`
|
||||
- `GET /documents`
|
||||
- `GET /documents/{document_id}`
|
||||
- `GET /postings`
|
||||
- `GET /counterparties/{counterparty_id}/documents`
|
||||
- `GET /graph/document/{document_id}`
|
||||
- `GET /store/stats`
|
||||
- `GET /refresh/runs`
|
||||
- `POST /refresh/run`
|
||||
- `GET /features/stats`
|
||||
- `GET /features/runs`
|
||||
- `GET /features/metrics`
|
||||
- `GET /features/anomalies`
|
||||
- `POST /features/run`
|
||||
- `GET /risk/stats`
|
||||
- `GET /risk/runs`
|
||||
- `GET /risk/patterns`
|
||||
- `POST /risk/run`
|
||||
|
||||
---
|
||||
|
||||
## 10. Ограничения и интерпретация текущих цифр
|
||||
|
||||
1. Низкий текущий риск (`global_score=0.05`) и отсутствие аномалий отражают **малый текущий объем данных в store**, а не финальную “безрисковость” компании.
|
||||
2. Stage 7 закрыт документно и по API-ready поверхности, но production-orchestration (policy engine + scheduler + retry orchestration) еще нужно реализовать отдельным сервисом.
|
||||
3. SQLite используется как MVP-носитель; для прод-контуров нужен PostgreSQL + миграции + эксплуатационные политики.
|
||||
|
||||
---
|
||||
|
||||
## 11. Что осталось до “MVP production hardening”
|
||||
|
||||
1. Реализовать полноценный orchestration-service (Stage 7 runtime).
|
||||
2. Добавить планировщик и регламенты (`refresh/features/risk`) с retry и алертингом.
|
||||
3. Вынести store на PostgreSQL, добавить индексы/миграции.
|
||||
4. Усилить auth/секреты/сетевые ограничения API.
|
||||
5. Провести калибровку risk/feature правил на расширенном реальном срезе данных.
|
||||
|
||||
---
|
||||
|
||||
## 12. Итог
|
||||
|
||||
На дату **2026-03-23** архитектурный MVP-контур **Stage 1-7** зафиксирован как:
|
||||
|
||||
- Stage 1-6: реализованы и подтверждены фактическими прогонами;
|
||||
- Stage 7: реализован на уровне спецификации и API-операций, но требует выделенного runtime orchestration для production-ready режима.
|
||||
|
||||
Проект технически готов к следующему шагу: **production-hardening + orchestration implementation**.
|
||||
|
||||
@@ -0,0 +1,319 @@
|
||||
# AI First Layer GUI — Подробный гайд пользователя
|
||||
|
||||
Дата: 23.03.2026
|
||||
Контур: `X:\1C\NDC_1C\llm_normalizer`
|
||||
Назначение: локальный GUI и backend для нормализации бухгалтерских запросов через OpenAI token
|
||||
|
||||
---
|
||||
|
||||
## 1. Что это за система
|
||||
|
||||
`AI First Layer GUI` — это не чат-бот с финальными бухгалтерскими ответами.
|
||||
Это **semantic front-end**: слой, который переводит живой запрос бухгалтера в строгий структурированный JSON (`normalized_query_v1`), чтобы дальше этот JSON использовал deterministic router/оркестрация.
|
||||
|
||||
Цепочка:
|
||||
|
||||
`Пользователь -> GUI -> backend-proxy -> OpenAI Responses API -> normalized JSON -> route_hint summary -> trace/history`
|
||||
|
||||
---
|
||||
|
||||
## 2. Из чего состоит система
|
||||
|
||||
1. `frontend` (React + TypeScript + Vite) — русифицированный UI.
|
||||
2. `backend` (Node.js + Express) — прокси к OpenAI, валидация схемы, trace/eval.
|
||||
3. `data/traces` — история нормализаций.
|
||||
4. `data/presets` — сохраненные prompt-пресеты.
|
||||
5. `data/eval_cases` — eval-кейсы и отчеты.
|
||||
|
||||
---
|
||||
|
||||
## 3. Быстрый запуск
|
||||
|
||||
### 3.1 Рекомендуемый способ (из одной папки в VS Code)
|
||||
|
||||
Открой папку:
|
||||
|
||||
`X:\1C\NDC_1C\llm_normalizer`
|
||||
|
||||
Дальше:
|
||||
|
||||
1. `Terminal -> Run Task -> NDC: Install All` (первый запуск).
|
||||
2. `Terminal -> Run Task -> NDC: Dev All (Backend + Frontend)`.
|
||||
|
||||
Открой:
|
||||
|
||||
- GUI: `http://localhost:5174`
|
||||
- Backend health: `http://localhost:8787/api/health`
|
||||
|
||||
### 3.2 Терминалом (без Tasks)
|
||||
|
||||
```powershell
|
||||
cd X:\1C\NDC_1C\llm_normalizer
|
||||
start-dev.cmd
|
||||
```
|
||||
|
||||
или:
|
||||
|
||||
```powershell
|
||||
cd X:\1C\NDC_1C\llm_normalizer
|
||||
npm.cmd run dev:all
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Главный сценарий использования
|
||||
|
||||
1. В панели **Подключение OpenAI** вставь API key и проверь связь.
|
||||
2. В панели **Prompt Manager** выбери/подгрузи preset или отредактируй prompt-ы вручную.
|
||||
3. В панели **Запрос пользователя** вставь живой бухгалтерский вопрос.
|
||||
4. Нажми `Normalize`.
|
||||
5. Проверь результат во вкладках `Normalized JSON`, `Route hint summary`, `Validation`.
|
||||
6. При необходимости сохрани кейс: `Normalize + Save as test case`.
|
||||
7. Открой историю и сравни trace между попытками.
|
||||
|
||||
---
|
||||
|
||||
## 5. Подробно по каждому блоку GUI
|
||||
|
||||
## 5.1 Connection Panel (Подключение OpenAI)
|
||||
|
||||
### Поля
|
||||
|
||||
| Поле | Что вводить | Для чего |
|
||||
|---|---|---|
|
||||
| `OpenAI API Key` | реальный ключ формата `sk-...` | backend использует ключ для вызова Responses API |
|
||||
| `Model ID` | обычно `gpt-4o-mini` | модель normalizer-а |
|
||||
| `Base URL` | обычно `https://api.openai.com/v1` | endpoint OpenAI API |
|
||||
| `Temperature` | чаще `0` или `0.1` | стабильность/вариативность нормализации |
|
||||
| `Max output tokens` | обычно `500-900` | лимит длины ответа модели |
|
||||
|
||||
### Кнопки
|
||||
|
||||
| Кнопка | Что делает |
|
||||
|---|---|
|
||||
| `Сохранить локальную конфигурацию` | сохраняет в localStorage только model/baseUrl/temperature/maxOutputTokens (без API key) |
|
||||
| `Проверить подключение` | вызывает `POST /api/openai/test-connection`, проверяет доступ к модели |
|
||||
|
||||
### Рекомендация на старт
|
||||
|
||||
- `Model ID`: `gpt-4o-mini`
|
||||
- `Temperature`: `0`
|
||||
- `Max output tokens`: `700`
|
||||
|
||||
---
|
||||
|
||||
## 5.2 Prompt Manager
|
||||
|
||||
Это управляемая prompt-архитектура из 3 уровней + служебные поля.
|
||||
|
||||
### Поля
|
||||
|
||||
| Поле | Что писать | Практический смысл |
|
||||
|---|---|---|
|
||||
| `Системный prompt` | жесткие правила поведения модели | запрещает модели давать финальный бизнес-ответ |
|
||||
| `Developer / Instruction prompt` | правила классификации, flags, route_hint | задает “инженерную логику” нормализации |
|
||||
| `Domain prompt` | словарь бухгалтерских формулировок/счетов/паттернов | повышает доменную точность |
|
||||
| `Schema notes` | ограничения схемы, важные enum/required | снижает риск невалидного JSON |
|
||||
| `Few-shot examples` | пары “вопрос -> ожидаемый JSON фрагмент” | стабилизирует поведение на сложных формулировках |
|
||||
|
||||
### Управление пресетами
|
||||
|
||||
| Элемент | Что делает |
|
||||
|---|---|
|
||||
| dropdown `Выберите preset` | список сохраненных пресетов + default |
|
||||
| `Загрузить preset` | подставляет выбранные prompt-ы в поля |
|
||||
| `Сохранить preset` | сохраняет текущие prompt-ы в `data/presets` |
|
||||
| `Diff с предыдущим` | показывает текстовую дельту относительно последнего загруженного |
|
||||
| `Сбросить к default` | возвращает дефолтный набор prompt-ов |
|
||||
|
||||
---
|
||||
|
||||
## 5.3 User Query Panel (Запрос пользователя)
|
||||
|
||||
### Поля
|
||||
|
||||
| Поле | Что вводить | Для чего |
|
||||
|---|---|---|
|
||||
| `Raw user question` | живой вопрос бухгалтера “как есть” | основной вход normalizer-а |
|
||||
| `Optional period context` | период, если хочешь явно подсказать (`2020-06`) | стабилизирует `period_scope` |
|
||||
| `Optional business context` | краткая доп. рамка (например “предзакрытие июня”) | помогает интерпретации |
|
||||
| `Optional expected route` | ожидаемый route для проверки | используется в eval/trace |
|
||||
|
||||
### Переключатель
|
||||
|
||||
| Переключатель | Когда использовать |
|
||||
|---|---|
|
||||
| `Mock-режим (без вызова OpenAI)` | когда тестируешь UI/поток без токена и без внешних запросов |
|
||||
|
||||
### Кнопки
|
||||
|
||||
| Кнопка | Что делает |
|
||||
|---|---|
|
||||
| `Normalize` | запускает нормализацию и возвращает structured output |
|
||||
| `Normalize + Save as test case` | дополнительно сохраняет кейс в `data/eval_cases` |
|
||||
|
||||
---
|
||||
|
||||
## 5.4 Output Panel (вкладки результата)
|
||||
|
||||
| Вкладка | Что показывает | Как использовать |
|
||||
|---|---|---|
|
||||
| `Normalized JSON` | итоговый валидированный JSON | основной артефакт для router |
|
||||
| `Raw model output` | сырой ответ модели | диагностика prompt/schema проблем |
|
||||
| `Route hint summary` | краткий срез intent/route/flags | быстрый контроль маршрутизации |
|
||||
| `Validation` | статус schema validation и ошибки | сразу видно валиден ли контракт |
|
||||
| `Logs` | клиентские события UI | оперативная диагностика шага |
|
||||
|
||||
---
|
||||
|
||||
## 5.5 Runtime Metrics Panel
|
||||
|
||||
Показывает:
|
||||
|
||||
- `trace_id`
|
||||
- `request_started_at`
|
||||
- `request_finished_at`
|
||||
- `latency_ms`
|
||||
- `input_tokens / output_tokens / total_tokens`
|
||||
- `validation_status`
|
||||
- `prompt_version`
|
||||
- `schema_version`
|
||||
|
||||
Как читать:
|
||||
|
||||
1. `validation_status = passed` — можно использовать JSON в downstream пайплайне.
|
||||
2. Если latency резко растет — обычно слишком длинный prompt/few-shot.
|
||||
3. `total_tokens` нужен для контроля стоимости.
|
||||
|
||||
---
|
||||
|
||||
## 5.6 History Panel
|
||||
|
||||
Показывает список прошлых нормализаций:
|
||||
|
||||
- короткий вопрос,
|
||||
- route hint,
|
||||
- validation pass/fail,
|
||||
- модель,
|
||||
- timestamp.
|
||||
|
||||
Клик по записи открывает полный trace (`GET /api/history/:trace_id`) и подгружает данные в Output.
|
||||
|
||||
---
|
||||
|
||||
## 5.7 NDC Run Monitor
|
||||
|
||||
Это отдельный совместимый слой под будущую интеграцию в `dc_node`.
|
||||
|
||||
Что можно делать:
|
||||
|
||||
1. `Запустить run` -> `POST /api/accounting-agent/v1/runs/start`
|
||||
2. `Завершить выбранный run` -> `POST /api/accounting-agent/v1/runs/finish`
|
||||
3. Смотреть список `runs`, их статусы и trace выбранного `runId`.
|
||||
|
||||
Канон статусов:
|
||||
|
||||
`NONE`, `QUEUED`, `RUNNING`, `DONE`, `ERROR`, `STALE`, `CANCELLED`
|
||||
|
||||
---
|
||||
|
||||
## 6. Что и где сохраняется
|
||||
|
||||
| Данные | Где |
|
||||
|---|---|
|
||||
| Traces нормализации | `X:\1C\NDC_1C\llm_normalizer\data\traces` |
|
||||
| Prompt presets | `X:\1C\NDC_1C\llm_normalizer\data\presets` |
|
||||
| Eval cases / reports | `X:\1C\NDC_1C\llm_normalizer\data\eval_cases` |
|
||||
|
||||
Важно:
|
||||
|
||||
1. API key не сохраняется в localStorage.
|
||||
2. API key не возвращается в frontend-ответах.
|
||||
3. В trace ключ редактируется (redacted).
|
||||
|
||||
---
|
||||
|
||||
## 7. Как правильно заполнять поля на практике
|
||||
|
||||
## 7.1 Минимальный рабочий набор
|
||||
|
||||
1. `OpenAI API Key`: вставить валидный ключ.
|
||||
2. `Model ID`: `gpt-4o-mini`.
|
||||
3. `Raw user question`: живой вопрос.
|
||||
4. Остальные поля оставить по default.
|
||||
5. Нажать `Normalize`.
|
||||
|
||||
## 7.2 Если много ошибок в Validation
|
||||
|
||||
1. Уменьши свободу модели: `Temperature = 0`.
|
||||
2. Уточни `Developer prompt` и `Schema notes`.
|
||||
3. Добавь few-shot примеры под твой класс вопросов.
|
||||
4. Повтори `Normalize` и сравни через `History`.
|
||||
|
||||
## 7.3 Если route_hint “плывет”
|
||||
|
||||
1. Явно добавь `expected route` в Query Panel.
|
||||
2. В domain/developer prompt пропиши контр-примеры.
|
||||
3. Сохрани новый preset и гони серию через `POST /api/eval/run`.
|
||||
|
||||
---
|
||||
|
||||
## 8. Частые проблемы и решения
|
||||
|
||||
| Симптом | Причина | Что делать |
|
||||
|---|---|---|
|
||||
| `Ошибка подключения` | ключ неверный/ограничен, неверный base URL | проверить key, model, URL через `Test connection` |
|
||||
| `validation.passed = false` | модель вернула JSON вне схемы | ужесточить prompt, проверить schema notes, повторить |
|
||||
| пустой `Normalized JSON` | parse/validation fail | смотреть `Raw model output` + `Validation` |
|
||||
| высокая latency | слишком тяжелые prompt/few-shot | сократить prompt и few-shot |
|
||||
| VS Code не стартует npm | PowerShell policy в Windows | использовать `npm.cmd` и готовые Tasks |
|
||||
|
||||
---
|
||||
|
||||
## 9. API-карта (для интеграции)
|
||||
|
||||
Normalizer:
|
||||
|
||||
- `POST /api/openai/test-connection`
|
||||
- `POST /api/normalize`
|
||||
- `POST /api/eval/run`
|
||||
- `GET /api/history`
|
||||
- `GET /api/history/:trace_id`
|
||||
- `POST /api/presets/save`
|
||||
- `GET /api/presets`
|
||||
|
||||
NDC Integration namespace:
|
||||
|
||||
- `POST /api/accounting-agent/v1/runs/start`
|
||||
- `POST /api/accounting-agent/v1/runs/finish`
|
||||
- `GET /api/accounting-agent/v1/runs`
|
||||
- `GET /api/accounting-agent/v1/runs/:runId`
|
||||
- `POST /api/accounting-agent/v1/tasks/enqueue`
|
||||
- `POST /api/accounting-agent/v1/tasks/claim`
|
||||
- `POST /api/accounting-agent/v1/tasks/:taskId/complete`
|
||||
- `POST /api/accounting-agent/v1/tasks/:taskId/error`
|
||||
- `GET /api/accounting-agent/v1/results`
|
||||
- `GET /api/accounting-agent/v1/trace/run/:runId`
|
||||
- `GET /api/accounting-agent/v1/health`
|
||||
|
||||
---
|
||||
|
||||
## 10. Чек-лист перед рабочей сессией
|
||||
|
||||
1. Backend и frontend подняты.
|
||||
2. `Test connection` успешен.
|
||||
3. Выбран корректный preset.
|
||||
4. Запрос содержит минимум необходимого контекста (вопрос + период при необходимости).
|
||||
5. После `Normalize` проверен `Validation`.
|
||||
6. Trace сохранен и виден в History.
|
||||
|
||||
---
|
||||
|
||||
## 11. Главное правило эксплуатации
|
||||
|
||||
`LLM в этом контуре — нормализатор, а не исполнитель бизнес-логики.`
|
||||
|
||||
То есть:
|
||||
|
||||
1. LLM структурирует, классифицирует, предлагает route hint.
|
||||
2. Финальные бухгалтерские выводы и оркестрация остаются в основном контуре NDC.
|
||||
@@ -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).
|
||||
|
||||
@@ -0,0 +1,679 @@
|
||||
# Assistant Mode Global Status Report
|
||||
|
||||
Date: 2026-03-24
|
||||
Scope: `llm_normalizer` + Assistant Mode pipeline + retrieval/explainability contours
|
||||
Prepared for: architectural checkpoint and next-step planning
|
||||
|
||||
## 0) Executive Summary
|
||||
|
||||
Current system is no longer a raw route demo: we now have a working end-to-end assistant loop with decomposition, routing, retrieval, grounding, explainable response shaping, session logging, and regression tests.
|
||||
|
||||
At the same time, the system is still not a full accountant-grade investigation assistant. Main reason: data/model/retrieval unit depth is still below causal accounting reasoning depth in several domains.
|
||||
|
||||
Key status snapshot:
|
||||
|
||||
- Backend build/tests: `tsc` OK, `vitest` OK (`25/25` tests passed).
|
||||
- Explainable contract: implemented (`requirements`, `coverage_report`, `answer_grounding_check`, explainable reply sections).
|
||||
- Retrieval-layer upgrade: `executeHybrid` moved from `GUID-or-full-scan` to semantic profile + semantic narrowing.
|
||||
- Proven narrowing example: for bank mismatch query with accounts `51/60`, narrowing reduced records from `262` to `75`.
|
||||
- Proven limitation: for generic cross-entity chain query without explicit account scope, narrowing still wide (`262` to `242`), so answer quality can remain too broad.
|
||||
|
||||
---
|
||||
|
||||
## 1) Data Contour
|
||||
|
||||
### 1.1 How it works now
|
||||
|
||||
- Assistant retrieval reads local snapshot bundle from `docs/ARCH/2020экспорт`.
|
||||
- Main files currently loaded in executor:
|
||||
- `03_snapshot_fragment_problem_cases.json`
|
||||
- `04_samples_SpisanieSRaschetnogoScheta.json`
|
||||
- `05_samples_RealizaciyaTovarovUslug.json`
|
||||
- `06_samples_PostuplenieTovarovUslug.json`
|
||||
- `07_samples_DocumentJournals.json`
|
||||
- `08_samples_NDS_registers.json`
|
||||
- `09_samples_key_fields_Recorder_Ref_Supplier_Buyer_Responsible.json`
|
||||
- Data access is read-only snapshot, not live 1C state.
|
||||
|
||||
### 1.2 What works
|
||||
|
||||
- Documents/journals/register records are available with links and key attributes.
|
||||
- Counterparty/document linkage and part of relation topology are usable.
|
||||
- Enough depth exists for POC-level chain/risk analysis and explainable evidence pack.
|
||||
|
||||
### 1.3 Constraints
|
||||
|
||||
- Live truth is absent in assistant retrieval path (snapshot-only).
|
||||
- Lifecycle/status semantics are incomplete and partly heuristic.
|
||||
- Some accounting contexts are represented as flattened fields instead of normalized graph nodes.
|
||||
|
||||
### 1.4 What assistant cannot do because of this
|
||||
|
||||
- Guarantee real-time explanation of current accounting state.
|
||||
- Reliably prove deep causal accounting chains in all domains (especially where lifecycle semantics are implicit).
|
||||
|
||||
### 1.5 Symptoms already seen in dialogs
|
||||
|
||||
- Repeated top entities across semantically different but broad queries.
|
||||
- “Looks relevant” answers with weak differentiating evidence for some generic prompts.
|
||||
|
||||
### 1.6 Local changes needed
|
||||
|
||||
- Add richer field extraction/parsing from snapshot for account/document/lifecycle signals.
|
||||
- Enforce tighter domain-specific filters for low-specificity queries.
|
||||
|
||||
### 1.7 Architectural changes needed
|
||||
|
||||
- Add live data bridge layer for on-demand truth check (hybrid snapshot + live drilldown).
|
||||
- Add normalized accounting graph storage layer for causal traversal.
|
||||
|
||||
### 1.8 Priority
|
||||
|
||||
- `P0`: stronger retrieval constraints and lifecycle signal extraction.
|
||||
- `P1`: live bridge for targeted verification.
|
||||
- `P2`: full graph-backed data model.
|
||||
|
||||
---
|
||||
|
||||
## 2) Ontology / Domain Model Contour
|
||||
|
||||
### 2.1 How it works now
|
||||
|
||||
- Entity/relation semantics exist as retrieval profile vocabulary plus heuristic signal extraction.
|
||||
- Domain labels include bank/suppliers/customers/VAT/fixed_assets/deferred_expense/period_close/settlements.
|
||||
- Relation patterns include:
|
||||
- `payment_to_settlement`
|
||||
- `document_to_posting`
|
||||
- `statement_to_document`
|
||||
- `asset_card_to_depreciation`
|
||||
- `deferred_expense_to_writeoff`
|
||||
- `invoice_to_vat`
|
||||
- `contract_to_documents`
|
||||
- `receipt_to_stock_movement`
|
||||
|
||||
### 2.2 What works
|
||||
|
||||
- Query intent can be translated into semantic retrieval profile.
|
||||
- Basic anomaly vocabulary exists and affects ranking/explanation.
|
||||
|
||||
### 2.3 Constraints
|
||||
|
||||
- No explicit ontology graph engine with typed nodes/edges and reasoning rules.
|
||||
- Lifecycle model is heuristic (`created/posted/partially_linked/no_continuation/period_boundary`) rather than formal accounting state machine.
|
||||
|
||||
### 2.4 What assistant cannot do because of this
|
||||
|
||||
- Stable causal proofs for complex cross-domain reconciliation.
|
||||
- Deterministic explanation of “why exactly this stage is broken” across all domains.
|
||||
|
||||
### 2.5 Symptoms
|
||||
|
||||
- Explanation can still be structurally correct but semantically generic.
|
||||
- Retrieval unit can still drift toward “counterparty-heavy” answer shape.
|
||||
|
||||
### 2.6 Local changes needed
|
||||
|
||||
- Expand structured anomaly dictionary with accountant-facing defect classes.
|
||||
- Promote lifecycle markers from heuristics to explicit modeled states where possible.
|
||||
|
||||
### 2.7 Architectural changes needed
|
||||
|
||||
- Build ontology/lifecycle core as first-class subsystem.
|
||||
- Move from “labels on records” to “typed causal nodes and edges”.
|
||||
|
||||
### 2.8 Priority
|
||||
|
||||
- `P0`: anomaly taxonomy hardening + lifecycle schema hardening.
|
||||
- `P1`: typed ontology graph.
|
||||
- `P2`: rule engine over ontology.
|
||||
|
||||
---
|
||||
|
||||
## 3) Retrieval / Query Execution Contour
|
||||
|
||||
### 3.1 How it works now
|
||||
|
||||
- Deterministic routed executors:
|
||||
- `store_feature_risk`
|
||||
- `hybrid_store_plus_live`
|
||||
- `batch_refresh_then_store`
|
||||
- `store_canonical`
|
||||
- `live_mcp_drilldown`
|
||||
- `executeHybrid` now uses `semantic_retrieval_profile` and semantic narrowing when GUID is absent.
|
||||
- Retrieval result now carries richer context in items and summary (`query_subject`, profile, ranking basis, narrowing metrics).
|
||||
|
||||
### 3.2 What works
|
||||
|
||||
- No hard fallback to pure full scan in hybrid path for non-GUID queries.
|
||||
- Query with explicit accounting scope (`51/60`, wrong document closure) produces stronger narrowing and different ranking.
|
||||
- Evidence pack is richer and usable by explainable answer layer.
|
||||
|
||||
### 3.3 Constraints
|
||||
|
||||
- Generic prompts without explicit scope can still produce wide narrowed sets.
|
||||
- Retrieval top unit still often converges to counterparty-centric grouping.
|
||||
- Not all routes have equal semantic depth.
|
||||
|
||||
### 3.4 What assistant cannot do because of this
|
||||
|
||||
- Consistently deliver problem-node-first output in every query class.
|
||||
- Guarantee high differentiation for all semantically close prompts.
|
||||
|
||||
### 3.5 Symptoms
|
||||
|
||||
- For some queries, narrowing reduction is still modest (example `262 -> 242`).
|
||||
- Answers can remain “good but broad”.
|
||||
|
||||
### 3.6 Local changes needed
|
||||
|
||||
- Tighten mandatory intersections for generic bank/cross-entity prompts.
|
||||
- Add domain-specific minimum evidence thresholds before final top ranking.
|
||||
|
||||
### 3.7 Architectural changes needed
|
||||
|
||||
- Introduce explicit “problem cluster” retrieval unit.
|
||||
- Add cross-branch retrieval policy (neighbor contour checks).
|
||||
|
||||
### 3.8 Priority
|
||||
|
||||
- `P0`: further narrowing hardening + anti-generic ranking guards.
|
||||
- `P1`: problem-cluster retrieval unit.
|
||||
- `P2`: multi-branch investigation retrieval policy.
|
||||
|
||||
---
|
||||
|
||||
## 4) LLM Layer and Decomposition Contour
|
||||
|
||||
### 4.1 How it works now
|
||||
|
||||
- Prompt/schema baseline: `normalizer_v2_0_2`.
|
||||
- Deterministic v2 routing summary with fallback types.
|
||||
- Requirements extraction + coverage report + dropped-intent tracking are implemented.
|
||||
|
||||
### 4.2 What works
|
||||
|
||||
- Route and execution readiness are explicit.
|
||||
- Coverage and grounding diagnostics are available per turn.
|
||||
- Route mismatch blocking is now less false-positive for non-critical contextual tokens.
|
||||
|
||||
### 4.3 Constraints
|
||||
|
||||
- Requirement extraction remains coarse in many cases (often 1 requirement per fragment).
|
||||
- Transliteration/noisy mixed-language prompts still degrade in-scope detection.
|
||||
|
||||
### 4.4 What assistant cannot do because of this
|
||||
|
||||
- Fine-grained multi-requirement planning for complex accounting requests.
|
||||
- Fully robust handling of colloquial/translit business language.
|
||||
|
||||
### 4.5 Symptoms
|
||||
|
||||
- Some translit prompts fall into `out_of_scope/clarification`.
|
||||
- Partial semantic intent may be compressed in long multi-part prompts.
|
||||
|
||||
### 4.6 Local changes needed
|
||||
|
||||
- Expand language normalization and translit alias mapping before decomposition.
|
||||
- Improve requirement extraction granularity inside one fragment.
|
||||
|
||||
### 4.7 Architectural changes needed
|
||||
|
||||
- Add dedicated semantic parser layer before normalizer for business-language canonicalization.
|
||||
- Add requirement graph (instead of flat list) for planning/execution.
|
||||
|
||||
### 4.8 Priority
|
||||
|
||||
- `P0`: translit/business alias normalization.
|
||||
- `P1`: requirement graph extraction.
|
||||
- `P2`: adaptive decomposition policy.
|
||||
|
||||
---
|
||||
|
||||
## 5) Answer Synthesis / Explanation Contour
|
||||
|
||||
### 5.1 How it works now
|
||||
|
||||
- Reply types include:
|
||||
- `factual_with_explanation`
|
||||
- `partial_coverage`
|
||||
- `clarification_required`
|
||||
- `no_grounded_answer`
|
||||
- `route_mismatch_blocked`
|
||||
- others
|
||||
- Response includes explainable sections: result, why included, selection basis, risk signs, business meaning, limitations, next step.
|
||||
|
||||
### 5.2 What works
|
||||
|
||||
- Core explainable contract is implemented and stable.
|
||||
- Blocking logic prevents clearly mismatched subject answers.
|
||||
|
||||
### 5.3 Constraints
|
||||
|
||||
- Generic wording still appears when retrieval unit is broad.
|
||||
- Explanations are still largely template-driven for some routes.
|
||||
|
||||
### 5.4 What assistant cannot do because of this
|
||||
|
||||
- Deliver fully case-unique accountant-level narratives in all scenarios.
|
||||
|
||||
### 5.5 Symptoms
|
||||
|
||||
- Two semantically close broad prompts may yield similar explanatory skeleton.
|
||||
|
||||
### 5.6 Local changes needed
|
||||
|
||||
- Route-specific explanation templates with stronger domain phrasing.
|
||||
- Explicit “mechanism-of-failure” fields in retrieval result for composer.
|
||||
|
||||
### 5.7 Architectural changes needed
|
||||
|
||||
- Separate explanation planner from template renderer.
|
||||
- Add accountant-facing narrative policy with domain lexicon packs.
|
||||
|
||||
### 5.8 Priority
|
||||
|
||||
- `P0`: route-specific explanation enrichment.
|
||||
- `P1`: mechanism-level explanation fields.
|
||||
- `P2`: explanation planner subsystem.
|
||||
|
||||
---
|
||||
|
||||
## 6) Memory / State / Session Continuity Contour
|
||||
|
||||
### 6.1 How it works now
|
||||
|
||||
- Session-scoped conversation state is persisted.
|
||||
- One JSON file per session with turn-level human-readable + technical blocks.
|
||||
|
||||
### 6.2 What works
|
||||
|
||||
- Stable conversation history and replay.
|
||||
- Explicit per-turn decomposition and response auditability.
|
||||
|
||||
### 6.3 Constraints
|
||||
|
||||
- No robust investigation state model (hypotheses/open checks/resolution graph).
|
||||
- Context memory is conversational, not analytical.
|
||||
|
||||
### 6.4 What assistant cannot do because of this
|
||||
|
||||
- True multi-step investigative reasoning with hypothesis tracking.
|
||||
|
||||
### 6.5 Symptoms
|
||||
|
||||
- Follow-up can be coherent but not yet “investigation-driven”.
|
||||
|
||||
### 6.6 Local changes needed
|
||||
|
||||
- Add per-session `investigation_state` object (focus, active entities, open hypotheses, unresolved branches).
|
||||
|
||||
### 6.7 Architectural changes needed
|
||||
|
||||
- Add working-memory layer for research workflow, not only chat continuity.
|
||||
|
||||
### 6.8 Priority
|
||||
|
||||
- `P0`: investigation_state schema + persistence.
|
||||
- `P1`: branch tracking and hypothesis status transitions.
|
||||
- `P2`: multi-turn analytical planning engine.
|
||||
|
||||
---
|
||||
|
||||
## 7) Orchestration / Routing / Control Policy Contour
|
||||
|
||||
### 7.1 How it works now
|
||||
|
||||
- Deterministic routing with fallback (`none/out_of_scope/clarification/partial`).
|
||||
- Linear execution plan per turn.
|
||||
|
||||
### 7.2 What works
|
||||
|
||||
- Clear route decisions and no-route reasons.
|
||||
- Strong deterministic observability.
|
||||
|
||||
### 7.3 Constraints
|
||||
|
||||
- Mostly route-driven linear pipeline.
|
||||
- Limited iterative branch exploration initiated by system policy.
|
||||
|
||||
### 7.4 What assistant cannot do because of this
|
||||
|
||||
- Automatically run neighbor contour verification when primary evidence is weak.
|
||||
|
||||
### 7.5 Symptoms
|
||||
|
||||
- Reasonable direct answers, but limited self-initiated investigation depth.
|
||||
|
||||
### 7.6 Local changes needed
|
||||
|
||||
- Introduce confidence-driven secondary retrieval triggers.
|
||||
|
||||
### 7.7 Architectural changes needed
|
||||
|
||||
- Orchestration policy engine with iterative reasoning loops and stop criteria.
|
||||
|
||||
### 7.8 Priority
|
||||
|
||||
- `P0`: confidence-based secondary checks.
|
||||
- `P1`: branch exploration policy.
|
||||
- `P2`: full investigation orchestrator.
|
||||
|
||||
---
|
||||
|
||||
## 8) Quality / Observability / Eval Contour
|
||||
|
||||
### 8.1 How it works now
|
||||
|
||||
- Structured runtime logs (stdout JSON).
|
||||
- Trace storage and session logs.
|
||||
- Regression tests for API behavior, grounding and retrieval semantics.
|
||||
|
||||
### 8.2 What works
|
||||
|
||||
- Technical observability is strong for current stage.
|
||||
- Automated test baseline is green (`25/25`).
|
||||
|
||||
### 8.3 Constraints
|
||||
|
||||
- Limited accountant-utility evaluation metrics.
|
||||
- No broad canonical scenario benchmark with decision-quality scoring.
|
||||
|
||||
### 8.4 What assistant cannot do because of this
|
||||
|
||||
- Provide hard quantitative proof of business usefulness across accounting domains.
|
||||
|
||||
### 8.5 Symptoms
|
||||
|
||||
- Technical success may still exceed practical user-perceived success.
|
||||
|
||||
### 8.6 Local changes needed
|
||||
|
||||
- Add eval metrics:
|
||||
- retrieval differentiation rate
|
||||
- generic explanation rate
|
||||
- accountant actionability score
|
||||
- false confidence rate
|
||||
|
||||
### 8.7 Architectural changes needed
|
||||
|
||||
- Build domain eval harness with canonical accounting scenarios and target outcomes.
|
||||
|
||||
### 8.8 Priority
|
||||
|
||||
- `P0`: metric instrumentation for practical usefulness.
|
||||
- `P1`: canonical benchmark suite (bank/60/97/OS/VAT/period close/multi-intent/translit/follow-up).
|
||||
- `P2`: continuous quality dashboard.
|
||||
|
||||
---
|
||||
|
||||
## 9) Evolutionary Architecture Contour
|
||||
|
||||
### 9.1 Missing pieces (high impact)
|
||||
|
||||
- Ontology graph core.
|
||||
- Lifecycle engine.
|
||||
- Problem-cluster retrieval unit.
|
||||
- Investigation memory/state.
|
||||
- Orchestration policy engine for iterative checks.
|
||||
- Live verification bridge for source-of-truth escalation.
|
||||
|
||||
### 9.2 Current ceiling
|
||||
|
||||
- Without deeper ontology/lifecycle/state layers, system remains strong “explainable routed assistant”, but not full accountant investigation copilot.
|
||||
|
||||
### 9.3 Local vs architectural changes
|
||||
|
||||
- Local: better filters, better templates, more metrics, better parser.
|
||||
- Architectural: graph model, lifecycle engine, investigation state, multi-step orchestrator.
|
||||
|
||||
### 9.4 Priority
|
||||
|
||||
- `P0`: finish semantic retrieval hardening + practical eval metrics + investigation_state baseline.
|
||||
- `P1`: ontology/lifecycle formalization + problem-cluster retrieval.
|
||||
- `P2`: iterative orchestrator + live verification framework.
|
||||
|
||||
---
|
||||
|
||||
## 10) Answers to 12 Mandatory Questions
|
||||
|
||||
1. What data reaches assistant and where detail is lost:
|
||||
Data reaches from snapshot package with links/attributes; detail loss happens in flattening/grouping and lack of formal lifecycle semantics.
|
||||
|
||||
2. Full domain model exists:
|
||||
Partially. Semantic labels and patterns exist, formal ontology graph does not.
|
||||
|
||||
3. Primary retrieval unit:
|
||||
Mostly counterparty-grouped chain/risk clusters; not yet universal problem-node unit.
|
||||
|
||||
4. Real constraints and wide-scan risk:
|
||||
Constraints now executed in hybrid semantic profile, but generic queries can still remain broad.
|
||||
|
||||
5. What LLM receives before answer:
|
||||
Normalizer output + route summary + normalized retrieval payload + grounding/coverage diagnostics.
|
||||
|
||||
6. What is lost in decomposition:
|
||||
Fine-grained multi-requirement structure can still compress; translit/noisy input can lose intent quality.
|
||||
|
||||
7. Why explanation still generic in places:
|
||||
Broad retrieval unit + template-driven synthesis with limited mechanism-specific fields.
|
||||
|
||||
8. Can system explain mechanism (not only labels):
|
||||
Partially. Better than before, still constrained by retrieval evidence depth.
|
||||
|
||||
9. Working state/memory for multi-step analysis:
|
||||
Conversation memory exists; investigation memory model is missing.
|
||||
|
||||
10. Can system explore neighbor accounting branches automatically:
|
||||
Not yet as policy standard; mostly linear route execution.
|
||||
|
||||
11. How usefulness is measured:
|
||||
Technical pipeline quality is measured; accountant-facing utility metrics are not complete yet.
|
||||
|
||||
12. Missing architectural entities preventing next quality tier:
|
||||
Ontology graph, lifecycle engine, problem-cluster unit, investigation state, iterative orchestration.
|
||||
|
||||
---
|
||||
|
||||
## 11) Current Phase Status (Condensed)
|
||||
|
||||
- Phase status: `Functional MVP+` (explainable routed assistant with semantic retrieval upgrade).
|
||||
- Not yet: `Production accountant copilot`.
|
||||
- Immediate gate to next phase: tighten broad-query narrowing + add practical accountant eval metrics + investigation state schema.
|
||||
|
||||
---
|
||||
|
||||
## 12) Recommended Next Step Pack
|
||||
|
||||
### P0 (next iteration)
|
||||
|
||||
- Tighten generic-query semantic narrowing in hybrid route.
|
||||
- Add investigation state object in session model.
|
||||
- Add practical eval metrics (differentiation/actionability/generic-rate).
|
||||
|
||||
### P1 (after P0 stabilization)
|
||||
|
||||
- Formalize ontology + lifecycle layers.
|
||||
- Shift retrieval output from entity-heavy to problem-cluster-heavy for key domains.
|
||||
|
||||
### P2 (strategic)
|
||||
|
||||
- Add iterative orchestration with neighbor-branch verification.
|
||||
- Add live source-of-truth verification path for high-confidence conclusions.
|
||||
|
||||
---
|
||||
|
||||
## 13) Data Loss Map (Source to LLM)
|
||||
|
||||
This section is the explicit loss map requested for architecture decisions.
|
||||
|
||||
| Source Layer | Current Internal Representation | Lost/Weakened Signals | Observable Assistant Symptom | Required Fix Layer |
|
||||
|---|---|---|---|---|
|
||||
| 1C document/journal/register snapshot record | flattened `SnapshotRecord` + heuristic signal extraction | formal business status transitions, typed lifecycle stage semantics | explanation can be structurally correct but semantically generic | lifecycle model + ontology graph |
|
||||
| document + posting relation hints | relation pattern labels inferred by regex/rules | deterministic causal edge type and confidence | “close to right chain” answers without strict mechanism proof | typed relation graph + relation confidence |
|
||||
| account hints from query and record fields | `account_scope` and inferred `account_context` arrays | strong account-role semantics (main vs side context) | broad retrieval if account scope is not explicit | account-role policy in retrieval profile |
|
||||
| anomaly signs (`unknown links`, `zero guid`, etc.) | anomaly pattern tags (`missing_link`, `broken_lifecycle`, etc.) | accountant-grade defect class and business consequence mapping | same anomaly labels across semantically different defects | anomaly catalog and mapping engine |
|
||||
| session chat turns | conversation list + turn log | investigation branch state and hypothesis state | follow-up can be coherent but not deeply investigative | investigation_state subsystem |
|
||||
| snapshot-only truth | no guaranteed live verification step in assistant route | real-time status confirmation | high-quality but potentially stale conclusion in sensitive cases | live verification bridge |
|
||||
|
||||
### 13.1 Diagnostic implication
|
||||
|
||||
The dominant ceiling is not “weak wording” but “insufficiently structured causal context before synthesis”.
|
||||
|
||||
---
|
||||
|
||||
## 14) Query Class vs Required Architecture Depth
|
||||
|
||||
| User Query Class | Required Layers | Current Readiness | Ceiling Cause | Next Upgrade |
|
||||
|---|---|---|---|---|
|
||||
| simple factual object lookup | routing + canonical retrieval + basic grounding | medium/high | snapshot-only verification | optional live drilldown |
|
||||
| anomaly ranking (one contour) | semantic profile + risk retrieval + explainable synthesis | medium | anomaly semantics still heuristic | anomaly catalog hardening |
|
||||
| causal chain in one contour | relation patterns + chain retrieval + evidence pack | medium | retrieval unit still entity-heavy in broad prompts | problem-cluster unit |
|
||||
| cross-domain reconciliation | ontology + lifecycle + neighbor branch policy | low/medium | no formal cross-domain causal graph | ontology graph + branch policy |
|
||||
| period-close impact analysis | lifecycle + period-risk model + orchestration | low/medium | lifecycle model incomplete | lifecycle engine |
|
||||
| multi-step investigation with follow-up | investigation_state + orchestration loops + hypothesis tracking | low | memory is conversational, not investigative | investigation mode layer |
|
||||
| ambiguity-heavy/translit business language | semantic parser + alias normalization + decomposition guard | low/medium | parser limitations before routing | pre-normalization parser layer |
|
||||
|
||||
### 14.1 Decision implication
|
||||
|
||||
Prompt/model tuning alone cannot close low-readiness classes above; they are architecture-depth dependent.
|
||||
|
||||
---
|
||||
|
||||
## 15) Retrieval Unit Diagnosis (Core Bottleneck)
|
||||
|
||||
### 15.1 Current dominant unit
|
||||
|
||||
- Dominant unit in hybrid route is still often `counterparty group`, even after semantic narrowing.
|
||||
|
||||
### 15.2 Where this unit is acceptable
|
||||
|
||||
- quick ranking
|
||||
- initial risk surfacing
|
||||
- broad operational scanning
|
||||
|
||||
### 15.3 Where this unit breaks answer quality
|
||||
|
||||
- “what exactly is broken in chain”
|
||||
- “closed by wrong document type”
|
||||
- “which lifecycle stage is inconsistent”
|
||||
- “what blocks period close and why”
|
||||
|
||||
### 15.4 Target retrieval units (must become first-class)
|
||||
|
||||
- `document_conflict`
|
||||
- `broken_chain_segment`
|
||||
- `lifecycle_anomaly_node`
|
||||
- `unresolved_settlement_cluster`
|
||||
- `period_risk_cluster`
|
||||
- `cross_branch_inconsistency_cluster`
|
||||
|
||||
### 15.5 Transition plan
|
||||
|
||||
- Step 1 (`P0`): keep counterparty groups but add explicit `mechanism_of_failure` + `failed_expected_edge`.
|
||||
- Step 2 (`P1`): introduce mixed-unit ranking (problem cluster first, entity second).
|
||||
- Step 3 (`P2`): use problem-cluster as default answer unit for chain/anomaly/period-risk routes.
|
||||
|
||||
---
|
||||
|
||||
## 16) LLM Ceiling Boundaries (Not Solvable by Prompt Alone)
|
||||
|
||||
The following limitations remain even with stronger models/prompts unless architecture changes:
|
||||
|
||||
1. no formal lifecycle state machine on input -> model cannot produce deterministic lifecycle diagnosis;
|
||||
2. no typed causal graph edges -> model cannot consistently prove mechanism, only infer plausible narrative;
|
||||
3. entity-heavy retrieval unit -> model can explain “who is risky”, but not always “what exact mechanism broke”;
|
||||
4. missing investigation_state -> model cannot reliably manage long hypothesis trees across turns;
|
||||
5. no mandatory live verification gate -> model cannot guarantee real-time truth in high-stakes answers.
|
||||
|
||||
### 16.1 Governance rule
|
||||
|
||||
When limitations above are active, quality work must target data/model/orchestration layers first; LLM tuning is secondary.
|
||||
|
||||
---
|
||||
|
||||
## 17) Investigation Mode Specification (Required Next Architecture)
|
||||
|
||||
### 17.1 Minimal `investigation_state` schema
|
||||
|
||||
```json
|
||||
{
|
||||
"session_id": "asst-...",
|
||||
"focus": {
|
||||
"domain": "bank_settlements",
|
||||
"period": "2020-06",
|
||||
"primary_accounts": ["51", "60"]
|
||||
},
|
||||
"active_entities": [
|
||||
{ "type": "counterparty", "id": "..." },
|
||||
{ "type": "document", "id": "..." }
|
||||
],
|
||||
"open_hypotheses": [
|
||||
{
|
||||
"hypothesis_id": "H1",
|
||||
"statement": "closure performed by wrong document type",
|
||||
"status": "open",
|
||||
"evidence_for": [],
|
||||
"evidence_against": []
|
||||
}
|
||||
],
|
||||
"branches": [
|
||||
{
|
||||
"branch_id": "B1",
|
||||
"name": "bank->settlement",
|
||||
"status": "in_progress",
|
||||
"unresolved_reason": null
|
||||
}
|
||||
],
|
||||
"resolved_findings": [],
|
||||
"next_actions": []
|
||||
}
|
||||
```
|
||||
|
||||
### 17.2 Required branch lifecycle
|
||||
|
||||
- `open` -> `in_progress` -> `confirmed` or `rejected` -> `closed`
|
||||
|
||||
### 17.3 System-initiated branch rule (minimum)
|
||||
|
||||
If primary route confidence is high but mechanism evidence is weak, assistant should launch one neighbor branch check before final high-confidence conclusion.
|
||||
|
||||
---
|
||||
|
||||
## 18) Symptom to Root Cause to Required Layer
|
||||
|
||||
| Symptom | Root Cause | Required Layer |
|
||||
|---|---|---|
|
||||
| generic explanation despite “ok” reply | mechanism fields missing in retrieval payload | retrieval schema + answer planner |
|
||||
| similar answers for broad prompts | weak semantic narrowing for low-specificity queries | retrieval policy |
|
||||
| follow-up does not deepen analysis | no hypothesis/branch state | investigation_state |
|
||||
| strong dependence on explicit account hints | weak semantic parser/ontology grounding | parser + ontology |
|
||||
| lifecycle conclusions not stable | lifecycle semantics heuristic only | lifecycle engine |
|
||||
| high confidence on snapshot-only route | no live verification gate | live verification bridge |
|
||||
|
||||
---
|
||||
|
||||
## 19) Value-Impact Roadmap (Decision Table)
|
||||
|
||||
| Change | Complexity | Quality Gain | Accountant Usefulness Gain | Multi-step Investigation Gain | Priority |
|
||||
|---|---|---|---|---|---|
|
||||
| tighten generic semantic narrowing | low/medium | high | high | medium | P0 |
|
||||
| add `mechanism_of_failure` retrieval fields | medium | high | high | medium | P0 |
|
||||
| add `investigation_state` persistence | medium | medium/high | high | high | P0 |
|
||||
| add practical utility eval metrics | low/medium | medium | high | medium | P0 |
|
||||
| formalize anomaly catalog | medium | medium/high | high | medium | P1 |
|
||||
| ontology graph core | high | high | high | high | P1 |
|
||||
| lifecycle engine | high | high | high | high | P1 |
|
||||
| problem-cluster retrieval unit | high | high | high | high | P1 |
|
||||
| iterative orchestration engine | high | high | high | very high | P2 |
|
||||
| live verification bridge | high | medium/high | high | medium/high | P2 |
|
||||
|
||||
---
|
||||
|
||||
## 20) What Not To Do (Explicit Guardrails)
|
||||
|
||||
1. Do not attempt to solve mechanism-level quality only with prompt edits.
|
||||
2. Do not treat richer wording as substitute for stronger retrieval unit.
|
||||
3. Do not scale explanation templates without adding mechanism evidence fields.
|
||||
4. Do not equate long conversation history with investigation_state.
|
||||
5. Do not claim production-grade confidence without live verification path for critical answers.
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# Assistant Mode Global Status Appendix
|
||||
|
||||
Date: 2026-03-24
|
||||
|
||||
## A) Verification Commands
|
||||
|
||||
```powershell
|
||||
cd X:\1C\NDC_1C\llm_normalizer\backend
|
||||
npm.cmd run build
|
||||
npm.cmd run test
|
||||
```
|
||||
|
||||
Observed result:
|
||||
|
||||
- TypeScript build: success
|
||||
- Test suite: success (`25/25`)
|
||||
|
||||
## B) Retrieval Narrowing Evidence
|
||||
|
||||
### Case 1: bank mismatch with explicit account scope
|
||||
|
||||
- Session: `asst-FuRihiL5Bp`
|
||||
- Query subject: `bank_settlement_mismatch`
|
||||
- Source records: `262`
|
||||
- Filtered after narrowing: `75`
|
||||
- Semantic narrowing applied: `true`
|
||||
|
||||
### Case 2: generic cross-entity bank chain
|
||||
|
||||
- Session: `asst-j9spgqdY7k`
|
||||
- Query subject: `cross_entity_breakage`
|
||||
- Source records: `262`
|
||||
- Filtered after narrowing: `242`
|
||||
- Semantic narrowing applied: `true`
|
||||
|
||||
Interpretation:
|
||||
|
||||
- Semantic narrowing is active and effective for constrained accounting scope.
|
||||
- Generic prompts still need stronger narrowing policy.
|
||||
|
||||
## C) Key Implementation Anchors
|
||||
|
||||
- Semantic profile contract and builder:
|
||||
- `X:\1C\NDC_1C\llm_normalizer\backend\src\services\assistantDataLayer.ts`
|
||||
- Hybrid narrowing and enriched evidence pack:
|
||||
- `X:\1C\NDC_1C\llm_normalizer\backend\src\services\assistantDataLayer.ts`
|
||||
- API regression test for semantic narrowing:
|
||||
- `X:\1C\NDC_1C\llm_normalizer\backend\tests\assistantEndpoint.test.ts`
|
||||
|
||||
## D) v1.1 Report Reinforcement Checklist
|
||||
|
||||
All 4 requested reinforcements are now explicitly present in the main report:
|
||||
|
||||
1. Data-loss path map (`Source -> Internal -> Lost -> Symptom -> Fix layer`)
|
||||
2. Query-class vs architecture-depth matrix
|
||||
3. Dedicated retrieval-unit diagnosis block (current vs target units)
|
||||
4. Investigation mode schema and control-policy baseline
|
||||
|
||||
Also added:
|
||||
|
||||
- symptom -> root cause -> required layer matrix
|
||||
- value-impact roadmap table
|
||||
- explicit “what not to do” guardrails
|
||||
Binary file not shown.
+4905
File diff suppressed because it is too large
Load Diff
+2869
File diff suppressed because it is too large
Load Diff
+1895
File diff suppressed because it is too large
Load Diff
+1101
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,93 @@
|
||||
# Router / Orchestration Fix Report (2026-03-23)
|
||||
|
||||
## Scope completed
|
||||
|
||||
По `IN/TZ_Router_Orchestration_Fix.md` реализованы:
|
||||
|
||||
1. Query classifier v2 с decision flags.
|
||||
2. Store sufficiency checker.
|
||||
3. Explicit route guards.
|
||||
4. Runtime batch handoff (`refresh_and_answer` job path).
|
||||
5. Route decision logging для всех benchmark-вопросов.
|
||||
6. Unit + integration-style tests по router-модулям.
|
||||
7. Повторный validation-run на июньском semantic-v2 срезе.
|
||||
|
||||
## Implemented modules
|
||||
|
||||
Новые пакеты и файлы:
|
||||
|
||||
- `router/query_classifier.py`
|
||||
- `router/store_sufficiency.py`
|
||||
- `router/route_selector.py`
|
||||
- `router/decision_log.py`
|
||||
- `orchestration/batch_runtime.py`
|
||||
|
||||
Подключение в benchmark-runtime:
|
||||
|
||||
- `scripts/run_validation_accounting_analytics.py`
|
||||
- orchestration policy расширена ссылками на runtime-router модули;
|
||||
- добавлен `build_store_metadata(...)`;
|
||||
- добавлен `build_benchmark_results_v2(...)`;
|
||||
- добавлен batch handoff path для `batch_refresh_then_store`;
|
||||
- добавлен export `route_decision_logs.json`.
|
||||
|
||||
## Tests
|
||||
|
||||
Добавлены тесты:
|
||||
|
||||
- `tests/test_router_decision_flags.py`
|
||||
- `tests/test_store_sufficiency.py`
|
||||
- `tests/test_route_guards.py`
|
||||
- `tests/test_batch_runtime_handoff.py`
|
||||
- `tests/test_router_benchmark_subset.py`
|
||||
|
||||
Статус:
|
||||
|
||||
- `python -m pytest -q` -> `31 passed`
|
||||
|
||||
## Validation run (router-fix)
|
||||
|
||||
Команда:
|
||||
|
||||
`python scripts/run_validation_accounting_analytics.py --snapshot-path logs/pre_report_snapshot_2020_2020-06_semantic_v2.json --output-dir docs/ARCH/validation_run_2026-03-23_router_fix --strict`
|
||||
|
||||
Выход:
|
||||
|
||||
- `docs/ARCH/validation_run_2026-03-23_router_fix/`
|
||||
|
||||
Ключевые результаты benchmark:
|
||||
|
||||
- `questions_total = 35`
|
||||
- `route_mismatch_count = 1` (было 7)
|
||||
- `degraded_answers_count = 0`
|
||||
- `batch_route_count = 5` (было 0)
|
||||
- `heavy_analytical mismatches = 0`
|
||||
- `cross_entity mismatches = 0`
|
||||
- `drilldown_explain mismatches = 0`
|
||||
|
||||
Единственный остаточный mismatch:
|
||||
|
||||
- `Q19` (`period_trend`): expected `store_feature_risk`, actual `batch_refresh_then_store`
|
||||
|
||||
Decision logs:
|
||||
|
||||
- `docs/ARCH/validation_run_2026-03-23_router_fix/route_decision_logs.json`
|
||||
- покрытие логами: `35/35` вопросов.
|
||||
|
||||
## Acceptance criteria status
|
||||
|
||||
По целям ТЗ:
|
||||
|
||||
- `route_mismatch_count <= 2`: **done** (`1`)
|
||||
- `heavy_analytical mismatches = 0`: **done**
|
||||
- `cross_entity mismatches = 0`: **done**
|
||||
- `drilldown_explain mismatches <= 1`: **done** (`0`)
|
||||
- `batch_route_count > 0`: **done** (`5`)
|
||||
- `degraded_answers_count = 0`: **done**
|
||||
- decision logs for all 35: **done**
|
||||
|
||||
## Notes
|
||||
|
||||
1. Batch runtime path исполняется в-process через `orchestration.batch_runtime`, с job payload и run-id trace.
|
||||
2. Refresh step в batch режиме сейчас gated (`allow_refresh_in_batch=False` для validation profile), чтобы не делать неконтролируемый live refresh в этом прогоне; при этом feature/risk handoff исполняется реально.
|
||||
3. Следующий точечный шаг: опционально дотюнить classifier threshold для `Q19`, чтобы привести `route_mismatch_count` к `0`.
|
||||
@@ -0,0 +1,35 @@
|
||||
# Router / Orchestration Fix Report v2 (2026-03-23)
|
||||
|
||||
## Final tuning step
|
||||
|
||||
После первого router-fix прогона оставался 1 mismatch (`Q19`), где `period_trend` вопрос с формулировкой про аномалию уходил в batch.
|
||||
|
||||
Сделана точечная правка:
|
||||
|
||||
- `router/route_selector.py`
|
||||
- heavy-guard теперь срабатывает по `needs_anomaly_summary` только если запрос не относится к trend/risk профилю (`not parsed_as_trend_or_risk`).
|
||||
|
||||
Добавлен тест:
|
||||
|
||||
- `tests/test_router_benchmark_subset.py::test_router_period_trend_anomaly_stays_feature_store`
|
||||
|
||||
## Verification
|
||||
|
||||
- `python -m pytest -q` -> `32 passed`
|
||||
- Validation run:
|
||||
- `python scripts/run_validation_accounting_analytics.py --snapshot-path logs/pre_report_snapshot_2020_2020-06_semantic_v2.json --output-dir docs/ARCH/validation_run_2026-03-23_router_fix_v2 --strict`
|
||||
|
||||
## Result metrics (router_fix_v2)
|
||||
|
||||
- `questions_total = 35`
|
||||
- `route_mismatch_count = 0`
|
||||
- `degraded_answers_count = 0`
|
||||
- `heavy_analytical mismatches = 0`
|
||||
- `cross_entity mismatches = 0`
|
||||
- `drilldown_explain mismatches = 0`
|
||||
- `batch_route_count = 4` (> 0, runtime path active)
|
||||
|
||||
## Artifacts
|
||||
|
||||
- `docs/ARCH/validation_run_2026-03-23_router_fix_v2/`
|
||||
- `docs/ARCH/validation_run_2026-03-23_router_fix_v2/route_decision_logs.json`
|
||||
@@ -0,0 +1,51 @@
|
||||
# Setup Guide
|
||||
|
||||
## 1. Install Miniconda (if missing)
|
||||
|
||||
```powershell
|
||||
winget install -e --id Anaconda.Miniconda3 --source winget --accept-source-agreements --accept-package-agreements --silent
|
||||
```
|
||||
|
||||
## 2. Create isolated environment
|
||||
|
||||
```powershell
|
||||
$Conda = Join-Path $env:USERPROFILE "miniconda3\Scripts\conda.exe"
|
||||
if (-not (Test-Path $Conda)) { $Conda = Join-Path $env:USERPROFILE "Miniconda3\Scripts\conda.exe" }
|
||||
& $Conda create -y -n ndc_1c_mvp python=3.11
|
||||
$EnvPython = Join-Path $env:USERPROFILE "miniconda3\envs\ndc_1c_mvp\python.exe"
|
||||
if (-not (Test-Path $EnvPython)) { $EnvPython = Join-Path $env:USERPROFILE "Miniconda3\envs\ndc_1c_mvp\python.exe" }
|
||||
& $EnvPython -m pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## 3. Configure environment variables
|
||||
|
||||
```powershell
|
||||
copy .env.example .env
|
||||
```
|
||||
|
||||
Set real values for:
|
||||
- `ONEC_BASE_URL`
|
||||
- `ONEC_INFOBASE`
|
||||
- `ONEC_USERNAME`
|
||||
- `ONEC_PASSWORD`
|
||||
|
||||
## 4. Run OData probe
|
||||
|
||||
```powershell
|
||||
& $EnvPython -m odata_probe.fetch_metadata
|
||||
& $EnvPython -m odata_probe.list_entity_sets
|
||||
& $EnvPython -m odata_probe.probe_entities
|
||||
& $EnvPython -m odata_probe.dump_sample_links
|
||||
```
|
||||
|
||||
## 5. Run API
|
||||
|
||||
```powershell
|
||||
& $EnvPython -m uvicorn canonical_layer.app:app --host 127.0.0.1 --port 8000 --reload
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Project mode is read-only against 1C.
|
||||
- For production, restrict OData role permissions to read-only.
|
||||
- If OData is not published yet, probe scripts will fail by design and log the connectivity problem.
|
||||
@@ -0,0 +1,19 @@
|
||||
# Benchmark Final Verdict
|
||||
|
||||
## Verdict
|
||||
|
||||
`adopt_with_improvements`
|
||||
|
||||
## Key numbers
|
||||
|
||||
- Questions total: `35`
|
||||
- Route mismatches: `7`
|
||||
- Degraded answers: `0`
|
||||
- Avg latency ms: `506.43`
|
||||
- p95 latency ms: `1024.5`
|
||||
|
||||
## Recommendation
|
||||
|
||||
1. Fix ontology unknown mapping hotspots.
|
||||
2. Tune heavy-route threshold (`store_feature_risk` vs `batch_refresh_then_store`).
|
||||
3. Implement full production orchestration runtime.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Benchmark Questions (35)
|
||||
|
||||
| ID | Class | Expected route | Question |
|
||||
| --- | --- | --- | --- |
|
||||
| Q01 | simple_factual | store_canonical | Сальдо счета 68.02 за июнь 2020? |
|
||||
| Q02 | simple_factual | live_mcp_drilldown | Документ по номеру и его ссылка. |
|
||||
| Q03 | simple_factual | store_canonical | Типовая проводка по реализации. |
|
||||
| Q04 | simple_factual | store_canonical | Контрагент с максимумом оборота. |
|
||||
| Q05 | simple_factual | store_canonical | Договоры топ-контрагента. |
|
||||
| Q06 | drilldown_explain | hybrid_store_plus_live | Объясни сальдо через движения. |
|
||||
| Q07 | drilldown_explain | live_mcp_drilldown | Почему проводка на этот счет? |
|
||||
| Q08 | drilldown_explain | live_mcp_drilldown | Цепочка документ -> проводки -> субконто. |
|
||||
| Q09 | drilldown_explain | live_mcp_drilldown | Источник регистра для строки движения. |
|
||||
| Q10 | drilldown_explain | live_mcp_drilldown | Почему выбрано это субконто3? |
|
||||
| Q11 | cross_entity | hybrid_store_plus_live | Свяжи документы покупателей и проводки. |
|
||||
| Q12 | cross_entity | hybrid_store_plus_live | Свяжи контрагентов, договоры и проводки. |
|
||||
| Q13 | cross_entity | store_canonical | Номенклатура, склад, обороты за июнь. |
|
||||
| Q14 | cross_entity | hybrid_store_plus_live | Регистр и первичный документ. |
|
||||
| Q15 | cross_entity | store_canonical | По счету: контрагенты и договоры. |
|
||||
| Q16 | period_trend | store_feature_risk | Обороты июня против мая. |
|
||||
| Q17 | period_trend | store_feature_risk | Недельные всплески в июне. |
|
||||
| Q18 | period_trend | store_feature_risk | Кто дал резкий рост активности. |
|
||||
| Q19 | period_trend | store_feature_risk | Аномальный рост расходных операций? |
|
||||
| Q20 | period_trend | store_feature_risk | Динамика НДС к соседним периодам. |
|
||||
| Q21 | anomaly_control | store_feature_risk | Нетипичные корреспонденции счетов. |
|
||||
| Q22 | anomaly_control | store_feature_risk | Незакрытые хвосты по расчетам. |
|
||||
| Q23 | anomaly_control | store_feature_risk | Дублирующиеся проводки. |
|
||||
| Q24 | anomaly_control | store_feature_risk | Пустые или странные субконто. |
|
||||
| Q25 | anomaly_control | store_feature_risk | Узлы с подозрительно большим degree. |
|
||||
| Q26 | heavy_analytical | batch_refresh_then_store | Полный риск-срез за июнь. |
|
||||
| Q27 | heavy_analytical | batch_refresh_then_store | Рейтинг риск-счетов. |
|
||||
| Q28 | heavy_analytical | batch_refresh_then_store | Рейтинг риск-контрагентов. |
|
||||
| Q29 | heavy_analytical | store_feature_risk | Baseline closed/open periods. |
|
||||
| Q30 | heavy_analytical | batch_refresh_then_store | Company anomaly summary. |
|
||||
| Q31 | ambiguous_fuzzy | store_feature_risk | Что по налогам и рискам? |
|
||||
| Q32 | ambiguous_fuzzy | store_feature_risk | Что странное в расходах? |
|
||||
| Q33 | ambiguous_fuzzy | store_feature_risk | Самые рисковые контрагенты? |
|
||||
| Q34 | ambiguous_fuzzy | hybrid_store_plus_live | Что с 68.02? |
|
||||
| Q35 | ambiguous_fuzzy | store_feature_risk | Проверить документы июня. |
|
||||
@@ -0,0 +1,19 @@
|
||||
# Benchmark Route Analysis
|
||||
|
||||
- Total mismatches: `7`
|
||||
|
||||
## Route confusion matrix
|
||||
|
||||
- `batch_refresh_then_store` -> store_feature_risk:4
|
||||
- `hybrid_store_plus_live` -> hybrid_store_plus_live:3, store_canonical:2
|
||||
- `live_mcp_drilldown` -> hybrid_store_plus_live:1, live_mcp_drilldown:4
|
||||
- `store_canonical` -> store_canonical:6
|
||||
- `store_feature_risk` -> store_feature_risk:15
|
||||
|
||||
## Mismatch by class
|
||||
|
||||
| Class | Mismatch count |
|
||||
| --- | --- |
|
||||
| cross_entity | 2 |
|
||||
| drilldown_explain | 1 |
|
||||
| heavy_analytical | 4 |
|
||||
@@ -0,0 +1,38 @@
|
||||
# Benchmark Run Report
|
||||
|
||||
## Aggregate statistics
|
||||
|
||||
| Metric | Value |
|
||||
| --- | --- |
|
||||
| questions_total | 35 |
|
||||
| avg_latency_ms | 506.43 |
|
||||
| median_latency_ms | 402 |
|
||||
| p90_latency_ms | 941.4 |
|
||||
| p95_latency_ms | 1024.5 |
|
||||
| avg_context_size | 2162.51 |
|
||||
| live_route_count | 8 |
|
||||
| store_route_count | 27 |
|
||||
| batch_route_count | 0 |
|
||||
| route_mismatch_count | 7 |
|
||||
| degraded_answers_count | 0 |
|
||||
|
||||
## Route distribution
|
||||
|
||||
| Route | Count |
|
||||
| --- | --- |
|
||||
| hybrid_store_plus_live | 4 |
|
||||
| live_mcp_drilldown | 4 |
|
||||
| store_canonical | 8 |
|
||||
| store_feature_risk | 19 |
|
||||
|
||||
## Question class distribution
|
||||
|
||||
| Class | Count |
|
||||
| --- | --- |
|
||||
| ambiguous_fuzzy | 5 |
|
||||
| anomaly_control | 5 |
|
||||
| cross_entity | 5 |
|
||||
| drilldown_explain | 5 |
|
||||
| heavy_analytical | 5 |
|
||||
| period_trend | 5 |
|
||||
| simple_factual | 5 |
|
||||
@@ -0,0 +1,827 @@
|
||||
{
|
||||
"status": "success",
|
||||
"slice_window_key": "2020-06",
|
||||
"generated_at": "2026-03-23T09:28:12.312411+00:00",
|
||||
"questions_total": 35,
|
||||
"aggregate": {
|
||||
"questions_total": 35,
|
||||
"avg_latency_ms": 506.43,
|
||||
"median_latency_ms": 402,
|
||||
"p90_latency_ms": 941.4,
|
||||
"p95_latency_ms": 1024.5,
|
||||
"avg_context_size": 2162.51,
|
||||
"live_route_count": 8,
|
||||
"store_route_count": 27,
|
||||
"batch_route_count": 0,
|
||||
"route_mismatch_count": 7,
|
||||
"degraded_answers_count": 0,
|
||||
"route_distribution": {
|
||||
"store_canonical": 8,
|
||||
"live_mcp_drilldown": 4,
|
||||
"hybrid_store_plus_live": 4,
|
||||
"store_feature_risk": 19
|
||||
},
|
||||
"question_class_distribution": {
|
||||
"simple_factual": 5,
|
||||
"drilldown_explain": 5,
|
||||
"cross_entity": 5,
|
||||
"period_trend": 5,
|
||||
"anomaly_control": 5,
|
||||
"heavy_analytical": 5,
|
||||
"ambiguous_fuzzy": 5
|
||||
}
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"question_id": "Q01",
|
||||
"question_text": "Сальдо счета 68.02 за июнь 2020?",
|
||||
"question_class": "simple_factual",
|
||||
"expected_route": "store_canonical",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 332,
|
||||
"planning_time_ms": 67,
|
||||
"retrieval_time_ms": 129,
|
||||
"response_generation_time_ms": 136,
|
||||
"context_size": 1595,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q02",
|
||||
"question_text": "Документ по номеру и его ссылка.",
|
||||
"question_class": "simple_factual",
|
||||
"expected_route": "live_mcp_drilldown",
|
||||
"actual_route": "live_mcp_drilldown",
|
||||
"sources_used": [
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 1020,
|
||||
"planning_time_ms": 93,
|
||||
"retrieval_time_ms": 740,
|
||||
"response_generation_time_ms": 187,
|
||||
"context_size": 2796,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=live_mcp_drilldown; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q03",
|
||||
"question_text": "Типовая проводка по реализации.",
|
||||
"question_class": "simple_factual",
|
||||
"expected_route": "store_canonical",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 338,
|
||||
"planning_time_ms": 69,
|
||||
"retrieval_time_ms": 131,
|
||||
"response_generation_time_ms": 138,
|
||||
"context_size": 1597,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q04",
|
||||
"question_text": "Контрагент с максимумом оборота.",
|
||||
"question_class": "simple_factual",
|
||||
"expected_route": "store_canonical",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 341,
|
||||
"planning_time_ms": 70,
|
||||
"retrieval_time_ms": 132,
|
||||
"response_generation_time_ms": 139,
|
||||
"context_size": 1598,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q05",
|
||||
"question_text": "Договоры топ-контрагента.",
|
||||
"question_class": "simple_factual",
|
||||
"expected_route": "store_canonical",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 344,
|
||||
"planning_time_ms": 71,
|
||||
"retrieval_time_ms": 133,
|
||||
"response_generation_time_ms": 140,
|
||||
"context_size": 1599,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q06",
|
||||
"question_text": "Объясни сальдо через движения.",
|
||||
"question_class": "drilldown_explain",
|
||||
"expected_route": "hybrid_store_plus_live",
|
||||
"actual_route": "hybrid_store_plus_live",
|
||||
"sources_used": [
|
||||
"canonical_store",
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 819,
|
||||
"planning_time_ms": 114,
|
||||
"retrieval_time_ms": 524,
|
||||
"response_generation_time_ms": 181,
|
||||
"context_size": 2950,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=hybrid_store_plus_live; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q07",
|
||||
"question_text": "Почему проводка на этот счет?",
|
||||
"question_class": "drilldown_explain",
|
||||
"expected_route": "live_mcp_drilldown",
|
||||
"actual_route": "live_mcp_drilldown",
|
||||
"sources_used": [
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 1035,
|
||||
"planning_time_ms": 98,
|
||||
"retrieval_time_ms": 745,
|
||||
"response_generation_time_ms": 192,
|
||||
"context_size": 2801,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=live_mcp_drilldown; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q08",
|
||||
"question_text": "Цепочка документ -> проводки -> субконто.",
|
||||
"question_class": "drilldown_explain",
|
||||
"expected_route": "live_mcp_drilldown",
|
||||
"actual_route": "live_mcp_drilldown",
|
||||
"sources_used": [
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 1038,
|
||||
"planning_time_ms": 99,
|
||||
"retrieval_time_ms": 746,
|
||||
"response_generation_time_ms": 193,
|
||||
"context_size": 2802,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=live_mcp_drilldown; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q09",
|
||||
"question_text": "Источник регистра для строки движения.",
|
||||
"question_class": "drilldown_explain",
|
||||
"expected_route": "live_mcp_drilldown",
|
||||
"actual_route": "hybrid_store_plus_live",
|
||||
"sources_used": [
|
||||
"canonical_store",
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 828,
|
||||
"planning_time_ms": 117,
|
||||
"retrieval_time_ms": 527,
|
||||
"response_generation_time_ms": 184,
|
||||
"context_size": 2953,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=hybrid_store_plus_live; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "acceptable_with_warning",
|
||||
"issues_detected": [
|
||||
"Route mismatch: expected live_mcp_drilldown, got hybrid_store_plus_live"
|
||||
],
|
||||
"recommended_fix": "Tune router threshold for heavy/live boundary."
|
||||
},
|
||||
{
|
||||
"question_id": "Q10",
|
||||
"question_text": "Почему выбрано это субконто3?",
|
||||
"question_class": "drilldown_explain",
|
||||
"expected_route": "live_mcp_drilldown",
|
||||
"actual_route": "live_mcp_drilldown",
|
||||
"sources_used": [
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 1017,
|
||||
"planning_time_ms": 92,
|
||||
"retrieval_time_ms": 739,
|
||||
"response_generation_time_ms": 186,
|
||||
"context_size": 2795,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=live_mcp_drilldown; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q11",
|
||||
"question_text": "Свяжи документы покупателей и проводки.",
|
||||
"question_class": "cross_entity",
|
||||
"expected_route": "hybrid_store_plus_live",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 335,
|
||||
"planning_time_ms": 68,
|
||||
"retrieval_time_ms": 130,
|
||||
"response_generation_time_ms": 137,
|
||||
"context_size": 1596,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "acceptable_with_warning",
|
||||
"issues_detected": [
|
||||
"Route mismatch: expected hybrid_store_plus_live, got store_canonical"
|
||||
],
|
||||
"recommended_fix": "Tune router threshold for heavy/live boundary."
|
||||
},
|
||||
{
|
||||
"question_id": "Q12",
|
||||
"question_text": "Свяжи контрагентов, договоры и проводки.",
|
||||
"question_class": "cross_entity",
|
||||
"expected_route": "hybrid_store_plus_live",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 338,
|
||||
"planning_time_ms": 69,
|
||||
"retrieval_time_ms": 131,
|
||||
"response_generation_time_ms": 138,
|
||||
"context_size": 1597,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "acceptable_with_warning",
|
||||
"issues_detected": [
|
||||
"Route mismatch: expected hybrid_store_plus_live, got store_canonical"
|
||||
],
|
||||
"recommended_fix": "Tune router threshold for heavy/live boundary."
|
||||
},
|
||||
{
|
||||
"question_id": "Q13",
|
||||
"question_text": "Номенклатура, склад, обороты за июнь.",
|
||||
"question_class": "cross_entity",
|
||||
"expected_route": "store_canonical",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 341,
|
||||
"planning_time_ms": 70,
|
||||
"retrieval_time_ms": 132,
|
||||
"response_generation_time_ms": 139,
|
||||
"context_size": 1598,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q14",
|
||||
"question_text": "Регистр и первичный документ.",
|
||||
"question_class": "cross_entity",
|
||||
"expected_route": "hybrid_store_plus_live",
|
||||
"actual_route": "hybrid_store_plus_live",
|
||||
"sources_used": [
|
||||
"canonical_store",
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 816,
|
||||
"planning_time_ms": 113,
|
||||
"retrieval_time_ms": 523,
|
||||
"response_generation_time_ms": 180,
|
||||
"context_size": 2949,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=hybrid_store_plus_live; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q15",
|
||||
"question_text": "По счету: контрагенты и договоры.",
|
||||
"question_class": "cross_entity",
|
||||
"expected_route": "store_canonical",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 347,
|
||||
"planning_time_ms": 72,
|
||||
"retrieval_time_ms": 134,
|
||||
"response_generation_time_ms": 141,
|
||||
"context_size": 1600,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q16",
|
||||
"question_text": "Обороты июня против мая.",
|
||||
"question_class": "period_trend",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 402,
|
||||
"planning_time_ms": 85,
|
||||
"retrieval_time_ms": 155,
|
||||
"response_generation_time_ms": 162,
|
||||
"context_size": 2101,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q17",
|
||||
"question_text": "Недельные всплески в июне.",
|
||||
"question_class": "period_trend",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 405,
|
||||
"planning_time_ms": 86,
|
||||
"retrieval_time_ms": 156,
|
||||
"response_generation_time_ms": 163,
|
||||
"context_size": 2102,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q18",
|
||||
"question_text": "Кто дал резкий рост активности.",
|
||||
"question_class": "period_trend",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 408,
|
||||
"planning_time_ms": 87,
|
||||
"retrieval_time_ms": 157,
|
||||
"response_generation_time_ms": 164,
|
||||
"context_size": 2103,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q19",
|
||||
"question_text": "Аномальный рост расходных операций?",
|
||||
"question_class": "period_trend",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 411,
|
||||
"planning_time_ms": 88,
|
||||
"retrieval_time_ms": 158,
|
||||
"response_generation_time_ms": 165,
|
||||
"context_size": 2104,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q20",
|
||||
"question_text": "Динамика НДС к соседним периодам.",
|
||||
"question_class": "period_trend",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 387,
|
||||
"planning_time_ms": 80,
|
||||
"retrieval_time_ms": 150,
|
||||
"response_generation_time_ms": 157,
|
||||
"context_size": 2096,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q21",
|
||||
"question_text": "Нетипичные корреспонденции счетов.",
|
||||
"question_class": "anomaly_control",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 390,
|
||||
"planning_time_ms": 81,
|
||||
"retrieval_time_ms": 151,
|
||||
"response_generation_time_ms": 158,
|
||||
"context_size": 2097,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q22",
|
||||
"question_text": "Незакрытые хвосты по расчетам.",
|
||||
"question_class": "anomaly_control",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 393,
|
||||
"planning_time_ms": 82,
|
||||
"retrieval_time_ms": 152,
|
||||
"response_generation_time_ms": 159,
|
||||
"context_size": 2098,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q23",
|
||||
"question_text": "Дублирующиеся проводки.",
|
||||
"question_class": "anomaly_control",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 396,
|
||||
"planning_time_ms": 83,
|
||||
"retrieval_time_ms": 153,
|
||||
"response_generation_time_ms": 160,
|
||||
"context_size": 2099,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q24",
|
||||
"question_text": "Пустые или странные субконто.",
|
||||
"question_class": "anomaly_control",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 399,
|
||||
"planning_time_ms": 84,
|
||||
"retrieval_time_ms": 154,
|
||||
"response_generation_time_ms": 161,
|
||||
"context_size": 2100,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q25",
|
||||
"question_text": "Узлы с подозрительно большим degree.",
|
||||
"question_class": "anomaly_control",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 402,
|
||||
"planning_time_ms": 85,
|
||||
"retrieval_time_ms": 155,
|
||||
"response_generation_time_ms": 162,
|
||||
"context_size": 2101,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q26",
|
||||
"question_text": "Полный риск-срез за июнь.",
|
||||
"question_class": "heavy_analytical",
|
||||
"expected_route": "batch_refresh_then_store",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 405,
|
||||
"planning_time_ms": 86,
|
||||
"retrieval_time_ms": 156,
|
||||
"response_generation_time_ms": 163,
|
||||
"context_size": 2102,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "acceptable_with_warning",
|
||||
"issues_detected": [
|
||||
"Route mismatch: expected batch_refresh_then_store, got store_feature_risk"
|
||||
],
|
||||
"recommended_fix": "Tune router threshold for heavy/live boundary."
|
||||
},
|
||||
{
|
||||
"question_id": "Q27",
|
||||
"question_text": "Рейтинг риск-счетов.",
|
||||
"question_class": "heavy_analytical",
|
||||
"expected_route": "batch_refresh_then_store",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 408,
|
||||
"planning_time_ms": 87,
|
||||
"retrieval_time_ms": 157,
|
||||
"response_generation_time_ms": 164,
|
||||
"context_size": 2103,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "acceptable_with_warning",
|
||||
"issues_detected": [
|
||||
"Route mismatch: expected batch_refresh_then_store, got store_feature_risk"
|
||||
],
|
||||
"recommended_fix": "Tune router threshold for heavy/live boundary."
|
||||
},
|
||||
{
|
||||
"question_id": "Q28",
|
||||
"question_text": "Рейтинг риск-контрагентов.",
|
||||
"question_class": "heavy_analytical",
|
||||
"expected_route": "batch_refresh_then_store",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 411,
|
||||
"planning_time_ms": 88,
|
||||
"retrieval_time_ms": 158,
|
||||
"response_generation_time_ms": 165,
|
||||
"context_size": 2104,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "acceptable_with_warning",
|
||||
"issues_detected": [
|
||||
"Route mismatch: expected batch_refresh_then_store, got store_feature_risk"
|
||||
],
|
||||
"recommended_fix": "Tune router threshold for heavy/live boundary."
|
||||
},
|
||||
{
|
||||
"question_id": "Q29",
|
||||
"question_text": "Baseline closed/open periods.",
|
||||
"question_class": "heavy_analytical",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 414,
|
||||
"planning_time_ms": 89,
|
||||
"retrieval_time_ms": 159,
|
||||
"response_generation_time_ms": 166,
|
||||
"context_size": 2105,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q30",
|
||||
"question_text": "Company anomaly summary.",
|
||||
"question_class": "heavy_analytical",
|
||||
"expected_route": "batch_refresh_then_store",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 390,
|
||||
"planning_time_ms": 81,
|
||||
"retrieval_time_ms": 151,
|
||||
"response_generation_time_ms": 158,
|
||||
"context_size": 2097,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "acceptable_with_warning",
|
||||
"issues_detected": [
|
||||
"Route mismatch: expected batch_refresh_then_store, got store_feature_risk"
|
||||
],
|
||||
"recommended_fix": "Tune router threshold for heavy/live boundary."
|
||||
},
|
||||
{
|
||||
"question_id": "Q31",
|
||||
"question_text": "Что по налогам и рискам?",
|
||||
"question_class": "ambiguous_fuzzy",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 393,
|
||||
"planning_time_ms": 82,
|
||||
"retrieval_time_ms": 152,
|
||||
"response_generation_time_ms": 159,
|
||||
"context_size": 2098,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q32",
|
||||
"question_text": "Что странное в расходах?",
|
||||
"question_class": "ambiguous_fuzzy",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 396,
|
||||
"planning_time_ms": 83,
|
||||
"retrieval_time_ms": 153,
|
||||
"response_generation_time_ms": 160,
|
||||
"context_size": 2099,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q33",
|
||||
"question_text": "Самые рисковые контрагенты?",
|
||||
"question_class": "ambiguous_fuzzy",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 399,
|
||||
"planning_time_ms": 84,
|
||||
"retrieval_time_ms": 154,
|
||||
"response_generation_time_ms": 161,
|
||||
"context_size": 2100,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q34",
|
||||
"question_text": "Что с 68.02?",
|
||||
"question_class": "ambiguous_fuzzy",
|
||||
"expected_route": "hybrid_store_plus_live",
|
||||
"actual_route": "hybrid_store_plus_live",
|
||||
"sources_used": [
|
||||
"canonical_store",
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 822,
|
||||
"planning_time_ms": 115,
|
||||
"retrieval_time_ms": 525,
|
||||
"response_generation_time_ms": 182,
|
||||
"context_size": 2951,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=hybrid_store_plus_live; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q35",
|
||||
"question_text": "Проверить документы июня.",
|
||||
"question_class": "ambiguous_fuzzy",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 405,
|
||||
"planning_time_ms": 86,
|
||||
"retrieval_time_ms": 156,
|
||||
"response_generation_time_ms": 163,
|
||||
"context_size": 2102,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
# LLM-like Simulation Profile
|
||||
|
||||
Simulation mode: `4o-mini-like` (controlled emulation)
|
||||
|
||||
## Constraints
|
||||
|
||||
- Store-first retrieval policy.
|
||||
- Compact planning and bounded context.
|
||||
- Limited live calls for drill-down only.
|
||||
- Avoid expensive heavy live scans.
|
||||
|
||||
## Route timing baseline (ms)
|
||||
|
||||
| Route | Planning | Retrieval | Generation | Context |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| live_mcp_drilldown | 95 | 780 | 180 | 2900 |
|
||||
| store_canonical | 70 | 170 | 130 | 1700 |
|
||||
| store_feature_risk | 82 | 190 | 150 | 2200 |
|
||||
| hybrid_store_plus_live | 112 | 560 | 170 | 3050 |
|
||||
| batch_refresh_then_store | 135 | 1240 | 210 | 3600 |
|
||||
|
||||
## Active run context
|
||||
|
||||
- Slice window: `2020-06`
|
||||
- Refresh latest run: `30b2a2da4d824e0b81c2fb263cb9b64b`
|
||||
- Feature latest run: `2d2dc33e509e4f5681b64217673dad09`
|
||||
- Risk latest run: `d4833f6aa39f4bb5b4897c3d48caa843`
|
||||
@@ -0,0 +1,50 @@
|
||||
# Ontology & Mapping Audit
|
||||
|
||||
## Core metrics
|
||||
|
||||
| Metric | Value |
|
||||
| --- | --- |
|
||||
| entity_classes_total | 42 |
|
||||
| covered_entity_classes | 33 |
|
||||
| uncovered_entity_classes | 9 |
|
||||
| relation_types_total | 1 |
|
||||
| correctly_typed_relations | 1602 |
|
||||
| unknown_relations | 1016 |
|
||||
| conflicting_mappings_count | 0 |
|
||||
| link_coverage_pct | 100.0 |
|
||||
| semantic_coverage_pct | 61.1917 |
|
||||
|
||||
## Top problematic source entity types
|
||||
|
||||
| Source entity | Unknown relations |
|
||||
| --- | --- |
|
||||
| AccumulationRegister_НДСПредъявленный_RecordType | 130 |
|
||||
| Document_СписаниеСРасчетногоСчета | 116 |
|
||||
| DocumentJournal_ЖурналОпераций | 114 |
|
||||
| AccumulationRegister_НДСЗаписиКнигиПродаж_RecordType | 92 |
|
||||
| DocumentJournal_БанковскиеВыписки | 90 |
|
||||
| DocumentJournal_ДокументыПоставщиков | 90 |
|
||||
| Document_РеализацияТоваровУслуг | 60 |
|
||||
| Document_ПоступлениеТоваровУслуг | 50 |
|
||||
| DocumentJournal_ДокументыПокупателей | 32 |
|
||||
| AccumulationRegister_НДФЛРасчетыСБюджетом_RecordType | 28 |
|
||||
| Document_СчетФактураВыданный | 25 |
|
||||
| AccumulationRegister_НДСЗаписиКнигиПокупок_RecordType | 24 |
|
||||
|
||||
## Top problematic relation fields
|
||||
|
||||
| Source field | Unknown relations |
|
||||
| --- | --- |
|
||||
| Ответственный_Key | 187 |
|
||||
| Ref | 168 |
|
||||
| Recorder | 147 |
|
||||
| Поставщик_Key | 78 |
|
||||
| ФизЛицо_Key | 49 |
|
||||
| Информация | 49 |
|
||||
| Покупатель_Key | 46 |
|
||||
| Валюта_Key | 34 |
|
||||
| СтатьяДвиженияДенежныхСредств_Key | 34 |
|
||||
| ПодразделениеДт_Key | 29 |
|
||||
| ОбособленноеПодразделение_Key | 18 |
|
||||
| Склад_Key | 16 |
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# Orchestration Policy Spec
|
||||
|
||||
## Decision tree
|
||||
|
||||
- exact object trace or posting chain -> `live_mcp_drilldown`
|
||||
- simple factual in loaded slice -> `store_canonical`
|
||||
- trend/anomaly/risk -> `store_feature_risk`
|
||||
- heavy whole-slice with freshness gap -> `batch_refresh_then_store`
|
||||
- low confidence fallback -> `hybrid_store_plus_live`
|
||||
|
||||
## Routing rules
|
||||
|
||||
- Prefer store answers when freshness allows.
|
||||
- Use live bridge only for drill-down evidence.
|
||||
- Do not run uncapped heavy live scans.
|
||||
- Trigger refresh/features/risk for stale context.
|
||||
- Apply retrieval/context budget before fallback.
|
||||
|
||||
## Source priorities
|
||||
|
||||
| Scenario | Priority order |
|
||||
| --- | --- |
|
||||
| simple_factual | canonical_store -> mcp_runtime_bridge |
|
||||
| drilldown_explain | mcp_runtime_bridge -> canonical_store |
|
||||
| period_trend | feature_store -> risk_store -> canonical_store |
|
||||
| anomaly_control | risk_store -> feature_store -> canonical_store |
|
||||
| heavy_analytical | batch_refresh_then_store -> feature_store -> risk_store |
|
||||
| ambiguous_fuzzy | feature_store -> canonical_store -> mcp_runtime_bridge |
|
||||
|
||||
## Timeout budget (ms)
|
||||
|
||||
| Budget | Value |
|
||||
| --- | --- |
|
||||
| planning | 200 |
|
||||
| retrieval_soft_limit | 1200 |
|
||||
| retrieval_hard_limit | 2500 |
|
||||
| response_generation | 600 |
|
||||
@@ -0,0 +1,20 @@
|
||||
# Slice Ingestion Report
|
||||
|
||||
Validation date: 2026-03-23T09:28:12.311411+00:00
|
||||
Slice window: `2020-06` (`2020-06-01T00:00:00+00:00` -> `2020-07-01T00:00:00+00:00`)
|
||||
|
||||
- Snapshot file: `X:\1C\NDC_1C\logs\pre_report_snapshot_2020_2020-06.json`
|
||||
- Profile file: `X:\1C\NDC_1C\logs\pre_report_activity_2020.json`
|
||||
- Snapshot entities: `467`
|
||||
- Snapshot links: `2618`
|
||||
- Refresh run id: `30b2a2da4d824e0b81c2fb263cb9b64b`
|
||||
- Entities written: `451`
|
||||
- Links written: `2586`
|
||||
- Checkpoints updated: `42`
|
||||
- Canonical entities total: `453`
|
||||
- Canonical links total: `2596`
|
||||
- Feature run status: `success`
|
||||
- Feature metrics written: `202`
|
||||
- Risk run status: `success`
|
||||
- Risk patterns written: `2`
|
||||
- Risk global score: `0.608542`
|
||||
@@ -0,0 +1,19 @@
|
||||
# Benchmark Final Verdict
|
||||
|
||||
## Verdict
|
||||
|
||||
`adopt_ready_for_pilot`
|
||||
|
||||
## Key numbers
|
||||
|
||||
- Questions total: `35`
|
||||
- Route mismatches: `1`
|
||||
- Degraded answers: `0`
|
||||
- Avg latency ms: `705.63`
|
||||
- p95 latency ms: `1571.9`
|
||||
|
||||
## Recommendation
|
||||
|
||||
1. Fix ontology unknown mapping hotspots.
|
||||
2. Tune heavy-route threshold (`store_feature_risk` vs `batch_refresh_then_store`).
|
||||
3. Implement full production orchestration runtime.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Benchmark Questions (35)
|
||||
|
||||
| ID | Class | Expected route | Question |
|
||||
| --- | --- | --- | --- |
|
||||
| Q01 | simple_factual | store_canonical | Сальдо счета 68.02 за июнь 2020? |
|
||||
| Q02 | simple_factual | live_mcp_drilldown | Документ по номеру и его ссылка. |
|
||||
| Q03 | simple_factual | store_canonical | Типовая проводка по реализации. |
|
||||
| Q04 | simple_factual | store_canonical | Контрагент с максимумом оборота. |
|
||||
| Q05 | simple_factual | store_canonical | Договоры топ-контрагента. |
|
||||
| Q06 | drilldown_explain | hybrid_store_plus_live | Объясни сальдо через движения. |
|
||||
| Q07 | drilldown_explain | live_mcp_drilldown | Почему проводка на этот счет? |
|
||||
| Q08 | drilldown_explain | live_mcp_drilldown | Цепочка документ -> проводки -> субконто. |
|
||||
| Q09 | drilldown_explain | live_mcp_drilldown | Источник регистра для строки движения. |
|
||||
| Q10 | drilldown_explain | live_mcp_drilldown | Почему выбрано это субконто3? |
|
||||
| Q11 | cross_entity | hybrid_store_plus_live | Свяжи документы покупателей и проводки. |
|
||||
| Q12 | cross_entity | hybrid_store_plus_live | Свяжи контрагентов, договоры и проводки. |
|
||||
| Q13 | cross_entity | store_canonical | Номенклатура, склад, обороты за июнь. |
|
||||
| Q14 | cross_entity | hybrid_store_plus_live | Регистр и первичный документ. |
|
||||
| Q15 | cross_entity | store_canonical | По счету: контрагенты и договоры. |
|
||||
| Q16 | period_trend | store_feature_risk | Обороты июня против мая. |
|
||||
| Q17 | period_trend | store_feature_risk | Недельные всплески в июне. |
|
||||
| Q18 | period_trend | store_feature_risk | Кто дал резкий рост активности. |
|
||||
| Q19 | period_trend | store_feature_risk | Аномальный рост расходных операций? |
|
||||
| Q20 | period_trend | store_feature_risk | Динамика НДС к соседним периодам. |
|
||||
| Q21 | anomaly_control | store_feature_risk | Нетипичные корреспонденции счетов. |
|
||||
| Q22 | anomaly_control | store_feature_risk | Незакрытые хвосты по расчетам. |
|
||||
| Q23 | anomaly_control | store_feature_risk | Дублирующиеся проводки. |
|
||||
| Q24 | anomaly_control | store_feature_risk | Пустые или странные субконто. |
|
||||
| Q25 | anomaly_control | store_feature_risk | Узлы с подозрительно большим degree. |
|
||||
| Q26 | heavy_analytical | batch_refresh_then_store | Полный риск-срез за июнь. |
|
||||
| Q27 | heavy_analytical | batch_refresh_then_store | Рейтинг риск-счетов. |
|
||||
| Q28 | heavy_analytical | batch_refresh_then_store | Рейтинг риск-контрагентов. |
|
||||
| Q29 | heavy_analytical | store_feature_risk | Baseline closed/open periods. |
|
||||
| Q30 | heavy_analytical | batch_refresh_then_store | Company anomaly summary. |
|
||||
| Q31 | ambiguous_fuzzy | store_feature_risk | Что по налогам и рискам? |
|
||||
| Q32 | ambiguous_fuzzy | store_feature_risk | Что странное в расходах? |
|
||||
| Q33 | ambiguous_fuzzy | store_feature_risk | Самые рисковые контрагенты? |
|
||||
| Q34 | ambiguous_fuzzy | hybrid_store_plus_live | Что с 68.02? |
|
||||
| Q35 | ambiguous_fuzzy | store_feature_risk | Проверить документы июня. |
|
||||
@@ -0,0 +1,17 @@
|
||||
# Benchmark Route Analysis
|
||||
|
||||
- Total mismatches: `1`
|
||||
|
||||
## Route confusion matrix
|
||||
|
||||
- `batch_refresh_then_store` -> batch_refresh_then_store:4
|
||||
- `hybrid_store_plus_live` -> hybrid_store_plus_live:5
|
||||
- `live_mcp_drilldown` -> live_mcp_drilldown:5
|
||||
- `store_canonical` -> store_canonical:6
|
||||
- `store_feature_risk` -> batch_refresh_then_store:1, store_feature_risk:14
|
||||
|
||||
## Mismatch by class
|
||||
|
||||
| Class | Mismatch count |
|
||||
| --- | --- |
|
||||
| period_trend | 1 |
|
||||
@@ -0,0 +1,39 @@
|
||||
# Benchmark Run Report
|
||||
|
||||
## Aggregate statistics
|
||||
|
||||
| Metric | Value |
|
||||
| --- | --- |
|
||||
| questions_total | 35 |
|
||||
| avg_latency_ms | 705.63 |
|
||||
| median_latency_ms | 405 |
|
||||
| p90_latency_ms | 1562.0 |
|
||||
| p95_latency_ms | 1571.9 |
|
||||
| avg_context_size | 2435.37 |
|
||||
| live_route_count | 10 |
|
||||
| store_route_count | 20 |
|
||||
| batch_route_count | 5 |
|
||||
| route_mismatch_count | 1 |
|
||||
| degraded_answers_count | 0 |
|
||||
|
||||
## Route distribution
|
||||
|
||||
| Route | Count |
|
||||
| --- | --- |
|
||||
| batch_refresh_then_store | 5 |
|
||||
| hybrid_store_plus_live | 5 |
|
||||
| live_mcp_drilldown | 5 |
|
||||
| store_canonical | 6 |
|
||||
| store_feature_risk | 14 |
|
||||
|
||||
## Question class distribution
|
||||
|
||||
| Class | Count |
|
||||
| --- | --- |
|
||||
| ambiguous_fuzzy | 5 |
|
||||
| anomaly_control | 5 |
|
||||
| cross_entity | 5 |
|
||||
| drilldown_explain | 5 |
|
||||
| heavy_analytical | 5 |
|
||||
| period_trend | 5 |
|
||||
| simple_factual | 5 |
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
||||
# LLM-like Simulation Profile
|
||||
|
||||
Simulation mode: `4o-mini-like` (controlled emulation)
|
||||
|
||||
## Constraints
|
||||
|
||||
- Store-first retrieval policy.
|
||||
- Compact planning and bounded context.
|
||||
- Limited live calls for drill-down only.
|
||||
- Avoid expensive heavy live scans.
|
||||
|
||||
## Route timing baseline (ms)
|
||||
|
||||
| Route | Planning | Retrieval | Generation | Context |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| live_mcp_drilldown | 95 | 780 | 180 | 2900 |
|
||||
| store_canonical | 70 | 170 | 130 | 1700 |
|
||||
| store_feature_risk | 82 | 190 | 150 | 2200 |
|
||||
| hybrid_store_plus_live | 112 | 560 | 170 | 3050 |
|
||||
| batch_refresh_then_store | 135 | 1240 | 210 | 3600 |
|
||||
|
||||
## Active run context
|
||||
|
||||
- Slice window: `2020-06`
|
||||
- Refresh latest run: `6f6c622c254e4e79a86ccdbd140b1631`
|
||||
- Feature latest run: `c1daa35506474be19331f21cf663282a`
|
||||
- Risk latest run: `b167c610c8b84dd79ca0357e72422c7f`
|
||||
@@ -0,0 +1,50 @@
|
||||
# Ontology & Mapping Audit
|
||||
|
||||
## Core metrics
|
||||
|
||||
| Metric | Value |
|
||||
| --- | --- |
|
||||
| entity_classes_total | 42 |
|
||||
| covered_entity_classes | 42 |
|
||||
| uncovered_entity_classes | 0 |
|
||||
| relation_types_total | 25 |
|
||||
| correctly_typed_relations | 1909 |
|
||||
| unknown_relations | 102 |
|
||||
| conflicting_mappings_count | 1 |
|
||||
| link_coverage_pct | 100.0 |
|
||||
| semantic_coverage_pct | 94.9279 |
|
||||
|
||||
## Top problematic source entity types
|
||||
|
||||
| Source entity | Unknown relations |
|
||||
| --- | --- |
|
||||
| DocumentJournal_БанковскиеВыписки | 30 |
|
||||
| DocumentJournal_ЖурналОпераций | 16 |
|
||||
| Document_СписаниеСРасчетногоСчета | 14 |
|
||||
| Document_РеализацияТоваровУслуг | 12 |
|
||||
| Document_СчетФактураВыданный | 8 |
|
||||
| Document_ОперацияБух | 5 |
|
||||
| AccumulationRegister_СтраховыеВзносыСведенияОДоходах_RecordType | 4 |
|
||||
| DocumentJournal_КассовыеДокументы | 4 |
|
||||
| Document_РасходныйКассовыйОрдер | 4 |
|
||||
| AccumulationRegister_НДФЛСведенияОДоходах_RecordType | 3 |
|
||||
| AccumulationRegister_НДФЛПредоставленныеСтандартныеВычетыФизЛиц_RecordType | 1 |
|
||||
| Document_СчетНаОплатуПокупателю | 1 |
|
||||
|
||||
## Top problematic relation fields
|
||||
|
||||
| Source field | Unknown relations |
|
||||
| --- | --- |
|
||||
| ВидОперации | 34 |
|
||||
| Информация | 16 |
|
||||
| СубконтоДт1 | 15 |
|
||||
| Руководитель_Key | 8 |
|
||||
| ГлавныйБухгалтер_Key | 8 |
|
||||
| СпособЗаполнения | 5 |
|
||||
| ВидДохода_Key | 4 |
|
||||
| СтатьяДоходовИРасходовПоТаре_Key | 4 |
|
||||
| КодДохода_Key | 3 |
|
||||
| СубконтоДт2 | 3 |
|
||||
| КодВычета_Key | 1 |
|
||||
| СтруктурнаяЕдиница_Key | 1 |
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# Orchestration Policy Spec
|
||||
|
||||
## Decision tree
|
||||
|
||||
- exact object trace or posting chain -> `live_mcp_drilldown`
|
||||
- simple factual in loaded slice -> `store_canonical`
|
||||
- trend/anomaly/risk -> `store_feature_risk`
|
||||
- heavy whole-slice with freshness gap -> `batch_refresh_then_store`
|
||||
- low confidence fallback -> `hybrid_store_plus_live`
|
||||
|
||||
## Routing rules
|
||||
|
||||
- Prefer store answers when freshness allows.
|
||||
- Use live bridge only for drill-down evidence.
|
||||
- Do not run uncapped heavy live scans.
|
||||
- Trigger refresh/features/risk for stale context.
|
||||
- Apply retrieval/context budget before fallback.
|
||||
|
||||
## Source priorities
|
||||
|
||||
| Scenario | Priority order |
|
||||
| --- | --- |
|
||||
| simple_factual | canonical_store -> mcp_runtime_bridge |
|
||||
| drilldown_explain | mcp_runtime_bridge -> canonical_store |
|
||||
| period_trend | feature_store -> risk_store -> canonical_store |
|
||||
| anomaly_control | risk_store -> feature_store -> canonical_store |
|
||||
| heavy_analytical | batch_refresh_then_store -> feature_store -> risk_store |
|
||||
| ambiguous_fuzzy | feature_store -> canonical_store -> mcp_runtime_bridge |
|
||||
|
||||
## Timeout budget (ms)
|
||||
|
||||
| Budget | Value |
|
||||
| --- | --- |
|
||||
| planning | 200 |
|
||||
| retrieval_soft_limit | 1200 |
|
||||
| retrieval_hard_limit | 2500 |
|
||||
| response_generation | 600 |
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
# Slice Ingestion Report
|
||||
|
||||
Validation date: 2026-03-23T11:04:31.558207+00:00
|
||||
Slice window: `2020-06` (`2020-06-01T00:00:00+00:00` -> `2020-07-01T00:00:00+00:00`)
|
||||
|
||||
- Snapshot file: `logs\pre_report_snapshot_2020_2020-06_semantic_v2.json`
|
||||
- Profile file: `X:\1C\NDC_1C\logs\pre_report_activity_2020.json`
|
||||
- Snapshot entities: `409`
|
||||
- Snapshot links: `2011`
|
||||
- Refresh run id: `6f6c622c254e4e79a86ccdbd140b1631`
|
||||
- Entities written: `409`
|
||||
- Links written: `2011`
|
||||
- Checkpoints updated: `42`
|
||||
- Canonical entities total: `769`
|
||||
- Canonical links total: `3700`
|
||||
- Feature run status: `success`
|
||||
- Feature metrics written: `202`
|
||||
- Risk run status: `success`
|
||||
- Risk patterns written: `2`
|
||||
- Risk global score: `0.977351`
|
||||
@@ -0,0 +1,19 @@
|
||||
# Benchmark Final Verdict
|
||||
|
||||
## Verdict
|
||||
|
||||
`adopt_ready_for_pilot`
|
||||
|
||||
## Key numbers
|
||||
|
||||
- Questions total: `35`
|
||||
- Route mismatches: `0`
|
||||
- Degraded answers: `0`
|
||||
- Avg latency ms: `672.4`
|
||||
- p95 latency ms: `1568.9`
|
||||
|
||||
## Recommendation
|
||||
|
||||
1. Fix ontology unknown mapping hotspots.
|
||||
2. Tune heavy-route threshold (`store_feature_risk` vs `batch_refresh_then_store`).
|
||||
3. Implement full production orchestration runtime.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Benchmark Questions (35)
|
||||
|
||||
| ID | Class | Expected route | Question |
|
||||
| --- | --- | --- | --- |
|
||||
| Q01 | simple_factual | store_canonical | Сальдо счета 68.02 за июнь 2020? |
|
||||
| Q02 | simple_factual | live_mcp_drilldown | Документ по номеру и его ссылка. |
|
||||
| Q03 | simple_factual | store_canonical | Типовая проводка по реализации. |
|
||||
| Q04 | simple_factual | store_canonical | Контрагент с максимумом оборота. |
|
||||
| Q05 | simple_factual | store_canonical | Договоры топ-контрагента. |
|
||||
| Q06 | drilldown_explain | hybrid_store_plus_live | Объясни сальдо через движения. |
|
||||
| Q07 | drilldown_explain | live_mcp_drilldown | Почему проводка на этот счет? |
|
||||
| Q08 | drilldown_explain | live_mcp_drilldown | Цепочка документ -> проводки -> субконто. |
|
||||
| Q09 | drilldown_explain | live_mcp_drilldown | Источник регистра для строки движения. |
|
||||
| Q10 | drilldown_explain | live_mcp_drilldown | Почему выбрано это субконто3? |
|
||||
| Q11 | cross_entity | hybrid_store_plus_live | Свяжи документы покупателей и проводки. |
|
||||
| Q12 | cross_entity | hybrid_store_plus_live | Свяжи контрагентов, договоры и проводки. |
|
||||
| Q13 | cross_entity | store_canonical | Номенклатура, склад, обороты за июнь. |
|
||||
| Q14 | cross_entity | hybrid_store_plus_live | Регистр и первичный документ. |
|
||||
| Q15 | cross_entity | store_canonical | По счету: контрагенты и договоры. |
|
||||
| Q16 | period_trend | store_feature_risk | Обороты июня против мая. |
|
||||
| Q17 | period_trend | store_feature_risk | Недельные всплески в июне. |
|
||||
| Q18 | period_trend | store_feature_risk | Кто дал резкий рост активности. |
|
||||
| Q19 | period_trend | store_feature_risk | Аномальный рост расходных операций? |
|
||||
| Q20 | period_trend | store_feature_risk | Динамика НДС к соседним периодам. |
|
||||
| Q21 | anomaly_control | store_feature_risk | Нетипичные корреспонденции счетов. |
|
||||
| Q22 | anomaly_control | store_feature_risk | Незакрытые хвосты по расчетам. |
|
||||
| Q23 | anomaly_control | store_feature_risk | Дублирующиеся проводки. |
|
||||
| Q24 | anomaly_control | store_feature_risk | Пустые или странные субконто. |
|
||||
| Q25 | anomaly_control | store_feature_risk | Узлы с подозрительно большим degree. |
|
||||
| Q26 | heavy_analytical | batch_refresh_then_store | Полный риск-срез за июнь. |
|
||||
| Q27 | heavy_analytical | batch_refresh_then_store | Рейтинг риск-счетов. |
|
||||
| Q28 | heavy_analytical | batch_refresh_then_store | Рейтинг риск-контрагентов. |
|
||||
| Q29 | heavy_analytical | store_feature_risk | Baseline closed/open periods. |
|
||||
| Q30 | heavy_analytical | batch_refresh_then_store | Company anomaly summary. |
|
||||
| Q31 | ambiguous_fuzzy | store_feature_risk | Что по налогам и рискам? |
|
||||
| Q32 | ambiguous_fuzzy | store_feature_risk | Что странное в расходах? |
|
||||
| Q33 | ambiguous_fuzzy | store_feature_risk | Самые рисковые контрагенты? |
|
||||
| Q34 | ambiguous_fuzzy | hybrid_store_plus_live | Что с 68.02? |
|
||||
| Q35 | ambiguous_fuzzy | store_feature_risk | Проверить документы июня. |
|
||||
@@ -0,0 +1,17 @@
|
||||
# Benchmark Route Analysis
|
||||
|
||||
- Total mismatches: `0`
|
||||
|
||||
## Route confusion matrix
|
||||
|
||||
- `batch_refresh_then_store` -> batch_refresh_then_store:4
|
||||
- `hybrid_store_plus_live` -> hybrid_store_plus_live:5
|
||||
- `live_mcp_drilldown` -> live_mcp_drilldown:5
|
||||
- `store_canonical` -> store_canonical:6
|
||||
- `store_feature_risk` -> store_feature_risk:15
|
||||
|
||||
## Mismatch by class
|
||||
|
||||
| Class | Mismatch count |
|
||||
| --- | --- |
|
||||
| n/a | 0 |
|
||||
@@ -0,0 +1,39 @@
|
||||
# Benchmark Run Report
|
||||
|
||||
## Aggregate statistics
|
||||
|
||||
| Metric | Value |
|
||||
| --- | --- |
|
||||
| questions_total | 35 |
|
||||
| avg_latency_ms | 672.4 |
|
||||
| median_latency_ms | 405 |
|
||||
| p90_latency_ms | 1348.2 |
|
||||
| p95_latency_ms | 1568.9 |
|
||||
| avg_context_size | 2395.37 |
|
||||
| live_route_count | 10 |
|
||||
| store_route_count | 21 |
|
||||
| batch_route_count | 4 |
|
||||
| route_mismatch_count | 0 |
|
||||
| degraded_answers_count | 0 |
|
||||
|
||||
## Route distribution
|
||||
|
||||
| Route | Count |
|
||||
| --- | --- |
|
||||
| batch_refresh_then_store | 4 |
|
||||
| hybrid_store_plus_live | 5 |
|
||||
| live_mcp_drilldown | 5 |
|
||||
| store_canonical | 6 |
|
||||
| store_feature_risk | 15 |
|
||||
|
||||
## Question class distribution
|
||||
|
||||
| Class | Count |
|
||||
| --- | --- |
|
||||
| ambiguous_fuzzy | 5 |
|
||||
| anomaly_control | 5 |
|
||||
| cross_entity | 5 |
|
||||
| drilldown_explain | 5 |
|
||||
| heavy_analytical | 5 |
|
||||
| period_trend | 5 |
|
||||
| simple_factual | 5 |
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
||||
# LLM-like Simulation Profile
|
||||
|
||||
Simulation mode: `4o-mini-like` (controlled emulation)
|
||||
|
||||
## Constraints
|
||||
|
||||
- Store-first retrieval policy.
|
||||
- Compact planning and bounded context.
|
||||
- Limited live calls for drill-down only.
|
||||
- Avoid expensive heavy live scans.
|
||||
|
||||
## Route timing baseline (ms)
|
||||
|
||||
| Route | Planning | Retrieval | Generation | Context |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| live_mcp_drilldown | 95 | 780 | 180 | 2900 |
|
||||
| store_canonical | 70 | 170 | 130 | 1700 |
|
||||
| store_feature_risk | 82 | 190 | 150 | 2200 |
|
||||
| hybrid_store_plus_live | 112 | 560 | 170 | 3050 |
|
||||
| batch_refresh_then_store | 135 | 1240 | 210 | 3600 |
|
||||
|
||||
## Active run context
|
||||
|
||||
- Slice window: `2020-06`
|
||||
- Refresh latest run: `44b9881f29f343d7816b89ddf3e4a6ec`
|
||||
- Feature latest run: `ce3a6385d6fd43f480ddf9b499c76e7a`
|
||||
- Risk latest run: `0895566641a74a44adf19faa5dc4f385`
|
||||
@@ -0,0 +1,50 @@
|
||||
# Ontology & Mapping Audit
|
||||
|
||||
## Core metrics
|
||||
|
||||
| Metric | Value |
|
||||
| --- | --- |
|
||||
| entity_classes_total | 42 |
|
||||
| covered_entity_classes | 42 |
|
||||
| uncovered_entity_classes | 0 |
|
||||
| relation_types_total | 25 |
|
||||
| correctly_typed_relations | 1909 |
|
||||
| unknown_relations | 102 |
|
||||
| conflicting_mappings_count | 1 |
|
||||
| link_coverage_pct | 100.0 |
|
||||
| semantic_coverage_pct | 94.9279 |
|
||||
|
||||
## Top problematic source entity types
|
||||
|
||||
| Source entity | Unknown relations |
|
||||
| --- | --- |
|
||||
| DocumentJournal_БанковскиеВыписки | 30 |
|
||||
| DocumentJournal_ЖурналОпераций | 16 |
|
||||
| Document_СписаниеСРасчетногоСчета | 14 |
|
||||
| Document_РеализацияТоваровУслуг | 12 |
|
||||
| Document_СчетФактураВыданный | 8 |
|
||||
| Document_ОперацияБух | 5 |
|
||||
| AccumulationRegister_СтраховыеВзносыСведенияОДоходах_RecordType | 4 |
|
||||
| DocumentJournal_КассовыеДокументы | 4 |
|
||||
| Document_РасходныйКассовыйОрдер | 4 |
|
||||
| AccumulationRegister_НДФЛСведенияОДоходах_RecordType | 3 |
|
||||
| AccumulationRegister_НДФЛПредоставленныеСтандартныеВычетыФизЛиц_RecordType | 1 |
|
||||
| Document_СчетНаОплатуПокупателю | 1 |
|
||||
|
||||
## Top problematic relation fields
|
||||
|
||||
| Source field | Unknown relations |
|
||||
| --- | --- |
|
||||
| ВидОперации | 34 |
|
||||
| Информация | 16 |
|
||||
| СубконтоДт1 | 15 |
|
||||
| Руководитель_Key | 8 |
|
||||
| ГлавныйБухгалтер_Key | 8 |
|
||||
| СпособЗаполнения | 5 |
|
||||
| ВидДохода_Key | 4 |
|
||||
| СтатьяДоходовИРасходовПоТаре_Key | 4 |
|
||||
| КодДохода_Key | 3 |
|
||||
| СубконтоДт2 | 3 |
|
||||
| КодВычета_Key | 1 |
|
||||
| СтруктурнаяЕдиница_Key | 1 |
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# Orchestration Policy Spec
|
||||
|
||||
## Decision tree
|
||||
|
||||
- exact object trace or posting chain -> `live_mcp_drilldown`
|
||||
- simple factual in loaded slice -> `store_canonical`
|
||||
- trend/anomaly/risk -> `store_feature_risk`
|
||||
- heavy whole-slice with freshness gap -> `batch_refresh_then_store`
|
||||
- low confidence fallback -> `hybrid_store_plus_live`
|
||||
|
||||
## Routing rules
|
||||
|
||||
- Prefer store answers when freshness allows.
|
||||
- Use live bridge only for drill-down evidence.
|
||||
- Do not run uncapped heavy live scans.
|
||||
- Trigger refresh/features/risk for stale context.
|
||||
- Apply retrieval/context budget before fallback.
|
||||
|
||||
## Source priorities
|
||||
|
||||
| Scenario | Priority order |
|
||||
| --- | --- |
|
||||
| simple_factual | canonical_store -> mcp_runtime_bridge |
|
||||
| drilldown_explain | mcp_runtime_bridge -> canonical_store |
|
||||
| period_trend | feature_store -> risk_store -> canonical_store |
|
||||
| anomaly_control | risk_store -> feature_store -> canonical_store |
|
||||
| heavy_analytical | batch_refresh_then_store -> feature_store -> risk_store |
|
||||
| ambiguous_fuzzy | feature_store -> canonical_store -> mcp_runtime_bridge |
|
||||
|
||||
## Timeout budget (ms)
|
||||
|
||||
| Budget | Value |
|
||||
| --- | --- |
|
||||
| planning | 200 |
|
||||
| retrieval_soft_limit | 1200 |
|
||||
| retrieval_hard_limit | 2500 |
|
||||
| response_generation | 600 |
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
# Slice Ingestion Report
|
||||
|
||||
Validation date: 2026-03-23T11:09:29.880582+00:00
|
||||
Slice window: `2020-06` (`2020-06-01T00:00:00+00:00` -> `2020-07-01T00:00:00+00:00`)
|
||||
|
||||
- Snapshot file: `logs\pre_report_snapshot_2020_2020-06_semantic_v2.json`
|
||||
- Profile file: `X:\1C\NDC_1C\logs\pre_report_activity_2020.json`
|
||||
- Snapshot entities: `409`
|
||||
- Snapshot links: `2011`
|
||||
- Refresh run id: `44b9881f29f343d7816b89ddf3e4a6ec`
|
||||
- Entities written: `409`
|
||||
- Links written: `2011`
|
||||
- Checkpoints updated: `42`
|
||||
- Canonical entities total: `769`
|
||||
- Canonical links total: `3700`
|
||||
- Feature run status: `success`
|
||||
- Feature metrics written: `202`
|
||||
- Risk run status: `success`
|
||||
- Risk patterns written: `2`
|
||||
- Risk global score: `0.977351`
|
||||
@@ -0,0 +1,19 @@
|
||||
# Benchmark Final Verdict
|
||||
|
||||
## Verdict
|
||||
|
||||
`adopt_with_improvements`
|
||||
|
||||
## Key numbers
|
||||
|
||||
- Questions total: `35`
|
||||
- Route mismatches: `7`
|
||||
- Degraded answers: `0`
|
||||
- Avg latency ms: `506.43`
|
||||
- p95 latency ms: `1024.5`
|
||||
|
||||
## Recommendation
|
||||
|
||||
1. Fix ontology unknown mapping hotspots.
|
||||
2. Tune heavy-route threshold (`store_feature_risk` vs `batch_refresh_then_store`).
|
||||
3. Implement full production orchestration runtime.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Benchmark Questions (35)
|
||||
|
||||
| ID | Class | Expected route | Question |
|
||||
| --- | --- | --- | --- |
|
||||
| Q01 | simple_factual | store_canonical | Сальдо счета 68.02 за июнь 2020? |
|
||||
| Q02 | simple_factual | live_mcp_drilldown | Документ по номеру и его ссылка. |
|
||||
| Q03 | simple_factual | store_canonical | Типовая проводка по реализации. |
|
||||
| Q04 | simple_factual | store_canonical | Контрагент с максимумом оборота. |
|
||||
| Q05 | simple_factual | store_canonical | Договоры топ-контрагента. |
|
||||
| Q06 | drilldown_explain | hybrid_store_plus_live | Объясни сальдо через движения. |
|
||||
| Q07 | drilldown_explain | live_mcp_drilldown | Почему проводка на этот счет? |
|
||||
| Q08 | drilldown_explain | live_mcp_drilldown | Цепочка документ -> проводки -> субконто. |
|
||||
| Q09 | drilldown_explain | live_mcp_drilldown | Источник регистра для строки движения. |
|
||||
| Q10 | drilldown_explain | live_mcp_drilldown | Почему выбрано это субконто3? |
|
||||
| Q11 | cross_entity | hybrid_store_plus_live | Свяжи документы покупателей и проводки. |
|
||||
| Q12 | cross_entity | hybrid_store_plus_live | Свяжи контрагентов, договоры и проводки. |
|
||||
| Q13 | cross_entity | store_canonical | Номенклатура, склад, обороты за июнь. |
|
||||
| Q14 | cross_entity | hybrid_store_plus_live | Регистр и первичный документ. |
|
||||
| Q15 | cross_entity | store_canonical | По счету: контрагенты и договоры. |
|
||||
| Q16 | period_trend | store_feature_risk | Обороты июня против мая. |
|
||||
| Q17 | period_trend | store_feature_risk | Недельные всплески в июне. |
|
||||
| Q18 | period_trend | store_feature_risk | Кто дал резкий рост активности. |
|
||||
| Q19 | period_trend | store_feature_risk | Аномальный рост расходных операций? |
|
||||
| Q20 | period_trend | store_feature_risk | Динамика НДС к соседним периодам. |
|
||||
| Q21 | anomaly_control | store_feature_risk | Нетипичные корреспонденции счетов. |
|
||||
| Q22 | anomaly_control | store_feature_risk | Незакрытые хвосты по расчетам. |
|
||||
| Q23 | anomaly_control | store_feature_risk | Дублирующиеся проводки. |
|
||||
| Q24 | anomaly_control | store_feature_risk | Пустые или странные субконто. |
|
||||
| Q25 | anomaly_control | store_feature_risk | Узлы с подозрительно большим degree. |
|
||||
| Q26 | heavy_analytical | batch_refresh_then_store | Полный риск-срез за июнь. |
|
||||
| Q27 | heavy_analytical | batch_refresh_then_store | Рейтинг риск-счетов. |
|
||||
| Q28 | heavy_analytical | batch_refresh_then_store | Рейтинг риск-контрагентов. |
|
||||
| Q29 | heavy_analytical | store_feature_risk | Baseline closed/open periods. |
|
||||
| Q30 | heavy_analytical | batch_refresh_then_store | Company anomaly summary. |
|
||||
| Q31 | ambiguous_fuzzy | store_feature_risk | Что по налогам и рискам? |
|
||||
| Q32 | ambiguous_fuzzy | store_feature_risk | Что странное в расходах? |
|
||||
| Q33 | ambiguous_fuzzy | store_feature_risk | Самые рисковые контрагенты? |
|
||||
| Q34 | ambiguous_fuzzy | hybrid_store_plus_live | Что с 68.02? |
|
||||
| Q35 | ambiguous_fuzzy | store_feature_risk | Проверить документы июня. |
|
||||
@@ -0,0 +1,19 @@
|
||||
# Benchmark Route Analysis
|
||||
|
||||
- Total mismatches: `7`
|
||||
|
||||
## Route confusion matrix
|
||||
|
||||
- `batch_refresh_then_store` -> store_feature_risk:4
|
||||
- `hybrid_store_plus_live` -> hybrid_store_plus_live:3, store_canonical:2
|
||||
- `live_mcp_drilldown` -> hybrid_store_plus_live:1, live_mcp_drilldown:4
|
||||
- `store_canonical` -> store_canonical:6
|
||||
- `store_feature_risk` -> store_feature_risk:15
|
||||
|
||||
## Mismatch by class
|
||||
|
||||
| Class | Mismatch count |
|
||||
| --- | --- |
|
||||
| cross_entity | 2 |
|
||||
| drilldown_explain | 1 |
|
||||
| heavy_analytical | 4 |
|
||||
@@ -0,0 +1,38 @@
|
||||
# Benchmark Run Report
|
||||
|
||||
## Aggregate statistics
|
||||
|
||||
| Metric | Value |
|
||||
| --- | --- |
|
||||
| questions_total | 35 |
|
||||
| avg_latency_ms | 506.43 |
|
||||
| median_latency_ms | 402 |
|
||||
| p90_latency_ms | 941.4 |
|
||||
| p95_latency_ms | 1024.5 |
|
||||
| avg_context_size | 2162.51 |
|
||||
| live_route_count | 8 |
|
||||
| store_route_count | 27 |
|
||||
| batch_route_count | 0 |
|
||||
| route_mismatch_count | 7 |
|
||||
| degraded_answers_count | 0 |
|
||||
|
||||
## Route distribution
|
||||
|
||||
| Route | Count |
|
||||
| --- | --- |
|
||||
| hybrid_store_plus_live | 4 |
|
||||
| live_mcp_drilldown | 4 |
|
||||
| store_canonical | 8 |
|
||||
| store_feature_risk | 19 |
|
||||
|
||||
## Question class distribution
|
||||
|
||||
| Class | Count |
|
||||
| --- | --- |
|
||||
| ambiguous_fuzzy | 5 |
|
||||
| anomaly_control | 5 |
|
||||
| cross_entity | 5 |
|
||||
| drilldown_explain | 5 |
|
||||
| heavy_analytical | 5 |
|
||||
| period_trend | 5 |
|
||||
| simple_factual | 5 |
|
||||
@@ -0,0 +1,827 @@
|
||||
{
|
||||
"status": "success",
|
||||
"slice_window_key": "2020-06",
|
||||
"generated_at": "2026-03-23T10:22:58.317178+00:00",
|
||||
"questions_total": 35,
|
||||
"aggregate": {
|
||||
"questions_total": 35,
|
||||
"avg_latency_ms": 506.43,
|
||||
"median_latency_ms": 402,
|
||||
"p90_latency_ms": 941.4,
|
||||
"p95_latency_ms": 1024.5,
|
||||
"avg_context_size": 2162.51,
|
||||
"live_route_count": 8,
|
||||
"store_route_count": 27,
|
||||
"batch_route_count": 0,
|
||||
"route_mismatch_count": 7,
|
||||
"degraded_answers_count": 0,
|
||||
"route_distribution": {
|
||||
"store_canonical": 8,
|
||||
"live_mcp_drilldown": 4,
|
||||
"hybrid_store_plus_live": 4,
|
||||
"store_feature_risk": 19
|
||||
},
|
||||
"question_class_distribution": {
|
||||
"simple_factual": 5,
|
||||
"drilldown_explain": 5,
|
||||
"cross_entity": 5,
|
||||
"period_trend": 5,
|
||||
"anomaly_control": 5,
|
||||
"heavy_analytical": 5,
|
||||
"ambiguous_fuzzy": 5
|
||||
}
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"question_id": "Q01",
|
||||
"question_text": "Сальдо счета 68.02 за июнь 2020?",
|
||||
"question_class": "simple_factual",
|
||||
"expected_route": "store_canonical",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 332,
|
||||
"planning_time_ms": 67,
|
||||
"retrieval_time_ms": 129,
|
||||
"response_generation_time_ms": 136,
|
||||
"context_size": 1595,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q02",
|
||||
"question_text": "Документ по номеру и его ссылка.",
|
||||
"question_class": "simple_factual",
|
||||
"expected_route": "live_mcp_drilldown",
|
||||
"actual_route": "live_mcp_drilldown",
|
||||
"sources_used": [
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 1020,
|
||||
"planning_time_ms": 93,
|
||||
"retrieval_time_ms": 740,
|
||||
"response_generation_time_ms": 187,
|
||||
"context_size": 2796,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=live_mcp_drilldown; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q03",
|
||||
"question_text": "Типовая проводка по реализации.",
|
||||
"question_class": "simple_factual",
|
||||
"expected_route": "store_canonical",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 338,
|
||||
"planning_time_ms": 69,
|
||||
"retrieval_time_ms": 131,
|
||||
"response_generation_time_ms": 138,
|
||||
"context_size": 1597,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q04",
|
||||
"question_text": "Контрагент с максимумом оборота.",
|
||||
"question_class": "simple_factual",
|
||||
"expected_route": "store_canonical",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 341,
|
||||
"planning_time_ms": 70,
|
||||
"retrieval_time_ms": 132,
|
||||
"response_generation_time_ms": 139,
|
||||
"context_size": 1598,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q05",
|
||||
"question_text": "Договоры топ-контрагента.",
|
||||
"question_class": "simple_factual",
|
||||
"expected_route": "store_canonical",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 344,
|
||||
"planning_time_ms": 71,
|
||||
"retrieval_time_ms": 133,
|
||||
"response_generation_time_ms": 140,
|
||||
"context_size": 1599,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q06",
|
||||
"question_text": "Объясни сальдо через движения.",
|
||||
"question_class": "drilldown_explain",
|
||||
"expected_route": "hybrid_store_plus_live",
|
||||
"actual_route": "hybrid_store_plus_live",
|
||||
"sources_used": [
|
||||
"canonical_store",
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 819,
|
||||
"planning_time_ms": 114,
|
||||
"retrieval_time_ms": 524,
|
||||
"response_generation_time_ms": 181,
|
||||
"context_size": 2950,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=hybrid_store_plus_live; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q07",
|
||||
"question_text": "Почему проводка на этот счет?",
|
||||
"question_class": "drilldown_explain",
|
||||
"expected_route": "live_mcp_drilldown",
|
||||
"actual_route": "live_mcp_drilldown",
|
||||
"sources_used": [
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 1035,
|
||||
"planning_time_ms": 98,
|
||||
"retrieval_time_ms": 745,
|
||||
"response_generation_time_ms": 192,
|
||||
"context_size": 2801,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=live_mcp_drilldown; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q08",
|
||||
"question_text": "Цепочка документ -> проводки -> субконто.",
|
||||
"question_class": "drilldown_explain",
|
||||
"expected_route": "live_mcp_drilldown",
|
||||
"actual_route": "live_mcp_drilldown",
|
||||
"sources_used": [
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 1038,
|
||||
"planning_time_ms": 99,
|
||||
"retrieval_time_ms": 746,
|
||||
"response_generation_time_ms": 193,
|
||||
"context_size": 2802,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=live_mcp_drilldown; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q09",
|
||||
"question_text": "Источник регистра для строки движения.",
|
||||
"question_class": "drilldown_explain",
|
||||
"expected_route": "live_mcp_drilldown",
|
||||
"actual_route": "hybrid_store_plus_live",
|
||||
"sources_used": [
|
||||
"canonical_store",
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 828,
|
||||
"planning_time_ms": 117,
|
||||
"retrieval_time_ms": 527,
|
||||
"response_generation_time_ms": 184,
|
||||
"context_size": 2953,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=hybrid_store_plus_live; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "acceptable_with_warning",
|
||||
"issues_detected": [
|
||||
"Route mismatch: expected live_mcp_drilldown, got hybrid_store_plus_live"
|
||||
],
|
||||
"recommended_fix": "Tune router threshold for heavy/live boundary."
|
||||
},
|
||||
{
|
||||
"question_id": "Q10",
|
||||
"question_text": "Почему выбрано это субконто3?",
|
||||
"question_class": "drilldown_explain",
|
||||
"expected_route": "live_mcp_drilldown",
|
||||
"actual_route": "live_mcp_drilldown",
|
||||
"sources_used": [
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 1017,
|
||||
"planning_time_ms": 92,
|
||||
"retrieval_time_ms": 739,
|
||||
"response_generation_time_ms": 186,
|
||||
"context_size": 2795,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=live_mcp_drilldown; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q11",
|
||||
"question_text": "Свяжи документы покупателей и проводки.",
|
||||
"question_class": "cross_entity",
|
||||
"expected_route": "hybrid_store_plus_live",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 335,
|
||||
"planning_time_ms": 68,
|
||||
"retrieval_time_ms": 130,
|
||||
"response_generation_time_ms": 137,
|
||||
"context_size": 1596,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "acceptable_with_warning",
|
||||
"issues_detected": [
|
||||
"Route mismatch: expected hybrid_store_plus_live, got store_canonical"
|
||||
],
|
||||
"recommended_fix": "Tune router threshold for heavy/live boundary."
|
||||
},
|
||||
{
|
||||
"question_id": "Q12",
|
||||
"question_text": "Свяжи контрагентов, договоры и проводки.",
|
||||
"question_class": "cross_entity",
|
||||
"expected_route": "hybrid_store_plus_live",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 338,
|
||||
"planning_time_ms": 69,
|
||||
"retrieval_time_ms": 131,
|
||||
"response_generation_time_ms": 138,
|
||||
"context_size": 1597,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "acceptable_with_warning",
|
||||
"issues_detected": [
|
||||
"Route mismatch: expected hybrid_store_plus_live, got store_canonical"
|
||||
],
|
||||
"recommended_fix": "Tune router threshold for heavy/live boundary."
|
||||
},
|
||||
{
|
||||
"question_id": "Q13",
|
||||
"question_text": "Номенклатура, склад, обороты за июнь.",
|
||||
"question_class": "cross_entity",
|
||||
"expected_route": "store_canonical",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 341,
|
||||
"planning_time_ms": 70,
|
||||
"retrieval_time_ms": 132,
|
||||
"response_generation_time_ms": 139,
|
||||
"context_size": 1598,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q14",
|
||||
"question_text": "Регистр и первичный документ.",
|
||||
"question_class": "cross_entity",
|
||||
"expected_route": "hybrid_store_plus_live",
|
||||
"actual_route": "hybrid_store_plus_live",
|
||||
"sources_used": [
|
||||
"canonical_store",
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 816,
|
||||
"planning_time_ms": 113,
|
||||
"retrieval_time_ms": 523,
|
||||
"response_generation_time_ms": 180,
|
||||
"context_size": 2949,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=hybrid_store_plus_live; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q15",
|
||||
"question_text": "По счету: контрагенты и договоры.",
|
||||
"question_class": "cross_entity",
|
||||
"expected_route": "store_canonical",
|
||||
"actual_route": "store_canonical",
|
||||
"sources_used": [
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 347,
|
||||
"planning_time_ms": 72,
|
||||
"retrieval_time_ms": 134,
|
||||
"response_generation_time_ms": 141,
|
||||
"context_size": 1600,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_canonical; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q16",
|
||||
"question_text": "Обороты июня против мая.",
|
||||
"question_class": "period_trend",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 402,
|
||||
"planning_time_ms": 85,
|
||||
"retrieval_time_ms": 155,
|
||||
"response_generation_time_ms": 162,
|
||||
"context_size": 2101,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q17",
|
||||
"question_text": "Недельные всплески в июне.",
|
||||
"question_class": "period_trend",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 405,
|
||||
"planning_time_ms": 86,
|
||||
"retrieval_time_ms": 156,
|
||||
"response_generation_time_ms": 163,
|
||||
"context_size": 2102,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q18",
|
||||
"question_text": "Кто дал резкий рост активности.",
|
||||
"question_class": "period_trend",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 408,
|
||||
"planning_time_ms": 87,
|
||||
"retrieval_time_ms": 157,
|
||||
"response_generation_time_ms": 164,
|
||||
"context_size": 2103,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q19",
|
||||
"question_text": "Аномальный рост расходных операций?",
|
||||
"question_class": "period_trend",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 411,
|
||||
"planning_time_ms": 88,
|
||||
"retrieval_time_ms": 158,
|
||||
"response_generation_time_ms": 165,
|
||||
"context_size": 2104,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q20",
|
||||
"question_text": "Динамика НДС к соседним периодам.",
|
||||
"question_class": "period_trend",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 387,
|
||||
"planning_time_ms": 80,
|
||||
"retrieval_time_ms": 150,
|
||||
"response_generation_time_ms": 157,
|
||||
"context_size": 2096,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q21",
|
||||
"question_text": "Нетипичные корреспонденции счетов.",
|
||||
"question_class": "anomaly_control",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 390,
|
||||
"planning_time_ms": 81,
|
||||
"retrieval_time_ms": 151,
|
||||
"response_generation_time_ms": 158,
|
||||
"context_size": 2097,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q22",
|
||||
"question_text": "Незакрытые хвосты по расчетам.",
|
||||
"question_class": "anomaly_control",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 393,
|
||||
"planning_time_ms": 82,
|
||||
"retrieval_time_ms": 152,
|
||||
"response_generation_time_ms": 159,
|
||||
"context_size": 2098,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q23",
|
||||
"question_text": "Дублирующиеся проводки.",
|
||||
"question_class": "anomaly_control",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 396,
|
||||
"planning_time_ms": 83,
|
||||
"retrieval_time_ms": 153,
|
||||
"response_generation_time_ms": 160,
|
||||
"context_size": 2099,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q24",
|
||||
"question_text": "Пустые или странные субконто.",
|
||||
"question_class": "anomaly_control",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 399,
|
||||
"planning_time_ms": 84,
|
||||
"retrieval_time_ms": 154,
|
||||
"response_generation_time_ms": 161,
|
||||
"context_size": 2100,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q25",
|
||||
"question_text": "Узлы с подозрительно большим degree.",
|
||||
"question_class": "anomaly_control",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 402,
|
||||
"planning_time_ms": 85,
|
||||
"retrieval_time_ms": 155,
|
||||
"response_generation_time_ms": 162,
|
||||
"context_size": 2101,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "good",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q26",
|
||||
"question_text": "Полный риск-срез за июнь.",
|
||||
"question_class": "heavy_analytical",
|
||||
"expected_route": "batch_refresh_then_store",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 405,
|
||||
"planning_time_ms": 86,
|
||||
"retrieval_time_ms": 156,
|
||||
"response_generation_time_ms": 163,
|
||||
"context_size": 2102,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "acceptable_with_warning",
|
||||
"issues_detected": [
|
||||
"Route mismatch: expected batch_refresh_then_store, got store_feature_risk"
|
||||
],
|
||||
"recommended_fix": "Tune router threshold for heavy/live boundary."
|
||||
},
|
||||
{
|
||||
"question_id": "Q27",
|
||||
"question_text": "Рейтинг риск-счетов.",
|
||||
"question_class": "heavy_analytical",
|
||||
"expected_route": "batch_refresh_then_store",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 408,
|
||||
"planning_time_ms": 87,
|
||||
"retrieval_time_ms": 157,
|
||||
"response_generation_time_ms": 164,
|
||||
"context_size": 2103,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "acceptable_with_warning",
|
||||
"issues_detected": [
|
||||
"Route mismatch: expected batch_refresh_then_store, got store_feature_risk"
|
||||
],
|
||||
"recommended_fix": "Tune router threshold for heavy/live boundary."
|
||||
},
|
||||
{
|
||||
"question_id": "Q28",
|
||||
"question_text": "Рейтинг риск-контрагентов.",
|
||||
"question_class": "heavy_analytical",
|
||||
"expected_route": "batch_refresh_then_store",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 411,
|
||||
"planning_time_ms": 88,
|
||||
"retrieval_time_ms": 158,
|
||||
"response_generation_time_ms": 165,
|
||||
"context_size": 2104,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "acceptable_with_warning",
|
||||
"issues_detected": [
|
||||
"Route mismatch: expected batch_refresh_then_store, got store_feature_risk"
|
||||
],
|
||||
"recommended_fix": "Tune router threshold for heavy/live boundary."
|
||||
},
|
||||
{
|
||||
"question_id": "Q29",
|
||||
"question_text": "Baseline closed/open periods.",
|
||||
"question_class": "heavy_analytical",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 414,
|
||||
"planning_time_ms": 89,
|
||||
"retrieval_time_ms": 159,
|
||||
"response_generation_time_ms": 166,
|
||||
"context_size": 2105,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q30",
|
||||
"question_text": "Company anomaly summary.",
|
||||
"question_class": "heavy_analytical",
|
||||
"expected_route": "batch_refresh_then_store",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 390,
|
||||
"planning_time_ms": 81,
|
||||
"retrieval_time_ms": 151,
|
||||
"response_generation_time_ms": 158,
|
||||
"context_size": 2097,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "acceptable_with_warning",
|
||||
"issues_detected": [
|
||||
"Route mismatch: expected batch_refresh_then_store, got store_feature_risk"
|
||||
],
|
||||
"recommended_fix": "Tune router threshold for heavy/live boundary."
|
||||
},
|
||||
{
|
||||
"question_id": "Q31",
|
||||
"question_text": "Что по налогам и рискам?",
|
||||
"question_class": "ambiguous_fuzzy",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 393,
|
||||
"planning_time_ms": 82,
|
||||
"retrieval_time_ms": 152,
|
||||
"response_generation_time_ms": 159,
|
||||
"context_size": 2098,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q32",
|
||||
"question_text": "Что странное в расходах?",
|
||||
"question_class": "ambiguous_fuzzy",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 396,
|
||||
"planning_time_ms": 83,
|
||||
"retrieval_time_ms": 153,
|
||||
"response_generation_time_ms": 160,
|
||||
"context_size": 2099,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q33",
|
||||
"question_text": "Самые рисковые контрагенты?",
|
||||
"question_class": "ambiguous_fuzzy",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 399,
|
||||
"planning_time_ms": 84,
|
||||
"retrieval_time_ms": 154,
|
||||
"response_generation_time_ms": 161,
|
||||
"context_size": 2100,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q34",
|
||||
"question_text": "Что с 68.02?",
|
||||
"question_class": "ambiguous_fuzzy",
|
||||
"expected_route": "hybrid_store_plus_live",
|
||||
"actual_route": "hybrid_store_plus_live",
|
||||
"sources_used": [
|
||||
"canonical_store",
|
||||
"mcp_runtime_bridge"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 822,
|
||||
"planning_time_ms": 115,
|
||||
"retrieval_time_ms": 525,
|
||||
"response_generation_time_ms": 182,
|
||||
"context_size": 2951,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=hybrid_store_plus_live; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
},
|
||||
{
|
||||
"question_id": "Q35",
|
||||
"question_text": "Проверить документы июня.",
|
||||
"question_class": "ambiguous_fuzzy",
|
||||
"expected_route": "store_feature_risk",
|
||||
"actual_route": "store_feature_risk",
|
||||
"sources_used": [
|
||||
"feature_store",
|
||||
"risk_store",
|
||||
"canonical_store"
|
||||
],
|
||||
"refresh_needed": false,
|
||||
"latency_ms": 405,
|
||||
"planning_time_ms": 86,
|
||||
"retrieval_time_ms": 156,
|
||||
"response_generation_time_ms": 163,
|
||||
"context_size": 2102,
|
||||
"answer_text": "[simulated-4o-mini-profile] route=store_feature_risk; answer synthesized from June-2020 slice + current stores.",
|
||||
"answer_quality_assessment": "acceptable",
|
||||
"route_quality_assessment": "good",
|
||||
"issues_detected": [],
|
||||
"recommended_fix": "No action required."
|
||||
}
|
||||
]
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
# CHECK Validation Run Accounting Analytics — Result (2026-03-23)
|
||||
|
||||
## Scope
|
||||
|
||||
Выполнен ремонт ontology/mapping слоя по чек-листу `IN/CHEK_Validation_Run_Accounting_Analytics.md`:
|
||||
|
||||
1. Расширены canonical entity classes под недостающие доменные роли.
|
||||
2. Переписан mapper на semantic-v2 подход:
|
||||
- entity type resolver (с приоритетом `*_Type`);
|
||||
- relation resolver (role/context-aware relations вместо одного `reference`);
|
||||
- null GUID filter;
|
||||
- composite source id builder.
|
||||
3. Проведён re-map июньского snapshot 2020 и повторный validation-run.
|
||||
|
||||
## Implemented changes
|
||||
|
||||
### 1) Canonical model expansion
|
||||
|
||||
Добавлены классы:
|
||||
|
||||
- `ResponsiblePerson`
|
||||
- `Currency`
|
||||
- `Warehouse`
|
||||
- `CashflowArticle`
|
||||
- `Department`
|
||||
- `Individual`
|
||||
- `Item`
|
||||
- `BankAccount`
|
||||
- `InvoiceDocument`
|
||||
- `RegisterRecord`
|
||||
|
||||
Файл: `canonical_layer/models.py`
|
||||
|
||||
### 2) Mapper architecture refactor
|
||||
|
||||
Файл: `canonical_layer/mappers.py`
|
||||
|
||||
Ключевые изменения:
|
||||
|
||||
- `map_record` больше не оставляет пустые/unknown `source_id`:
|
||||
- сначала пробует `Ref_Key/Ref/ID/...`,
|
||||
- затем строит `cmp:<sha1>` составной id по стабильному payload.
|
||||
- links строятся через semantic resolvers:
|
||||
- `register_recorded_by_document`
|
||||
- `journal_refers_to_document`
|
||||
- `document_has_counterparty`
|
||||
- `document_has_contract`
|
||||
- `document_belongs_to_organization`
|
||||
- `document_has_currency`
|
||||
- `document_has_responsible`
|
||||
- `register_relates_to_supplier`
|
||||
- `register_relates_to_buyer`
|
||||
- `register_relates_to_invoice`
|
||||
- и др.
|
||||
- `*_Type` используется как приоритетный target type hint.
|
||||
- `00000000-0000-0000-0000-000000000000` фильтруется из canonical links.
|
||||
- Добавлен `canonical_relation_rule_catalog()` для прозрачной выгрузки правил.
|
||||
|
||||
### 3) Regression tests
|
||||
|
||||
Файл: `tests/test_mappers.py` (переписан)
|
||||
|
||||
Проверки включают:
|
||||
|
||||
- document counterparty relation;
|
||||
- register composite source id;
|
||||
- journal `Ref` -> document relation;
|
||||
- supplier/buyer role typing;
|
||||
- `СчетФактура` -> `InvoiceDocument` (без ложного `Account`);
|
||||
- zero-GUID filtering.
|
||||
|
||||
Статус тестов:
|
||||
|
||||
- `python -m pytest -q` -> `17 passed`
|
||||
|
||||
## Re-map and validation results
|
||||
|
||||
### Re-map command
|
||||
|
||||
`python scripts/remap_snapshot_semantic_v2.py`
|
||||
|
||||
Артефакты:
|
||||
|
||||
- `logs/pre_report_snapshot_2020_2020-06_semantic_v2.json`
|
||||
- `logs/pre_report_snapshot_2020_2020-06_semantic_v2_metrics.json`
|
||||
|
||||
### Before vs after (snapshot-level metrics)
|
||||
|
||||
- `source_id_unknown`: `358 -> 0`
|
||||
- `unknown_links`: `1016 -> 102`
|
||||
- `semantic_coverage_pct`: `61.1917 -> 94.9279`
|
||||
- `relation_types_total`: `1 -> 25`
|
||||
|
||||
### Validation run on semantic-v2 snapshot
|
||||
|
||||
Команда:
|
||||
|
||||
`python scripts/run_validation_accounting_analytics.py --snapshot-path logs/pre_report_snapshot_2020_2020-06_semantic_v2.json --output-dir docs/ARCH/validation_run_2026-03-23_semantic_v2 --strict`
|
||||
|
||||
Папка результатов:
|
||||
|
||||
- `docs/ARCH/validation_run_2026-03-23_semantic_v2/`
|
||||
|
||||
Ключевые ontology-аудит метрики:
|
||||
|
||||
- `covered_entity_classes`: `33 -> 42`
|
||||
- `uncovered_entity_classes`: `9 -> 0`
|
||||
- `unknown_relations`: `1016 -> 102`
|
||||
- `semantic_coverage_pct`: `61.1917 -> 94.9279`
|
||||
- `relation_types_total`: `1 -> 25`
|
||||
|
||||
## Export package refresh
|
||||
|
||||
Обновлён пакет `docs/ARCH/2020экспорт` на базе semantic-v2 snapshot:
|
||||
|
||||
- `01_ontology_mapping_layer.md` (обновлённые классы/метрики)
|
||||
- `02_canonical_relation_rules.md` (каталог semantic relations из маппера)
|
||||
- все sample/json файлы перегенерированы
|
||||
|
||||
Команда:
|
||||
|
||||
`python scripts/export_arch_2020_package.py`
|
||||
|
||||
## Remaining gap (post-fix)
|
||||
|
||||
Топ остаточных unknown-полей после semantic-v2:
|
||||
|
||||
- `ВидОперации`
|
||||
- `Информация`
|
||||
- `СубконтоДт1`
|
||||
- `Руководитель_Key`
|
||||
- `ГлавныйБухгалтер_Key`
|
||||
|
||||
Следующий шаг:
|
||||
|
||||
- добавить точечные semantic rules для перечисленных полей;
|
||||
- отдельно закрыть `Subconto*` mapping в детальный typed-slot слой;
|
||||
- после этого повторить remap + validation и зафиксировать delta.
|
||||
@@ -0,0 +1,27 @@
|
||||
# LLM-like Simulation Profile
|
||||
|
||||
Simulation mode: `4o-mini-like` (controlled emulation)
|
||||
|
||||
## Constraints
|
||||
|
||||
- Store-first retrieval policy.
|
||||
- Compact planning and bounded context.
|
||||
- Limited live calls for drill-down only.
|
||||
- Avoid expensive heavy live scans.
|
||||
|
||||
## Route timing baseline (ms)
|
||||
|
||||
| Route | Planning | Retrieval | Generation | Context |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| live_mcp_drilldown | 95 | 780 | 180 | 2900 |
|
||||
| store_canonical | 70 | 170 | 130 | 1700 |
|
||||
| store_feature_risk | 82 | 190 | 150 | 2200 |
|
||||
| hybrid_store_plus_live | 112 | 560 | 170 | 3050 |
|
||||
| batch_refresh_then_store | 135 | 1240 | 210 | 3600 |
|
||||
|
||||
## Active run context
|
||||
|
||||
- Slice window: `2020-06`
|
||||
- Refresh latest run: `368e424624bb4e1d818091e6189ab222`
|
||||
- Feature latest run: `d61114c3a5c5405f89ed2952a1755516`
|
||||
- Risk latest run: `2785fa2100e84935a210687af6bb850b`
|
||||
@@ -0,0 +1,50 @@
|
||||
# Ontology & Mapping Audit
|
||||
|
||||
## Core metrics
|
||||
|
||||
| Metric | Value |
|
||||
| --- | --- |
|
||||
| entity_classes_total | 42 |
|
||||
| covered_entity_classes | 42 |
|
||||
| uncovered_entity_classes | 0 |
|
||||
| relation_types_total | 25 |
|
||||
| correctly_typed_relations | 1909 |
|
||||
| unknown_relations | 102 |
|
||||
| conflicting_mappings_count | 1 |
|
||||
| link_coverage_pct | 100.0 |
|
||||
| semantic_coverage_pct | 94.9279 |
|
||||
|
||||
## Top problematic source entity types
|
||||
|
||||
| Source entity | Unknown relations |
|
||||
| --- | --- |
|
||||
| DocumentJournal_БанковскиеВыписки | 30 |
|
||||
| DocumentJournal_ЖурналОпераций | 16 |
|
||||
| Document_СписаниеСРасчетногоСчета | 14 |
|
||||
| Document_РеализацияТоваровУслуг | 12 |
|
||||
| Document_СчетФактураВыданный | 8 |
|
||||
| Document_ОперацияБух | 5 |
|
||||
| AccumulationRegister_СтраховыеВзносыСведенияОДоходах_RecordType | 4 |
|
||||
| DocumentJournal_КассовыеДокументы | 4 |
|
||||
| Document_РасходныйКассовыйОрдер | 4 |
|
||||
| AccumulationRegister_НДФЛСведенияОДоходах_RecordType | 3 |
|
||||
| AccumulationRegister_НДФЛПредоставленныеСтандартныеВычетыФизЛиц_RecordType | 1 |
|
||||
| Document_СчетНаОплатуПокупателю | 1 |
|
||||
|
||||
## Top problematic relation fields
|
||||
|
||||
| Source field | Unknown relations |
|
||||
| --- | --- |
|
||||
| ВидОперации | 34 |
|
||||
| Информация | 16 |
|
||||
| СубконтоДт1 | 15 |
|
||||
| Руководитель_Key | 8 |
|
||||
| ГлавныйБухгалтер_Key | 8 |
|
||||
| СпособЗаполнения | 5 |
|
||||
| ВидДохода_Key | 4 |
|
||||
| СтатьяДоходовИРасходовПоТаре_Key | 4 |
|
||||
| КодДохода_Key | 3 |
|
||||
| СубконтоДт2 | 3 |
|
||||
| КодВычета_Key | 1 |
|
||||
| СтруктурнаяЕдиница_Key | 1 |
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# Orchestration Policy Spec
|
||||
|
||||
## Decision tree
|
||||
|
||||
- exact object trace or posting chain -> `live_mcp_drilldown`
|
||||
- simple factual in loaded slice -> `store_canonical`
|
||||
- trend/anomaly/risk -> `store_feature_risk`
|
||||
- heavy whole-slice with freshness gap -> `batch_refresh_then_store`
|
||||
- low confidence fallback -> `hybrid_store_plus_live`
|
||||
|
||||
## Routing rules
|
||||
|
||||
- Prefer store answers when freshness allows.
|
||||
- Use live bridge only for drill-down evidence.
|
||||
- Do not run uncapped heavy live scans.
|
||||
- Trigger refresh/features/risk for stale context.
|
||||
- Apply retrieval/context budget before fallback.
|
||||
|
||||
## Source priorities
|
||||
|
||||
| Scenario | Priority order |
|
||||
| --- | --- |
|
||||
| simple_factual | canonical_store -> mcp_runtime_bridge |
|
||||
| drilldown_explain | mcp_runtime_bridge -> canonical_store |
|
||||
| period_trend | feature_store -> risk_store -> canonical_store |
|
||||
| anomaly_control | risk_store -> feature_store -> canonical_store |
|
||||
| heavy_analytical | batch_refresh_then_store -> feature_store -> risk_store |
|
||||
| ambiguous_fuzzy | feature_store -> canonical_store -> mcp_runtime_bridge |
|
||||
|
||||
## Timeout budget (ms)
|
||||
|
||||
| Budget | Value |
|
||||
| --- | --- |
|
||||
| planning | 200 |
|
||||
| retrieval_soft_limit | 1200 |
|
||||
| retrieval_hard_limit | 2500 |
|
||||
| response_generation | 600 |
|
||||
@@ -0,0 +1,20 @@
|
||||
# Slice Ingestion Report
|
||||
|
||||
Validation date: 2026-03-23T10:22:58.316163+00:00
|
||||
Slice window: `2020-06` (`2020-06-01T00:00:00+00:00` -> `2020-07-01T00:00:00+00:00`)
|
||||
|
||||
- Snapshot file: `logs\pre_report_snapshot_2020_2020-06_semantic_v2.json`
|
||||
- Profile file: `X:\1C\NDC_1C\logs\pre_report_activity_2020.json`
|
||||
- Snapshot entities: `409`
|
||||
- Snapshot links: `2011`
|
||||
- Refresh run id: `368e424624bb4e1d818091e6189ab222`
|
||||
- Entities written: `409`
|
||||
- Links written: `2011`
|
||||
- Checkpoints updated: `42`
|
||||
- Canonical entities total: `769`
|
||||
- Canonical links total: `3700`
|
||||
- Feature run status: `success`
|
||||
- Feature metrics written: `202`
|
||||
- Risk run status: `success`
|
||||
- Risk patterns written: `3`
|
||||
- Risk global score: `0.988676`
|
||||
Reference in New Issue
Block a user