構建高效代理
在最近的一篇研究論文《構建高效智慧體》中,Anthropic 分享了關於構建高效大型語言模型(LLM)智慧體的寶貴見解。這項研究特別有趣的地方在於,它強調簡單性和可組合性,而非複雜的框架。讓我們探討如何使用 Spring AI 將這些原則轉化為實際的實現。
雖然模式描述和圖表來源於 Anthropic 的原始出版物,但我們將重點關注如何使用 Spring AI 的模型可移植性和結構化輸出功能來實現這些模式。我們建議首先閱讀原始論文。
spring-ai-examples 倉庫中的 agentic-patterns 目錄包含了以下所有示例的程式碼。
智慧體系統
該研究論文對兩種型別的智慧體系統進行了重要的架構區分
-
工作流:LLM 和工具透過預定義程式碼路徑(例如,規範性系統)進行協調的系統
-
智慧體:LLM 動態指導其自身流程和工具使用的系統
關鍵的見解是,雖然完全自主的智慧體可能看起來很有吸引力,但工作流通常能為明確定義的任務提供更好的可預測性和一致性。這與企業對可靠性和可維護性的關鍵要求完全一致。
讓我們研究 Spring AI 如何透過五個基本模式實現這些概念,每種模式都服務於特定的用例
1. 鏈式工作流
鏈式工作流模式體現了將複雜任務分解為更簡單、更易管理步驟的原則。
何時使用: - 具有清晰順序步驟的任務 - 當您希望以延遲換取更高準確性時 - 當每個步驟都建立在前一個步驟的輸出之上時
以下是 Spring AI 實現的一個實際示例
public class ChainWorkflow {
private final ChatClient chatClient;
private final String[] systemPrompts;
public String chain(String userInput) {
String response = userInput;
for (String prompt : systemPrompts) {
String input = String.format("{%s}\n {%s}", prompt, response);
response = chatClient.prompt(input).call().content();
}
return response;
}
}
此實現演示了幾個關鍵原則
-
每個步驟都具有集中的職責
-
一個步驟的輸出成為下一個步驟的輸入
-
鏈式結構易於擴充套件和維護
2. 並行化工作流
LLM 可以同時處理任務,並透過程式設計方式聚合它們的輸出。
何時使用: - 處理大量相似但獨立的項時 - 需要多個獨立視角的任務 - 當處理時間至關重要且任務可並行化時
List<String> parallelResponse = new ParallelizationWorkflow(chatClient)
.parallel(
"Analyze how market changes will impact this stakeholder group.",
List.of(
"Customers: ...",
"Employees: ...",
"Investors: ...",
"Suppliers: ..."
),
4
);
3. 路由工作流
路由模式實現了智慧任務分發,為不同型別的輸入提供專門處理。
何時使用: - 具有不同輸入類別的複雜任務 - 當不同輸入需要專門處理時 - 當分類能夠準確處理時
@Autowired
private ChatClient chatClient;
RoutingWorkflow workflow = new RoutingWorkflow(chatClient);
Map<String, String> routes = Map.of(
"billing", "You are a billing specialist. Help resolve billing issues...",
"technical", "You are a technical support engineer. Help solve technical problems...",
"general", "You are a customer service representative. Help with general inquiries..."
);
String input = "My account was charged twice last week";
String response = workflow.route(input, routes);
4. 協調器-工作器
何時使用: - 無法預先預測子任務的複雜任務 - 需要不同方法或視角的任務 - 需要自適應問題解決的情況
public class OrchestratorWorkersWorkflow {
public WorkerResponse process(String taskDescription) {
// 1. Orchestrator analyzes task and determines subtasks
OrchestratorResponse orchestratorResponse = // ...
// 2. Workers process subtasks in parallel
List<String> workerResponses = // ...
// 3. Results are combined into final response
return new WorkerResponse(/*...*/);
}
}
使用示例
ChatClient chatClient = // ... initialize chat client
OrchestratorWorkersWorkflow workflow = new OrchestratorWorkersWorkflow(chatClient);
WorkerResponse response = workflow.process(
"Generate both technical and user-friendly documentation for a REST API endpoint"
);
System.out.println("Analysis: " + response.analysis());
System.out.println("Worker Outputs: " + response.workerResponses());
5. 評估器-最佳化器
何時使用: - 存在明確的評估標準 - 迭代改進提供可衡量的價值 - 任務受益於多輪批評
public class EvaluatorOptimizerWorkflow {
public RefinedResponse loop(String task) {
Generation generation = generate(task, context);
EvaluationResponse evaluation = evaluate(generation.response(), task);
return new RefinedResponse(finalSolution, chainOfThought);
}
}
使用示例
ChatClient chatClient = // ... initialize chat client
EvaluatorOptimizerWorkflow workflow = new EvaluatorOptimizerWorkflow(chatClient);
RefinedResponse response = workflow.loop(
"Create a Java class implementing a thread-safe counter"
);
System.out.println("Final Solution: " + response.solution());
System.out.println("Evolution: " + response.chainOfThought());
Spring AI 實現的優勢
Spring AI 對這些模式的實現提供了與 Anthropic 建議一致的幾個好處
模型可移植性
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
結構化輸出
EvaluationResponse response = chatClient.prompt(prompt)
.call()
.entity(EvaluationResponse.class);
一致的 API
-
跨不同 LLM 提供商的統一介面
-
內建錯誤處理和重試
-
靈活的提示管理
最佳實踐和建議
-
從簡單開始
-
在增加複雜性之前,從基本工作流開始
-
使用滿足您需求的最簡單模式
-
僅在需要時增加複雜性
-
為可靠性設計
-
實現清晰的錯誤處理
-
儘可能使用型別安全的響應
-
在每個步驟中構建驗證
-
考慮權衡
-
平衡延遲與準確性
-
評估何時使用並行處理
-
在固定工作流和動態智慧體之間做出選擇