在当今的大模型(LLM)应用开发中,我们正在从单纯的 "Chat"(对话)模式向 "Agent"(智能体)模式演进。
什么是 Agent?简单来说,Agent = LLM + Planning(规划) + Memory(记忆) + Tools(工具)。
今天,我将基于 Spring AI,分享如何构建一个特定领域的 Agent——题目生成 Agent。它不仅能出题,还能自己“批改”题目,如果发现题目质量不高,它会自动进行修改,直到满意为止。
这正是 Agent 范式中经典的 Reflection(反思) 与 ReAct****(推理与行动) 思想的体现。
-
业务场景与需求分析
在教育科技领域,自动化出题是一个高频场景。直接让 GPT 生成题目往往存在以下痛点:
-
幻觉问题:生成的知识点可能不准确。
-
格式错误:JSON格式不合法,导致程序无法解析。
-
难度失控:要求的“中等难度”可能生成了“简单”题目。
为了解决这些问题,我们需要设计一个工作流(Workflow****),而不是一个简单的 API 调用。我们的目标是构建一个具备以下能力的 Agent:
-
理解需求:根据知识点、难度、题型生成题目。
-
自我验证:有一个“审核员”角色对题目进行打分。
-
自我修正:如果审核不通过,根据反馈意见重新优化题目。
-
Agent范式选型:ReAct
分析题目生成的特点
-
需要外部知识:需要搜索专业领域的知识,知识库分析,生成具有定制作用的。
-
需要精确计算:如计算题目,数学问题 可交给计算器工具,避免LLM的计算错误。
-
需要与API交互:如操作数据库、调用某个服务的API来完成特定功能。
针对该特点 非常适合思考-行动-观察 的React范式:
ReAct是一种Agent设计范式。它认识到思考与行动是相辅相成的。通过思考指导行动,而行动的结果又反过来修正思考。为此,ReAct范式通过一种特殊的提示工程来引导模型,使其每一步的输出都遵循一个固定的轨迹:
-
Thought (思考): 智能体分析当前情况、分解任务、制定计划,或者反思上一步的结果。
-
Action (行动): 智能体结合思考结果,决定采取实际的具体动作,通常是调用一个外部工具,例如调用工具,MCP服务等
-
Observation (观察): 这是执行
Action后从外部工具返回的结果,例如搜索结果或者API的返回值。
智能体不断重复这个 Thought -> Action -> Observation 的循环,将新的观察结果追加到历史记录中,形成一个不断增长的上下文,直到它在Thought中认为已经找到了最终答案,然后输出结果。这个过程形成了一个强大的协同效应:推理使得行动更具目的性,而行动则为推理提供了事实依据。
-
系统架构设计
基于React 设计了如下的流程
使用责任链模式来实现这个 Agent。
核心节点如下:
-
Context (上下文):在节点间传递数据(题目、验证结果、轮次)。
-
GenerateNode:根据上下文决定是“初次生成”还是“根据反馈优化”。
-
ValidateNode:评估题目质量,决定是“通过”还是“打回重做”。
-
SummaryNode:包装最终结果。
-
核心代码实现
我们将使用 Java + Spring AI 来实现。以下是关键部分的解析。
4.1 定义上下文
QuestionGenerateContext 提供记忆,记录了当前的题目、第几轮修改、以及验证器的反馈...。
Java
@Data
@Builder
public class QuestionGenerateContext {
private String questionId;
private int currentRound; // 当前轮次
private int maxRounds = 3; // 最大容忍轮次
private JSONObject currentQuestion; // 当前生成的题目
private JSONObject validationResult; // 验证器的反馈
private boolean completed;
// ...
}
4.2 生成节点:ReAct 的落地
QuestionGenerateNode 是执行者。请注意它的 Prompt 设计,它包含了两套逻辑:初次生成和基于反馈优化。
Java
@Service
public class QuestionGenerateNode extends AbstractQuestionGenerateNode {
// 注入验证节点,形成闭环
@Resourceprivate QuestionValidateNode questionValidateNode;
@Override
public AbstractQuestionGenerateNode execute(QuestionGenerateRequestEntity request, QuestionGenerateContext context) {
context.incrementRound();
// 决策:是初次生成还是优化?if (context.getCurrentQuestion() == null) {
log.info("📝 Act: 初次生成题目");
question = generateQuestion(request, null);
} else {
log.info("🔧 Act: 根据反馈优化题目");
question = refineQuestion(request, context);
}
// 更新上下文并流转到验证节点
context.setCurrentQuestion(question);
return questionValidateNode;
}
}
Prompt 的技巧:
我们在 SYSTEM_PROMPT 中明确要求了思维链纪律:
"思维链纪律:始终以深思熟虑、逐步的方式进行内部推理... 不要在最终JSON中暴露思维链文本。"
4.3 验证节点:
QuestionValidateNode
该节点负责验证和观察 --- Observation
@Service
public class QuestionValidateNode extends AbstractQuestionGenerateNode {
@Resource@Lazy // 解决循环依赖private QuestionGenerateNode questionGenerateNode;
@Overridepublic AbstractQuestionGenerateNode execute(QuestionGenerateRequestEntity request, QuestionGenerateContext context) {
// 调用 LLM 进行评审
JSONObject validationResult = validateQuestion(context.getCurrentQuestion());
String decision = validationResult.getString("decision");
// 核心循环逻辑if ("approve".equals(decision)) {
log.info("✅ 验证通过!");
context.setCompleted(true);
return getBean("questionSummaryNode");
}
// 如果未通过且未达最大轮次,回退到生成节点if (!context.reachedMaxRounds()) {
log.info("🔄 质量不足,回退优化");
return questionGenerateNode;
}
return getBean("questionSummaryNode");
}
}
-
运行效果演示
在测试类 QuestionGeneratorServiceTest 中,我们可以看到 Agent 的思考过程。
输入请求:
JSON
{
"knowledgePoint": "数据库基础理论",
"difficulty": "medium",
"focus": "事务"
}
日志追踪:
Plaintext
=== 第 1 轮 ReAct 循环 ===
📝 Act: 生成题目
🔍 Observe: 验证题目质量
📊 验证结果: request_modification (评分: 70)
⚠️ 建议: 选项C的描述过于模糊,建议使用更专业的术语。
=== 第 2 轮 ReAct 循环 ===
🔧 Act: 优化题目 (LLM 根据"选项C模糊"的反馈进行重写)
🔍 Observe: 验证题目质量
📊 验证结果: approve (评分: 95)
✅ 验证通过!
通过日志我们可以清晰地看到,Agent 自己意识到了问题并修正了它,这就是 Agent 的魅力所在。
-
总结
通过 Spring AI 和责任链模式,我们构建了一个简单的 自我反思的题目生成和验证的 Agent。与传统的 API 调用相比,它具备了:
-
鲁棒性:通过验证机制拦截低质量输出。
-
智能性:通过上下文传递,模型能理解“哪里错了”并针对性修改。
未来优化方向:
-
RAG 增强:在
GenerateNode中引入向量数据库,MCP等Tool 让出题基于特定知识生成。 -
多 Agent 协作:引入“教学大纲专家” Agent先规划考点,再由“出题 Agent” 执行。专业人做专业事
-
细化生成和验证流程:细化生成和验证流程 提高Agent能力