14 KiB
14 KiB
飞书提问慢 + AI 管家分层回复 + 历史需求不同步 — 修改计划
目标问题
- 飞书里把需求写成问句时,系统经常只回答,不同步到需求/信号链路。
- 飞书连续追问时,上一条需求和上下文不能稳定续上。
- 内置 AI 管家回复偏“分层汇报/任务分派”,不够直接。
- 部分问题会被拉进深度推理链路,导致响应时间明显偏长。
本计划目标
- 问句式需求也能进入同步链路,不再被
QA bypass吃掉。 - 飞书问答建立可持续的 chat/session 上下文,不再依赖
asked_by。 - 历史需求支持“即时可见 + 默认可召回”,不依赖“之前/上次/历史”关键词。
- AI 管家事实问答改成直接回答风格,执行回执和问答风格分离。
- 控制飞书直答长尾时延,避免无必要进入 deep reasoning。
非目标
- 本次不改飞书卡片 UI。
- 本次不做多渠道统一会话中心重构。
- 本次不改业务字段模型的大范围语义定义,只修正问答/同步链路。
实施状态(2026-03-06)
- Phase 1 已启动:问句式需求从“只答不入队”改为“答复 + 继续同步”。
- Phase 5 部分已启动:RAG 事实问答关闭默认角色 prompt 注入,减少模板化分层回答污染。
- 已补首批轻量单测:问句需求识别与问句转陈述归一化。
- Phase 2 部分已启动:飞书问答接入
conversation_key,asked_by=None也可复用 Redis recent turns。 - Phase 3 部分已启动:飞书 recent conversation 走同步缓存读取,不依赖向量入库完成。
- Phase 4 部分已启动:飞书渠道默认补充
feishu检索域(有source_chat_id时)。 - Phase 6 部分已启动:飞书渠道 deep 触发改为“显式深查意图”白名单,默认不强制 deep。
- Phase 6 部分已启动:飞书 deep 检索预算收紧(steps/top_k 下调),降低长尾时延风险。
- Phase 3 部分补齐:
capture_from_feishu在非 RAG 分支同步写 recent cache(Redis),减少“刚发需求即追问”丢上下文。 - 回归压测脚本补齐:
ai_steward_pressure_coach.py新增feishu_capture模式与question_requirement_hit_rate指标,ai_steward_eval_compare.py可比较 pressure 报告。 - 飞书分流稳定性补丁:
level/signal/project_prefill在 LLM 空返回或异常时走规则兜底,不再直接pipeline_failed。
一、根因拆分
1. 问句式需求被直接路由为 QA
- 现状:
intent == "question"时直接走rag_service.answer_question(...),并跳过signal/project处理。 - 结果:用户把需求写成“这个要不要支持 X”“能不能加 Y”时,只得到回答,不会同步到需求链路。
2. 飞书侧没有会话态
- 现状:飞书问答传入
asked_by=None,RAG 层不创建 session,也不加载 recent conversation。 - 结果:后续追问缺少主语继承、纠错继承、最近 10 轮上下文。
3. 飞书历史是异步 eventual consistency
- 现状:飞书消息向量化使用
asyncio.create_task(...)后台入库。 - 结果:用户刚发完需求马上追问时,上一条消息可能还没进入检索库。
4. 飞书历史不是默认检索域
- 现状:只有命中“之前/上次/历史”等关键词才显式加入
feishu检索域。 - 结果:即使同群同线程,系统也不会默认回看最近飞书上下文。
5. 问答 prompt 与执行回执 prompt 混用
- 现状:RAG 问答默认套用“产品经理(任务分派)”角色 prompt;飞书回复层又要求“先确认,再给建议”。
- 结果:事实问答也会被答成分层汇报风格。
6. Deep reasoning 触发范围偏宽
- 现状:纠错类、引擎链类问题会被强制切到 deep;同时存在 mixed routing / escalation / 较长 timeout。
- 结果:飞书直答的长尾延迟被放大。
二、总体改造策略
本次按 4 条主线并行改:
-
路由修正
- 把“问句”和“需求”从互斥关系改成可并行判定。
- 新增
question_requirement场景:既回答用户,也同步需求。
-
会话补齐
- 给飞书引入基于
source_chat_id + sender_open_id的 conversation key。 - 让飞书侧也能复用
session state / rewrite history / recent turns。
- 给飞书引入基于
-
同步改强
- 最近消息缓存同步写入 Redis。
- 向量化继续异步,但“最近上下文”不再依赖向量写库完成。
-
回答链路瘦身
- 事实问答关闭任务分派型 role prompt。
- 飞书执行回执与事实问答拆成两套 prompt。
- 缩小 deep 模式触发面,限制长尾。
三、详细改造项
Phase 1 — 问句式需求不再丢同步
目标
- “这个需求要不要支持飞书同步?”
- “能不能给项目列表加筛选?”
- “这个是不是也要记录到需求池?”
以上消息不再只走 QA,而是进入“回答 + 需求同步”双通道。
修改点
backend/app/services/feishu_signal_pipeline.py- 把当前
question / mixed / statement三段式改为:pure_qaqa_with_requirementpure_requirement
- 在
intent == "question"后增加二次判定:- 是否包含需求动作词
- 是否存在功能/模块/页面/流程对象
- 是否指向已有项目或潜在新需求
- 命中时:
- 保留 direct reply
- 同时继续执行 signal/project 分流
- 把当前
实现建议
- 新增 helper:
_is_requirement_like_question(message: str) -> bool_extract_question_requirement_statement(message: str) -> str
- 对
question_requirement:rag_question_part继续回答message_for_sync进入_classify_level/_extract_signal/_project_prefill
验收
- 问句式需求消息能生成 direct reply。
- 同一消息同时落需求队列或自动入 signal。
AIProcessingLog.routing_decision不再统一落到direct_qa。
Phase 2 — 为飞书补 session / state
目标
- 飞书连续两三句追问时,可以继承上一轮主语。
- “不是这个意思”“我说的是刚才那个需求”可以命中纠错链路。
修改点
backend/app/services/adaptive_rag_service.pybackend/app/schemas/rag.pybackend/app/api/rag.pybackend/app/api/ai_steward.pybackend/app/services/context_cache.py
设计
- 新增统一字段:
conversation_key- Web:
user:{asked_by}:session:{session_id} - Feishu:
feishu:{source_chat_id}:{sender_open_id or sender_hash}
- Web:
answer_question(...)新增可选参数:conversation_keyexternal_actor_idchannel_thread_id
asked_by is None时:- 不再直接返回空 session
- 改为基于
conversation_key维护轻量会话态
数据方案
- 优先最小改造,不先扩 DB 表:
QASessionState继续存结构化 state- Redis 里为飞书维护 recent turns
- 如现有表难以复用,再补一张轻量表:
external_qa_sessionsidtenant_idchannelconversation_keysource_chat_idexternal_actor_idlast_message_atmessage_count
验收
- 飞书下第二句“分别是什么”“不是这个意思”可以继承上一轮主语。
- 不依赖
asked_by也能拿到 recent conversation。
Phase 3 — 最近消息同步写缓存,向量化继续异步
目标
- 解决“上一条需求刚发完,下一条就检索不到”的即时一致性问题。
修改点
backend/app/services/signal_capture.pybackend/app/services/adaptive_rag_service.pybackend/app/services/context_cache.py
方案
- 飞书消息接收后,拆成两层写入:
- 同步写 Redis recent turns
- key:
pmflow:feishu:recent:{tenant_id}:{conversation_key} - 保存最近 20 条消息
- key:
- 异步写向量库
- 保留原
ingest_feishu_message_async(...)
- 保留原
- 同步写 Redis recent turns
- RAG 检索时增加优先级:
- 先读 recent turns cache
- 再查结构化 state
- 最后再查向量库历史
好处
- 不阻塞主链路。
- 用户下一句追问时,最近上下文立即可用。
- 避免把“即时续聊”完全压到 embedding/vector 检索上。
验收
- 连续两条飞书消息间隔 < 3 秒,第二条仍可读到第一条内容。
Phase 4 — 飞书历史默认参与召回
目标
- 不再要求用户必须说“之前/上次/历史”才能召回飞书历史。
修改点
backend/app/services/adaptive_rag_service.py
方案
_route_domains(question)增加 channel-aware 行为:- 若
asked_via == "feishu"且存在source_chat_id - 默认把
feishu_recent加入检索域
- 若
- 区分两类历史:
feishu_recent:同 chat 最近 N 轮,低成本、默认启用feishu_vector:更早历史,命中 history cues 或低证据时再启用
检索顺序
- recent chat cache
- session state
- db / graph / pmflow
- feishu vector history
验收
- 不带“之前/上次”关键词,仍可在同群连续追问中续上上下文。
Phase 5 — 问答 prompt 与执行回执 prompt 解耦
目标
- AI 管家 factual QA 直接回答,不再默认“复述需求 + 下一步动作”。
- 飞书执行回执保留有人味,但不污染事实问答。
修改点
backend/app/services/llm.pybackend/app/config/ai_prompts.pybackend/app/services/feishu_integration.pybackend/app/services/adaptive_rag_service.py
方案
- 新增 2 类 prompt 配置:
rag_factual_qafeishu_execution_receipt
AdaptiveRAGService._generate_answer(...)- 默认
use_prompt_profile=False - 或只允许使用专门的
rag_factual_qarole
- 默认
FeishuIntegrationService._reply_with_active_role_prompt(...)- 只用于执行回执、纠错说明、状态反馈
- 不再包裹 direct QA 的正文
回复规范
- factual QA:
- 先直接给答案
- 证据不足直接说“不确定/缺少字段”
- 不强制“下一步动作”
- execution receipt:
- 可保留确认式口吻
- 但限制为 1 句确认 + 1 句后续动作
验收
- “这个接口在哪?”这类问题不再答成任务分派。
- 飞书 direct QA 不再出现“先确认,再给 1-3 条建议”的固定模板。
Phase 6 — 收紧 deep reasoning 触发条件
目标
- 降低飞书长尾时延。
修改点
backend/app/services/adaptive_rag_service.pybackend/app/services/llm.py
方案
_forced_deep_reason(...)收紧:- 仅对显式引擎链/代码链/纠错且证据不足场景触发
- Feishu 普通产品问答默认不自动 deep
_should_auto_deep_retry(...)增加预算:- Feishu 渠道最多一次 retry
- 若 recent chat 命中充分,禁止 deep retry
- 配置预算:
- Feishu direct QA 目标
p95 < 3s - deep 模式 hard timeout 更短
- Feishu direct QA 目标
验收
- 同类飞书问题不再轻易进入 deep。
- 平均耗时和 p95 明显下降。
四、接口/数据变更清单
1. RAG 请求入参
- 新增:
conversation_key?: strexternal_actor_id?: strchannel_thread_id?: str
2. Redis keys
pmflow:feishu:recent:{tenant_id}:{conversation_key}pmflow:feishu:state:{tenant_id}:{conversation_key}
3. 日志字段
conversation_keysync_mode=sync_recent_cache/async_vector_onlyquestion_requirement=true/falsereply_style=factual_qa/execution_receipt
五、测试计划
1. 单元测试
tests/test_feishu_question_requirement_routing.py- 问句式需求不再 bypass
tests/test_feishu_conversation_state.pyasked_by=None时仍可续接上下文
tests/test_feishu_recent_cache_sync.py- recent cache 同步可见
tests/test_rag_prompt_style_split.py- factual QA 不再输出任务分派模板
2. 集成测试
- 基于现有
backend/evals/feishu_replay_eval.py- 新增 case:
- “这个功能是不是也要支持飞书同步?”
- “再加一个导出按钮”
- “分别是什么”
- “不是这个意思,我说的是刚才那个需求”
- 新增 case:
3. 回归压测
- 扩展现有压测脚本:
scripts/ai_steward_pressure_coach.pyscripts/ai_steward_eval_compare.py
- 重点指标:
- Feishu direct QA
p50 - Feishu direct QA
p95 - deep hit rate
- requirement sync hit rate
- recent-context recall hit rate
- Feishu direct QA
六、验收标准
功能验收
- 问句式需求能同时“回答 + 同步”。
- 飞书连续追问能继承上一轮上下文。
- 不带“之前/上次”关键词也能续上同 chat 最近上下文。
- direct QA 回复风格改为直接回答,不再模板化分层。
性能验收
- Feishu direct QA:
p50 < 1.5sp95 < 3s
- 无明显 template leak
- 无大面积 deep auto-trigger
稳定性验收
- recent cache 写入失败不影响主流程
- async vector ingestion 失败不影响 direct reply
- queue / signal / project 逻辑不回归
七、实施顺序
第 1 天
- Phase 1 路由修正
- 补
question_requirement测试
第 2 天
- Phase 2 会话补齐
- recent turns cache 接入
第 3 天
- Phase 3 即时同步
- Phase 4 默认召回 recent feishu history
第 4 天
- Phase 5 prompt 解耦
- 修 direct QA 风格
第 5 天
- Phase 6 deep 触发收紧
- 压测与 replay 回归
八、风险点
-
问句式需求误判增加
- 对策:增加白名单/黑名单词表 + replay eval。
-
Feishu recent cache 引入脏上下文
- 对策:只保留最近 20 条,同 chat + 同 actor 隔离。
-
prompt 解耦导致执行回执变冷
- 对策:仅 direct QA 关闭分派 prompt,执行回执不动。
-
deep 收紧后准确率下降
- 对策:保留显式 deep 开关和低证据兜底 retry。
九、建议的首批改动文件
backend/app/services/feishu_signal_pipeline.pybackend/app/services/adaptive_rag_service.pybackend/app/services/context_cache.pybackend/app/services/feishu_integration.pybackend/app/services/llm.pybackend/app/config/ai_prompts.pytests/test_feishu_question_requirement_routing.pytests/test_feishu_conversation_state.py
十、一句话决策
这次不要只调 prompt。要同时改 路由、会话、即时同步、回复风格、deep 触发 五个点,否则“飞书里提需求慢 + 需求不同步 + 回答像汇报”会反复出现。