Java 實現(xiàn) ReAct Agent工具調用與推理循環(huán)的過程
什么是 Agent?
普通 LLM 是被動的:你問,它答,結束。
Agent 是主動的:它能思考、制定計劃、調用工具獲取信息、基于結果繼續(xù)思考,直到完成目標。
典型場景:
- “幫我查一下上海的天氣,然后推薦合適的穿搭”
- “搜索最新的 Java 21 新特性,寫一份技術對比報告”
- “查詢數(shù)據(jù)庫中的銷售數(shù)據(jù),生成本月分析報告”
ReAct 模式
ReAct = Reasoning + Acting,交替進行推理和行動:
Question: 用戶的問題 ↓ Thought: LLM 思考:需要什么信息?用什么工具? ↓ Action: 調用工具(get_weather) Action Input: 工具參數(shù)("上海") ↓ Observation: 工具返回結果("上海天氣晴,25°C") ↓ Thought: 基于結果,還需要其他信息嗎? ↓ (如需要,重復 Action → Observation 循環(huán)) ↓ Final Answer: 最終回答
Step 1:定義工具
工具是 Agent 的"手和腳",本質上是一個帶描述的函數(shù):
// 天氣查詢工具
Tool getWeather = Tool.builder()
.name("get_weather") // 工具名稱(LLM 調用時使用)
.params("location: String") // 參數(shù)描述
.description("獲取城市天氣信息,輸入城市名稱") // 工具描述(LLM 理解用途)
.func(location -> // 實際執(zhí)行邏輯
String.format("%s 天氣晴,氣溫 25°C", location)
)
.build();
// 時間查詢工具
Tool getTime = Tool.builder()
.name("get_time")
.params("city: String")
.description("獲取城市當前時間,輸入城市名稱")
.func(city -> String.format("%s 當前時間 14:30", city))
.build();生產中,
func里可以調用真實 API、數(shù)據(jù)庫查詢、HTTP 請求——任何 Java 能做的事。
Step 2:ReAct Prompt 模板
這是 Agent 的"大腦",告訴 LLM 如何思考和行動:
PromptTemplate prompt = PromptTemplate.fromTemplate(
"""
盡你所能回答以下問題。你有以下工具可以使用:
${tools} ← 工具列表自動注入
請按以下格式回答:
Question: 你必須回答的問題
Thought: 思考是否已有足夠信息回答
Action: 要執(zhí)行的動作,必須是 [${toolNames}] 之一
Action Input: 動作的輸入
Observation: 動作結果
(可重復 Thought/Action/Observation,最多3次)
Final Answer: 最終回答
Question: ${input}
Thought:
"""
);
// 將工具注入 Prompt
List<Tool> tools = List.of(getWeather, getTime);
prompt.withTools(tools);Step 3:構建推理循環(huán)
這是 ReAct 的核心——循環(huán)執(zhí)行,直到得到最終答案:
FlowInstance agentChain = chainActor.builder()
.next(prompt)
.loop(
// 循環(huán)條件:還需要調用工具 && 未超過最大次數(shù)
shouldContinue,
// 循環(huán)體
llm, // LLM 推理(生成 Thought/Action)
chainActor.builder()
.next(cutAtObservation) // 截斷 LLM 自己編造的 Observation
.next(parseAction) // 解析 Action 和 Action Input
.next(
Info.c(needsToolCall, executeTool), // 需要工具調用
Info.c(input -> ContextBus.get().getResult(llm.getNodeId())) // 已有答案,退出循環(huán)
)
.build()
)
.next(new StrOutputParser())
.next(extractFinalAnswer) // 提取 "Final Answer:" 后面的內容
.build();關鍵細節(jié):
為什么要截斷 Observation?
LLM 有時會自己"編造"工具的返回結果(Observation)而不真正調用。通過截斷 Observation: 之前的內容,強制讓框架執(zhí)行真實的工具調用。
循環(huán)退出條件:
Function<Integer, Boolean> shouldContinue = i -> {
Map<String, String> parsed = ContextBus.get().getResult(parseAction.getNodeId());
return i < maxIterations // 未超過最大次數(shù)
&& (parsed == null // 還沒開始
|| (parsed.containsKey("Action") && parsed.containsKey("Action Input"))); // 還需要調用工具
};
Step 4:工具執(zhí)行邏輯
每次循環(huán),如果 LLM 決定調用工具,執(zhí)行器會:
- 找到對應工具
- 執(zhí)行工具函數(shù)
- 將
Observation追加到 Prompt,構造下一輪推理上下文
TranslateHandler<Object, Map<String, String>> executeTool = new TranslateHandler<>(map -> {
// 找到 LLM 決定調用的工具
Tool useTool = tools.stream()
.filter(t -> t.getName().equalsIgnoreCase(map.get("Action")))
.findFirst().orElse(null);
// 執(zhí)行工具,獲取觀察結果
String observation = (String) useTool.getFunc().apply(map.get("Action Input"));
System.out.println("Observation: " + observation);
// 將觀察結果追加到 Prompt,形成下一輪推理的上下文
String agentScratchpad = thoughtPart + "\nObservation:" + observation + "\nThought:";
promptValue.setText(promptValue.getText().trim() + agentScratchpad);
return promptValue;
});完整執(zhí)行示例
執(zhí)行 chainActor.invoke(agentChain, Map.of("input", "上?,F(xiàn)在的天氣怎么樣?")) 的完整輸出:
> 進入 AgentExecutor 鏈... Thought: 我需要查詢上海的天氣。 Action: get_weather Action Input: 上海 Observation: 上海 天氣晴,氣溫 25°C Thought: 我已經(jīng)獲得了上海的天氣信息,可以回答問題了。 Final Answer: 上?,F(xiàn)在天氣晴朗,氣溫25攝氏度。 > 鏈執(zhí)行完成。 === 最終答案 === 上?,F(xiàn)在天氣晴朗,氣溫25攝氏度。
與 LangChain Python 對比
| 特性 | LangChain Python | j-langchain Java |
|---|---|---|
| ReAct Agent | create_react_agent | chainActor.builder().loop(...) |
| 工具定義 | @tool 裝飾器 | Tool.builder() |
| 循環(huán)控制 | 框架內置 | 顯式 loop(condition, ...) |
| 透明度 | 框架封裝,較黑盒 | 完全透明,可調試每一步 |
j-langchain 選擇顯式構建推理循環(huán),好處是:每一步都在你的代碼中,方便調試和定制。
完整代碼見:src/test/java/org/salt/jlangchain/demo/article/Article04ReactAgent.java
到此這篇關于Java 實現(xiàn) ReAct Agent工具調用與推理循環(huán)的過程的文章就介紹到這了,更多相關Java ReAct Agent工具調用與推理循環(huán)內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java實現(xiàn)圖片上傳至服務器功能(FTP協(xié)議)
這篇文章主要為大家詳細介紹了Java實現(xiàn)圖片上傳至服務器功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-06-06
servlet之web路徑問題_動力節(jié)點Java學院整理
這篇文章主要為大家詳細介紹了servlet之web路徑問題的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07
解決JAVA非對稱加密不同系統(tǒng)加密結果不一致的問題
這篇文章主要介紹了解決JAVA非對稱加密不同系統(tǒng)加密結果不一致的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10

