247 lines
12 KiB
Markdown
247 lines
12 KiB
Markdown
# PMFlow 当前飞书接 AI 流程说明
|
||
|
||
更新时间:2026-03-10
|
||
|
||
## 1. 结论(当前接入方式)
|
||
|
||
- 当前生产链路是 **长连接(long_connection)**,不是 webhook。
|
||
- 真实入口链路:`FeishuLongConnectionManager -> FeishuIntegrationService -> ProactiveSignalCaptureService -> AIPMOKernelService`。
|
||
- 回消息统一走 **Outbox(feishu_reply_outbox)**,支持重试与补偿发送。
|
||
- `FeishuSignalPipelineService` 仍在代码中,但当前主链路未直接调用,主要用于历史/评测链路。
|
||
|
||
## 2. 端到端时序
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant U as Feishu User
|
||
participant F as Feishu Open Platform
|
||
participant LC as FeishuLongConnectionManager
|
||
participant FI as FeishuIntegrationService
|
||
participant SC as ProactiveSignalCaptureService
|
||
participant K as AIPMOKernelService
|
||
participant DB as DB
|
||
participant OB as FeishuReplyOutbox
|
||
participant API as Feishu HTTP API
|
||
|
||
U->>F: 群消息 / @机器人
|
||
F-->>LC: long connection event (im.message.receive_v1)
|
||
LC->>FI: handle_message_event(event)
|
||
FI->>SC: capture_from_feishu(...)
|
||
SC->>K: process_feishu_message(...)
|
||
K->>DB: ingest_events/work_items/decision/plan/reply_receipts/signal
|
||
K-->>SC: capture_result (status/classification/direct_reply_text)
|
||
SC-->>FI: pipeline_result
|
||
FI->>OB: enqueue reply (pending)
|
||
OB->>API: send_message_to_group
|
||
API-->>OB: sent / retrying / failed
|
||
```
|
||
|
||
## 3. 详细流程
|
||
|
||
### 3.1 配置与启动
|
||
|
||
1. 前端配置页保存 `app_id/app_secret` 到 `POST /feishu/config`。
|
||
2. 后端写入 `integrations(type=feishu)`,并调用长连接管理器 `restart()`。
|
||
3. 应用启动时(`main.py` lifespan):
|
||
- 初始化并启动 `FeishuLongConnectionManager`。
|
||
- 启动 `feishu_outbox_drain_loop`,持续补偿发送 outbox。
|
||
|
||
补充:长连接重试策略来自环境变量:
|
||
- `FEISHU_LONG_CONNECTION_RETRY_BASE_SECONDS`(默认 1)
|
||
- `FEISHU_LONG_CONNECTION_RETRY_MAX_ATTEMPTS`(最大 3)
|
||
|
||
### 3.2 飞书事件接收(长连接)
|
||
|
||
1. 管理器线程内创建 `lark_oapi ws.Client`。
|
||
2. 仅业务事件 `message.receive_v1 / im.message.receive_v1` 进入主队列。
|
||
3. Worker 从队列取事件,调用 `FeishuIntegrationService.handle_message_event()`。
|
||
|
||
### 3.3 消息解析与预处理
|
||
|
||
在 `FeishuIntegrationService._handle_message_receive`:
|
||
|
||
1. 忽略机器人/应用发送者(`sender_type in {app, bot}`)。
|
||
2. 解析消息内容(支持 `text/post/image/file/media`),附件会归一化。
|
||
3. 记录 ingress trace 到 `ai_processing_logs`。
|
||
4. 无文本但被 @ 时,会回一条“请补充文字需求”的提示。
|
||
|
||
### 3.4 AI PMO 决策主链路
|
||
|
||
`ProactiveSignalCaptureService.capture_from_feishu` 会调用 `AIPMOKernelService.process_feishu_message`:
|
||
|
||
1. 清洗文本,先过滤空消息/纯噪音。
|
||
2. 生成 `source_message_id`,并写 `ingest_events` 做幂等去重。
|
||
3. 创建 `work_items`(状态机起点 `received`)。
|
||
4. 构建 world model(项目、预算、产能、技能、章程、任务、风险)。
|
||
5. Intent 识别:
|
||
- `query.read_only`
|
||
- `project.create`
|
||
- `signal.create`
|
||
- `signal_source.onboard`
|
||
- `followup.confirm / followup.continue`
|
||
- `ignore`
|
||
6. 三脑决策与仿真:战略、战术、执行前仿真 + policy gate。
|
||
7. 根据策略:
|
||
- 可自动执行:进入 typed executor。
|
||
- 不可自动执行:进入 `waiting_manual`,并推送站内待办通知。
|
||
8. 生成唯一回执(`reply_receipts`),避免同消息同 phase 重复回复。
|
||
|
||
### 3.5 Typed Executor 分支
|
||
|
||
- `query.read_only`:调用 `AdaptiveRAGService.answer_question`。
|
||
- `project.create`:调用 `AIStewardService.create_project_from_natural_language`。
|
||
- `signal.create`:直接创建 `signals`(可带 `project_id`)。
|
||
- `signal_source.onboard`:创建信号后,走 `SignalSourceDomainWorkflow`(底层编排 `SignalSourceOrchestrationService` / OpenClaw)。
|
||
- `followup.*`:尝试恢复最近待确认工作项继续执行。
|
||
|
||
### 3.6 回复生成与发送
|
||
|
||
`FeishuIntegrationService` 会按 scene 路由回复:
|
||
|
||
- `execute`:优先固定执行回执模板(避免“教程式”回复)。
|
||
- `qa`:
|
||
- 若 `direct_reply_required=true`,直接回 `direct_reply_text`;
|
||
- 否则仅在明确 `@PMFlow` 时触发人设化回复。
|
||
- `error`:固定错误模板。
|
||
|
||
发送路径:
|
||
|
||
1. 先入 `feishu_reply_outbox(status=pending)`。
|
||
2. 异步立即派发一次;失败则指数退避重试。
|
||
3. 后台 drain loop 持续扫 `pending/retrying` 做补偿发送。
|
||
|
||
## 4. 可靠性与幂等设计
|
||
|
||
关键幂等点:
|
||
|
||
- `ingest_events`:`(tenant_id, channel, event_key)` 唯一。
|
||
- `work_items`:`(tenant_id, source_system, source_message_id)` 唯一。
|
||
- `reply_receipts`:`(tenant_id, source_system, source_message_id, receipt_phase)` 唯一。
|
||
|
||
关键可靠性点:
|
||
|
||
- 长连接断线自动重连(最多 3 次,指数退避)。
|
||
- Outbox 发送失败自动重试 + 后台补偿。
|
||
- 全链路 `ai_processing_logs` 留痕,便于回放排障。
|
||
|
||
## 5. 关键数据表(当前链路涉及)
|
||
|
||
- `integrations`:飞书配置。
|
||
- `ingest_events`:入站事件幂等账本。
|
||
- `work_items`:AI PMO 工作项与状态机。
|
||
- `decision_records` / `plan_bundles`:决策与计划快照。
|
||
- `reply_receipts`:回执唯一性控制。
|
||
- `feishu_reply_outbox`:发送队列与重试。
|
||
- `signals` / `project_signal_links`:落库信号与项目关联。
|
||
- `ai_processing_logs`:处理过程日志。
|
||
|
||
## 6. 运维排查入口
|
||
|
||
- `GET /feishu/config`:是否配置、当前模式、长连接状态。
|
||
- `POST /feishu/test-connection`:token + 长连接线程健康检查。
|
||
- `GET /feishu/long-connection/status`:运行态/错误码/重试窗口。
|
||
- `POST /feishu/long-connection/restart`:手动重启长连接。
|
||
|
||
常见失败定位:
|
||
|
||
- `auth_failed`:`app_id/app_secret` 或应用权限问题。
|
||
- `network_error`:后端到飞书网络/TLS 问题。
|
||
- `sdk_missing`:缺少 `lark-oapi` 依赖。
|
||
- outbox `failed`:下游发送失败,查看 `last_error`。
|
||
|
||
## 7. 现状说明(避免误判)
|
||
|
||
- `FeishuSignalPipelineService` 与 `feishu_items` 仍存在,但当前主入口未直接调用该服务。
|
||
- 现在线上主流程以 `AIPMOKernelService` 为统一决策中枢。
|
||
- 如果后续要彻底收敛,可考虑把历史队列链路标记为 deprecated 并逐步下线。
|
||
|
||
### 7.1 这套历史链路现在“还有什么用”
|
||
|
||
当前仍有 4 类明确用途:
|
||
|
||
1. 回归评测与回放:`backend/evals/feishu_replay_eval.py` 仍直接驱动 `FeishuSignalPipelineService`,用于离线评估路由/回执一致性。
|
||
2. 单元测试基座:多处测试直接依赖其工具函数与判定逻辑(例如 `backend/tests/test_inbox_queue_view.py`、`backend/tests/test_feishu_routing_receipts.py`)。
|
||
3. 历史数据兼容:`ai_logs`、`project_knowledge_graph` 仍会读取 `feishu_items` 做项目过滤和增量图谱事件。
|
||
4. 数据迁移与幂等治理:Alembic 与启动自检里仍有 `feishu_items` 去重/唯一索引修复逻辑,保障旧数据不炸库。
|
||
|
||
一句话:它对“新消息在线处理”不是主链路,但对“测试、历史数据、迁移兼容”仍有实际价值。
|
||
|
||
## 8. 阶段与 Agent(服务)映射
|
||
|
||
> 你问的“走到哪用哪个 agent”,按当前代码可对应为下表。
|
||
|
||
| 阶段 | Agent/服务 | 作用 |
|
||
| --- | --- | --- |
|
||
| 事件接入 | `FeishuLongConnectionManager` | 与飞书建立长连接,接收 `im.message.receive_v1` 事件并投递队列 |
|
||
| 渠道适配 | `FeishuIntegrationService` | 解析飞书消息、提取文本/附件、场景分流、触发回复 |
|
||
| 消息捕获 | `ProactiveSignalCaptureService` | 预清洗与噪音过滤,统一进入 AI PMO 内核 |
|
||
| 意图解析 | `IntentResolver`(内核组件) | 把文本收口为 `query/project.create/signal.create/...` |
|
||
| 组合决策 | `DecisionEngine` + `StrategicBrain` + `TacticalBrain` + `SimulationEngine` + `ExecutionPolicyBrain` | 做战略/战术/仿真/自动执行边界判定 |
|
||
| 执行落地 | `TypedExecutor` | 按 intent 进行 `RAG问答/立项/信号入库/信号源接入` |
|
||
| 结果复核 | `AIPMOReviewService` | 校验执行后状态与风险,生成 review summary |
|
||
| 回复渲染 | `ReplyRenderer` | 统一生成 `action/pending/error` 回执文本 |
|
||
| 回复幂等 | `ReplyReceipt`(账本) | 保证同消息同 phase 只发一次业务回执 |
|
||
| 消息投递 | `FeishuReplyOutbox` + dispatch worker | 发送到飞书并做失败重试/补偿 |
|
||
| 知识沉淀 | `AdaptiveRAGService.ingest_feishu_message_async` | 异步把飞书内容纳入检索知识域 |
|
||
|
||
### 8.1 具体 Agent 名称(字符串级)
|
||
|
||
下面是你要的“具体名称”。
|
||
|
||
1. 角色 Agent(`role_key`)
|
||
- `pm_dispatcher`(默认 active,角色名:产品经理(任务分派))
|
||
- `tech_architect`(角色名:技术架构师)
|
||
- `delivery_coach`(角色名:交付推进官)
|
||
|
||
2. 主链路实际会命中的 LLM Agent 名(`function_name`)
|
||
- `feishu_humanized_reply`:飞书被 @ 且需要人设化回复时使用。
|
||
- `signal_source_onboarding_plan`:识别到“新增信号源接入”时的规划器。
|
||
- `signal_source_ai_worker_execution`:信号源接入子 worker 执行器。
|
||
- `openclaw_command_dispatch`:OpenClaw 指挥层把自然语言转操作计划。
|
||
- `rag_intent_classification`:RAG 问答意图分类(query/mixed/statement)。
|
||
- `rag_db_project_semantic_retrieval`:RAG 的项目语义检索快路由。
|
||
|
||
3. 历史链路 Agent 名(`FeishuSignalPipelineService`,非当前主入口)
|
||
- `feishu_level_classification`
|
||
- `feishu_signal_extraction`
|
||
- `feishu_project_prefill`
|
||
- `feishu_task_orchestration`
|
||
- `feishu_project_signal_classification`
|
||
- `feishu_new_project_brief`
|
||
|
||
说明:上面第 3 组名称仍在评测/历史链路中使用,但实时主入口不直接走这条链路。
|
||
|
||
### 8.2 `glm` / `minimax` 在哪一步、做什么
|
||
|
||
> 依据:`backend/.openclaw/pmflow-routing-rules.json`(当前默认 `OPENCLAW_ROUTING_ENABLED=true`,`LLM_MIXED_ROUTING_ENABLED=false`)。
|
||
|
||
#### A. 当前飞书主链路(实时)
|
||
|
||
| 步骤 | function_name | 默认命中模型 | 具体作用 |
|
||
| --- | --- | --- | --- |
|
||
| 飞书 @ 人设回复 | `feishu_humanized_reply` | `zai/glm-4-flash` | 把执行结果转成短中文回复,控制语气与可执行建议 |
|
||
| RAG 意图判定 | `rag_intent_classification` | `zai/glm-4-flash` | 把用户输入判定为 question / mixed / statement |
|
||
| RAG 项目语义检索 | `rag_db_project_semantic_retrieval` | `openai-compatible/GLM-5` | 从项目索引中做语义命中与回答草案 |
|
||
| RAG 最终答案生成(normal/deep) | `adaptive_rag_answer_normal` / `adaptive_rag_answer_deep` | `openai-compatible/GLM-5` | 生成最终回答(结论+证据+不确定项) |
|
||
|
||
#### B. 主链路中的“信号源接入子流程”(命中时)
|
||
|
||
| 步骤 | function_name | 默认命中模型 | 具体作用 |
|
||
| --- | --- | --- | --- |
|
||
| 接入规划器 | `signal_source_onboarding_plan` | **active 引擎**(未在规则中显式绑定) | 判断是否应接入、产出 source 元数据与 worker 角色 |
|
||
| OpenClaw 指挥计划 | `openclaw_command_dispatch` | **active 引擎**(未在规则中显式绑定) | 把自然语言转 typed operations |
|
||
| 子 worker 执行 | `signal_source_ai_worker_execution` | **active 引擎**(未在规则中显式绑定) | 各角色生成 deliverables/risks/next_actions |
|
||
|
||
说明:这 3 个函数名不在当前 OpenClaw 规则文件中,因此在默认配置下走 active 引擎;若 active 仍是默认 OpenClaw low 模型,则通常表现为 `glm`。
|
||
|
||
#### C. 历史/评测链路(`FeishuSignalPipelineService`)
|
||
|
||
| 步骤 | function_name | 默认命中模型 | 具体作用 |
|
||
| --- | --- | --- | --- |
|
||
| 层级判断 | `feishu_level_classification` | `zai/glm-4-flash` | 判定 project-level 还是 signal-level |
|
||
| 信号抽取 | `feishu_signal_extraction` | `zai/glm-4-flash` | 抽取标题、类型、优先级、置信度 |
|
||
| 项目预填充 | `feishu_project_prefill` | `openai-compatible/GLM-5` | 生成建议项目名/描述/owner/timeline |
|
||
| 任务编排 | `feishu_task_orchestration` | `openai-compatible/GLM-5` | 生成任务拆解与分配建议 |
|
||
| 项目信号分类 | `feishu_project_signal_classification` | `openai-compatible/GLM-5` | 对新项目/已有项目/非需求做高层分类 |
|
||
| 新项目摘要 | `feishu_new_project_brief` | `openai-compatible/GLM-5` | 生成项目简报(brief) |
|