跳转至

Ask Router Simulation:主动询问路由仿真

实验定位

主动询问的风险不是技术上能不能发消息,而是会不会问错人、群发、重复打扰、问得不清楚,或者把未确认回复直接沉淀成正式知识。

ask_router_simulation 在未接入企业微信前,用统一 owner registry 和 9 个任务场景验证四件事:

  • Agentic Search 发现证据不足后,能否选择少数相关 owner。
  • 询问消息是否包含任务、缺口、为什么问、期望格式、使用范围和 review 状态。
  • 同一 owner、同一任务、同一缺口在冷却窗口内是否会被重复询问。
  • 回复入口是否先形成 knowledge_card,而不是直接发布到 docs。

运行命令:

bash python scripts/ask_router_simulation.py --write-report

当前结果

指标 结果
场景数 9
Top1 准确率 100%
Expected Recall@3 100%
安全路由率 100%
forbidden 命中数 0
未允许候选命中数 0
负反馈处理通过率 100%
节流处理通过率 100%
重复询问抑制数 1
消息契约通过率 100%

当前 owner 来源已经统一为 load_owner_registry()

  • 存在显式 org-directory.json 时使用该目录,便于后续替换为企微通讯录 adapter 输出。
  • 显式目录缺失时从 domain-topology.json 派生 owner profiles,保证本地 topology 也能独立驱动主动询问。
  • route_ask_request_guarded() 可在不传入 people 参数时自动使用 topology fallback。

关键样例:

场景 Top1 候选人
客户合同付款状态 finance-owner finance-owner, crm-owner
企微回调重复询问 - -,wecom-owner 被冷却窗口抑制
D3 context document schema search-owner search-owner, knowledge-maintainer
GitHub CI 缺口 engineering-owner engineering-owner
CRM 反馈财务不是 owner crm-owner crm-owner

这轮修正暴露的坑

第一版只靠 token overlap 会把“当前提问人”或泛化 owner 排到前面,因为“上下文”“确认”“负责人”等词太通用。修正后,当前提问人只做兜底,不参与常规 owner 排名。

第一版对 not_owner 只做降权,仍可能把被反馈不是负责人的人放进候选。修正后,明确负反馈的人本轮直接排除。

只检查 forbidden 也不够。某些人虽然不是禁忌对象,但也不该被问。本轮新增 unexpected_hits,要求候选人必须属于期望 owner 或允许 secondary。

Top3 也不能机械填满。现在使用相对分数阈值,只保留接近 Top1 的候选,避免弱相关人被顺手问到。

只做 owner 排名也不够。重复询问会破坏组织体验。本轮新增 recent_ask_eventscooldown_minutes:同一 owner、同一任务、同一缺口在冷却窗口内已问过时,本轮不会重复发送,也不会为了绕过节流改问 requester。

问错人的回复不能只停留在 knowledge card 文本里。当前 ask_feedback_event_from_reply 会从结构化回复中的 better_owner 或“不是我负责”信号生成 AskFeedbackEventapply_feedback_events 会把原 owner 标为 not_owner 并把更合适负责人前置到下一轮建议 owner。这是主动询问 loop 的最小纠错闭环。

无企微 MVP 里,这个事件流先落在 domain/orgreorg-demo/ask-feedback-events.jsonorgreorg_demo --feedback-log 写入,orgreorg_demo --ask-feedback-log 读取并影响下一轮路由。

对企微接入的要求

企业微信接入后,发送消息前至少要保留这些字段:

text task knowledge_gap selected_owner_ids selection_reasons use_scope review_status rate_limit_key feedback_state ask_feedback_events recent_ask_events cooldown_minutes gap_hash

被询问人回复“不是我负责”时,要把负反馈写回 owner registry 或路由日志;否则系统会重复问错人。

企业微信接入后,真实消息 ID、会话 ID、发送时间和送达状态应写入 recent_ask_events。节流判断应发生在发送前,而不是发送失败后补救。

补充回复默认进入 review_status=pendingknowledge_card。只有经过人工 review,才允许提升到 vault wiki、项目页或 docs。

原始输出见 vault/50-outputs/ask-router-simulation-analysis.md