6.2 KiB
Address Architecture Contract V1
Дата: 2026-04-01
1) Зачем документ
Этот контракт фиксирует архитектурные границы address_query-контура, чтобы система оставалась переносимой между разными 1С-базами и не обрастала company-specific логикой.
Контракт обязателен для всех следующих инкрементов (M2.4+), рефакторов и новых intent/recipe.
2) Непересекаемые принципы
MCP/live-first: основной источник фактов - live MCP.MSP-onlyв runtime: production path работает через MCP/MSP; snapshot - только controlled fallback.snapshotдопускается только как явный fallback с reason code, а не как скрытая подмена.runtime = data-agnostic: никаких хардкодов под конкретную компанию.acceptance = data-aware: positive-кейсы можно подбирать на текущей базе только для проверки.false_factual_rate = 0: factual-ответ только при подтвержденныхrows_matched > 0.whitelist execution only: никаких свободных NL->query генераторов.
3) Канонический pipeline
Stage A: Decompose
Назначение: интерпретация текста вопроса, без обращения к данным компании.
Выход stage:
question_modequery_shapeintent_candidatesanchors_rawtime_scope_rawfilters_rawdecomposition_plan(опционально, для compound)
Запрещено на этапе Decompose:
- резолвить реальные объекты базы (контрагентов, договоры, документы);
- тянуть company-specific словари;
- генерировать запросы к 1С.
Stage B: Resolve
Назначение: привязка raw-якорей к живым объектам через MCP.
Выход stage:
anchor_typeanchor_value_rawanchor_value_resolvedresolver_confidenceambiguity_count
Правило:
- если якорь не подтвержден, runtime не выдумывает факт и идет в
LIMITED_WITH_REASON.
Stage C: Execute
Назначение: выполнение только через recipe whitelist.
Правила:
intent -> recipe_idтолько из каталога;- fixed
limit/sort/windowполитика; MCPread-only;MSP/MCP-onlyexecution path в production;- snapshot fallback только явный.
Диагностика по стадиям:
no_raw_rowsraw_rows_received_but_not_materializedmaterialized_but_not_anchor_matchedmaterialized_but_filtered_out_by_recipematched_non_emptyerror
Stage D: Compose
Назначение: финальный ответ строго по execution-результату.
Правила:
- factual только из
rows_matched; - если пусто -
LIMITED_WITH_REASONс конкретной причиной; - без reasoning-галлюцинаций и без “догадки по смыслу”.
4) Политика словарей
Разрешено (статически в коде):
- доменная типовая лексика (
доки,остаток,договор,дебиторкаи т.д.); - правила парсинга дат/периодов/счетов;
- stop-слова и служебные alias-правила.
Запрещено:
- хранить в коде списки компаний, ИНН, договоров, документов конкретной базы;
- пополнять глобальные normalization-библиотеки живыми entity-именами;
- строить скрытые “памяти компании” вне runtime-сессии.
Допустимо:
- использовать runtime-сессионный контекст диалога (
followup context) без записи в глобальные словари.
5) Критерии переносимости между компаниями
Система считается переносимой, если:
- новая база подключается без code change в resolver/intent logic;
- меняются только live-данные MCP, а не кодовые словари;
- question-bank остается валиден (с ожидаемыми различиями factual/limited по данным).
6) Антипаттерны (нельзя делать)
- Добавлять company alias map в
src/services/*с реальными названиями контрагентов. - Перекладывать проблему резолвинга в hardcoded
if company == .... - Подмешивать deep-analysis ответ в address factual-блок без явного route handoff.
- Поднимать “временные” exceptions, которые ломают stage-контракт.
7) Техническая дисциплина кода
Новая логика должна ложиться в явные stage-модули:
- decompose
- resolve
- execute
- compose
- diagnostics
Если функция не относится к stage - это smell и повод к вынесению.
8) Как подключать LLM decompose
LLM на первом этапе нужен не для “знания компании”, а для структурной интерпретации вопроса.
LLM должен возвращать схему-stage-output:
- intent candidates
- shape
- anchor spans
- time scope
- filter hints
- confidence
Дальше все company-specific подтверждается только Resolver/Execute через MCP.
Итог:
- LLM decompose уменьшает NLP-хрупкость;
- не требует жирных живых словарей компаний;
- не нарушает data-agnostic принцип runtime.