1.概述
在智能体逐渐成为人工智能应用核心的今天,如何让它“聪明”且“高效”是开发者最关心的问题。本文将带你从设计思路、核心能力到工程实践,全面解析高效智能体的构建方法。无论是任务分解、知识获取,还是与外部工具的协同,都会结合实际案例,帮助你理解如何打造一个真正能落地、能进化的智能体。
2.内容
2.1 什么是智能体
智能体(Agent)是人工智能领域中的核心概念,可以理解为一种具备 感知、决策和执行能力的自主系统。它能够从环境中获取信息,结合自身的知识或模型进行推理和判断,并通过调用工具或执行操作来完成任务。与传统程序不同,智能体不仅仅是被动执行预设指令,而是具备一定程度的自主性和适应性,能够在复杂、多变的环境中不断优化行为。
在实际应用中,智能体的使用场景非常广泛:
- 对话交互:例如智能客服或AI助手,能够理解用户需求并给出合适的回应;
- 任务自动化:如自动化办公、数据分析、代码生成,帮助人类提高效率;
- 智能决策:在金融风控、供应链优化、推荐系统中,智能体可以快速处理复杂数据并做出判断;
- 虚拟与现实结合:从游戏NPC到智能机器人,智能体能够与真实世界或虚拟环境交互,带来更智能的体验。
简而言之,智能体的核心价值在于 替人类完成复杂任务、提升效率和创造力,它正逐渐成为AI应用的关键载体。
2.2 何时使用智能体以及智能体框架
并不是所有问题都需要引入智能体,有些场景用普通脚本或固定规则就能解决。但当任务具备 复杂性、动态性和不确定性 时,智能体和智能体框架就展现出独特优势。
适合使用智能体的典型场景:
1. 任务复杂、需要自主规划
例如在 数据分析 中,不仅要获取数据,还要清洗、建模、可视化。传统脚本需要逐步编写流程,而智能体可以根据目标自动分解任务,并灵活调用工具完成每个环节。
2. 环境动态、信息来源多样
在 金融风控 中,数据源包含市场行情、新闻资讯、历史交易记录,信息随时变化。智能体能持续监控并动态调整策略。
3. 需要多轮交互与记忆
在 智能客服 或 教育辅导 场景中,用户问题往往连续且上下文相关,智能体通过框架中的“记忆机制”保持连贯性,而不是每次都从零开始。
4. 需要调用多种外部工具或API
比如在 软件研发 中,智能体能先检索文档,再调用代码生成工具,最后利用测试框架验证结果,形成一个完整闭环。
智能体框架的价值 在于降低开发门槛。它提供了任务调度、插件管理、上下文记忆等通用能力,让开发者可以专注于业务逻辑。例如:
- LangChain 适合构建多步推理与工具调用场景;
- AutoGen 擅长多智能体协作;
- LlamaIndex 在知识库问答中表现突出。
当你的问题是 一次性、结构化、固定逻辑 → 用传统脚本即可;
当你的问题是 多步骤、不确定性强、需要灵活应对 → 就是使用智能体和框架的好时机。
3.智能体模式
3.1 链式工作流智能体
Prompt Chaining 工作流模式 是在大型语言模型(LLM)应用开发中常见且高效的一种设计思路。其核心理念是:将复杂的任务 分解为一系列有机衔接的步骤,每个步骤由一次 LLM 调用完成,并且后续步骤会基于前一步的输出继续处理。
提示链(Prompt Chaining)模式 在以下几类场景中尤为适用:
- 任务复杂度高:当问题难以一次性解决时,可以将其拆解为一系列更简单、可控的步骤;
- 需要逐步验证:每个中间输出都可能需要检查、修正或转换,确保最终结果的准确性;
- 保持清晰链路:通过分步骤衔接,能够清楚追踪数据或逻辑的流转过程,避免“黑箱式”结果。
例如,下述案例展示了一个针对 文本中数值数据处理 的四步工作流:
- 提取数值和指标 —— 从原始文本中识别出数字及其对应的含义;
- 标准化格式 —— 将不同表示方式统一为百分比格式,确保结果一致;
- 排序处理 —— 按照数值大小进行降序排序,便于后续分析;
- 结果输出 —— 将整理好的数据转换为 Markdown 表格,便于展示与阅读。
通过这种链式调用方式,复杂的数据处理过程被拆分为结构清晰、可追踪的步骤,既提升了 准确性和可维护性,又让开发者能够灵活地对每一环节进行优化和扩展。
具体实现代码如下所示:- import org.springframework.ai.chat.client.ChatClient;
- public class ChainWorkflow {
- /**
- * Array of system prompts that define the transformation steps in the chain.
- * Each prompt acts as a gate that validates and transforms the output before
- * proceeding to the next step.
- */
- private static final String[] DEFAULT_SYSTEM_PROMPTS = {
- // Step 1
- """
- Extract only the numerical values and their associated metrics from the text.
- Format each as'value: metric' on a new line.
- Example format:
- 92: customer satisfaction
- 45%: revenue growth""",
- // Step 2
- """
- Convert all numerical values to percentages where possible.
- If not a percentage or points, convert to decimal (e.g., 92 points -> 92%).
- Keep one number per line.
- Example format:
- 92%: customer satisfaction
- 45%: revenue growth""",
- // Step 3
- """
- Sort all lines in descending order by numerical value.
- Keep the format 'value: metric' on each line.
- Example:
- 92%: customer satisfaction
- 87%: employee satisfaction""",
- // Step 4
- """
- Format the sorted data as a markdown table with columns:
- | Metric | Value |
- |:--|--:|
- | Customer Satisfaction | 92% | """
- };
- private final ChatClient chatClient;
- private final String[] systemPrompts;
- public ChainWorkflow(ChatClient chatClient) {
- this(chatClient, DEFAULT_SYSTEM_PROMPTS);
- }
- public ChainWorkflow(ChatClient chatClient, String[] systemPrompts) {
- this.chatClient = chatClient;
- this.systemPrompts = systemPrompts;
- }
- public String chain(String userInput) {
- int step = 0;
- String response = userInput;
- System.out.println(String.format("\nSTEP %s:\n %s", step++, response));
- for (String prompt : systemPrompts) {
- // 1. Compose the input using the response from the previous step.
- String input = String.format("{%s}\n {%s}", prompt, response);
- // 2. Call the chat client with the new input and get the new response.
- response = chatClient.prompt(input).call().content();
- System.out.println(String.format("\nSTEP %s:\n %s", step++, response));
- }
- return response;
- }
- }
复制代码 主服务入口代码实现:- import org.springframework.ai.chat.client.ChatClient;
- import org.springframework.boot.CommandLineRunner;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.context.annotation.Bean;
- // ------------------------------------------------------------
- // PROPMT CHAINING WORKFLOW
- // ------------------------------------------------------------
- @SpringBootApplication
- public class Application {
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- String report = """
- Q3 Performance Summary:
- Our customer satisfaction score rose to 92 points this quarter.
- Revenue grew by 45% compared to last year.
- Market share is now at 23% in our primary market.
- Customer churn decreased to 5% from 8%.
- New user acquisition cost is $43 per user.
- Product adoption rate increased to 78%.
- Employee satisfaction is at 87 points.
- Operating margin improved to 34%.
- """;
- @Bean
- public CommandLineRunner commandLineRunner(ChatClient.Builder chatClientBuilder) {
- return args -> {
- new ChainWorkflow(chatClientBuilder.build()).chain(report);
- };
- }
- }
复制代码 该示例通过一系列提示来处理第三季度的绩效报告。以下是示例输入:- Q3 Performance Summary:
- Our customer satisfaction score rose to 92 points this quarter.
- Revenue grew by 45% compared to last year.
- Market share is now at 23% in our primary market.
- Customer churn decreased to 5% from 8%.
- New user acquisition cost is $43 per user.
- Product adoption rate increased to 78%.
- Employee satisfaction is at 87 points.
- Operating margin improved to 34%.
复制代码 工作流程通过四个步骤来处理此问题:
1.提取值:提取数值及其指标- 92: customer satisfaction
- 45%: revenue growth
- 23%: market share
- 5%: customer churn
- 43: user acquisition cost
- 78%: product adoption
- 87: employee satisfaction
- 34%: operating margin
复制代码 2.标准化格式:将适用的值转换为百分比- 92%: customer satisfaction
- 45%: revenue growth
- 23%: market share
- 5%: customer churn
- 78%: product adoption
- 87%: employee satisfaction
- 34%: operating margin
复制代码 3.排序:按降序排列值- 92%: customer satisfaction
- 87%: employee satisfaction
- 78%: product adoption
- 45%: revenue growth
- 34%: operating margin
- 23%: market share
- 5%: customer churn
复制代码 4.格式:创建 markdown 表- | Metric | Value |
- |:--|--:|
- | Customer Satisfaction | 92% |
- | Employee Satisfaction | 87% |
- | Product Adoption | 78% |
- | Revenue Growth | 45% |
- | Operating Margin | 34% |
- | Market Share | 23% |
- | Customer Churn | 5% |
复制代码 3.2 评估器-优化器智能体
评估器–优化器模式(Evaluator–Optimizer Pattern) 是一种典型的 双 LLM 协作工作流。它模拟了人类作者“写—审—改”的迭代过程:一个模型负责生成候选答案,另一个模型则充当评估员,给出改进建议,二者循环迭代,直到得到令人满意的结果。
该模式包含两个核心组件:
- 生成器 LLM(Optimizer/Generator):负责为任务生成初始响应,并在收到反馈后进行改进;
- 评估员 LLM(Evaluator):根据预设的质量标准(如准确性、逻辑性、风格或完整性)对响应进行分析,并输出具体的改进意见。
工作机制如下:
- 初始生成 —— 生成器 LLM 根据任务需求给出初稿;
- 质量评估 —— 评估员 LLM 审查初稿,基于评估标准给出反馈;
- 改进迭代 —— 如果结果不符合要求,生成器根据反馈重新生成内容;
- 收敛输出 —— 当评估员确认结果达到满意水平时,最终答案被采纳。
这种模式的优势在于:
- 提升结果质量:避免“一次性生成”的粗糙输出,通过多轮改进获得更佳结果;
- 增强鲁棒性:减少模型幻觉或逻辑错误;
- 灵活性高:评估标准可以根据不同任务(如代码正确性、文本风格、数据完整性)进行定制。
应用场景示例:
- 内容创作:生成文章后由评估员检查逻辑流畅性和语言风格,再反复打磨;
- 代码生成:评估员负责检测语法错误和单元测试结果,生成器根据反馈修复代码;
- 问答系统:确保答案不仅正确,还要清晰、全面。
简而言之,评估器–优化器模式就像“作者与编辑”的协作,前者负责创作,后者负责把关,两者交替工作,最终产出高质量成果。
评估器–优化器模式 在以下场景中特别适用:
- 有明确的质量标准:当任务结果能够通过清晰的指标(如正确性、逻辑性、风格或一致性)进行评估时;
- 迭代能带来显著改进:输出质量在多轮反馈中能逐步优化,而不是“一次生成定型”;
- 任务需要深度审查:复杂问题往往需要多轮批评与修正,才能得到高质量的结果。
示例应用
- 文学翻译:在直译之外捕捉语境和风格的细微差别,通过多轮优化更贴近原文意境;
- 复杂搜索与分析:如学术研究或市场调研,需要多次筛选、比对和总结;
- 代码生成与调试:初始生成后经过系统性审查,逐步修复语法错误、逻辑漏洞或性能问题;
- 内容创作:写作往往需要多次草稿与润色,模型在迭代过程中可不断提升逻辑连贯性和表达质量。
简而言之,当任务 可以被客观评估 且 质量提升依赖迭代打磨 时,这种模式能显著提高最终成果的可靠性与可用性。
具体实现代码如下:- import java.util.ArrayList;
- import java.util.List;
- import java.util.StringJoiner;
- import org.springframework.ai.chat.client.ChatClient;
- import org.springframework.util.Assert;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- public class EvaluatorOptimizer {
- private static final Logger logger = LoggerFactory.getLogger(EvaluatorOptimizer.class);
-
- public static final String DEFAULT_GENERATOR_PROMPT = """
- Your goal is to complete the task based on the input. If there are feedback
- from your previous generations, you should reflect on them to improve your solution.
- CRITICAL: Your response must be a SINGLE LINE of valid JSON with NO LINE BREAKS except those explicitly escaped with \\n.
- Here is the exact format to follow, including all quotes and braces:
- {"thoughts":"Brief description here","response":"public class Example {\\n // Code here\\n}"}
- Rules for the response field:
- 1. ALL line breaks must use \\n
- 2. ALL quotes must use \"
- 3. ALL backslashes must be doubled: \\
- 4. NO actual line breaks or formatting - everything on one line
- 5. NO tabs or special characters
- 6. Java code must be complete and properly escaped
- Example of properly formatted response:
- {"thoughts":"Implementing counter","response":"public class Counter {\\n private int count;\\n public Counter() {\\n count = 0;\\n }\\n public void increment() {\\n count++;\\n }\\n}"}
- Follow this format EXACTLY - your response must be valid JSON on a single line.
- """;
- public static final String DEFAULT_EVALUATOR_PROMPT = """
- Evaluate this code implementation for correctness, time complexity, and best practices.
- Ensure the code have proper javadoc documentation.
- Respond with EXACTLY this JSON format on a single line:
- {"evaluation":"PASS, NEEDS_IMPROVEMENT, or FAIL", "feedback":"Your feedback here"}
- The evaluation field must be one of: "PASS", "NEEDS_IMPROVEMENT", "FAIL"
- Use "PASS" only if all criteria are met with no improvements needed.
- """;
- public static final int MAX_ITERATIONS = 10;
- public enum Evaluation {
- PASS, NEEDS_IMPROVEMENT, FAIL
- }
- public record EvaluationResponse(Evaluation evaluation, String feedback) {}
- public record RefinedResponse(String solution, List<Generation> chainOfThought) {}
- public record Generation(String thoughts, String response) {}
- private final ChatClient chatClient;
- private final String generatorPrompt;
- private final String evaluatorPrompt;
- private final int maxIterations;
- public EvaluatorOptimizer(ChatClient chatClient) {
- this(chatClient, DEFAULT_GENERATOR_PROMPT, DEFAULT_EVALUATOR_PROMPT, MAX_ITERATIONS);
- }
- public EvaluatorOptimizer(ChatClient chatClient, String generatorPrompt, String evaluatorPrompt) {
- this(chatClient, generatorPrompt, evaluatorPrompt, MAX_ITERATIONS);
- }
- public EvaluatorOptimizer(ChatClient chatClient, String generatorPrompt,
- String evaluatorPrompt, int maxIterations) {
- Assert.notNull(chatClient, "ChatClient must not be null");
- Assert.hasText(generatorPrompt, "Generator prompt must not be empty");
- Assert.hasText(evaluatorPrompt, "Evaluator prompt must not be empty");
- Assert.isTrue(maxIterations > 0, "Max iterations must be positive");
- this.chatClient = chatClient;
- this.generatorPrompt = generatorPrompt;
- this.evaluatorPrompt = evaluatorPrompt;
- this.maxIterations = maxIterations;
- }
- public RefinedResponse loop(String task) {
- return loop(task, new ArrayList<>(), new ArrayList<>(), 0);
- }
- private RefinedResponse loop(String task, List<String> memory,
- List<Generation> chainOfThought, int iteration) {
-
- if (iteration >= maxIterations) {
- logger.warn("Max iterations ({}) reached without finding a PASS solution", maxIterations);
- return new RefinedResponse(getBestSolution(memory), chainOfThought);
- }
- String context = buildContext(memory, chainOfThought);
- Generation generation = generate(task, context);
-
- memory.add(generation.response());
- chainOfThought.add(generation);
- EvaluationResponse evaluation = evaluate(generation.response(), task);
- if (evaluation.evaluation() == Evaluation.PASS) {
- logger.info("Solution accepted after {} iterations", iteration + 1);
- return new RefinedResponse(generation.response(), chainOfThought);
- }
- logger.debug("Iteration {}: Evaluation {}", iteration + 1, evaluation.evaluation());
- return loop(task, memory, chainOfThought, iteration + 1);
- }
- private String buildContext(List<String> memory, List<Generation> chainOfThought) {
- if (memory.isEmpty()) {
- return "";
- }
- StringJoiner context = new StringJoiner("\n");
- context.add("Previous attempts and feedback:");
-
- for (int i = 0; i < memory.size(); i++) {
- context.add(String.format("Attempt %d:", i + 1));
- context.add("Code: " + memory.get(i));
- if (i < chainOfThought.size()) {
- context.add("Thoughts: " + chainOfThought.get(i).thoughts());
- }
- }
- return context.toString();
- }
- private Generation generate(String task, String context) {
- try {
- Generation generation = chatClient.prompt()
- .user(u -> u.text("{prompt}\n{context}\nTask: {task}")
- .param("prompt", generatorPrompt)
- .param("context", context)
- .param("task", task))
- .call()
- .entity(Generation.class);
- logGeneration(generation);
- return generation;
- } catch (Exception e) {
- logger.error("Generation failed for task: {}", task, e);
- throw new RuntimeException("Failed to generate solution", e);
- }
- }
- private EvaluationResponse evaluate(String content, String task) {
- try {
- EvaluationResponse evaluation = chatClient.prompt()
- .user(u -> u.text("{prompt}\nOriginal task: {task}\nContent to evaluate: {content}")
- .param("prompt", evaluatorPrompt)
- .param("task", task)
- .param("content", content))
- .call()
- .entity(EvaluationResponse.class);
- logEvaluation(evaluation);
- return evaluation;
- } catch (Exception e) {
- logger.error("Evaluation failed for content: {}", content, e);
- return new EvaluationResponse(Evaluation.NEEDS_IMPROVEMENT,
- "Evaluation service unavailable. Please review the code manually.");
- }
- }
- private void logGeneration(Generation generation) {
- if (logger.isDebugEnabled()) {
- logger.debug("\n=== GENERATOR OUTPUT ===\nTHOUGHTS: {}\n\nRESPONSE:\n{}\n",
- generation.thoughts(), generation.response());
- }
- }
- private void logEvaluation(EvaluationResponse evaluation) {
- if (logger.isDebugEnabled()) {
- logger.debug("\n=== EVALUATOR OUTPUT ===\nEVALUATION: {}\n\nFEEDBACK: {}\n",
- evaluation.evaluation(), evaluation.feedback());
- }
- }
- private String getBestSolution(List<String> solutions) {
- return solutions.isEmpty() ? "" : solutions.get(solutions.size() - 1);
- }
- }
复制代码 主服务入口代码实现:- import com.example.agentic.EvaluatorOptimizer.RefinedResponse;
- import org.springframework.ai.chat.client.ChatClient;
- import org.springframework.boot.CommandLineRunner;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.context.annotation.Bean;
- // ------------------------------------------------------------
- // EVALUATOR-OPTIMIZER
- // ------------------------------------------------------------
- @SpringBootApplication
- public class Application {
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- @Bean
- public CommandLineRunner commandLineRunner(ChatClient.Builder chatClientBuilder) {
- var chatClient = chatClientBuilder.build();
- return args -> {
- RefinedResponse refinedResponse = new EvaluatorOptimizer(chatClient).loop("""
- <user input>
- Implement a Stack in Java with:
- 1. push(x)
- 2. pop()
- 3. getMin()
- All operations should be O(1).
- All inner fields should be private and when used should be prefixed with 'this.'.
- </user input>
- """);
- System.out.println("FINAL OUTPUT:\n : " + refinedResponse);
- };
- }
- }
复制代码 3.3 协调器-工作者智能体
Orchestrator–Workers 模式 是一种灵活且强大的工作流结构,专为 需要动态任务分解和专门处理的复杂任务 而设计。它借鉴了现实世界中的“项目经理 + 专业团队”协作模式,将任务拆解、分配和合并,最终形成高质量的解决方案。
该模式通常包含三个核心组件:
- 协调器(Orchestrator):作为中央 LLM,负责理解整体任务,识别所需的子任务,并将它们分配给合适的 Worker;
- 工作者(Workers):一组专门化的 LLM,每个 Worker 负责解决特定子任务(如数据分析、写作、代码生成等);
- 合成器(Synthesizer):整合所有 Worker 的输出,对结果进行统一、归纳和优化,形成最终答案。
该模式在以下场景中尤其有效:
- 任务难以预先规划:当子任务结构不确定、需要运行中动态拆解时;
- 需要多种方法或视角:例如既要逻辑推理,又要创造性写作;
- 强调适应性的问题:面对信息不完整或需求变化的任务,能够灵活调整策略;
- 专业化处理能提升结果质量:如不同 Worker 分别处理数据检索、知识推理和结果润色。
应用示例
- 多学科研究:协调器将问题拆解为文献检索、数据分析和总结,交由不同 Worker 执行;
- 内容生成:如撰写长文,协调器负责分解大纲,Worker 生成各章节,合成器最终汇总润色;
- 软件开发:协调器拆分需求,Worker 负责代码编写、单元测试与文档撰写,合成器整合成完整项目。
简而言之,Orchestrator–Workers 模式就像一个“AI 项目团队”:协调器是项目经理,Workers 是领域专家,合成器则是总编辑,三者协作确保任务既能 分工明确 又能 产出高效。
具体实现代码如下:- import java.util.List;
- import org.springframework.ai.chat.client.ChatClient;
- import org.springframework.util.Assert;
- public class OrchestratorWorkers {
- private final ChatClient chatClient;
- private final String orchestratorPrompt;
- private final String workerPrompt;
- public static final String DEFAULT_ORCHESTRATOR_PROMPT = """
- Analyze this task and break it down into 2-3 distinct approaches:
- Task: {task}
- Return your response in this JSON format:
- \\{
- "analysis": "Explain your understanding of the task and which variations would be valuable.
- Focus on how each approach serves different aspects of the task.",
- "tasks": [
- \\{
- "type": "formal",
- "description": "Write a precise, technical version that emphasizes specifications"
- \\},
- \\{
- "type": "conversational",
- "description": "Write an engaging, friendly version that connects with readers"
- \\}
- ]
- \\}
- """;
- public static final String DEFAULT_WORKER_PROMPT = """
- Generate content based on:
- Task: {original_task}
- Style: {task_type}
- Guidelines: {task_description}
- """;
- /**
- * Represents a subtask identified by the orchestrator that needs to be executed
- * by a worker.
- *
- * @param type The type or category of the task (e.g., "formal",
- * "conversational")
- * @param description Detailed description of what the worker should accomplish
- */
- public static record Task(String type, String description) {
- }
- /**
- * Response from the orchestrator containing task analysis and breakdown into
- * subtasks.
- *
- * @param analysis Detailed explanation of the task and how different approaches
- * serve its aspects
- * @param tasks List of subtasks identified by the orchestrator to be
- * executed by workers
- */
- public static record OrchestratorResponse(String analysis, List<Task> tasks) {
- }
- public static record FinalResponse(String analysis, List<String> workerResponses) {
- }
- public OrchestratorWorkers(ChatClient chatClient) {
- this(chatClient, DEFAULT_ORCHESTRATOR_PROMPT, DEFAULT_WORKER_PROMPT);
- }
- public OrchestratorWorkers(ChatClient chatClient, String orchestratorPrompt, String workerPrompt) {
- Assert.notNull(chatClient, "ChatClient must not be null");
- Assert.hasText(orchestratorPrompt, "Orchestrator prompt must not be empty");
- Assert.hasText(workerPrompt, "Worker prompt must not be empty");
- this.chatClient = chatClient;
- this.orchestratorPrompt = orchestratorPrompt;
- this.workerPrompt = workerPrompt;
- }
- @SuppressWarnings("null")
- public FinalResponse process(String taskDescription) {
- Assert.hasText(taskDescription, "Task description must not be empty");
- // Step 1: Get orchestrator response
- OrchestratorResponse orchestratorResponse = this.chatClient.prompt()
- .user(u -> u.text(this.orchestratorPrompt)
- .param("task", taskDescription))
- .call()
- .entity(OrchestratorResponse.class);
- System.out.println(String.format("\n=== ORCHESTRATOR OUTPUT ===\nANALYSIS: %s\n\nTASKS: %s\n",
- orchestratorResponse.analysis(), orchestratorResponse.tasks()));
- // Step 2: Process each task
- List<String> workerResponses = orchestratorResponse.tasks().stream().map(task -> this.chatClient.prompt()
- .user(u -> u.text(this.workerPrompt)
- .param("original_task", taskDescription)
- .param("task_type", task.type())
- .param("task_description", task.description()))
- .call()
- .content()).toList();
- System.out.println("\n=== WORKER OUTPUT ===\n" + workerResponses);
- return new FinalResponse(orchestratorResponse.analysis(), workerResponses);
- }
- }
复制代码 主服务入口代码:- import org.springframework.ai.chat.client.ChatClient;
- import org.springframework.boot.CommandLineRunner;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.context.annotation.Bean;
- // ------------------------------------------------------------
- // ORCHESTRATOR WORKERS
- // ------------------------------------------------------------
- @SpringBootApplication
- public class Application {
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- @Bean
- public CommandLineRunner commandLineRunner(ChatClient.Builder chatClientBuilder) {
- var chatClient = chatClientBuilder.build();
- return args -> {
- new OrchestratorWorkers(chatClient)
- .process("Write a product description for a new eco-friendly water bottle");
- };
- }
- }
复制代码 3.4 并行化智能体
并行化工作流模式是一种提高大型语言模型(LLM)处理效率与结果质量的策略,其核心思想是 同时执行多个任务或多次调用,以加快处理速度并获取更多视角。该模式主要体现在两个方面:
- 分段(Segmentation)
- 将复杂任务拆分为相互独立的子任务,使其能够并行处理,减少单个任务的执行瓶颈。
- 投票(Voting / Ensemble)
- 对同一任务进行多次并行调用,以生成不同版本的响应,然后通过多数决、加权或其他策略选出最优结果,从而获得更可靠和多样化的答案。
主要优点
- 提升吞吐量:并行处理多个子任务或调用,提高整体任务处理速度;
- 优化资源利用:充分利用 LLM API 或计算资源,避免单线程浪费;
- 缩短批量任务时间:相比串行处理,大幅降低整体执行时长;
- 提高结果质量:通过多视角、多样化输出,结合投票机制,可显著改善准确性和稳健性。
应用示例
- 文本分析:将长文拆分为段落并行分析,最后汇总结果;
- 内容生成:对同一写作任务多次生成不同版本,通过投票选择最优稿件;
- 问答系统:对复杂问题进行多次推理,整合答案以减少偏差;
- 数据标注:多个模型或提示并行执行标注任务,再通过多数投票提高标注一致性。
并行化模式就像团队协作中的分工+讨论机制:既能让每个成员(LLM调用)专注完成独立任务,又能通过多方意见汇总,获得更全面、更可靠的最终成果。
具体实现代码如下:- import java.util.List;
- import java.util.concurrent.CompletableFuture;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.stream.Collectors;
- import org.springframework.ai.chat.client.ChatClient;
- import org.springframework.util.Assert;
- public class ParallelizationlWorkflow {
- private final ChatClient chatClient;
- public ParallelizationlWorkflow(ChatClient chatClient) {
- this.chatClient = chatClient;
- }
- public List<String> parallel(String prompt, List<String> inputs, int nWorkers) {
- Assert.notNull(prompt, "Prompt cannot be null");
- Assert.notEmpty(inputs, "Inputs list cannot be empty");
- Assert.isTrue(nWorkers > 0, "Number of workers must be greater than 0");
- ExecutorService executor = Executors.newFixedThreadPool(nWorkers);
- try {
- List<CompletableFuture<String>> futures = inputs.stream()
- .map(input -> CompletableFuture.supplyAsync(() -> {
- try {
- return chatClient.prompt(prompt + "\nInput: " + input).call().content();
- } catch (Exception e) {
- throw new RuntimeException("Failed to process input: " + input, e);
- }
- }, executor))
- .collect(Collectors.toList());
- // Wait for all tasks to complete
- CompletableFuture<Void> allFutures = CompletableFuture.allOf(
- futures.toArray(CompletableFuture[]::new));
- allFutures.join();
- return futures.stream()
- .map(CompletableFuture::join)
- .collect(Collectors.toList());
- } finally {
- executor.shutdown();
- }
- }
- }
复制代码 主服务入口代码:- import java.util.List;
- import org.springframework.ai.chat.client.ChatClient;
- import org.springframework.boot.CommandLineRunner;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.context.annotation.Bean;
- @SpringBootApplication
- public class Application {
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- @Bean
- public CommandLineRunner commandLineRunner(ChatClient.Builder chatClientBuilder) {
- return args -> {
- // ------------------------------------------------------------
- // PARALLEL WORKFLOW
- // ------------------------------------------------------------
- List<String> parallelResponse = new ParallelizationlWorkflow(chatClientBuilder.build())
- .parallel("""
- Analyze how market changes will impact this stakeholder group.
- Provide specific impacts and recommended actions.
- Format with clear sections and priorities.
- """,
- List.of(
- """
- Customers:
- - Price sensitive
- - Want better tech
- - Environmental concerns
- """,
- """
- Employees:
- - Job security worries
- - Need new skills
- - Want clear direction
- """,
- """
- Investors:
- - Expect growth
- - Want cost control
- - Risk concerns
- """,
- """
- Suppliers:
- - Capacity constraints
- - Price pressures
- - Tech transitions
- """),
- 4);
- System.out.println(parallelResponse);
- };
- }
- }
复制代码 3.5 路由智能体
路由工作流模式(Routing Workflow Pattern) 专为处理复杂任务而设计,尤其适用于 输入类型多样且需要不同处理策略的场景。其核心理念是:利用 LLM 对输入进行分析和分类,然后将其分发到最合适的专用提示符或处理程序,以获得更高效和准确的结果。
主要优点
- 关注点分离:每条路线可以针对特定类型的输入进行优化,避免单一流程处理所有任务导致效率低下;
- 提高准确性:专门的提示或处理程序能够更好地发挥其优势,提升结果质量;
- 可扩展架构:轻松新增路线和专门处理模块,系统能够随需求变化灵活扩展;
- 资源优化:更简单的任务可分配给轻量模型,复杂任务由高性能模型处理,实现计算资源的合理利用。
该模式在以下场景尤其有效:
- 输入类型多样:任务涉及不同格式、主题或结构的数据,需要采用不同处理策略;
- 可分类任务:LLM 能够准确识别输入类型,从而决定路由路径;
- 专业化需求:不同类型的输入需要不同领域的知识或处理方法,例如技术文档 vs. 创意写作、财务数据 vs. 市场分析。
应用示例
- 客户服务:根据问题类型(退货、账单、技术支持)路由到不同的自动回复或处理模块;
- 内容生成:针对不同主题或风格,路由到特定提示符生成高质量文本;
- 数据处理:将结构化数据、非结构化文本或图像输入路由到不同的分析模型;
- 多模态应用:结合文本、音频或图像输入,分别调用最适合的模型进行处理。
路由工作流模式就像 智能分拣系统:先判断“物品类型”,再送到最适合的处理通道,从而提高效率、保证质量,并且易于扩展。
具体实现代码如下:- public record RoutingResponse(
- /**
- * The reasoning behind the route selection, explaining why this particular
- * route was chosen based on the input analysis.
- */
- String reasoning,
- /**
- * The selected route name that will handle the input based on the
- * classification analysis.
- */
- String selection) {
- }
复制代码- import java.util.Map;
- import org.springframework.ai.chat.client.ChatClient;
- import org.springframework.util.Assert;
- public class RoutingWorkflow {
- private final ChatClient chatClient;
- public RoutingWorkflow(ChatClient chatClient) {
- this.chatClient = chatClient;
- }
- public String route(String input, Map<String, String> routes) {
- Assert.notNull(input, "Input text cannot be null");
- Assert.notEmpty(routes, "Routes map cannot be null or empty");
- // Determine the appropriate route for the input
- String routeKey = determineRoute(input, routes.keySet());
- // Get the selected prompt from the routes map
- String selectedPrompt = routes.get(routeKey);
- if (selectedPrompt == null) {
- throw new IllegalArgumentException("Selected route '" + routeKey + "' not found in routes map");
- }
- // Process the input with the selected prompt
- return chatClient.prompt(selectedPrompt + "\nInput: " + input).call().content();
- }
- private String determineRoute(String input, Iterable<String> availableRoutes) {
- System.out.println("\nAvailable routes: " + availableRoutes);
- String selectorPrompt = String.format("""
- Analyze the input and select the most appropriate support team from these options: %s
- First explain your reasoning, then provide your selection in this JSON format:
- \\{
- "reasoning": "Brief explanation of why this ticket should be routed to a specific team.
- Consider key terms, user intent, and urgency level.",
- "selection": "The chosen team name"
- \\}
- Input: %s""", availableRoutes, input);
- RoutingResponse routingResponse = chatClient.prompt(selectorPrompt).call().entity(RoutingResponse.class);
- System.out.println(String.format("Routing Analysis:%s\nSelected route: %s",
- routingResponse.reasoning(), routingResponse.selection()));
- return routingResponse.selection();
- }
- }
复制代码 主服务入口代码:- import java.util.List;
- import java.util.Map;
- import org.springframework.ai.chat.client.ChatClient;
- import org.springframework.boot.CommandLineRunner;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.context.annotation.Bean;
- // ------------------------------------------------------------
- // ROUTER WORKFLOW
- // ------------------------------------------------------------
- @SpringBootApplication
- public class Application {
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- @Bean
- public CommandLineRunner commandLineRunner(ChatClient.Builder chatClientBuilder) {
-
- return args -> {
- Map<String, String> supportRoutes = Map.of("billing",
- """
- You are a billing support specialist. Follow these guidelines:
- 1. Always start with "Billing Support Response:"
- 2. First acknowledge the specific billing issue
- 3. Explain any charges or discrepancies clearly
- 4. List concrete next steps with timeline
- 5. End with payment options if relevant
- Keep responses professional but friendly.
- Input: """,
- "technical",
- """
- You are a technical support engineer. Follow these guidelines:
- 1. Always start with "Technical Support Response:"
- 2. List exact steps to resolve the issue
- 3. Include system requirements if relevant
- 4. Provide workarounds for common problems
- 5. End with escalation path if needed
- Use clear, numbered steps and technical details.
- Input: """,
- "account",
- """
- You are an account security specialist. Follow these guidelines:
- 1. Always start with "Account Support Response:"
- 2. Prioritize account security and verification
- 3. Provide clear steps for account recovery/changes
- 4. Include security tips and warnings
- 5. Set clear expectations for resolution time
- Maintain a serious, security-focused tone.
- Input: """,
- "product",
- """
- You are a product specialist. Follow these guidelines:
- 1. Always start with "Product Support Response:"
- 2. Focus on feature education and best practices
- 3. Include specific examples of usage
- 4. Link to relevant documentation sections
- 5. Suggest related features that might help
- Be educational and encouraging in tone.
- Input: """);
- List<String> tickets = List.of(
- """
- Subject: Can't access my account
- Message: Hi, I've been trying to log in for the past hour but keep getting an 'invalid password' error.
- I'm sure I'm using the right password. Can you help me regain access? This is urgent as I need to
- submit a report by end of day.
- - John""",
- """
- Subject: Unexpected charge on my card
- Message: Hello, I just noticed a charge of .99 on my credit card from your company, but I thought
- I was on the .99 plan. Can you explain this charge and adjust it if it's a mistake?
- Thanks,
- Sarah""",
- """
- Subject: How to export data?
- Message: I need to export all my project data to Excel. I've looked through the docs but can't
- figure out how to do a bulk export. Is this possible? If so, could you walk me through the steps?
- Best regards,
- Mike""");
- var routerWorkflow = new RoutingWorkflow(chatClientBuilder.build());
- int i = 1;
- for (String ticket : tickets) {
- System.out.println("\nTicket " + i++);
- System.out.println("------------------------------------------------------------");
- System.out.println(ticket);
- System.out.println("------------------------------------------------------------");
- System.out.println(routerWorkflow.route(ticket, supportRoutes));
- }
- };
- }
- }
复制代码 4.总结
开发一个高效的智能体,不仅仅是调用大型语言模型,更在于 合理设计工作流、优化任务处理和迭代改进。本文介绍了多种关键模式——从 提示链(Prompt Chaining)、评估器–优化器(Evaluator–Optimizer)、Orchestrator–Workers、并行化 到 路由工作流——每一种方法都有其独特价值,针对不同任务场景提供最佳实践。
通过这些模式的灵活组合,智能体能够实现 复杂任务分解、专业化处理、多轮改进和高效输出,同时提升准确性、可扩展性和资源利用效率。最终,高效智能体的目标是让模型不仅能“完成任务”,还能 以可控、可靠且高质量的方式应对多样化问题。
5.结束语
这篇博客就和大家分享到这里,如果大家在研究学习的过程当中有什么问题,可以加群进行讨论或发送邮件给我,我会尽我所能为您解答,与君共勉!
另外,博主出新书了《Hadoop与Spark大数据全景解析》、同时已出版的《深入理解Hive》、《Kafka并不难学》和《Hadoop大数据挖掘从入门到进阶实战》也可以和新书配套使用,喜欢的朋友或同学, 可以在公告栏那里点击购买链接购买博主的书进行学习,在此感谢大家的支持。关注下面公众号,根据提示,可免费获取书籍的教学视频。
公众号:
作者:哥不是小萝莉 [关于我][犒赏]
出处:http://www.cnblogs.com/smartloli/
转载请注明出处,谢谢合作!
来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除 |