55 lines
4.6 KiB
Markdown
55 lines
4.6 KiB
Markdown
# DATAFLOW
|
||
|
||
## Signal Planner Flow (Post-Commit Async)
|
||
1. `AIPMOKernelService` creates signal (`signal.create`) in transaction.
|
||
2. Transaction commits.
|
||
3. Background task triggers `SignalPlannerService.analyze(signal_id, tenant_id, ...)`.
|
||
4. Planner service opens isolated `AsyncSessionLocal` and loads context:
|
||
- signal content/project context
|
||
- project members (`user_projects -> users -> user_workloads -> user_skill_bindings -> skill_tags`)
|
||
5. Planner calls `llm_service.generate_structured_object(function_name="signal_planner_analyze")` with hard wait timeout (`25s`).
|
||
6. Structured success:
|
||
- `SignalStrategicAnalysisService.merge_and_save(...)`
|
||
- update `signals.planner_status=completed`
|
||
- write planner payload into `strategic_analysis.ai_planner`
|
||
7. Structured invalid / timeout fallback:
|
||
- build degraded planner payload (`fallback_mode=true`)
|
||
- still `merge_and_save(...)` and mark `signals.planner_status=completed`
|
||
8. Hard failure (DB write / unexpected exception):
|
||
- `SignalStrategicAnalysisService.mark_failed(...)`
|
||
- update `signals.planner_status=failed`
|
||
- try enqueue compensate reply via `FeishuOutboxService.enqueue(...)`
|
||
|
||
## Model Routing Flow
|
||
1. Frontend `ModelRoutingConfigPage` reads current mapping via `/model-routing/functions/{function_name}`.
|
||
2. Manager updates mapping via PUT API.
|
||
3. Backend persists override into `integrations(type='model_routing')`.
|
||
4. `LLMService` resolves function-level override at runtime before default control-plane rules.
|
||
|
||
## Query Route Gateway Flow
|
||
1. `AIPMOKernelService.process_ingress()` 先完成 `plan_mode` gate;命中 `reply/thread`、`work_item_id`、active requirement context、draft/workspace lock 时继续留在 requirement/draft 主链。
|
||
- 若已绑定 active requirement context 且用户显式说 `退出需求模式`,必须先把当前带 active draft 的 live requirement topic 挂起,再回到普通 `query.answer`;同 scope 下后续 idle query topic 不得抢走这次绑定。
|
||
2. 非 `plan_mode` 的 `query.answer` 进入 `TypedExecutor._execute_query_intent()`,在调用 `AdaptiveRAG.answer_question()` 前先执行 `preview_query_route_decision(...)`。
|
||
3. `AdaptiveRAGQueryRouteGatewayMixin` 产出单次结构化 `query_profile`(`needs_private_context / needs_freshness / referenced_objects`),并分别运行:
|
||
- `InternalProbe`:`config_hit_count / private_object_hit_count / private_scope_hit / vector_top1_score / vector_topk_support / graph_fact_hit_count`
|
||
- `ExternalProbe`:`freshness_required / trusted_domain_hit_count / answerable_page_hit_count / cross_source_agreement / external_entity_hit`
|
||
4. Gateway 结合 `query_route_memories` 的相似样本先验,输出 `route_mode / effective_source_policy / decision_origin / reply_contract / probe_snapshot`。
|
||
5. 若 `route_mode=internal`,内部只读查询必须先生成 `Query DSL Plan`:统一收口 `query_type=existence/count/list/status/explain/diagnose/compare/unknown`、`entity_type`、`answer_contract`、`filters`、`scope` 与 `retrieval_policy`;协议短回复、模式控制、执行动作必须在此之前就被 gate 掉,不得混入 DSL 规划。
|
||
6. `Bounded Executor` 只按白名单模板执行内部查询:
|
||
- 优先查 `semantic_facts`
|
||
- facts 不足时再做 `db/graph/doc/config` 的受控 fallback retrieval
|
||
- 全程自动绑定 `tenant_id`
|
||
- 不接收自由 SQL
|
||
7. `Answer Verifier` 在出站前检查“问法合同、证据合同、来源合同”是否一致;若发现 existence/status/compare 被答成 total count、或证据与结果不符,必须重试或显式失败。
|
||
8. `AdaptiveRAG.answer_question()` 只消费已经收口好的 route 决策和对应结果:`internal` 只走受控内部查询主链;`external` 统一走 `External Query Planner -> External Query Gateway -> External Provider Registry -> MCP adapter 优先(当前已接通 Microsoft Learn backend-direct runtime)-> bounded fallback live search -> external answer verifier`,禁止再直接混入内部检索结果;`uncertain` 仅允许 `external-first` 或 clarification。
|
||
9. 回答完成后:
|
||
- `QARecord.routing_snapshot`、`citations`、`sources_used` 继续落盘
|
||
- `query_route_memories` 追加或更新该次样本
|
||
- `QAFeedback` / `FeedbackCenterRecord` 后续会把 route feedback 回写到 `query_route_memories.feedback_outcome`
|
||
|
||
## Task Brief Flow
|
||
1. Frontend chooses template / trigger generate.
|
||
2. Backend `task_brief_service` stores template and run records in `integrations(type='task_briefs')`.
|
||
3. Generation run writes summary + artifact path.
|
||
4. `/task-briefs/center` aggregates latest generated cards for sidebar center.
|