找回密码
 立即注册
首页 业界区 业界 如何开发一个高效的智能体

如何开发一个高效的智能体

仰翡邸 昨天 20:46
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 调用完成,并且后续步骤会基于前一步的输出继续处理。
1.png

提示链(Prompt Chaining)模式 在以下几类场景中尤为适用:

  • 任务复杂度高:当问题难以一次性解决时,可以将其拆解为一系列更简单、可控的步骤;
  • 需要逐步验证:每个中间输出都可能需要检查、修正或转换,确保最终结果的准确性;
  • 保持清晰链路:通过分步骤衔接,能够清楚追踪数据或逻辑的流转过程,避免“黑箱式”结果。
例如,下述案例展示了一个针对 文本中数值数据处理 的四步工作流:

  • 提取数值和指标 —— 从原始文本中识别出数字及其对应的含义;
  • 标准化格式 —— 将不同表示方式统一为百分比格式,确保结果一致;
  • 排序处理 —— 按照数值大小进行降序排序,便于后续分析;
  • 结果输出 —— 将整理好的数据转换为 Markdown 表格,便于展示与阅读。
通过这种链式调用方式,复杂的数据处理过程被拆分为结构清晰、可追踪的步骤,既提升了 准确性和可维护性,又让开发者能够灵活地对每一环节进行优化和扩展。
具体实现代码如下所示:
  1. import org.springframework.ai.chat.client.ChatClient;
  2. public class ChainWorkflow {
  3.     /**
  4.      * Array of system prompts that define the transformation steps in the chain.
  5.      * Each prompt acts as a gate that validates and transforms the output before
  6.      * proceeding to the next step.
  7.      */
  8.     private static final String[] DEFAULT_SYSTEM_PROMPTS = {
  9.             // Step 1
  10.             """
  11.                     Extract only the numerical values and their associated metrics from the text.
  12.                     Format each as'value: metric' on a new line.
  13.                     Example format:
  14.                     92: customer satisfaction
  15.                     45%: revenue growth""",
  16.             // Step 2
  17.             """
  18.                     Convert all numerical values to percentages where possible.
  19.                     If not a percentage or points, convert to decimal (e.g., 92 points -> 92%).
  20.                     Keep one number per line.
  21.                     Example format:
  22.                     92%: customer satisfaction
  23.                     45%: revenue growth""",
  24.             // Step 3
  25.             """
  26.                     Sort all lines in descending order by numerical value.
  27.                     Keep the format 'value: metric' on each line.
  28.                     Example:
  29.                     92%: customer satisfaction
  30.                     87%: employee satisfaction""",
  31.             // Step 4
  32.             """
  33.                     Format the sorted data as a markdown table with columns:
  34.                     | Metric | Value |
  35.                     |:--|--:|
  36.                     | Customer Satisfaction | 92% | """
  37.     };
  38.     private final ChatClient chatClient;
  39.     private final String[] systemPrompts;
  40.     public ChainWorkflow(ChatClient chatClient) {
  41.         this(chatClient, DEFAULT_SYSTEM_PROMPTS);
  42.     }
  43.     public ChainWorkflow(ChatClient chatClient, String[] systemPrompts) {
  44.         this.chatClient = chatClient;
  45.         this.systemPrompts = systemPrompts;
  46.     }
  47.     public String chain(String userInput) {
  48.         int step = 0;
  49.         String response = userInput;
  50.         System.out.println(String.format("\nSTEP %s:\n %s", step++, response));
  51.         for (String prompt : systemPrompts) {
  52.             // 1. Compose the input using the response from the previous step.
  53.             String input = String.format("{%s}\n {%s}", prompt, response);
  54.             // 2. Call the chat client with the new input and get the new response.
  55.             response = chatClient.prompt(input).call().content();
  56.             System.out.println(String.format("\nSTEP %s:\n %s", step++, response));
  57.         }
  58.         return response;
  59.     }
  60. }
复制代码
主服务入口代码实现:
  1. import org.springframework.ai.chat.client.ChatClient;
  2. import org.springframework.boot.CommandLineRunner;
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.context.annotation.Bean;
  6. // ------------------------------------------------------------
  7. // PROPMT CHAINING WORKFLOW
  8. // ------------------------------------------------------------
  9. @SpringBootApplication
  10. public class Application {
  11.     public static void main(String[] args) {
  12.         SpringApplication.run(Application.class, args);
  13.     }
  14.     String report = """
  15.             Q3 Performance Summary:
  16.             Our customer satisfaction score rose to 92 points this quarter.
  17.             Revenue grew by 45% compared to last year.
  18.             Market share is now at 23% in our primary market.
  19.             Customer churn decreased to 5% from 8%.
  20.             New user acquisition cost is $43 per user.
  21.             Product adoption rate increased to 78%.
  22.             Employee satisfaction is at 87 points.
  23.             Operating margin improved to 34%.
  24.             """;
  25.     @Bean
  26.     public CommandLineRunner commandLineRunner(ChatClient.Builder chatClientBuilder) {
  27.         return args -> {
  28.             new ChainWorkflow(chatClientBuilder.build()).chain(report);
  29.         };
  30.     }
  31. }
复制代码
该示例通过一系列提示来处理第三季度的绩效报告。以下是示例输入:
  1. Q3 Performance Summary:
  2. Our customer satisfaction score rose to 92 points this quarter.
  3. Revenue grew by 45% compared to last year.
  4. Market share is now at 23% in our primary market.
  5. Customer churn decreased to 5% from 8%.
  6. New user acquisition cost is $43 per user.
  7. Product adoption rate increased to 78%.
  8. Employee satisfaction is at 87 points.
  9. Operating margin improved to 34%.
复制代码
工作流程通过四个步骤来处理此问题:
1.提取值:提取数值及其指标
  1. 92: customer satisfaction
  2. 45%: revenue growth
  3. 23%: market share
  4. 5%: customer churn
  5. 43: user acquisition cost
  6. 78%: product adoption
  7. 87: employee satisfaction
  8. 34%: operating margin
复制代码
2.标准化格式:将适用的值转换为百分比
  1. 92%: customer satisfaction
  2. 45%: revenue growth
  3. 23%: market share
  4. 5%: customer churn
  5. 78%: product adoption
  6. 87%: employee satisfaction
  7. 34%: operating margin
复制代码
3.排序:按降序排列值
  1. 92%: customer satisfaction
  2. 87%: employee satisfaction
  3. 78%: product adoption
  4. 45%: revenue growth
  5. 34%: operating margin
  6. 23%: market share
  7. 5%: customer churn
复制代码
4.格式:创建 markdown 表
  1. | Metric | Value |
  2. |:--|--:|
  3. | Customer Satisfaction | 92% |
  4. | Employee Satisfaction | 87% |
  5. | Product Adoption | 78% |
  6. | Revenue Growth | 45% |
  7. | Operating Margin | 34% |
  8. | Market Share | 23% |
  9. | Customer Churn | 5% |
复制代码
3.2 评估器-优化器智能体

2.png

评估器–优化器模式(Evaluator–Optimizer Pattern) 是一种典型的 双 LLM 协作工作流。它模拟了人类作者“写—审—改”的迭代过程:一个模型负责生成候选答案,另一个模型则充当评估员,给出改进建议,二者循环迭代,直到得到令人满意的结果。
该模式包含两个核心组件:

  • 生成器 LLM(Optimizer/Generator):负责为任务生成初始响应,并在收到反馈后进行改进;
  • 评估员 LLM(Evaluator):根据预设的质量标准(如准确性、逻辑性、风格或完整性)对响应进行分析,并输出具体的改进意见。
工作机制如下:

  • 初始生成 —— 生成器 LLM 根据任务需求给出初稿;
  • 质量评估 —— 评估员 LLM 审查初稿,基于评估标准给出反馈;
  • 改进迭代 —— 如果结果不符合要求,生成器根据反馈重新生成内容;
  • 收敛输出 —— 当评估员确认结果达到满意水平时,最终答案被采纳。
这种模式的优势在于:

  • 提升结果质量:避免“一次性生成”的粗糙输出,通过多轮改进获得更佳结果;
  • 增强鲁棒性:减少模型幻觉或逻辑错误;
  • 灵活性高:评估标准可以根据不同任务(如代码正确性、文本风格、数据完整性)进行定制。
应用场景示例:

  • 内容创作:生成文章后由评估员检查逻辑流畅性和语言风格,再反复打磨;
  • 代码生成:评估员负责检测语法错误和单元测试结果,生成器根据反馈修复代码;
  • 问答系统:确保答案不仅正确,还要清晰、全面。
简而言之,评估器–优化器模式就像“作者与编辑”的协作,前者负责创作,后者负责把关,两者交替工作,最终产出高质量成果。
3.png

评估器–优化器模式 在以下场景中特别适用:

  • 有明确的质量标准:当任务结果能够通过清晰的指标(如正确性、逻辑性、风格或一致性)进行评估时;
  • 迭代能带来显著改进:输出质量在多轮反馈中能逐步优化,而不是“一次生成定型”;
  • 任务需要深度审查:复杂问题往往需要多轮批评与修正,才能得到高质量的结果。
示例应用

  • 文学翻译:在直译之外捕捉语境和风格的细微差别,通过多轮优化更贴近原文意境;
  • 复杂搜索与分析:如学术研究或市场调研,需要多次筛选、比对和总结;
  • 代码生成与调试:初始生成后经过系统性审查,逐步修复语法错误、逻辑漏洞或性能问题;
  • 内容创作:写作往往需要多次草稿与润色,模型在迭代过程中可不断提升逻辑连贯性和表达质量。
简而言之,当任务 可以被客观评估 且 质量提升依赖迭代打磨 时,这种模式能显著提高最终成果的可靠性与可用性。
具体实现代码如下:
  1. import java.util.ArrayList;
  2. import java.util.List;
  3. import java.util.StringJoiner;
  4. import org.springframework.ai.chat.client.ChatClient;
  5. import org.springframework.util.Assert;
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. public class EvaluatorOptimizer {
  9.     private static final Logger logger = LoggerFactory.getLogger(EvaluatorOptimizer.class);
  10.    
  11.     public static final String DEFAULT_GENERATOR_PROMPT = """
  12.             Your goal is to complete the task based on the input. If there are feedback
  13.             from your previous generations, you should reflect on them to improve your solution.
  14.             CRITICAL: Your response must be a SINGLE LINE of valid JSON with NO LINE BREAKS except those explicitly escaped with \\n.
  15.             Here is the exact format to follow, including all quotes and braces:
  16.             {"thoughts":"Brief description here","response":"public class Example {\\n    // Code here\\n}"}
  17.             Rules for the response field:
  18.             1. ALL line breaks must use \\n
  19.             2. ALL quotes must use \"
  20.             3. ALL backslashes must be doubled: \\
  21.             4. NO actual line breaks or formatting - everything on one line
  22.             5. NO tabs or special characters
  23.             6. Java code must be complete and properly escaped
  24.             Example of properly formatted response:
  25.             {"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}"}
  26.             Follow this format EXACTLY - your response must be valid JSON on a single line.
  27.             """;
  28.     public static final String DEFAULT_EVALUATOR_PROMPT = """
  29.             Evaluate this code implementation for correctness, time complexity, and best practices.
  30.             Ensure the code have proper javadoc documentation.
  31.             Respond with EXACTLY this JSON format on a single line:
  32.             {"evaluation":"PASS, NEEDS_IMPROVEMENT, or FAIL", "feedback":"Your feedback here"}
  33.             The evaluation field must be one of: "PASS", "NEEDS_IMPROVEMENT", "FAIL"
  34.             Use "PASS" only if all criteria are met with no improvements needed.
  35.             """;
  36.     public static final int MAX_ITERATIONS = 10;
  37.     public enum Evaluation {
  38.         PASS, NEEDS_IMPROVEMENT, FAIL
  39.     }
  40.     public record EvaluationResponse(Evaluation evaluation, String feedback) {}
  41.     public record RefinedResponse(String solution, List<Generation> chainOfThought) {}
  42.     public record Generation(String thoughts, String response) {}
  43.     private final ChatClient chatClient;
  44.     private final String generatorPrompt;
  45.     private final String evaluatorPrompt;
  46.     private final int maxIterations;
  47.     public EvaluatorOptimizer(ChatClient chatClient) {
  48.         this(chatClient, DEFAULT_GENERATOR_PROMPT, DEFAULT_EVALUATOR_PROMPT, MAX_ITERATIONS);
  49.     }
  50.     public EvaluatorOptimizer(ChatClient chatClient, String generatorPrompt, String evaluatorPrompt) {
  51.         this(chatClient, generatorPrompt, evaluatorPrompt, MAX_ITERATIONS);
  52.     }
  53.     public EvaluatorOptimizer(ChatClient chatClient, String generatorPrompt,
  54.                              String evaluatorPrompt, int maxIterations) {
  55.         Assert.notNull(chatClient, "ChatClient must not be null");
  56.         Assert.hasText(generatorPrompt, "Generator prompt must not be empty");
  57.         Assert.hasText(evaluatorPrompt, "Evaluator prompt must not be empty");
  58.         Assert.isTrue(maxIterations > 0, "Max iterations must be positive");
  59.         this.chatClient = chatClient;
  60.         this.generatorPrompt = generatorPrompt;
  61.         this.evaluatorPrompt = evaluatorPrompt;
  62.         this.maxIterations = maxIterations;
  63.     }
  64.     public RefinedResponse loop(String task) {
  65.         return loop(task, new ArrayList<>(), new ArrayList<>(), 0);
  66.     }
  67.     private RefinedResponse loop(String task, List<String> memory,
  68.                                List<Generation> chainOfThought, int iteration) {
  69.         
  70.         if (iteration >= maxIterations) {
  71.             logger.warn("Max iterations ({}) reached without finding a PASS solution", maxIterations);
  72.             return new RefinedResponse(getBestSolution(memory), chainOfThought);
  73.         }
  74.         String context = buildContext(memory, chainOfThought);
  75.         Generation generation = generate(task, context);
  76.         
  77.         memory.add(generation.response());
  78.         chainOfThought.add(generation);
  79.         EvaluationResponse evaluation = evaluate(generation.response(), task);
  80.         if (evaluation.evaluation() == Evaluation.PASS) {
  81.             logger.info("Solution accepted after {} iterations", iteration + 1);
  82.             return new RefinedResponse(generation.response(), chainOfThought);
  83.         }
  84.         logger.debug("Iteration {}: Evaluation {}", iteration + 1, evaluation.evaluation());
  85.         return loop(task, memory, chainOfThought, iteration + 1);
  86.     }
  87.     private String buildContext(List<String> memory, List<Generation> chainOfThought) {
  88.         if (memory.isEmpty()) {
  89.             return "";
  90.         }
  91.         StringJoiner context = new StringJoiner("\n");
  92.         context.add("Previous attempts and feedback:");
  93.         
  94.         for (int i = 0; i < memory.size(); i++) {
  95.             context.add(String.format("Attempt %d:", i + 1));
  96.             context.add("Code: " + memory.get(i));
  97.             if (i < chainOfThought.size()) {
  98.                 context.add("Thoughts: " + chainOfThought.get(i).thoughts());
  99.             }
  100.         }
  101.         return context.toString();
  102.     }
  103.     private Generation generate(String task, String context) {
  104.         try {
  105.             Generation generation = chatClient.prompt()
  106.                     .user(u -> u.text("{prompt}\n{context}\nTask: {task}")
  107.                             .param("prompt", generatorPrompt)
  108.                             .param("context", context)
  109.                             .param("task", task))
  110.                     .call()
  111.                     .entity(Generation.class);
  112.             logGeneration(generation);
  113.             return generation;
  114.         } catch (Exception e) {
  115.             logger.error("Generation failed for task: {}", task, e);
  116.             throw new RuntimeException("Failed to generate solution", e);
  117.         }
  118.     }
  119.     private EvaluationResponse evaluate(String content, String task) {
  120.         try {
  121.             EvaluationResponse evaluation = chatClient.prompt()
  122.                     .user(u -> u.text("{prompt}\nOriginal task: {task}\nContent to evaluate: {content}")
  123.                             .param("prompt", evaluatorPrompt)
  124.                             .param("task", task)
  125.                             .param("content", content))
  126.                     .call()
  127.                     .entity(EvaluationResponse.class);
  128.             logEvaluation(evaluation);
  129.             return evaluation;
  130.         } catch (Exception e) {
  131.             logger.error("Evaluation failed for content: {}", content, e);
  132.             return new EvaluationResponse(Evaluation.NEEDS_IMPROVEMENT,
  133.                 "Evaluation service unavailable. Please review the code manually.");
  134.         }
  135.     }
  136.     private void logGeneration(Generation generation) {
  137.         if (logger.isDebugEnabled()) {
  138.             logger.debug("\n=== GENERATOR OUTPUT ===\nTHOUGHTS: {}\n\nRESPONSE:\n{}\n",
  139.                     generation.thoughts(), generation.response());
  140.         }
  141.     }
  142.     private void logEvaluation(EvaluationResponse evaluation) {
  143.         if (logger.isDebugEnabled()) {
  144.             logger.debug("\n=== EVALUATOR OUTPUT ===\nEVALUATION: {}\n\nFEEDBACK: {}\n",
  145.                     evaluation.evaluation(), evaluation.feedback());
  146.         }
  147.     }
  148.     private String getBestSolution(List<String> solutions) {
  149.         return solutions.isEmpty() ? "" : solutions.get(solutions.size() - 1);
  150.     }
  151. }
复制代码
主服务入口代码实现:
  1. import com.example.agentic.EvaluatorOptimizer.RefinedResponse;
  2. import org.springframework.ai.chat.client.ChatClient;
  3. import org.springframework.boot.CommandLineRunner;
  4. import org.springframework.boot.SpringApplication;
  5. import org.springframework.boot.autoconfigure.SpringBootApplication;
  6. import org.springframework.context.annotation.Bean;
  7. // ------------------------------------------------------------
  8. // EVALUATOR-OPTIMIZER
  9. // ------------------------------------------------------------
  10. @SpringBootApplication
  11. public class Application {
  12.     public static void main(String[] args) {
  13.         SpringApplication.run(Application.class, args);
  14.     }
  15.     @Bean
  16.     public CommandLineRunner commandLineRunner(ChatClient.Builder chatClientBuilder) {
  17.         var chatClient = chatClientBuilder.build();
  18.         return args -> {
  19.             RefinedResponse refinedResponse = new EvaluatorOptimizer(chatClient).loop("""
  20.                     <user input>
  21.                     Implement a Stack in Java with:
  22.                     1. push(x)
  23.                     2. pop()
  24.                     3. getMin()
  25.                     All operations should be O(1).
  26.                     All inner fields should be private and when used should be prefixed with 'this.'.
  27.                     </user input>
  28.                     """);
  29.             System.out.println("FINAL OUTPUT:\n : " + refinedResponse);
  30.         };
  31.     }
  32. }
复制代码
3.3 协调器-工作者智能体

4.png

 
Orchestrator–Workers 模式 是一种灵活且强大的工作流结构,专为 需要动态任务分解和专门处理的复杂任务 而设计。它借鉴了现实世界中的“项目经理 + 专业团队”协作模式,将任务拆解、分配和合并,最终形成高质量的解决方案。
该模式通常包含三个核心组件:

  • 协调器(Orchestrator):作为中央 LLM,负责理解整体任务,识别所需的子任务,并将它们分配给合适的 Worker;
  • 工作者(Workers):一组专门化的 LLM,每个 Worker 负责解决特定子任务(如数据分析、写作、代码生成等);
  • 合成器(Synthesizer):整合所有 Worker 的输出,对结果进行统一、归纳和优化,形成最终答案。
该模式在以下场景中尤其有效:

  • 任务难以预先规划:当子任务结构不确定、需要运行中动态拆解时;
  • 需要多种方法或视角:例如既要逻辑推理,又要创造性写作;
  • 强调适应性的问题:面对信息不完整或需求变化的任务,能够灵活调整策略;
  • 专业化处理能提升结果质量:如不同 Worker 分别处理数据检索、知识推理和结果润色。
应用示例

  • 多学科研究:协调器将问题拆解为文献检索、数据分析和总结,交由不同 Worker 执行;
  • 内容生成:如撰写长文,协调器负责分解大纲,Worker 生成各章节,合成器最终汇总润色;
  • 软件开发:协调器拆分需求,Worker 负责代码编写、单元测试与文档撰写,合成器整合成完整项目。
简而言之,Orchestrator–Workers 模式就像一个“AI 项目团队”:协调器是项目经理,Workers 是领域专家,合成器则是总编辑,三者协作确保任务既能 分工明确 又能 产出高效。
具体实现代码如下:
  1. import java.util.List;
  2. import org.springframework.ai.chat.client.ChatClient;
  3. import org.springframework.util.Assert;
  4. public class OrchestratorWorkers {
  5.     private final ChatClient chatClient;
  6.     private final String orchestratorPrompt;
  7.     private final String workerPrompt;
  8.     public static final String DEFAULT_ORCHESTRATOR_PROMPT = """
  9.             Analyze this task and break it down into 2-3 distinct approaches:
  10.             Task: {task}
  11.             Return your response in this JSON format:
  12.             \\{
  13.             "analysis": "Explain your understanding of the task and which variations would be valuable.
  14.                          Focus on how each approach serves different aspects of the task.",
  15.             "tasks": [
  16.                 \\{
  17.                 "type": "formal",
  18.                 "description": "Write a precise, technical version that emphasizes specifications"
  19.                 \\},
  20.                 \\{
  21.                 "type": "conversational",
  22.                 "description": "Write an engaging, friendly version that connects with readers"
  23.                 \\}
  24.             ]
  25.             \\}
  26.             """;
  27.     public static final String DEFAULT_WORKER_PROMPT = """
  28.             Generate content based on:
  29.             Task: {original_task}
  30.             Style: {task_type}
  31.             Guidelines: {task_description}
  32.             """;
  33.     /**
  34.      * Represents a subtask identified by the orchestrator that needs to be executed
  35.      * by a worker.
  36.      *
  37.      * @param type        The type or category of the task (e.g., "formal",
  38.      *                    "conversational")
  39.      * @param description Detailed description of what the worker should accomplish
  40.      */
  41.     public static record Task(String type, String description) {
  42.     }
  43.     /**
  44.      * Response from the orchestrator containing task analysis and breakdown into
  45.      * subtasks.
  46.      *
  47.      * @param analysis Detailed explanation of the task and how different approaches
  48.      *                 serve its aspects
  49.      * @param tasks    List of subtasks identified by the orchestrator to be
  50.      *                 executed by workers
  51.      */
  52.     public static record OrchestratorResponse(String analysis, List<Task> tasks) {
  53.     }
  54.     public static record FinalResponse(String analysis, List<String> workerResponses) {
  55.     }
  56.     public OrchestratorWorkers(ChatClient chatClient) {
  57.         this(chatClient, DEFAULT_ORCHESTRATOR_PROMPT, DEFAULT_WORKER_PROMPT);
  58.     }
  59.     public OrchestratorWorkers(ChatClient chatClient, String orchestratorPrompt, String workerPrompt) {
  60.         Assert.notNull(chatClient, "ChatClient must not be null");
  61.         Assert.hasText(orchestratorPrompt, "Orchestrator prompt must not be empty");
  62.         Assert.hasText(workerPrompt, "Worker prompt must not be empty");
  63.         this.chatClient = chatClient;
  64.         this.orchestratorPrompt = orchestratorPrompt;
  65.         this.workerPrompt = workerPrompt;
  66.     }
  67.     @SuppressWarnings("null")
  68.     public FinalResponse process(String taskDescription) {
  69.         Assert.hasText(taskDescription, "Task description must not be empty");
  70.         // Step 1: Get orchestrator response
  71.         OrchestratorResponse orchestratorResponse = this.chatClient.prompt()
  72.                 .user(u -> u.text(this.orchestratorPrompt)
  73.                         .param("task", taskDescription))
  74.                 .call()
  75.                 .entity(OrchestratorResponse.class);
  76.         System.out.println(String.format("\n=== ORCHESTRATOR OUTPUT ===\nANALYSIS: %s\n\nTASKS: %s\n",
  77.                 orchestratorResponse.analysis(), orchestratorResponse.tasks()));
  78.         // Step 2: Process each task
  79.         List<String> workerResponses = orchestratorResponse.tasks().stream().map(task -> this.chatClient.prompt()
  80.                 .user(u -> u.text(this.workerPrompt)
  81.                         .param("original_task", taskDescription)
  82.                         .param("task_type", task.type())
  83.                         .param("task_description", task.description()))
  84.                 .call()
  85.                 .content()).toList();
  86.         System.out.println("\n=== WORKER OUTPUT ===\n" + workerResponses);
  87.         return new FinalResponse(orchestratorResponse.analysis(), workerResponses);
  88.     }
  89. }
复制代码
主服务入口代码:
  1. import org.springframework.ai.chat.client.ChatClient;
  2. import org.springframework.boot.CommandLineRunner;
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.context.annotation.Bean;
  6. // ------------------------------------------------------------
  7. // ORCHESTRATOR WORKERS
  8. // ------------------------------------------------------------
  9. @SpringBootApplication
  10. public class Application {
  11.     public static void main(String[] args) {
  12.         SpringApplication.run(Application.class, args);
  13.     }
  14.     @Bean
  15.     public CommandLineRunner commandLineRunner(ChatClient.Builder chatClientBuilder) {
  16.         var chatClient = chatClientBuilder.build();
  17.         return args -> {
  18.             new OrchestratorWorkers(chatClient)
  19.                     .process("Write a product description for a new eco-friendly water bottle");
  20.         };
  21.     }
  22. }
复制代码
3.4 并行化智能体

5.png

并行化工作流模式是一种提高大型语言模型(LLM)处理效率与结果质量的策略,其核心思想是 同时执行多个任务或多次调用,以加快处理速度并获取更多视角。该模式主要体现在两个方面:

  • 分段(Segmentation)

    • 将复杂任务拆分为相互独立的子任务,使其能够并行处理,减少单个任务的执行瓶颈。

  • 投票(Voting / Ensemble)

    • 对同一任务进行多次并行调用,以生成不同版本的响应,然后通过多数决、加权或其他策略选出最优结果,从而获得更可靠和多样化的答案。

主要优点

  • 提升吞吐量:并行处理多个子任务或调用,提高整体任务处理速度;
  • 优化资源利用:充分利用 LLM API 或计算资源,避免单线程浪费;
  • 缩短批量任务时间:相比串行处理,大幅降低整体执行时长;
  • 提高结果质量:通过多视角、多样化输出,结合投票机制,可显著改善准确性和稳健性。
应用示例

  • 文本分析:将长文拆分为段落并行分析,最后汇总结果;
  • 内容生成:对同一写作任务多次生成不同版本,通过投票选择最优稿件;
  • 问答系统:对复杂问题进行多次推理,整合答案以减少偏差;
  • 数据标注:多个模型或提示并行执行标注任务,再通过多数投票提高标注一致性。
并行化模式就像团队协作中的分工+讨论机制:既能让每个成员(LLM调用)专注完成独立任务,又能通过多方意见汇总,获得更全面、更可靠的最终成果。
具体实现代码如下:
  1. import java.util.List;
  2. import java.util.concurrent.CompletableFuture;
  3. import java.util.concurrent.ExecutorService;
  4. import java.util.concurrent.Executors;
  5. import java.util.stream.Collectors;
  6. import org.springframework.ai.chat.client.ChatClient;
  7. import org.springframework.util.Assert;
  8. public class ParallelizationlWorkflow {
  9.     private final ChatClient chatClient;
  10.     public ParallelizationlWorkflow(ChatClient chatClient) {
  11.         this.chatClient = chatClient;
  12.     }
  13.     public List<String> parallel(String prompt, List<String> inputs, int nWorkers) {
  14.         Assert.notNull(prompt, "Prompt cannot be null");
  15.         Assert.notEmpty(inputs, "Inputs list cannot be empty");
  16.         Assert.isTrue(nWorkers > 0, "Number of workers must be greater than 0");
  17.         ExecutorService executor = Executors.newFixedThreadPool(nWorkers);
  18.         try {
  19.             List<CompletableFuture<String>> futures = inputs.stream()
  20.                     .map(input -> CompletableFuture.supplyAsync(() -> {
  21.                         try {
  22.                             return chatClient.prompt(prompt + "\nInput: " + input).call().content();
  23.                         } catch (Exception e) {
  24.                             throw new RuntimeException("Failed to process input: " + input, e);
  25.                         }
  26.                     }, executor))
  27.                     .collect(Collectors.toList());
  28.             // Wait for all tasks to complete
  29.             CompletableFuture<Void> allFutures = CompletableFuture.allOf(
  30.                     futures.toArray(CompletableFuture[]::new));
  31.             allFutures.join();
  32.             return futures.stream()
  33.                     .map(CompletableFuture::join)
  34.                     .collect(Collectors.toList());
  35.         } finally {
  36.             executor.shutdown();
  37.         }
  38.     }
  39. }
复制代码
主服务入口代码:
  1. import java.util.List;
  2. import org.springframework.ai.chat.client.ChatClient;
  3. import org.springframework.boot.CommandLineRunner;
  4. import org.springframework.boot.SpringApplication;
  5. import org.springframework.boot.autoconfigure.SpringBootApplication;
  6. import org.springframework.context.annotation.Bean;
  7. @SpringBootApplication
  8. public class Application {
  9.     public static void main(String[] args) {
  10.         SpringApplication.run(Application.class, args);
  11.     }
  12.     @Bean
  13.     public CommandLineRunner commandLineRunner(ChatClient.Builder chatClientBuilder) {
  14.         return args -> {
  15.             // ------------------------------------------------------------
  16.             // PARALLEL WORKFLOW
  17.             // ------------------------------------------------------------
  18.             List<String> parallelResponse = new ParallelizationlWorkflow(chatClientBuilder.build())
  19.                     .parallel("""
  20.                             Analyze how market changes will impact this stakeholder group.
  21.                             Provide specific impacts and recommended actions.
  22.                             Format with clear sections and priorities.
  23.                             """,
  24.                             List.of(
  25.                                     """
  26.                                             Customers:
  27.                                             - Price sensitive
  28.                                             - Want better tech
  29.                                             - Environmental concerns
  30.                                             """,
  31.                                     """
  32.                                             Employees:
  33.                                             - Job security worries
  34.                                             - Need new skills
  35.                                             - Want clear direction
  36.                                             """,
  37.                                     """
  38.                                             Investors:
  39.                                             - Expect growth
  40.                                             - Want cost control
  41.                                             - Risk concerns
  42.                                             """,
  43.                                     """
  44.                                             Suppliers:
  45.                                             - Capacity constraints
  46.                                             - Price pressures
  47.                                             - Tech transitions
  48.                                             """),
  49.                             4);
  50.             System.out.println(parallelResponse);
  51.         };
  52.     }
  53. }
复制代码
3.5 路由智能体

6.png

 
路由工作流模式(Routing Workflow Pattern) 专为处理复杂任务而设计,尤其适用于 输入类型多样且需要不同处理策略的场景。其核心理念是:利用 LLM 对输入进行分析和分类,然后将其分发到最合适的专用提示符或处理程序,以获得更高效和准确的结果。
主要优点

  • 关注点分离:每条路线可以针对特定类型的输入进行优化,避免单一流程处理所有任务导致效率低下;
  • 提高准确性:专门的提示或处理程序能够更好地发挥其优势,提升结果质量;
  • 可扩展架构:轻松新增路线和专门处理模块,系统能够随需求变化灵活扩展;
  • 资源优化:更简单的任务可分配给轻量模型,复杂任务由高性能模型处理,实现计算资源的合理利用。
该模式在以下场景尤其有效:

  • 输入类型多样:任务涉及不同格式、主题或结构的数据,需要采用不同处理策略;
  • 可分类任务:LLM 能够准确识别输入类型,从而决定路由路径;
  • 专业化需求:不同类型的输入需要不同领域的知识或处理方法,例如技术文档 vs. 创意写作、财务数据 vs. 市场分析。
应用示例

  • 客户服务:根据问题类型(退货、账单、技术支持)路由到不同的自动回复或处理模块;
  • 内容生成:针对不同主题或风格,路由到特定提示符生成高质量文本;
  • 数据处理:将结构化数据、非结构化文本或图像输入路由到不同的分析模型;
  • 多模态应用:结合文本、音频或图像输入,分别调用最适合的模型进行处理。
路由工作流模式就像 智能分拣系统:先判断“物品类型”,再送到最适合的处理通道,从而提高效率、保证质量,并且易于扩展。
具体实现代码如下:
  1. public record RoutingResponse(
  2.         /**
  3.          * The reasoning behind the route selection, explaining why this particular
  4.          * route was chosen based on the input analysis.
  5.          */
  6.         String reasoning,
  7.         /**
  8.          * The selected route name that will handle the input based on the
  9.          * classification analysis.
  10.          */
  11.         String selection) {
  12. }
复制代码
  1. import java.util.Map;
  2. import org.springframework.ai.chat.client.ChatClient;
  3. import org.springframework.util.Assert;
  4. public class RoutingWorkflow {
  5.     private final ChatClient chatClient;
  6.     public RoutingWorkflow(ChatClient chatClient) {
  7.         this.chatClient = chatClient;
  8.     }
  9.     public String route(String input, Map<String, String> routes) {
  10.         Assert.notNull(input, "Input text cannot be null");
  11.         Assert.notEmpty(routes, "Routes map cannot be null or empty");
  12.         // Determine the appropriate route for the input
  13.         String routeKey = determineRoute(input, routes.keySet());
  14.         // Get the selected prompt from the routes map
  15.         String selectedPrompt = routes.get(routeKey);
  16.         if (selectedPrompt == null) {
  17.             throw new IllegalArgumentException("Selected route '" + routeKey + "' not found in routes map");
  18.         }
  19.         // Process the input with the selected prompt
  20.         return chatClient.prompt(selectedPrompt + "\nInput: " + input).call().content();
  21.     }
  22.     private String determineRoute(String input, Iterable<String> availableRoutes) {
  23.         System.out.println("\nAvailable routes: " + availableRoutes);
  24.         String selectorPrompt = String.format("""
  25.                 Analyze the input and select the most appropriate support team from these options: %s
  26.                 First explain your reasoning, then provide your selection in this JSON format:
  27.                 \\{
  28.                     "reasoning": "Brief explanation of why this ticket should be routed to a specific team.
  29.                                 Consider key terms, user intent, and urgency level.",
  30.                     "selection": "The chosen team name"
  31.                 \\}
  32.                 Input: %s""", availableRoutes, input);
  33.         RoutingResponse routingResponse = chatClient.prompt(selectorPrompt).call().entity(RoutingResponse.class);
  34.         System.out.println(String.format("Routing Analysis:%s\nSelected route: %s",
  35.                 routingResponse.reasoning(), routingResponse.selection()));
  36.         return routingResponse.selection();
  37.     }
  38. }
复制代码
主服务入口代码:
  1. import java.util.List;
  2. import java.util.Map;
  3. import org.springframework.ai.chat.client.ChatClient;
  4. import org.springframework.boot.CommandLineRunner;
  5. import org.springframework.boot.SpringApplication;
  6. import org.springframework.boot.autoconfigure.SpringBootApplication;
  7. import org.springframework.context.annotation.Bean;
  8. // ------------------------------------------------------------
  9. // ROUTER WORKFLOW
  10. // ------------------------------------------------------------
  11. @SpringBootApplication
  12. public class Application {
  13.     public static void main(String[] args) {
  14.         SpringApplication.run(Application.class, args);
  15.     }
  16.     @Bean
  17.     public CommandLineRunner commandLineRunner(ChatClient.Builder chatClientBuilder) {
  18.         
  19.         return args -> {
  20.             Map<String, String> supportRoutes = Map.of("billing",
  21.                     """
  22.                             You are a billing support specialist. Follow these guidelines:
  23.                             1. Always start with "Billing Support Response:"
  24.                             2. First acknowledge the specific billing issue
  25.                             3. Explain any charges or discrepancies clearly
  26.                             4. List concrete next steps with timeline
  27.                             5. End with payment options if relevant
  28.                             Keep responses professional but friendly.
  29.                             Input: """,
  30.                     "technical",
  31.                     """
  32.                             You are a technical support engineer. Follow these guidelines:
  33.                             1. Always start with "Technical Support Response:"
  34.                             2. List exact steps to resolve the issue
  35.                             3. Include system requirements if relevant
  36.                             4. Provide workarounds for common problems
  37.                             5. End with escalation path if needed
  38.                             Use clear, numbered steps and technical details.
  39.                             Input: """,
  40.                     "account",
  41.                     """
  42.                             You are an account security specialist. Follow these guidelines:
  43.                             1. Always start with "Account Support Response:"
  44.                             2. Prioritize account security and verification
  45.                             3. Provide clear steps for account recovery/changes
  46.                             4. Include security tips and warnings
  47.                             5. Set clear expectations for resolution time
  48.                             Maintain a serious, security-focused tone.
  49.                             Input: """,
  50.                     "product",
  51.                     """
  52.                             You are a product specialist. Follow these guidelines:
  53.                             1. Always start with "Product Support Response:"
  54.                             2. Focus on feature education and best practices
  55.                             3. Include specific examples of usage
  56.                             4. Link to relevant documentation sections
  57.                             5. Suggest related features that might help
  58.                             Be educational and encouraging in tone.
  59.                             Input: """);
  60.             List<String> tickets = List.of(
  61.                     """
  62.                             Subject: Can't access my account
  63.                             Message: Hi, I've been trying to log in for the past hour but keep getting an 'invalid password' error.
  64.                             I'm sure I'm using the right password. Can you help me regain access? This is urgent as I need to
  65.                             submit a report by end of day.
  66.                             - John""",
  67.                     """
  68.                             Subject: Unexpected charge on my card
  69.                             Message: Hello, I just noticed a charge of .99 on my credit card from your company, but I thought
  70.                             I was on the .99 plan. Can you explain this charge and adjust it if it's a mistake?
  71.                             Thanks,
  72.                             Sarah""",
  73.                     """
  74.                             Subject: How to export data?
  75.                             Message: I need to export all my project data to Excel. I've looked through the docs but can't
  76.                             figure out how to do a bulk export. Is this possible? If so, could you walk me through the steps?
  77.                             Best regards,
  78.                             Mike""");
  79.             var routerWorkflow = new RoutingWorkflow(chatClientBuilder.build());
  80.             int i = 1;
  81.             for (String ticket : tickets) {
  82.                 System.out.println("\nTicket " + i++);
  83.                 System.out.println("------------------------------------------------------------");
  84.                 System.out.println(ticket);
  85.                 System.out.println("------------------------------------------------------------");
  86.                 System.out.println(routerWorkflow.route(ticket, supportRoutes));
  87.             }
  88.         };
  89.     }
  90. }
复制代码
4.总结

开发一个高效的智能体,不仅仅是调用大型语言模型,更在于 合理设计工作流、优化任务处理和迭代改进。本文介绍了多种关键模式——从 提示链(Prompt Chaining)、评估器–优化器(Evaluator–Optimizer)、Orchestrator–Workers、并行化 到 路由工作流——每一种方法都有其独特价值,针对不同任务场景提供最佳实践。
通过这些模式的灵活组合,智能体能够实现 复杂任务分解、专业化处理、多轮改进和高效输出,同时提升准确性、可扩展性和资源利用效率。最终,高效智能体的目标是让模型不仅能“完成任务”,还能 以可控、可靠且高质量的方式应对多样化问题。
5.结束语

这篇博客就和大家分享到这里,如果大家在研究学习的过程当中有什么问题,可以加群进行讨论或发送邮件给我,我会尽我所能为您解答,与君共勉!
另外,博主出新书了《Hadoop与Spark大数据全景解析》、同时已出版的《深入理解Hive》、《Kafka并不难学》和《Hadoop大数据挖掘从入门到进阶实战》也可以和新书配套使用,喜欢的朋友或同学, 可以在公告栏那里点击购买链接购买博主的书进行学习,在此感谢大家的支持。关注下面公众号,根据提示,可免费获取书籍的教学视频。

公众号:

7.png



作者:哥不是小萝莉 [关于我][犒赏]

出处:http://www.cnblogs.com/smartloli/

转载请注明出处,谢谢合作!


来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除

相关推荐

您需要登录后才可以回帖 登录 | 立即注册