借鉴论文 3 的事前信心引导:每个 Agent 决策节点加 confidence 评分(0-1),低信心时输出"我不知道"并触发 Frank 拍板。配套 LangGraph interrupt 机制,让 Agent 在关键决策点暂停等人。
Agent 信心不足时,强行输出一个看起来合理但错误的决策。例如:
"为账号 X 推荐剧 Y"(实际 X 的粉丝画像不支持 Y 的题材)
后果:发出去的视频 0 播放,浪费素材 + 账号权重
Agent 信心不足时,报错"无法决策"然后停机。例如:
"对不起,我没有足够信息选剧,请提供更多上下文..."
后果:Loop 卡死,Frank 不知道发生了什么
v3 解决思路:引入第三种状态——"我不知道 + 具体原因"。Agent 诚实输出信心不足的事实和原因,触发 Frank 拍板,而不是硬编或放弃。论文 3 验证:这种方法比硬编/放弃都更靠谱。
Agent 信心 ≥ 80%,按决策结果自动执行。不发飞书告警。
Agent 信心 60-80%,按决策结果执行,但同步飞书告警,让 Frank 看到但不需要立即拍板。
Agent 信心 < 60%,不输出决策结果,而是返回 {status: "uncertain", reason: "..."},触发 LangGraph interrupt,Frank 在飞书卡片拍板后继续。
在 LangGraph 状态里增加 confidence + uncertain_reason + human_decision 三个字段。
from typing import TypedDict, Literal, Optional from langgraph.graph import StateGraph, END # ===== v3 Loop 状态:加 3 个新字段 ===== class LoopState(TypedDict): # ===== v1-v2 原有字段 ===== run_id: str feedback: dict candidates: list[dict] selected: list[dict] owned_tasks: list[dict] cut_outputs: list[dict] publish_results: list[dict] errors: list[dict] # ===== v3 新增:决策信心相关 ===== last_decision: Optional[dict] # 最近一次决策结果 confidence: float # 0-1,决策信心 uncertain_reason: Optional[str] "我不知道"的原因 decision_history: list[dict] # 所有决策历史(含信心) human_decision: Optional[dict] # Frank 拍板结果 human_decision_required: bool # 是否需要 Frank 拍板 daily_interrupt_count: int # 当日已触发拍板次数(上限 10)
关键设计:
• confidence < 0.6 → human_decision_required = True → 触发 interrupt
• human_decision 记录 Frank 拍板内容("选 A" / "选 B" / "跳过" / "重新选"),供后续 run 借鉴
• daily_interrupt_count 防止 Frank 拍板疲劳(D2 决策点:日上限 10 次)
from langgraph.graph import StateGraph, END from langgraph.checkpoint.postgres import PostgresSaver from langgraph.prebuilt import ToolNode import random # ===== 决策节点:每次决策都带 confidence ===== async def decision_node(state: LoopState) -> dict: """ 调用 Qwen-Max 做选剧/剪辑/发布决策。 返回结果必须包含 confidence 字段。 """ user_input = state.get("last_user_input", "") feedback = state."feedback" # Qwen-Max 返回 JSON:{action, params, confidence, reason} response = await qwen_max.decide( prompt=build_decision_prompt(user_input, feedback), tools=state."available_tools", # 来自 M1 工具箱 schema={ "action": "string", "params": "object", "confidence": "number", # 0-1 "reason": "string", } ) confidence = response["confidence"] daily_count = state.get("daily_interrupt_count", 0) # ===== 论文 3 核心:信心分层处理 ===== if confidence >= 0.8: # 高信心:直接执行 return { "last_decision": response, "confidence": confidence, "human_decision_required": False, "decision_history": state.get("decision_history", []) + [{ "decision": response, "layer": "auto_high", "ts": now() }], } elif confidence >= 0.6: # 中信心:执行 + 飞书告警 await feishu.send_alert( title="⚠️ AI Loop 中信心决策", body=f"决策: {response['action']} 信心: {confidence} 原因: {response['reason']}", level="warn", ) return { "last_decision": response, "confidence": confidence, "human_decision_required": False, "decision_history": state.get("decision_history", []) + [{ "decision": response, "layer": "auto_mid_alert", "ts": now() }], } # 低信心:检查日拍板上限 if daily_count >= 10: # 超过上限:降级到中信心执行 await feishu.send_alert( title="🚨 AI Loop 拍板超限,降级自动执行", body=f"日拍板已 {daily_count} 次,降级自动。决策: {response['action']}", level="critical", ) return { "last_decision": response, "confidence": confidence, "human_decision_required": False, "decision_history": state.get("decision_history", []) + [{ "decision": response, "layer": "auto_degraded", "ts": now() }], } # 正常低信心:触发拍板 await feishu.send_decision_card( title="🤔 AI Loop 需要你拍板", decision=response, run_id=state["run_id"], ) return { "last_decision": response, "confidence": confidence, "uncertain_reason": response["reason"], "human_decision_required": True, "daily_interrupt_count": daily_count + 1, } # ===== 路由:检查是否需要等 Frank 拍板 ===== def route_after_decision(state: LoopState) -> Literal["human_review", "execute"]: if state.get("human_decision_required", False): return "human_review" return "execute" # ===== Human Review 节点:等 Frank 拍板 ===== def human_review_node(state: LoopState) -> dict: """ LangGraph interrupt 模式:暂停,等 Frank 在飞书卡片上点按钮。 """ # interrupt() 会暂停整个 graph,等外部输入 human_input = interrupt({ "question": state["uncertain_reason"], "ai_suggestion": state["last_decision"], "options": ["采用 AI 建议", "选 A 方案", "选 B 方案", "跳过", "重新选"], }) # Frank 拍板后继续 return { "human_decision": human_input, "human_decision_required": False, "decision_history": state.get("decision_history", []) + [{ "decision": human_input, "layer": "human_review", "ts": now() }], }
Frank 在飞书群里直接看到卡片,点按钮拍板,Agent 自动继续。
🤔 需要你拍板 · run_20260606_001
0.42,信心 0.45。
AI 建议:改选"婚姻家庭"类短剧
Top 3 备选:
① 《豪门婆婆的逆袭》— 婚姻家庭 / 完播率 78%
② 《全职妈妈重返职场》— 婚姻家庭 / 完播率 72%
③ 《50 岁离婚记》— 婚姻家庭 / 完播率 68%
点击"采用 AI 建议"或选 ①/②/③ 触发 LangGraph interrupt 恢复; 点击"跳过"则该 run 放弃,记录到 history。
M1 工具调用历史 → M4 沉淀期更新工具库 → 提升 M3 决策信心
良性循环:M1 工具箱规模越大 → LLM 决策时"可参考的案例"越多 → 信心自动提升 → 触发 Frank 拍板的频率自动降低。D1 可能 30% 触发拍板,D30 降到 10%,D60 降到 5%。
confidence / uncertain_reason / human_decision 加进 LangGraph Statedecision_history 表(包含 ts / layer / decision 字段)route_after_decision 函数(高/中/低三路)daily_interrupt_count 上限检查(10 次/天)需要 Frank 联系飞书 admin:① 申请 AI Loop 机器人"interactive card"权限 ② 消息推到"AI Loop 拍板群"(新群?现有 AI Loop 群加 Frank/玉 即可)③ 测试 Frank 点按钮能否触发 callback URL
截止:D2 18:00 · 负责人:Frank · 协调对象:飞书 admin / 玉
文档默认 10 次/天。Frank 需要根据 D3-D6 实际体验决定:① 上限是 10 还是 20?② 是否分"选剧/剪辑/发布"独立计数?③ 周末是否提高上限(Frank 不在时)?
截止:D6 12:00 · 负责人:Frank
§5 给出的卡片是 MVP,Frank 看完可能想改:① 按钮文案("采用 AI 建议" 还是"执行")② 是否加"我不确定"二次确认按钮 ③ 卡片在群里怎么 @ 谁(@Frank 全部 vs @specific)
截止:D3 14:00 · 负责人:Frank
M3 依赖 checkpointer 持久化状态(LangGraph interrupt 必需)。需要 Frank 协调:① 复用现有 Postgres 实例?② 单独建一个新库?③ iCenter 后端运维负责人配合
截止:D1 22:00 · 负责人:Frank · 协调对象:iCenter 后端运维
文档默认 0.8 / 0.6。Frank 需根据 4 个组业务复杂度决定:① 选剧阈值 ② 剪辑阈值 ③ 发布阈值(可不一样)。阈值越低 → 越少拍板 → 越多自动执行
截止:D4 18:00 · 负责人:Frank · 与 4 个组讨论
Frank 偶尔点"跳过"(不想处理),需要兜底:① 跳过 → 用 AI 建议自动执行 ② 跳过 → 推回人工池 ③ 跳过 → 等明天?建议 Frank 在 D5 测试后给结论
截止:D5 · 负责人:Frank
Frank 的拍板记录是否要给 4 个组看到?CEO 是否要看到?建议 ① 4 个组可见自己拍的板 ② Frank 全部可见 ③ CEO 可见汇总(不含具体理由)。Frank 拍板
截止:D5 · 负责人:Frank