Java大模型開發入門 (6/15):對話的靈魂 - 深入理解LangChain4j中的模型、提示和解析器

前言

在上一篇文章中,我們見證了@AiService注解的驚人威力。僅僅通過定義一個Java接口,我們就實現了一個功能完備的AI聊天服務。這感覺就像魔法一樣!

但作為專業的工程師,我們知道“任何足夠先進的技術,都與魔法無異”。今天,我們的任務就是揭開這層魔法的面紗,深入理解其背后支撐我們與AI進行高質量對話的三大支柱:

  1. 語言模型 (Models):AI的“大腦”,我們如何理解并與它交互。
  2. 提示模板 (Prompt Templates):控制我們對AI“說什么”的藝術,實現動態、可復用的指令。
  3. 輸出解析器 (Output Parsers):馴服AI的“輸出”,讓它返回我們需要的Java對象,而不僅僅是文本。

掌握了這三者,你將從一個簡單的AI“調用者”,蛻變為一個能精確控制AI行為的“指揮家”。

第一部分:再探模型 (Models) - AI的“大腦”

application.properties中,我們配置了langchain4j.open-ai.chat-model.*等屬性,并通過LangChain4jConfig創建了一個ChatLanguageModel類型的Bean。

ChatLanguageModel是LangChain4j中的一個核心接口,它代表了所有聊天式AI模型(如GPT-3.5/4, DeepSeek-Chat)的統一抽象。你可以把它想象成Java JDBC規范中的DataSource接口,它為所有不同廠商的數據庫提供了統一的訪問標準。

我們配置的OpenAiChatModel是這個接口的一個具體實現。如果我們想換成Google的Gemini模型,只需引入langchain4j-google-vertex-ai依賴,并創建一個VertexAiChatModel的Bean即可,而我們上層的業務代碼(如Assistant接口)幾乎無需改動。這就是面向接口編程的威力。

核心概念

  • ChatLanguageModel: 用于一次請求-響應的交互。
  • StreamingChatLanguageModel: ChatLanguageModel的子接口,用于流式響應。AI的回答會一個詞一個詞地“流”回來,能極大地提升用戶體驗,我們將在后續文章中探討它。
第二部分:提示模板 (Prompt Templates) - 控制AI的“輸入”

在上一篇中,我們使用了簡單的assistant.chat(userMessage)。LangChain4j只是將userMessage作為用戶提問直接發給了AI。但如果我們想讓AI扮演特定角色,或者根據多個動態參數來提問呢?這時就需要提示模板。

在LangChain4j中,我們可以通過@UserMessage注解和{{...}}占位符來創建強大的提示模板。

實戰:創建一個食譜生成器

讓我們來改造Assistant接口,讓它能根據菜系和原料生成食譜。

  1. 修改Assistant接口

    package com.example.aidemoapp.service;import dev.langchain4j.service.SystemMessage;
    import dev.langchain4j.service.UserMessage;
    import dev.langchain4j.service.spring.AiService;@AiService
    public interface Assistant {@SystemMessage("You are a polite assistant")String chat(String userMessage);// 新增一個使用模板的方法@UserMessage("""請創建一個 {{dish_type}} 菜肴的食譜。 主要食材是:{{ingredients}}。 請提供包含標題、簡要描述、所需食材列表以及逐步操作說明的完整食譜。""")String createRecipe(@V("dish_type") String dish_type, @V("ingredients") String ingredients);
    }
    

    代碼解析

    • 我們在@UserMessage注解中使用了Java 15的文本塊(三引號),方便編寫多行提示。
    • {{dish_type}}{{ingredients}}是占位符。
    • LangChain4j會自動將createRecipe方法的dish_type參數值填充到{{dish_type}}占位符中,ingredients參數同理。
  2. ChatController中調用新方法

    package com.example.aidemoapp.controller;// ... imports ...@RestController
    @RequestMapping("/api/v2/chat")
    @RequiredArgsConstructor
    public class ChatController {private final Assistant assistant;@GetMappingpublic String chat(@RequestParam("message") String message) {return assistant.chat(message);}@GetMapping("/recipe")public String recipe(@RequestParam String dishType, @RequestParam String ingredients) {return assistant.createRecipe(dishType, ingredients);}
    }
    

現在,當你請求GET /api/v2/chat/recipe?dishType=Sichuan&ingredients=tofu,garlic,chili時,LangChain4j會向AI發送一個被完整填充的、結構化的Prompt,從而得到一個高質量的食譜。

第三部分:輸出解析器 (Output Parsers) - 控制AI的“輸出”

上面的食譜生成器返回的是一個長字符串。在真實應用中,我們更希望得到一個結構化的Java對象(POJO),以便于在前端展示或進行后續處理。

LangChain4j的AiServices能做到這一點!只要你將方法的返回類型從String改為一個自定義的Java類,LangChain4j就會自動指示AI以JSON格式輸出,并自動將JSON反序列化為你的Java對象。這就是輸出解析器的魔力!

實戰:將食譜輸出為Java對象

  1. 創建Recipe POJO
    com.example.aidemoapp下創建dto包,并新建Recipe.java類。

    package com.example.aidemoapp.dto;import lombok.Data;
    import java.util.List;@Data // Lombok注解,自動生成getter, setter, toString等
    public class Recipe {private String title;private String description;private List<String> ingredients;private List<String> instructions;
    }
    
  2. 再次修改Assistant接口
    我們將createRecipe方法的返回類型改為Recipe

    // ... imports ...
    import com.example.aidemoapp.dto.Recipe; // 引入Recipe類@AiService
    public interface Assistant {@SystemMessage("You are a polite assistant")String chat(String userMessage);// 新增一個使用模板的方法@UserMessage("""請創建一個 {{dish_type}} 菜肴的食譜。 主要食材是:{{ingredients}}。 請提供包含標題、簡要描述、所需食材列表以及逐步操作說明的完整食譜。""")Recipe createRecipe(@V("dish_type") String dish_type, @V("ingredients") String ingredients);
    }
    

    提示詞增強:我們明確在提示中要求AI以JSON格式返回,并描述了JSON的結構。雖然LangChain4j在很多情況下會自動處理,但明確地指示AI可以極大地提高成功率和穩定性。

  3. 修改ChatController

    // ... imports ...
    import com.example.aidemoapp.dto.Recipe;// ...
    public class ChatController {// ... chat和recipe方法 ...@GetMapping("/recipe-object")public Recipe recipeObject(@RequestParam String dishType, @RequestParam String ingredients) {return assistant.createRecipeAsObject(dishType, ingredients);}
    }
    

    由于@RestController的存在,Spring Boot會自動將返回的Recipe對象序列化為JSON字符串,作為HTTP響應返回給前端。

現在,當你請求GET /api/v2/chat/recipe-object?dishType=Italian&ingredients=pasta,tomatoes,basil時,你將直接得到一個干凈的、結構化的JSON響應!

源碼獲取

本文中所有實戰代碼均已同步更新至Gitee倉庫,方便您下載、運行和學習。

源碼地址:https://gitee.com/chaocloud/springboot-langchain4j-demo

總結

今天,我們揭開了LangChain4j高效開發的神秘面紗。我們學習了:

  • Models是連接AI大腦的統一接口。
  • Prompt Templates (@UserMessage{{...}}) 讓我們能精確地、動態地控制輸入
  • Output Parsers (通過改變返回類型) 讓我們能將AI的輸出從非結構化的文本,轉換為結構化的、可被程序直接利用的Java對象。

我們已經從簡單的“你問我答”進化到了可以與AI進行可預測、結構化交互的新階段。但這還不夠,我們的AI助手還是“金魚般的記憶”,每次對話都是一次全新的開始。如何讓它記住上下文,進行真正的多輪對話呢?


下一篇預告:
Java大模型開發入門 (7/15):讓AI擁有記憶 - 使用LangChain4j實現多輪對話》—— 我們將為我們的Assistant裝上“記憶芯片”,探索LangChain4j中的ChatMemory機制,打造一個能真正聯系上下文的智能聊天機器人!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/84912.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/84912.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/84912.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

用Rust如何構建高性能爬蟲

習慣了使用Python來寫爬蟲&#xff0c;如果使用Rust需要有哪些考量&#xff1f; 根據我了解的Rust 在性能、資源效率和并發處理方面完勝 Python&#xff0c;但是 Python 在開發速度和生態成熟度上占優。所以說&#xff0c;具體用那種模式&#xff0c;結合你項目特點做個詳細的…

CentOS7報錯:Cannot find a valid baseurl for repo: base/7/x86_64

這個錯誤通常出現在 CentOS/RHEL 7 系統中&#xff0c;當你嘗試運行 yum update 或 yum install 時&#xff0c;系統無法連接到默認的軟件倉庫&#xff08;repository&#xff09;。 可能的原因 網絡連接問題&#xff1a;系統無法訪問互聯網或倉庫服務器。錯誤的倉庫配置&…

云平臺|Linux部分指令

目錄 云平臺 操作系統&#xff08;鏡像&#xff09; 管理應用實例 遠程連接 遠程連接工具 linux相關命令&#xff08;重點&#xff09; 云平臺 1、阿里云&#xff08;學生免費&#xff0c;不包流量 流量0.8---1G&#xff09; 2、騰訊云&#xff08;搶&#xff09; 3、華…

AI首次自主發現人工生命

轉&#xff1a; 近日&#xff0c;人工智能領域迎來了一項革命性的突破。Transformer 論文作者之一的 Llion Jones 與前谷歌研究人員 David Ha 共同創立的人工智能公司 Sakana AI&#xff0c;聯合MIT、OpenAI、瑞士AI實驗室IDSIA等機構的研究人員&#xff0c;共同提出了一種名為…

Day.31

變量類型&#xff1a; name: str "Alice" age: int 30 height: float 1.75 is_student: bool False 注解&#xff1a; def add(a: int, b: int) -> int: return a b def greet(name: str) -> None: print(f"Hello, {name}") 定義矩形類&a…

光譜數據分析的方法有哪些?

光譜數據分析是通過特征光譜識別物質結構與成分的核心技術&#xff0c;其標準化流程如下&#xff1a; ?一、數據預處理?&#xff08;消除干擾噪聲&#xff09; ?去噪平滑? Savitzky-Golay濾波&#xff1a;保留光譜特征峰形&#xff0c;消除高頻噪聲。 移動平均法&#…

RabbitMQ的使用--Spring AMQP(更新中)

1.首先是創建項目 在一個父工程 mq_demo 的基礎上建立兩個子模塊&#xff0c;生產者模塊publisher&#xff0c;消費者模塊 consumer 創建項目&#xff1a; 建立成功&#xff1a; 刪除多余文件 創建子模塊1&#xff1a;publisher&#xff08;生產者模塊&#xff09; 右鍵---…

DAY 31 文件的規范拆分和寫法

浙大疏錦行 今日的示例代碼包含2個部分 notebook文件夾內的ipynb文件&#xff0c;介紹下今天的思路項目文件夾中其他部分&#xff1a;拆分后的信貸項目&#xff0c;學習下如何拆分的&#xff0c;未來你看到的很多大項目都是類似的拆分方法 知識點回顧 規范的文件命名規范的文件…

EtherCAT至TCP/IP異構網絡互聯:施耐德M580 PLC對接倍福CX5140解決方案

一、項目背景與需求 某智能工廠致力于打造高度自動化的生產流水線&#xff0c;其中部分核心設備采用EtherCAT協議進行通信&#xff0c;以實現高速、高精度的控制&#xff0c;例如基于EtherCAT總線的倍福&#xff08;Beckhoff&#xff09;CX5140PLC&#xff0c;它能夠快速響應設…

[學習] FIR多項濾波器的數學原理詳解:從多相分解到高效實現(完整仿真代碼)

FIR多項濾波器的數學原理詳解&#xff1a;從多相分解到高效實現 文章目錄 FIR多項濾波器的數學原理詳解&#xff1a;從多相分解到高效實現引言一、FIR濾波器基礎與多相分解原理1.1 FIR濾波器數學模型1.2 多相分解的數學推導1.3 多相分解的物理意義 二、插值應用中的數學原理2.1…

Java并發編程實戰 Day 22:高性能無鎖編程技術

【Java并發編程實戰 Day 22】高性能無鎖編程技術 文章簡述 在高并發場景下&#xff0c;傳統的鎖機制&#xff08;如synchronized、ReentrantLock&#xff09;雖然能夠保證線程安全&#xff0c;但在高競爭環境下容易引發性能瓶頸。本文深入探討無鎖編程技術&#xff0c;重點介紹…

打破語言壁壘!DHTMLX Gantt 與 Scheduler 文檔正式上線中文等多語言版本!

你還在為英文技術文檔望而卻步嗎&#xff1f;現在好消息來了&#xff01;DHTMLX 團隊宣布&#xff0c;其兩款明星組件——DHTMLX Gantt&#xff08;甘特圖&#xff09;與 DHTMLX Scheduler&#xff08;日程排程器&#xff09;的官方文檔&#xff0c;現已全面支持中文、德語、韓…

無監督 vs 有監督的本質區別

一、無監督 vs 有監督的本質區別 1. 無監督學習 定義&#xff1a;數據中沒有人為標注的 “正確答案”&#xff08;如類別標簽、目標值&#xff09;&#xff0c;模型需自己發現數據中的模式。任務目標&#xff1a;學習數據的分布規律、結構或生成邏輯。例子&#xff1a; 文本續…

【Linux】初見,進程概念

前言&#xff1a; 上文我們講到了Linux下的第一個程序&#xff1a;進度條 【Linux】LInux下第一個程序&#xff1a;進度條-CSDN博客 本文我們來講一講Linux中下一個非常重要的東西&#xff1a;進程 1.馮諾依曼體系結構 我們所見的大部分計算機都是遵循的馮諾依曼體系結構…

Linux進程間通信(IPC)詳解:從入門到理解

引言 作為一名C開發初學者&#xff0c;理解Linux下的進程間通信&#xff08;Inter-Process Communication&#xff0c;簡稱IPC&#xff09;機制是非常重要的一步。本文將用通俗易懂的語言&#xff0c;配合直觀的圖示&#xff0c;幫助你理解Linux進程間通信的基本概念和各種實現…

SQL進階之旅 Day 27:存儲過程與函數高級應用

【SQL進階之旅 Day 27】存儲過程與函數高級應用 文章簡述 在數據庫開發中&#xff0c;存儲過程和函數是實現復雜業務邏輯、提高代碼復用性和提升系統性能的重要工具。本文作為“SQL進階之旅”系列的第27天&#xff0c;深入探討存儲過程與函數的高級應用&#xff0c;涵蓋其設計…

泰國零售巨頭 CJ Express 借助 SAP 內存數據庫實現高效數據管理

泰國 CJ Express 運用 SAP 內存數據庫有效控制數據增長案例 “Datavard Outboard 操作簡便、配置輕松&#xff0c;我們得以在生產系統上完成數據歸檔&#xff0c;成功將約 730GB 數據遷移至 Hadoop 集群。”——K. Jak&#xff0c;J Express 技術服務經理 關于 CJ Express …

ImageSharp.Web 使用指南:高效處理ASP.NET Core中的圖像

文章目錄 前言一、ImageSharp.Web簡介二、安裝與配置1. 安裝NuGet包2. 基本配置3. 高級配置 三、核心功能與使用示例1. 基本圖像處理2. 處理模式詳解3. 自定義處理命令 四、緩存策略1. 物理文件系統緩存2. 分布式緩存3. 自定義緩存 五、性能優化建議六、常見問題解決1. 圖像處理…

使用R進行數字信號處理:嬰兒哭聲分析深度解析

音頻信號處理將原始聲音數據轉化為有意義的洞見&#xff0c;適用于語音分析、生物聲學和醫學診斷等領域。使用R語言&#xff0c;我們可以處理音頻文件、可視化頻率內容&#xff0c;并生成如聲譜圖等詳細圖表。本指南將展示如何使用R包tuneR、seewave和rpanel分析嬰兒哭聲音頻文…

【環境配置】解決linux每次打開終端都需要source .bashrc文件的問題

解決方法&#xff1a; cd vim .bash_profile輸入下面內容后 :wq 保存并退出 # .bash_profileif [ -f ~/.bashrc ]; then. ~/.bashrc fi 參考鏈接&am…