Initial import NDC_1C

This commit is contained in:
2026-03-26 10:38:25 +03:00
commit a162d77ef7
2943 changed files with 3615871 additions and 0 deletions
@@ -0,0 +1,234 @@
# 260323_ACCOUNTING_AGENT_GUI_INTEGRATION_GUIDELINES
Дата: 23.03.2026 (MSK)
Контур: NodeDC (`dc_node`) / бухгалтерский агент (черновой GUI + временный монолитный backend)
Статус: интеграционные рекомендации для внешнего разработчика
---
## 1. Цель документа
Зафиксировать единые требования к GUI и backend бухгалтерского агента, который разрабатывается изолированно, чтобы:
1. интеграция в текущий `Node.js`-проект прошла без болезненных переделок;
2. архитектура оставалась совместимой с текущей моделью NodeDC (`UI -> runtime -> OPS`);
3. переход с временного монолита на будущую runtime-оркестрацию был обратимым и предсказуемым.
---
## 2. Базовые принципы (обязательные)
1. Сначала совместимость, потом скорость: любое быстрое решение допускается только если не ломает будущую интеграцию.
2. GUI и backend делаются как изолируемый модуль, а не как форк всей платформы.
3. Контракты API/событий/статусов должны быть стабильными с первой версии.
4. Нельзя смешивать UI-логику, runtime-логику исполнения и слой хранения в один неразделимый блок.
5. Пользовательская терминология в интерфейсе: использовать `NDC` (не `N8N`) в текстах UI.
6. Технические идентификаторы не переименовывать: routes, env vars, payload keys, event names, internal symbols остаются техническими.
---
## 3. Технологический профиль (что нужно соблюдать)
### 3.1 Frontend
1. Совместимый стек: `React 18` + `TypeScript` + подход, совместимый с `Vite`.
2. Архитектурно: компонентный UI с разделением на контейнеры данных и презентационные блоки.
3. Все сетевые вызовы через единый API-клиент-слой (не `fetch` хаотично по компонентам).
4. Состояние:
- локальное UI-состояние отдельно;
- серверное состояние отдельно (runs, statuses, results, trace).
### 3.2 Backend
1. Совместимый стек: `Node.js` + `Express` + JSON API.
2. Формат тела запроса: поддержка `application/json` и `application/*+json`.
3. Для хранения/аналитики ориентироваться на модель, совместимую с Postgres-онтологией (`session/run/result/event`).
4. Временный runtime монолитный, но за абстракцией (см. раздел 8).
### 3.3 Форматы
1. Время только в `ISO 8601`.
2. Денежные поля и суммы: явная валюта + числовой формат без двусмысленностей.
3. Ошибки API: структурированный ответ с `code`, `message`, `details`.
4. Любой статус должен быть машинно-читаемым и человеко-понятным.
---
## 4. Архитектурные границы ответственности
1. GUI отвечает за:
- запуск/остановку;
- отображение состояния;
- фильтры/настройки;
- операторские действия.
2. Backend отвечает за:
- исполнение сценария;
- очередь и жизненный цикл задач;
- запись результатов и ошибок;
- выдачу данных для монитора.
3. Слой данных отвечает за:
- историчность;
- идемпотентность результатов;
- диагностируемость событий.
4. GUI не должен содержать тяжелую бизнес-обработку бухгалтерских документов/очередей.
---
## 5. Минимальный API-контракт (для безболезненной интеграции)
Рекомендуется выделить отдельный namespace, например `/api/accounting-agent/*`, и зафиксировать минимум:
1. `POST /runs/start`
- старт сессии/прогона;
- возвращает `sessionId`, `runId`, `status`.
2. `POST /runs/finish`
- нормализованное завершение `DONE/FAILED/CANCELLED`;
- причина/метаданные ошибки при неуспехе.
3. `GET /runs`
- список прогонов с фильтрами.
4. `GET /runs/:runId`
- карточка прогона + агрегированный статус.
5. `POST /tasks/enqueue`
- постановка бухгалтерской задачи в очередь.
6. `POST /tasks/claim` (или эквивалент)
- получение следующей задачи worker-частью.
7. `POST /tasks/:taskId/complete`
- успешное завершение с результатом.
8. `POST /tasks/:taskId/error`
- завершение с нормализованной ошибкой.
9. `GET /results`
- витрина результатов для GUI/монитора.
10. `GET /trace/run/:runId`
- лента событий для диагностики.
11. `GET /health`
- техническое здоровье сервиса.
Важно:
1. Контракты payload фиксируются версией (`v1`) и не ломаются без явной миграции.
2. Поля `sessionId/runId/taskId` обязательны в событиях и логах.
---
## 6. Канон статусов и жизненного цикла
Единый словарь статусов для GUI и backend:
1. `NONE`
2. `QUEUED`
3. `RUNNING`
4. `DONE`
5. `ERROR`
6. `STALE`
7. `CANCELLED`
Правила:
1. Терминальные статусы (`DONE/ERROR/CANCELLED`) имеют приоритет и не откатываются в `RUNNING`.
2. Повторный запуск не перетирает историю, а создаёт новую сущность запуска/задачи.
3. Для каждого перехода статуса обязателен `updatedAt` и источник изменения (`source`).
---
## 7. Требования к GUI бухгалтерского агента
### 7.1 Что обязательно в первой версии
1. Панель запуска и остановки.
2. Панель прогонов (`runs`) со статусом, временем, инициатором.
3. Панель результатов (`results`) с фильтрами и быстрым поиском.
4. Панель ошибок/исключений.
5. Панель трассировки (`trace`) по выбранному `runId`.
6. Явная индикация: что обновляется в реальном времени, а что по ручному refresh.
### 7.2 UX-правила
1. Никаких скрытых магических фильтров, влияющих на выдачу без отображения в UI.
2. Любое действие пользователя должно иметь видимый эффект: `queued/running/done/error`.
3. Длинные операции не блокируют интерфейс целиком.
4. Ошибки показываются в 2 слоя:
- коротко для оператора;
- подробно для диагностики (код, traceId/runId).
### 7.3 Терминология UI
1. Во всех пользовательских текстах использовать `NDC`.
2. Не использовать `N8N` в текстах интерфейса.
3. В техническом коде/маршрутах внутренние названия не переписывать автоматически.
---
## 8. Требования к временному монолитному backend (с прицелом на замену runtime)
Чтобы потом перейти к отдельному runtime/оркестрации без переписывания GUI:
1. Ввести слой-адаптер исполнения (runtime adapter) как отдельный модуль.
2. GUI/backend общаются с этим адаптером через стабильный внутренний контракт.
3. В монолитной версии адаптер реализован локально.
4. В будущей версии адаптер можно заменить на внешний runtime (без смены GUI API).
5. Очередь/ретраи/лимиты должны быть инкапсулированы в backend, а не в GUI.
Минимальные способности адаптера исполнения:
1. `startRun`;
2. `stopRun`;
3. `enqueueTask`;
4. `claimTask`;
5. `completeTask`;
6. `failTask`;
7. `getRunState`;
8. `getRunTrace`.
---
## 9. Наблюдаемость, логирование, диагностика
1. Логи в структурированном формате JSON.
2. Обязательные поля логов: `timestamp`, `level`, `service`, `sessionId`, `runId`, `taskId`, `eventType`.
3. Для ошибок обязательны: `errorCode`, `errorMessage`, `stack` (где применимо).
4. Должна быть возможность получить trace по `runId` без ручного доступа к серверу.
5. Учитывать рабочую таймзону проекта: `Europe/Moscow` в операционных отчётах.
---
## 10. Безопасность и эксплуатационные правила
1. В секретах/ключах не хранить чувствительные данные в открытых логах.
2. Любые внешние интеграции — через конфигурацию окружения, без хардкода.
3. Все потенциально тяжелые операции ограничить по timeout/retry.
4. Обязательны idempotency-защиты для endpoint-ов старта/завершения/записи результатов.
---
## 11. Definition of Done для подрядчика
Задача считается готовой, если выполнено всё:
1. GUI поднимается и работает локально в связке с backend.
2. Есть запуск/остановка/мониторинг прогонов.
3. Статусы и жизненный цикл реализованы по канону раздела 6.
4. API покрывает минимальный контракт раздела 5.
5. Есть trace-диагностика по `runId`.
6. Ошибки и логирование структурированы.
7. Терминология UI приведена к `NDC`.
8. Подтверждена обратимая миграция с монолита на внешний runtime-адаптер без смены UI-контрактов.
---
## 12. Интеграционный чеклист перед вливанием в `dc_node`
1. Совпадает ли словарь статусов с существующим монитором.
2. Присутствуют ли `sessionId/runId` во всех критичных сущностях и событиях.
3. Нет ли скрытых зависимостей GUI от конкретной монолитной реализации runtime.
4. Не дублирует ли модуль существующие механизмы хранения/трассировки.
5. Не конфликтуют ли route-префиксы и форматы ответов с текущим API-паттерном.
6. Можно ли подключить модуль в NodeDC поэтапно (feature flag / scoped rollout).
---
## 13. Короткий итог для разработчика GUI
1. Делай интерфейс и backend как автономный модуль, но по контрактам, совместимым с NodeDC.
2. Сейчас runtime может быть монолитным, но обязан быть спрятан за адаптером.
3. UI должен опираться на стабильные статусы, `run/session`-идентификаторы и наблюдаемую trace-модель.
4. Всё, что пользователь видит, называем через `NDC`.
@@ -0,0 +1,840 @@
AI СЛОЙ ДЛЯ НАРМАЛИЗАЦИИ ЗАПРОСОВ ОТ ЮЗЕРА - ГУЙ ДОЛЖЕН БЫТЬ ПОЛНОСТЬЮ РУИФИЦИРОВАН !!!
Ниже — **конкретное ТЗ для Codex** на первый этап интеграции LLM в контур бухгалтерского ассистента.
Основа решения: использовать **Responses API**, а не legacy-путь Assistants, и заставить модель возвращать **строго структурированный JSON** через structured outputs / JSON schema. API-ключ нельзя светить в client-side коде, поэтому даже для localhost-стенда запросы должны идти через локальный backend-proxy. ([OpenAI Платформа][1])
---
# ТЗ: LLM Normalizer Playground + Pre-Router Normalization Layer
## 1. Цель этапа
Реализовать локальный тестовый стенд и базовый backend-слой для интеграции LLM в качестве **нормализатора человеческих бухгалтерских запросов**.
LLM на этом этапе **не отвечает за финальный бухгалтерский ответ** и **не ходит напрямую в данные**.
LLM отвечает только за:
* разбор человеческого запроса;
* выделение сущностей, периода, типа задачи и причинно-следственной формы;
* возврат строго структурированного JSON;
* подготовку нормализованного input для существующего router/orchestration слоя.
---
## 2. Бизнес-смысл этапа
Текущий deterministic router хорошо работает на каноничных и полуструктурированных вопросах, но заметно хуже справляется с длинными человеческими формулировками, особенно в cross-entity и causal explain сценариях.
Цель этого этапа — не заменить router, а поставить перед ним **semantic front-end**, который переводит живой язык пользователя в нормализованный внутренний контракт.
Новая целевая цепочка:
**Пользователь → LLM Normalizer → Normalized Query JSON → Existing Router → Existing Retrieval/Stores/Batch → Final Answer Layer**
---
## 3. Что должно получиться на выходе
После реализации должен существовать рабочий localhost-стенд, в котором можно:
* вставить API key;
* выбрать модель;
* редактировать системный / developer prompt;
* редактировать domain prompt;
* ввести человеческий бухгалтерский вопрос;
* отправить запрос в OpenAI через локальный backend;
* получить:
* raw model output,
* normalized JSON output,
* parsed route hint,
* confidence,
* token usage,
* latency,
* trace/log записи;
* сохранить результат как тест-кейс для дальнейшей оценки.
---
## 4. Технологическое решение
### 4.1 API-путь
Использовать **Responses API** как основной способ интеграции. Это соответствует текущему рекомендуемому стеку OpenAI для новых интеграций. ([OpenAI Платформа][1])
### 4.2 Формат ответа модели
Использовать **structured outputs / JSON schema response format**, чтобы модель возвращала не свободный текст, а строго валидируемый JSON-объект. ([OpenAI Платформа][1])
### 4.3 Безопасность ключа
API key не должен использоваться напрямую из фронта.
Ключ должен передаваться в локальный backend-proxy и использоваться только серверной частью. В документации OpenAI прямо сказано, что API key — секрет и его нельзя светить в браузере или клиентском коде. ([OpenAI Платформа][2])
### 4.4 Целевая модель первого этапа
Для первого этапа предусмотреть параметризуемую модель, по умолчанию — `gpt-4o-mini` как fast/cheap normalizer-кандидат. Конкретный model id должен быть настраиваемым из UI, без хардкода в коде.
---
## 5. Scope этапа
### В scope входит
* localhost GUI playground;
* локальный backend-proxy для OpenAI API;
* normalizer prompt system;
* structured JSON schema;
* вызов Responses API;
* валидация JSON-ответа;
* логирование запросов/ответов;
* нормализация route hints;
* сохранение trace;
* базовый eval-mode на заранее заданном наборе вопросов.
### В scope не входит
* полноценный production chat;
* tool use;
* live access к 1С данным;
* финальный answer synthesis;
* agentic orchestration;
* самостоятельный выбор model toolchain;
* дообучение модели;
* интеграция в production UI Node/DC.
---
## 6. Архитектура решения
## 6.1 Общая схема
### Компоненты
1. **Frontend Playground**
2. **Local Backend Proxy**
3. **Prompt Manager**
4. **Normalizer Service**
5. **Schema Validator**
6. **Trace Logger**
7. **Optional Eval Runner**
8. **Route Hint Adapter** для передачи результата в существующий router
### Поток
1. Пользователь вводит сырой вопрос.
2. Frontend отправляет payload на local backend.
3. Backend собирает prompt + schema + user input.
4. Backend вызывает Responses API.
5. Backend получает structured JSON.
6. Backend валидирует JSON по schema.
7. Backend вычисляет route hint summary.
8. Backend возвращает UI:
* raw response,
* normalized JSON,
* parse status,
* validation status,
* usage,
* latency,
* trace id.
---
## 7. Требования к GUI
Нужен простой localhost GUI. Подойдёт React/Vite/Next localhost-only интерфейс или любой быстрый web UI.
## 7.1 Обязательные блоки интерфейса
### A. Connection Panel
Поля:
* `OpenAI API Key`
* `Model ID`
* `Base URL` (опционально, по умолчанию OpenAI)
* `Temperature`
* `Max output tokens`
Кнопки:
* `Save local session config`
* `Test connection`
### B. Prompt Panel
Отдельные текстовые области:
* `System Prompt`
* `Developer / Instruction Prompt`
* `Domain Prompt`
* `Schema Notes` (опционально)
* `Few-shot examples` (опционально)
Кнопки:
* `Load preset`
* `Save preset`
* `Diff with previous`
* `Reset to default`
### C. User Query Panel
Поля:
* `Raw user question`
* `Optional period context`
* `Optional business context`
* `Optional expected route` (для eval mode)
Кнопки:
* `Normalize`
* `Normalize + Save as test case`
### D. Output Panel
Вкладки:
* `Normalized JSON`
* `Raw model output`
* `Route hint summary`
* `Validation`
* `Logs`
### E. Runtime Metrics Panel
Показывать:
* `trace_id`
* `request_started_at`
* `request_finished_at`
* `latency_ms`
* `input_tokens`
* `output_tokens`
* `total_tokens`
* `validation_status`
* `confidence`
* `schema_version`
* `prompt_version`
### F. History Panel
Список прошлых запросов:
* timestamp
* shortened question
* model
* confidence
* validation pass/fail
* route hint
* save status
---
## 8. Требования к backend
Backend должен быть локальным HTTP-сервисом.
Подойдут:
* Node.js + Express / Fastify
или
* Python + FastAPI
Рекомендуемый вариант для скорости: **Node.js + Fastify**.
## 8.1 Обязательные endpoint’ы
### `POST /api/openai/test-connection`
Проверка, что ключ рабочий и Responses API доступен.
### `POST /api/normalize`
Основной endpoint для нормализации вопроса.
Вход:
```json
{
"apiKey": "string",
"model": "gpt-4o-mini",
"temperature": 0,
"systemPrompt": "string",
"developerPrompt": "string",
"domainPrompt": "string",
"schemaVersion": "v1",
"userQuestion": "string",
"context": {
"period_hint": "2020-06",
"business_context": "optional"
}
}
```
Выход:
```json
{
"trace_id": "string",
"ok": true,
"normalized": { ... },
"route_hint_summary": { ... },
"raw_model_output": "string or object",
"validation": {
"passed": true,
"errors": []
},
"usage": {
"input_tokens": 0,
"output_tokens": 0,
"total_tokens": 0
},
"latency_ms": 0,
"prompt_version": "normalizer_v1",
"schema_version": "v1"
}
```
### `POST /api/eval/run`
Запуск серии нормализаций на тестовом наборе.
### `GET /api/history`
История запросов.
### `GET /api/history/:trace_id`
Получение полного trace.
### `POST /api/presets/save`
Сохранение набора prompt’ов / конфигурации.
### `GET /api/presets`
Получение доступных prompt presets.
---
## 9. Центральная сущность: Normalized Query JSON
Это ключевой контракт между LLM и вашим deterministic router.
## 9.1 Schema version
Первая версия:
* `schema_version = "normalized_query_v1"`
## 9.2 Обязательные поля
```json
{
"schema_version": "normalized_query_v1",
"user_question_raw": "string",
"normalized_question": "string",
"intent_class": "heavy_analytical | cross_entity | drilldown_explain | rule_based_account_control | anomaly_probe | period_close_risk | ambiguous_human_query | simple_factual",
"business_problem_type": "string",
"domain_entities": ["string"],
"accounts_mentioned": ["string"],
"documents_mentioned": ["string"],
"registers_mentioned": ["string"],
"period_scope": {
"type": "explicit | inferred | missing",
"value": "string | null",
"confidence": "high | medium | low"
},
"requires": {
"needs_cross_entity_join": true,
"needs_causal_chain": true,
"needs_exact_object_trace": false,
"needs_ranking": false,
"needs_anomaly_summary": false,
"needs_runtime_truth": false,
"needs_period_cut": true,
"needs_evidence": true
},
"expected_output_shape": "ranked_list | evidence_chain | anomaly_summary | point_answer | reconciliation_report | prioritized_review_list",
"route_hint": "store_canonical | store_feature_risk | hybrid_store_plus_live | live_mcp_drilldown | batch_refresh_then_store",
"ambiguities": [
{
"field": "period_scope",
"reason": "month not specified",
"severity": "medium"
}
],
"confidence": {
"overall": "high | medium | low",
"intent_class": "high | medium | low",
"route_hint": "high | medium | low"
}
}
```
---
## 10. Семанические требования к normalizer
LLM normalizer обязан:
### 10.1 Не отвечать на бухгалтерский вопрос по сути
Она не должна возвращать:
* “вероятно, проблема в 62 счёте”
* “скорее всего, не хватает оплаты”
Она должна возвращать **нормализованную интерпретацию**, а не бизнес-ответ.
### 10.2 Выделять причинно-следственную форму
Если вопрос содержит конструкции типа:
* “не бьётся”
* “не собралось в цепочку”
* “разложи по документам, оплатам, закрывающим”
* “чем подтверждается”
* “почему висит хвост”
* “не видно прихода под реализацию”
LLM должна поднимать:
* `needs_cross_entity_join = true`
* `needs_causal_chain = true`
* часто `needs_evidence = true`
### 10.3 Отдельно распознавать exact object trace
Если вопрос про:
* конкретный документ,
* конкретную проводку,
* конкретную строку,
* конкретный объект,
* конкретный номер / ref / line / posting
Тогда поднимать:
* `needs_exact_object_trace = true`
### 10.4 Различать множественный explain и точечный drilldown
Если вопрос:
* “по нескольким материалам покажи, почему зависли”
* “по каким кейсам это происходит”
* “по каким поставщикам не бьётся”
Это **не** exact drilldown.
Это множественный causal explain → чаще `hybrid_store_plus_live`.
### 10.5 Не путать risk-лексику с risk-route
Если в вопросе есть слова:
* “риск”
* “проблема”
* “аномалия”
* “опасный”
но одновременно есть document/payment/posting chain semantics,
то normalizer не должен автоматически относить это к `store_feature_risk`.
Он должен сохранять causal cross-entity приоритет.
---
## 11. Prompt system
Нужна управляемая prompt-архитектура.
## 11.1 Структура prompt’ов
Разделить prompt минимум на 3 уровня:
### `system_prompt`
Общие жесткие правила:
* ты не отвечаешь на бухгалтерский вопрос;
* ты возвращаешь только JSON;
* ты обязан следовать schema;
* ты не выдумываешь период, если его нельзя разумно вывести;
* ты явно помечаешь ambiguity.
### `developer_prompt`
Правила нормализации:
* классификация типов вопросов;
* различение heavy/cross-entity/drilldown;
* правила выбора route_hint;
* правила confidence;
* правила causal semantics.
### `domain_prompt`
Предметная специфика:
* словарь бухгалтерских формулировок;
* названия счетов;
* доменные сущности;
* типовые паттерны “хвост”, “не бьётся”, “акт сверки”, “закрывающие”, “реализация без оплаты”, “продажа раньше прихода”, “ошибка даты”, “97 счёт”, “ОС”, “банковская выписка” и т.д.
## 11.2 Few-shot examples
Добавить отдельный блок примеров:
* raw question
* expected normalized JSON fragment
Минимум 10–15 примеров на старт.
---
## 12. Route Hint Adapter
Нужен слой, который переводит normalized JSON в input существующего router.
## 12.1 Требования
На основе `normalized_query_v1` строить объект:
```json
{
"intent_class": "cross_entity",
"decision_flags": {
"needs_cross_entity_join": true,
"needs_causal_chain": true,
"needs_exact_object_trace": false,
"needs_ranking": false,
"needs_anomaly_summary": false,
"needs_runtime_truth": false
},
"route_hint": "hybrid_store_plus_live",
"confidence": "medium",
"entities": { ... },
"period_scope": { ... }
}
```
## 12.2 Поведение
Этот adapter пока только готовит payload и показывает его в UI.
Интеграция в боевой router может быть следующей фазой.
---
## 13. Логирование и traceability
Каждая нормализация должна логироваться.
## 13.1 Что сохранять
* `trace_id`
* timestamp
* model
* prompt_version
* schema_version
* raw user question
* context
* raw request payload
* raw model response
* parsed normalized JSON
* validation result
* route_hint
* confidence
* token usage
* latency
* optional expected route
* optional eval label
## 13.2 Формат хранения
Хранить локально в JSONL или SQLite.
Рекомендуемый вариант:
* `data/normalizer_traces/*.json`
или
* `data/normalizer.sqlite`
---
## 14. Eval mode
Нужен режим оценки качества normalizer.
## 14.1 Источник eval-набора
Собрать eval corpus из:
* каноничных benchmark-вопросов;
* creative stress вопросов;
* реальных человеческих фраз из диалогов.
## 14.2 Формат тест-кейса
```json
{
"case_id": "NQ-001",
"raw_question": "Где у нас не бьются взаиморасчёты по поставщикам...",
"expected": {
"intent_class": "cross_entity",
"route_hint": "hybrid_store_plus_live",
"requires": {
"needs_cross_entity_join": true,
"needs_causal_chain": true
},
"accounts_mentioned": ["60"],
"expected_output_shape": "reconciliation_report"
}
}
```
## 14.3 Метрики eval
Считать:
* `intent_class_accuracy`
* `route_hint_accuracy`
* `causal_flag_accuracy`
* `period_scope_accuracy`
* `entity_extraction_accuracy`
* `schema_validation_pass_rate`
* `high_confidence_error_rate`
---
## 15. Валидация structured output
## 15.1 Обязательное правило
Если модель вернула невалидный JSON:
* backend не должен silently repair;
* backend должен помечать `validation.passed = false`;
* UI должен показывать ошибку;
* запись должна логироваться.
## 15.2 Допустимый soft-recovery
Разрешён только один controlled retry:
* при invalid JSON
* с дополнительной server-side инструкцией “return valid JSON strictly matching schema”
Но не больше 1 повтора на запрос.
---
## 16. Security requirements
### 16.1 Обязательные требования
* ключ не хранить в localStorage в открытом виде;
* ключ не отправлять в сторонние домены;
* ключ не логировать в trace;
* ключ не возвращать во frontend response;
* backend должен редактировать чувствительные поля из логов.
### 16.2 Допустимый режим для localhost
Разрешается:
* временно держать ключ в памяти backend-процесса;
* или вводить ключ вручную на сессию без персистентного хранения.
---
## 17. Нефункциональные требования
* UI должен быть пригоден для localhost-тестов без production hardening.
* Нормализация одного запроса должна быть достаточно быстрой для интерактивной работы.
* Код должен быть модульным, чтобы потом normalizer можно было вынести из playground в основной backend.
* Все schema и prompts должны быть версионируемыми.
* Архитектура должна позволять заменить модель без переписывания всего пайплайна.
---
## 18. Предлагаемая структура проекта
```text
llm_normalizer/
frontend/
src/
components/
pages/
api/
state/
package.json
backend/
src/
server.ts
routes/
normalize.ts
presets.ts
history.ts
eval.ts
testConnection.ts
services/
openaiResponsesClient.ts
normalizerService.ts
promptBuilder.ts
schemaValidator.ts
routeHintAdapter.ts
traceLogger.ts
schemas/
normalized_query_v1.json
prompts/
system/
developer/
domain/
fewshot/
storage/
types/
package.json
data/
presets/
traces/
eval_cases/
docs/
README.md
API.md
SCHEMA.md
PROMPTS.md
```
---
## 19. Acceptance criteria
Этап считается принятым, если выполнены все условия:
### Функционально
* localhost GUI запускается;
* можно ввести ключ, модель и вопрос;
* backend успешно вызывает Responses API; ([OpenAI Платформа][1])
* модель возвращает structured JSON по schema; ([OpenAI Платформа][1])
* JSON проходит валидацию минимум в 90% тестовых кейсов;
* сохраняются traces;
* route hint summary отображается в UI;
* есть история запросов;
* есть eval-mode на локальном наборе кейсов.
### Архитектурно
* frontend не ходит напрямую в OpenAI API с ключом; ([OpenAI Платформа][2])
* prompts версионируются;
* schema версионируется;
* normalizer отделён от router;
* код модульный и пригоден к дальнейшей интеграции.
### Качественно
На стартовом eval-наборе целевые ориентиры:
* `schema_validation_pass_rate >= 90%`
* `intent_class_accuracy >= 80%`
* `route_hint_accuracy >= 75%`
* `causal_flag_accuracy >= 80%`
* `high_confidence_error_rate <= 10%`
---
## 20. Порядок реализации
### Этап 1
Поднять backend-proxy и test connection.
### Этап 2
Сделать GUI с input/output блоками.
### Этап 3
Сделать prompt manager и schema loader.
### Этап 4
Сделать `POST /api/normalize` и structured JSON parsing.
### Этап 5
Сделать route hint adapter и validation panel.
### Этап 6
Сделать history + trace logging.
### Этап 7
Сделать eval mode и загрузку тестовых кейсов.
### Этап 8
Подготовить README и пример prompt presets.
---
## 21. Что Codex должен сгенерировать
Codex должен выдать:
1. Полностью рабочий localhost-проект.
2. Frontend + backend.
3. JSON schema `normalized_query_v1`.
4. Стартовые prompt-файлы:
* system
* developer
* domain
* fewshot
5. Примеры test cases.
6. README с инструкцией запуска.
7. Пример `.env.example`.
8. Пример trace storage.
9. Минимальные тесты:
* schema validation
* route hint adapter
* normalize endpoint
* prompt builder
---
## 22. Ключевое архитектурное правило
Самое важное правило этого этапа:
**LLM — это semantic front-end, а не исполнитель бизнес-логики.**
LLM должна:
* нормализовать,
* структурировать,
* классифицировать,
* подсказывать route hint.
LLM не должна:
* сама принимать окончательное orchestration-решение;
* сама лезть в данные;
* сама становиться вашим retrieval engine.
---
Если хочешь, следующим сообщением я дам **сразу вторую часть ТЗ**: уже не про playground, а про **встраивание normalizer’а в существующий router/orchestration pipeline**.
[1]: https://platform.openai.com/docs/api-reference/responses/list?ref=test-ippon.ghost.io&utm_source=chatgpt.com "Responses | OpenAI API Reference"
[2]: https://platform.openai.com/docs/api-reference/chat/create%23chat-create-temperature?utm_source=chatgpt.com "Chat Completions | OpenAI API Reference"