智能体工作流实现培训问答模块方案
培训考核、知识快测、情景演练等场景,在 MVP / 演示阶段 往往不必自建后端与数据库。本文给出一套通用方案:用智能体平台的 Workflow(工作流) 承载抽题、判分、会话状态与成绩单;LLM 只负责展示与润色,不算分、不改题。适用于 Dify / Coze / FastGPT 等具备会话变量与代码节点的平台。非特定行业落地手册。
目录
一、结论与适用边界
可以。 培训问答类功能在演示与试点阶段,完全可以只靠智能体平台工作流实现,无需自建服务或业务库。
| 能力 | 纯工作流 | 说明 |
|---|
| 随机抽题 | ✅ | 题库放 JSON / 附件 / 工作流常量 |
| 即时判分 | ✅ | 代码节点或条件分支,不交给 LLM 算分 |
| 错题解析 | ✅ | 题库自带 explanation,LLM 仅润色 |
| 会话内计分与状态 | ✅ | 会话变量 / 工作流变量 |
| 情景分支对话 | ✅ | 多轮 + 条件路由 + 剧本 JSON |
| 跨用户排行榜 / 长期档案 | ⚠️ 弱 | 需平台库插件或结束时导出 |
约束前提:不依赖外部业务库、不对接企业核心系统,仅用平台内置能力。
推荐模式:用 Workflow 承载培训考核主路径,而非纯 Chat Bot 自由对话——后者易跑题、丢状态、计分不可靠。
二、总体状态机
1
2
3
4
5
6
7
8
9
10
11
| 用户进入培训
→ 初始化状态(score=0, index=0, wrong=[])
→ 从题库抽一题(排除已答 ID)
→ 展示题目 + 选项
→ 等待用户作答
→ 判题
├─ 正确 → score + 1
└─ 错误 → wrong_list 追加
→ 已答够 N 题?
├─ 否 → 继续抽题
└─ 是 → 输出成绩单(错题回顾 + 薄弱点建议)
|
核心原则:每轮用户回复后,工作流 读出状态 → 判题 → 写回状态 → 分支决定下一题或结束。不要指望 LLM 自行「记住答了几题、得几分」。
三、会话状态设计
3.1 会话内状态对象(必做)
用平台 会话变量 / 工作流变量 维护 JSON,每答一题更新并传入下一节点:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| {
"mode": "quiz",
"total_questions": 5,
"current_index": 2,
"score": 1,
"asked_ids": ["Q001", "Q003"],
"wrong_items": [
{
"id": "Q003",
"user_answer": "B",
"correct_answer": "C",
"category": "基础概念",
"explanation": "标准解析文本……"
}
],
"started_at": "2026-06-23T10:00:00"
}
|
3.2 关键变量
| 变量名 | 类型 | 用途 |
|---|
mode | string | quiz(快测)/ scenario(情景) |
total_questions | int | 本轮总题数 |
current_index | int | 已答题数 |
score | int | 当前得分 |
asked_ids | array | 已出题目 ID,防重复 |
wrong_items | array | 错题明细,供结尾解析 |
scenario_id | string | 情景剧本 ID(可选) |
scenario_step | int | 情景当前步骤 |
started_at | string | 开始时间(培训记录) |
3.3 各平台状态载体
| 平台 | 会话状态载体 | 备注 |
|---|
| Dify | Conversation Variables + 节点间变量 | 常见 Demo 首选 |
| Coze | Bot 记忆 / 工作流全局 / 用户变量 | 用户变量通常需登录 |
| FastGPT | 工作流全局变量 + 可选 HTTP 插件 | 思路与 Dify 类似 |
3.4 跨会话持久化(可选)
| 方案 | 实现 | 局限 |
|---|
| 会话内 | 结束时输出 Markdown 成绩单 | 刷新即丢失 |
| 导出 CSV | 代码节点生成文本供复制 | 需用户手动保存 |
| 平台用户变量 | 登录用户写入 user variable | 依赖登录 |
| 外部存储 | 表格/文档/平台库插件 | 超出「纯工作流」 |
演示期:会话内成绩单 + 可选 CSV 导出 通常足够。
四、题库与情景剧本
4.1 单题 JSON 结构
1
2
3
4
5
6
7
8
9
10
11
12
13
| {
"id": "Q001",
"category": "基础概念",
"type": "single",
"stem": "题干文本?",
"options": {
"A": "选项 A",
"B": "选项 B",
"C": "选项 C"
},
"correct": "B",
"explanation": "标准解析,判错后直接引用。"
}
|
| 字段 | 说明 |
|---|
id | 唯一标识,用于 asked_ids 去重 |
category | 知识点分类,供薄弱点聚合 |
type | single / multi |
stem / options | 题干与选项 |
correct | 正确答案;多选可用 "A,C" |
explanation | 标准解析 |
4.2 题库存放
| 方式 | 优点 | 缺点 |
|---|
| 代码节点内嵌 JSON | 自包含 | 改题需改工作流;适合题量较少(如三十题以内) |
| 知识库附件(JSON 文件) | 易维护 | 需代码读取,不宜纯 RAG 当题库 |
| 平台常量 / 环境变量 | 部署清晰 | 依赖平台能力 |
建议:Demo 用约 20 题 JSON 嵌入代码节点或作工作流附件;分类覆盖目标领域若干主题即可。
4.3 情景剧本(进阶)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| {
"scenario_id": "S01",
"title": "典型业务场景名称",
"steps": [
{
"step": 1,
"narrative": "情境描述……",
"question": "此时你应该?",
"options": { "A": "…", "B": "…", "C": "…" },
"correct": "B",
"feedback_wrong": "答错时的简短反馈。",
"next": 2
}
]
}
|
- 用
scenario_step 推进;答错可展示 feedback_wrong 后继续。 - 结束后汇总情景得分与关键决策回顾。
五、计分职责与代码示例
5.1 职责分工
| 环节 | 负责组件 | 原因 |
|---|
| 判对错 | 代码 / 条件分支 | 确定性,避免 LLM 算错 |
| 更新 score / wrong_items | 代码节点 | 状态一致 |
| 题目展示、解析润色 | LLM 节点 | 自然语言体验 |
| 薄弱点分析 | LLM 读 wrong_items | 按 category 聚合建议 |
| 是否继续 | 条件分支 | 状态机控制 |
5.2 判分规则
| 题型 | 规则 | 得分 |
|---|
| 单选 | 与 correct 完全一致(忽略大小写) | 对 +1,错 0 |
| 多选 | 选项集合完全一致 | 对 +1,错 0 |
| 情景 | 关键决策点答对 +1;演示版答错也可继续 | 按步计分 |
进阶可设:多选部分正确给 0.5;情景仅若干关键点计分。
5.3 代码节点示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| import random
def grade(question: dict, user_answer: str, state: dict) -> tuple:
"""判题并更新 state,返回 (state, is_correct, explanation)"""
correct = question["correct"]
qtype = question.get("type", "single")
user = user_answer.strip().upper()
if qtype == "single":
is_correct = user == correct.upper()
elif qtype == "multi":
user_set = set(u.strip() for u in user.replace(" ", "").split(",") if u)
correct_set = set(correct.upper().split(","))
is_correct = user_set == correct_set
else:
is_correct = False
state["current_index"] = state.get("current_index", 0) + 1
state.setdefault("asked_ids", []).append(question["id"])
if is_correct:
state["score"] = state.get("score", 0) + 1
else:
state.setdefault("wrong_items", []).append({
"id": question["id"],
"user_answer": user_answer,
"correct_answer": correct,
"category": question["category"],
"explanation": question["explanation"],
})
return state, is_correct, question["explanation"]
def pick_question(bank: list, asked_ids: list) -> dict:
"""从未出过的题中随机抽取"""
pool = [q for q in bank if q["id"] not in asked_ids]
if not pool:
return None
return random.choice(pool)
|
5.4 薄弱点分析 Prompt 模板
1
2
3
4
5
6
| 以下是用户错题列表(JSON):
请按 category 统计错题分布,用 3 条以内要点说明薄弱知识点,
并各给 1 条复习建议。语气专业、简洁。
不要编造题目中没有的知识点。
|
六、工作流节点设计
6.1 主流程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| [开始]
→ [意图识别 / 关键词路由]
├─ 非培训意图 → [普通 RAG 问答] → [结束]
└─ 培训意图(「开始培训」「开始测验」等)
→ [代码:初始化 state]
→ [代码:随机抽题]
→ [LLM:展示题目](固定模板,禁止改选项/答案)
→ [等待用户输入]
→ [代码:grade + 更新 state]
→ [LLM:即时反馈]
→ [条件] current_index < total_questions ?
├─ 是 → 回到抽题
└─ 否 → [LLM:成绩单 + 错题回顾 + 薄弱点]
→ [可选:导出 CSV]
→ [结束]
|
6.2 节点职责
| 节点类型 | 名称 | 输入 | 输出 |
|---|
| 代码 | 初始化 state | 用户触发 | state |
| 代码 | 随机抽题 | state, question_bank | question, state |
| LLM | 展示题目 | question | 格式化题目文本 |
| 代码 | 判题 | question, user_answer, state | state, is_correct, explanation |
| 条件 | 是否继续 | current_index | 分支 |
| LLM | 总结报告 | state | 成绩单 Markdown |
6.3 「展示题目」Prompt 要点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| 你是培训助手。请严格按以下 JSON 展示题目,不要修改题干和选项:
输出格式:
---
【第 / 题】
A. ...
B. ...
C. ...
请回复选项字母(多选用逗号分隔,如 A,C)
---
|
七、快测与情景模式对照
| 维度 | 快测模式 | 情景模式 |
|---|
| 题目来源 | 题库随机抽 | 剧本 steps 顺序推进 |
| 状态字段 | asked_ids | scenario_step |
| 答错处理 | 记 wrong,继续下一题 | 展示 feedback,仍可 next |
| 结束条件 | 答满 N 题 | 走完所有 step |
情景可再做 3~5 步「虚拟流程」剧本,便于演示录制。
与产品能力的粗映射:
| 能力项 | 工作流要点 |
|---|
| 培训问答 | 快测 + 代码判分 + 会话变量 |
| 情景模拟 | 剧本 JSON + scenario_step |
| 培训记录 | 结束节点成绩单;可选 CSV |
八、纯 Bot 与工作流对比
| 对比项 | 纯 Bot(单 Agent + Prompt) | 工作流模式 |
|---|
| 开发速度 | 快 | 稍慢 |
| 状态可靠性 | 易丢题号、重复出题、计分飘 | 可控 |
| 演示稳定性 | 一般 | 较好 |
| 主路径推荐 | 不推荐 | 推荐 |
若平台只能用 Bot:可在 System Prompt 要求每轮末尾输出隐藏 STATE JSON,下一轮解析——不稳定,仅备选。
九、MVP 落地与常见坑
9.1 一期范围(约 1~2 天可出 Demo)
- 5 题快测,覆盖若干知识点分类
- 1 个情景,约 3 步
- 计分 + 错题回顾 + 薄弱 category 提示
- 会话内 Markdown 成绩单
9.2 演示对话示意
1
2
3
4
5
6
7
8
9
| 用户:开始培训
助手:好的,本次共 5 题。第 1 题……
用户:B
助手:回答正确。……
(5 题结束后)
助手:本次得分 4/5。错题 1 道(某分类)……
薄弱点建议:……
|
9.3 常见坑
| 问题 | 对策 |
|---|
| LLM 改题或泄露答案 | 展示用模板,判题走代码 |
| 重复出题 | 维护 asked_ids |
| 用户输入「B. 选项全文」 | 代码提取首字母或正则 |
| 刷新丢状态 | 同会话完成;或提示需重新开始 |
| 情景跑题 | 每步只接受 A/B/C |
9.4 后续可扩展(本期不做)
| 能力 | 路径 |
|---|
| 题库后台 | 外部 JSON + 同步 |
| 组织级统计 | 导出 CSV 汇总 |
| 账号绑定 | 登录与人员标识关联 |
| 语音答题 | ASR 转文字后走同一判题 |
十、小结
| 要点 | 结论 |
|---|
| 能否纯工作流 | MVP / 演示阶段可以,无需自建库 |
| 主路径 | Workflow + 会话变量,而非自由对话 Bot |
| 分工 | 代码判分与状态;LLM 展示与润色 |
| 题库 | 结构化 JSON;情景用剧本 steps |
| 持久化 | 演示靠会话内成绩单;长期档案需额外能力 |