在当今的大模型(LLM)应用开发中,我们正在从单纯的 "Chat"(对话)模式向 "Agent"(智能体)模式演进。

什么是 Agent?简单来说,Agent = LLM + Planning(规划) + Memory(记忆) + Tools(工具)

今天,我将基于 Spring AI,分享如何构建一个特定领域的 Agent——题目生成 Agent。它不仅能出题,还能自己“批改”题目,如果发现题目质量不高,它会自动进行修改,直到满意为止。

这正是 Agent 范式中经典的 Reflection(反思)ReAct****(推理与行动) 思想的体现。

  1. 业务场景与需求分析

在教育科技领域,自动化出题是一个高频场景。直接让 GPT 生成题目往往存在以下痛点:

  1. 幻觉问题:生成的知识点可能不准确。

  2. 格式错误:JSON格式不合法,导致程序无法解析。

  3. 难度失控:要求的“中等难度”可能生成了“简单”题目。

为了解决这些问题,我们需要设计一个工作流Workflow****),而不是一个简单的 API 调用。我们的目标是构建一个具备以下能力的 Agent:

  • 理解需求:根据知识点、难度、题型生成题目。

  • 自我验证:有一个“审核员”角色对题目进行打分。

  • 自我修正:如果审核不通过,根据反馈意见重新优化题目。

  1. Agent范式选型:ReAct

分析题目生成的特点

  • 需要外部知识:需要搜索专业领域的知识,知识库分析,生成具有定制作用的。

  • 需要精确计算:如计算题目,数学问题 可交给计算器工具,避免LLM的计算错误。

  • 需要与API交互:如操作数据库、调用某个服务的API来完成特定功能。

针对该特点 非常适合思考-行动-观察 的React范式:

ReAct是一种Agent设计范式。它认识到思考与行动是相辅相成的。通过思考指导行动,而行动的结果又反过来修正思考。为此,ReAct范式通过一种特殊的提示工程来引导模型,使其每一步的输出都遵循一个固定的轨迹:

  • Thought (思考): 智能体分析当前情况、分解任务、制定计划,或者反思上一步的结果。

  • Action (行动): 智能体结合思考结果,决定采取实际的具体动作,通常是调用一个外部工具,例如调用工具,MCP服务等

  • Observation (观察): 这是执行Action后从外部工具返回的结果,例如搜索结果或者API的返回值。

智能体不断重复这个 Thought -> Action -> Observation 的循环,将新的观察结果追加到历史记录中,形成一个不断增长的上下文,直到它在Thought中认为已经找到了最终答案,然后输出结果。这个过程形成了一个强大的协同效应:推理使得行动更具目的性,而行动则为推理提供了事实依据。

  1. 系统架构设计

基于React 设计了如下的流程

使用责任链模式来实现这个 Agent。

核心节点如下:

  1. Context (上下文):在节点间传递数据(题目、验证结果、轮次)。

  2. GenerateNode:根据上下文决定是“初次生成”还是“根据反馈优化”。

  3. ValidateNode:评估题目质量,决定是“通过”还是“打回重做”。

  4. SummaryNode:包装最终结果。

  5. 核心代码实现

我们将使用 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");
    }
}
  1. 运行效果演示

在测试类 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 的魅力所在。

  1. 总结

通过 Spring AI 和责任链模式,我们构建了一个简单的 自我反思的题目生成和验证的 Agent。与传统的 API 调用相比,它具备了:

  1. 鲁棒性:通过验证机制拦截低质量输出。

  2. 智能性:通过上下文传递,模型能理解“哪里错了”并针对性修改。

未来优化方向:

  • RAG 增强:在 GenerateNode 中引入向量数据库,MCP等Tool 让出题基于特定知识生成。

  • 多 Agent 协作:引入“教学大纲专家” Agent先规划考点,再由“出题 Agent” 执行。专业人做专业事

  • 细化生成和验证流程:细化生成和验证流程 提高Agent能力