PMFlow/mdproject/feishu-ai-steward-sync-fix-...

14 KiB
Raw Blame History

飞书提问慢 + 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 条主线并行改:

  1. 路由修正

    • 把“问句”和“需求”从互斥关系改成可并行判定。
    • 新增 question_requirement 场景:既回答用户,也同步需求。
  2. 会话补齐

    • 给飞书引入基于 source_chat_id + sender_open_id 的 conversation key。
    • 让飞书侧也能复用 session state / rewrite history / recent turns。
  3. 同步改强

    • 最近消息缓存同步写入 Redis。
    • 向量化继续异步,但“最近上下文”不再依赖向量写库完成。
  4. 回答链路瘦身

    • 事实问答关闭任务分派型 role prompt。
    • 飞书执行回执与事实问答拆成两套 prompt。
    • 缩小 deep 模式触发面,限制长尾。

三、详细改造项

Phase 1 — 问句式需求不再丢同步

目标

  • “这个需求要不要支持飞书同步?”
  • “能不能给项目列表加筛选?”
  • “这个是不是也要记录到需求池?”

以上消息不再只走 QA,而是进入“回答 + 需求同步”双通道。

修改点

  • backend/app/services/feishu_signal_pipeline.py
    • 把当前 question / mixed / statement 三段式改为:
      • pure_qa
      • qa_with_requirement
      • pure_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.py
  • backend/app/schemas/rag.py
  • backend/app/api/rag.py
  • backend/app/api/ai_steward.py
  • backend/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}
  • answer_question(...) 新增可选参数:
    • conversation_key
    • external_actor_id
    • channel_thread_id
  • asked_by is None 时:
    • 不再直接返回空 session
    • 改为基于 conversation_key 维护轻量会话态

数据方案

  • 优先最小改造,不先扩 DB 表:
    • QASessionState 继续存结构化 state
    • Redis 里为飞书维护 recent turns
  • 如现有表难以复用,再补一张轻量表:
    • external_qa_sessions
      • id
      • tenant_id
      • channel
      • conversation_key
      • source_chat_id
      • external_actor_id
      • last_message_at
      • message_count

验收

  • 飞书下第二句“分别是什么”“不是这个意思”可以继承上一轮主语。
  • 不依赖 asked_by 也能拿到 recent conversation。

Phase 3 — 最近消息同步写缓存,向量化继续异步

目标

  • 解决“上一条需求刚发完,下一条就检索不到”的即时一致性问题。

修改点

  • backend/app/services/signal_capture.py
  • backend/app/services/adaptive_rag_service.py
  • backend/app/services/context_cache.py

方案

  • 飞书消息接收后,拆成两层写入:
    • 同步写 Redis recent turns
      • key: pmflow:feishu:recent:{tenant_id}:{conversation_key}
      • 保存最近 20 条消息
    • 异步写向量库
      • 保留原 ingest_feishu_message_async(...)
  • 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 或低证据时再启用

检索顺序

  1. recent chat cache
  2. session state
  3. db / graph / pmflow
  4. feishu vector history

验收

  • 不带“之前/上次”关键词,仍可在同群连续追问中续上上下文。

Phase 5 — 问答 prompt 与执行回执 prompt 解耦

目标

  • AI 管家 factual QA 直接回答,不再默认“复述需求 + 下一步动作”。
  • 飞书执行回执保留有人味,但不污染事实问答。

修改点

  • backend/app/services/llm.py
  • backend/app/config/ai_prompts.py
  • backend/app/services/feishu_integration.py
  • backend/app/services/adaptive_rag_service.py

方案

  • 新增 2 类 prompt 配置:
    • rag_factual_qa
    • feishu_execution_receipt
  • AdaptiveRAGService._generate_answer(...)
    • 默认 use_prompt_profile=False
    • 或只允许使用专门的 rag_factual_qa role
  • 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.py
  • backend/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 更短

验收

  • 同类飞书问题不再轻易进入 deep。
  • 平均耗时和 p95 明显下降。

四、接口/数据变更清单

1. RAG 请求入参

  • 新增:
    • conversation_key?: str
    • external_actor_id?: str
    • channel_thread_id?: str

2. Redis keys

  • pmflow:feishu:recent:{tenant_id}:{conversation_key}
  • pmflow:feishu:state:{tenant_id}:{conversation_key}

3. 日志字段

  • conversation_key
  • sync_mode = sync_recent_cache / async_vector_only
  • question_requirement = true/false
  • reply_style = factual_qa / execution_receipt

五、测试计划

1. 单元测试

  • tests/test_feishu_question_requirement_routing.py
    • 问句式需求不再 bypass
  • tests/test_feishu_conversation_state.py
    • asked_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:
      • “这个功能是不是也要支持飞书同步?”
      • “再加一个导出按钮”
      • “分别是什么”
      • “不是这个意思,我说的是刚才那个需求”

3. 回归压测

  • 扩展现有压测脚本:
    • scripts/ai_steward_pressure_coach.py
    • scripts/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

六、验收标准

功能验收

  • 问句式需求能同时“回答 + 同步”。
  • 飞书连续追问能继承上一轮上下文。
  • 不带“之前/上次”关键词也能续上同 chat 最近上下文。
  • direct QA 回复风格改为直接回答,不再模板化分层。

性能验收

  • Feishu direct QA:
    • p50 < 1.5s
    • p95 < 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 回归

八、风险点

  1. 问句式需求误判增加

    • 对策:增加白名单/黑名单词表 + replay eval。
  2. Feishu recent cache 引入脏上下文

    • 对策:只保留最近 20 条,同 chat + 同 actor 隔离。
  3. prompt 解耦导致执行回执变冷

    • 对策:仅 direct QA 关闭分派 prompt,执行回执不动。
  4. deep 收紧后准确率下降

    • 对策:保留显式 deep 开关和低证据兜底 retry。

九、建议的首批改动文件

  • backend/app/services/feishu_signal_pipeline.py
  • backend/app/services/adaptive_rag_service.py
  • backend/app/services/context_cache.py
  • backend/app/services/feishu_integration.py
  • backend/app/services/llm.py
  • backend/app/config/ai_prompts.py
  • tests/test_feishu_question_requirement_routing.py
  • tests/test_feishu_conversation_state.py

十、一句话决策

这次不要只调 prompt。要同时改 路由、会话、即时同步、回复风格、deep 触发 五个点,否则“飞书里提需求慢 + 需求不同步 + 回答像汇报”会反复出现。