最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 實現(xiàn) ReAct Agent工具調(diào)用與推理循環(huán)的過程

 更新時間:2026年04月24日 09:08:33   作者:花千樹-010  
文章介紹了Agent的概念,與普通LLM的區(qū)別,并詳細(xì)講解了ReAct模式,包括定義工具、ReAct Prompt模板、構(gòu)建推理循環(huán)和工具執(zhí)行邏輯,還對比了j-langchain和LangChain Python的特點,強調(diào)了j-langchain的透明度和可調(diào)試性

什么是 Agent?

普通 LLM 是被動的:你問,它答,結(jié)束。

Agent 是主動的:它能思考、制定計劃、調(diào)用工具獲取信息、基于結(jié)果繼續(xù)思考,直到完成目標(biāo)。

典型場景

  • “幫我查一下上海的天氣,然后推薦合適的穿搭”
  • “搜索最新的 Java 21 新特性,寫一份技術(shù)對比報告”
  • “查詢數(shù)據(jù)庫中的銷售數(shù)據(jù),生成本月分析報告”

ReAct 模式

ReAct = Reasoning + Acting,交替進(jìn)行推理和行動:

Question: 用戶的問題
  ↓
Thought: LLM 思考:需要什么信息?用什么工具?
  ↓
Action: 調(diào)用工具(get_weather)
Action Input: 工具參數(shù)("上海")
  ↓
Observation: 工具返回結(jié)果("上海天氣晴,25°C")
  ↓
Thought: 基于結(jié)果,還需要其他信息嗎?
  ↓
(如需要,重復(fù) Action → Observation 循環(huán))
  ↓
Final Answer: 最終回答

Step 1:定義工具

工具是 Agent 的"手和腳",本質(zhì)上是一個帶描述的函數(shù):

// 天氣查詢工具
Tool getWeather = Tool.builder()
    .name("get_weather")                            // 工具名稱(LLM 調(diào)用時使用)
    .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("獲取城市當(dāng)前時間,輸入城市名稱")
    .func(city -> String.format("%s 當(dāng)前時間 14:30", city))
    .build();

生產(chǎn)中,func 里可以調(diào)用真實 API、數(shù)據(jù)庫查詢、HTTP 請求——任何 Java 能做的事。

Step 2:ReAct Prompt 模板

這是 Agent 的"大腦",告訴 LLM 如何思考和行動:

PromptTemplate prompt = PromptTemplate.fromTemplate(
    """
    盡你所能回答以下問題。你有以下工具可以使用:
    ${tools}           ← 工具列表自動注入
    請按以下格式回答:
    Question: 你必須回答的問題
    Thought: 思考是否已有足夠信息回答
    Action: 要執(zhí)行的動作,必須是 [${toolNames}] 之一
    Action Input: 動作的輸入
    Observation: 動作結(jié)果
    (可重復(fù) Thought/Action/Observation,最多3次)
    Final Answer: 最終回答
    Question: ${input}
    Thought:
    """
);
// 將工具注入 Prompt
List<Tool> tools = List.of(getWeather, getTime);
prompt.withTools(tools);

Step 3:構(gòu)建推理循環(huán)

這是 ReAct 的核心——循環(huán)執(zhí)行,直到得到最終答案:

FlowInstance agentChain = chainActor.builder()
    .next(prompt)
    .loop(
        // 循環(huán)條件:還需要調(diào)用工具 && 未超過最大次數(shù)
        shouldContinue,
        // 循環(huán)體
        llm,                   // LLM 推理(生成 Thought/Action)
        chainActor.builder()
            .next(cutAtObservation)  // 截斷 LLM 自己編造的 Observation
            .next(parseAction)       // 解析 Action 和 Action Input
            .next(
                Info.c(needsToolCall, executeTool),  // 需要工具調(diào)用
                Info.c(input -> ContextBus.get().getResult(llm.getNodeId())) // 已有答案,退出循環(huán)
            )
            .build()
    )
    .next(new StrOutputParser())
    .next(extractFinalAnswer)  // 提取 "Final Answer:" 后面的內(nèi)容
    .build();

關(guān)鍵細(xì)節(jié)

為什么要截斷 Observation?

LLM 有時會自己"編造"工具的返回結(jié)果(Observation)而不真正調(diào)用。通過截斷 Observation: 之前的內(nèi)容,強制讓框架執(zhí)行真實的工具調(diào)用。

循環(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"))); // 還需要調(diào)用工具
};

Step 4:工具執(zhí)行邏輯

每次循環(huán),如果 LLM 決定調(diào)用工具,執(zhí)行器會:

  1. 找到對應(yīng)工具
  2. 執(zhí)行工具函數(shù)
  3. Observation 追加到 Prompt,構(gòu)造下一輪推理上下文
TranslateHandler<Object, Map<String, String>> executeTool = new TranslateHandler<>(map -> {
    // 找到 LLM 決定調(diào)用的工具
    Tool useTool = tools.stream()
        .filter(t -> t.getName().equalsIgnoreCase(map.get("Action")))
        .findFirst().orElse(null);
    // 執(zhí)行工具,獲取觀察結(jié)果
    String observation = (String) useTool.getFunc().apply(map.get("Action Input"));
    System.out.println("Observation: " + observation);
    // 將觀察結(jié)果追加到 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)在的天氣怎么樣?")) 的完整輸出:

> 進(jì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 Pythonj-langchain Java
ReAct Agentcreate_react_agentchainActor.builder().loop(...)
工具定義@tool 裝飾器Tool.builder()
循環(huán)控制框架內(nèi)置顯式 loop(condition, ...)
透明度框架封裝,較黑盒完全透明,可調(diào)試每一步

j-langchain 選擇顯式構(gòu)建推理循環(huán),好處是:每一步都在你的代碼中,方便調(diào)試和定制。

完整代碼見:src/test/java/org/salt/jlangchain/demo/article/Article04ReactAgent.java

到此這篇關(guān)于Java 實現(xiàn) ReAct Agent工具調(diào)用與推理循環(huán)的過程的文章就介紹到這了,更多相關(guān)Java ReAct Agent工具調(diào)用與推理循環(huán)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java實現(xiàn)dijkstra最短路徑尋路算法

    java實現(xiàn)dijkstra最短路徑尋路算法

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)dijkstra最短路徑尋路算法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • Java基礎(chǔ)概述面試題復(fù)習(xí)

    Java基礎(chǔ)概述面試題復(fù)習(xí)

    這篇文章主要介紹了java基礎(chǔ)面試題,文中的描述非常詳細(xì),對正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下,希望能給你帶來幫助
    2021-08-08
  • Java實現(xiàn)圖片上傳至服務(wù)器功能(FTP協(xié)議)

    Java實現(xiàn)圖片上傳至服務(wù)器功能(FTP協(xié)議)

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)圖片上傳至服務(wù)器功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • Java中的Future獲取任務(wù)返回值詳解

    Java中的Future獲取任務(wù)返回值詳解

    這篇文章主要介紹了Java中的Future獲取任務(wù)返回值詳解,在向線程池ThreadPoolExecutor提交任務(wù)時,一般為了方便操作采用execute提交任務(wù),這時線程其實是無返回值的,需要的朋友可以參考下
    2023-12-12
  • SpringCloud啟動失敗問題匯總

    SpringCloud啟動失敗問題匯總

    這篇文章主要介紹了SpringCloud啟動失敗問題匯總,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • java中如何獲取線程名稱

    java中如何獲取線程名稱

    這篇文章主要介紹了java中如何獲取線程名稱問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • servlet之web路徑問題_動力節(jié)點Java學(xué)院整理

    servlet之web路徑問題_動力節(jié)點Java學(xué)院整理

    這篇文章主要為大家詳細(xì)介紹了servlet之web路徑問題的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Java實現(xiàn)AES加密算法的簡單示例分享

    Java實現(xiàn)AES加密算法的簡單示例分享

    這篇文章主要介紹了Java實現(xiàn)AES加密算法的簡單示例分享,AES算法是基于對密碼值的置換和替代,需要的朋友可以參考下
    2016-04-04
  • 解決JAVA非對稱加密不同系統(tǒng)加密結(jié)果不一致的問題

    解決JAVA非對稱加密不同系統(tǒng)加密結(jié)果不一致的問題

    這篇文章主要介紹了解決JAVA非對稱加密不同系統(tǒng)加密結(jié)果不一致的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • Java集合中的List超詳細(xì)講解

    Java集合中的List超詳細(xì)講解

    本文詳細(xì)介紹了Java集合框架中的List接口,包括其在集合中的位置、繼承體系、常用操作和代碼示例,以及不同實現(xiàn)類(如ArrayList、LinkedList和Vector)的底層原理和應(yīng)用場景,感興趣的朋友一起看看吧
    2025-02-02

最新評論

双牌县| 许昌市| 平顶山市| 垫江县| 汝城县| 腾冲县| 进贤县| 昌邑市| 汉川市| 白山市| 尼木县| 普宁市| 门源| 东丽区| 仁化县| 鲁山县| 鲁甸县| 塘沽区| 梓潼县| 乐亭县| 临西县| 辰溪县| 龙山县| 卢龙县| 霸州市| 行唐县| 西乌| 大冶市| 临澧县| 峨边| 牙克石市| 静宁县| 昌吉市| 个旧市| 长兴县| 新晃| 聂荣县| 吉安市| 朝阳区| 黑山县| 吴川市|