【langchain4j】Springboot如何接入大模型以及實戰開發-AI問答助手(一)

langchain4j介紹

官網地址:https://docs.langchain4j.dev/get-started

langchain4j可以說是java和spring的關系,spring讓我們開發java應用非常簡單,那么langchain4j對應的就是java開發ai的 “Spring”
他集成了AI應用的多種場景,并且抽象多種接口,讓我們開發AI應用非常簡單,下面介紹其常用功能,以及開發一個小的ai問答應用

AI應用的實現需求:支持對話、上下文對話、流式對話、對話數據隔離、對話數據持久化、Function Call實現特殊場景結合業務進行ai問答

為了降低模型的使用門檻,這里開發使用國內模型-阿里千問系列進行開發,登錄去控制臺獲取key就行
https://bailian.console.aliyun.com/

項目依賴引入

依賴需要引入兩個東西:langchain4j的依賴、對應的模型的依賴,但是如果通過starter的形式,只需要引入starter即可,具體可以看官方的文檔
https://docs.langchain4j.dev/integrations/language-models/dashscope
注意:需要使用jdk17環境,SpringBoot3.x系列

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.xujie</groupId><artifactId>langchain4j-demo</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.boot.version>3.2.4</spring.boot.version><langchain4j.version>1.0.0-beta3</langchain4j.version></properties><dependencyManagement><dependencies><!-- Spring Boot Starter父依賴 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>${spring.boot.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-community-bom</artifactId><version>${langchain4j.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId></dependency><!-- Langchain4j自己的核心庫 --><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j</artifactId><version>${langchain4j.version}</version></dependency><!-- Web依賴,以及Webflux依賴,實現流式響應 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><!-- Redis的依賴,用于消息持久化 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency></dependencies>
</project>

功能體驗

首先我們先逐個體驗其功能,最后再統一集成

AI對話

Langchain4j將AI的功能封裝成一個Model,通過Model即可調用對應的AI功能,我們要使用千問的模型,new 一個千問的Model即可
這里有兩種方式,一種是通過SpringBoot的配置文件,將模型注入到IOC容器中,另一種就是通過代碼進行配置

ChatLanguageModel qwenModel = QwenChatModel.builder().apiKey("You API key here").modelName("qwen-max").build();

官方示例:

langchain4j.community.dashscope.api-key=<You API Key here>
langchain4j.community.dashscope.model-name=qwen-max
# The properties are the same as `QwenChatModel`
# e.g.
# langchain4j.community.dashscope.temperature=0.7
# langchain4j.community.dashscope.max-tokens=4096
langchain4j:community:dashscope:chat-model:api-key: ${Ali_AI_KEY} //通過環境參數model-name: qwen-max

這里我們就使用注入的方式

/*** @author Xujie* @since 2025/4/19 21:44**/
@Slf4j
@SpringBootTest
public class TestAi {@Resourceprivate ChatLanguageModel qwenChatModel;@Testpublic void test() {String response = qwenChatModel.chat("你好呀");log.info(response);}
}

控制臺輸出:

2025-04-19T21:47:29.593+08:00  INFO 12660 --- [           main] com.xujie.TestAi                         : 你好!有什么可以幫助你的嗎?

這里說明成功了

文生圖

我們再來體驗一下文生圖的功能,這里用的阿里 wanx2.1-t2i-turbo 模型,大家也可以去阿里的模型廣場看看有哪些支持圖片生成的模型,調用即可,這里我們就通過手動構造的模式去構成圖片模型

@Value("${langchain4j.community.dashscope.chat-model.api-key}")private String apiKey;@Testpublic void testGeneratePicture() {WanxImageModel.WanxImageModelBuilder builder = WanxImageModel.builder();WanxImageModel wanxImageModel = builder.apiKey(apiKey).modelName("wanx2.1-t2i-turbo").build();Response<Image> imageResponse = wanxImageModel.generate("生成一只剃了毛的黑色拉布拉多");log.info(imageResponse.toString());}
Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
2025-04-19T21:54:42.892+08:00  INFO 31912 --- [           main] com.xujie.TestAi                         : Response { content = Image { url = "https://dashscope-result-wlcb-acdr-1.oss-cn-wulanchabu-acdr-1.aliyuncs.com/1d/e3/20250419/b0fe3396/15a89e1c-f792-4156-bff2-5d2ccb80561e3378775189.png?Expires=1745157281&OSSAccessKeyId=LTAI5tKPD3TMqf2Lna1fASuh&Signature=m3QvlCGR4aGwVyI7Vj1IFnVY95Y%3D", base64Data = null, mimeType = null, revisedPrompt = "寫實寵物攝影,一只黑色拉布拉多犬在戶外草地上。它全身毛發被修剪得非常短,露出光滑的黑皮膚。狗狗四肢強健,肌肉線條明顯,正抬頭望向鏡頭,眼神機警靈動。背景是大片綠色草地和藍天白云,陽光灑在狗身上形成自然光影效果。高清彩色攝影,近景側面捕捉狗狗優雅姿態。" }, tokenUsage = null, finishReason = null, metadata = {} }

可以看見,這里也是成功的生成圖片了,效果一般,也有可能是我Promot的問題

在這里插入圖片描述

文生語音

同樣,我們去模型廣場看看哪些支持生成語音的模型,這里就使用cosyvoice-v1模型

@Testpublic void testGenerateVoice() {SpeechSynthesisParam param = SpeechSynthesisParam.builder().apiKey(apiKey).voice("longxiaochun").model("cosyvoice-v1").build();SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(param,null);ByteBuffer call = speechSynthesizer.call("你好,給我唱一首生日快樂歌");// Maven項目標準資源目錄File file = new File("src/main/resources/response.mp3");// 確保目錄存在file.getParentFile().mkdirs();try(FileOutputStream fileOutputStream = new FileOutputStream(file)) {fileOutputStream.write(call.array());} catch (Exception e) {throw new RuntimeException(e);}}

然語音文件的路徑實在resources下面,也是成功了
在這里插入圖片描述

對話上下文

首先,我們理解一下什么是對話上下文,我們要清楚,AI的服務是不會記錄我們對話的記錄,我們每一次請求都是獨立的返回,不會關聯我們之前的問題,那么我就要實現上下文,就只能將之前的對話記錄一起加上這一次的提問,一起請求給AI,這才實現了上下文的功能
我們進行驗證一下,AI是否會自動記錄上下文:
我們簡單改造一下第一個用例

  @Testpublic void test() {String response1 = qwenChatModel.chat("你好呀,我是XJ");String response2 = qwenChatModel.chat("我是什么名字");log.info(response1);log.info(response2);}
Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
2025-04-19T22:14:23.835+08:00  INFO 38908 --- [           main] com.xujie.TestAi                         : 你好,XJ!很高興認識你。我是Qwen,由阿里云開發的超大規模語言模型。我在這里可以幫助你解答問題、提供信息或者進行各種話題的交流。有什么我可以幫到你的嗎?
2025-04-19T22:14:23.835+08:00  INFO 38908 --- [           main] com.xujie.TestAi                         : 您好!您并沒有告訴我您的名字,所以我無法直接知道您的名字是什么。如果您愿意分享的話,可以告訴我您的名字或者您想讓我怎么稱呼您。

可以看到,兩次回復都是毫無關聯的;
既然這樣我們如何實現上下文呢,那最簡單暴力的方式就是將前面的請求和響應一起發給AI,如下

    @Testpublic void test() {UserMessage userMessage1 = new UserMessage("你好呀,我是XJ");ChatResponse chatResponse1 = qwenChatModel.chat(userMessage1);AiMessage aiMessage = chatResponse1.aiMessage();// 拿到ai的響應UserMessage userMessage2 = new UserMessage("我是什么名字");ChatResponse chatResponse2 = qwenChatModel.chat(userMessage1,aiMessage,userMessage2);log.info(chatResponse1.aiMessage().text());log.info(chatResponse2.aiMessage().text());}

兩次相應如下

Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
2025-04-19T22:18:23.274+08:00  INFO 40264 --- [           main] com.xujie.TestAi                         : 你好,XJ!很高興認識你。有什么我可以幫助你的嗎?或者你想聊些什么?
2025-04-19T22:18:23.274+08:00  INFO 40264 --- [           main] com.xujie.TestAi                         : 你剛才告訴我你的名字是XJ。如果你有其他的名字或者昵稱,也可以告訴我哦!

可以發現,AI對話已經具有的上下文的功能,但是這樣是不是太復雜?
沒當發現一個東西復雜的時候,總會有對應的不復雜的情況,如果沒有,那就自己造,如果要我們自己實現,那其實也是很簡單,將請求AI的接口封裝一下,并且內部維護對話記錄,每次請求,將歷史的記錄攜帶即可。

但是框架Langchain4j的已經幫我們實現了,具體是采用動態代理的模式實現的
在這里插入圖片描述

public interface AiChat{String chat(String text);TokenStream tokenStream(String text);}@Testpublic void test() {AiChat aiChat = AiServices.builder(AiChat.class).chatLanguageModel(qwenChatModel).chatMemory(MessageWindowChatMemory.withMaxMessages(10))//限制10上下文.build();String response1 = aiChat.chat("我的名字是小徐");String response2 = aiChat.chat("我的名字是什么");log.info(response1);log.info(response2);}
Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
2025-04-19T22:30:34.652+08:00  INFO 32428 --- [           main] com.xujie.TestAi                         : 你好,小徐!很高興認識你。有什么我可以幫助你的嗎?
2025-04-19T22:30:34.652+08:00  INFO 32428 --- [           main] com.xujie.TestAi                         : 你的名字是小徐。如果你還有其他問題或需要幫助,隨時告訴我哦!

通過返回可以看的,確實是具有的上下文的能力

回話隔離

我們與ai進行回話,通常是具有對此回話的,每一次的回話主題都不一樣,需要進行隔離,那我們來看看Langchain4j如何實現的回話隔離,上面我們實現了回話的上下文,跟最初一樣,我們理解一下如何實現回話隔離呢?
那肯定是通過什么ID或者其他的唯一標識來區分
而且,也確實是這樣實現的
我們只需要每一次對話傳入ID即可
相比上面加了一個注解以及id字段,這個注解是Langchain4j提供的,在代理中通過注解去拿到對應的值

   public interface AiChat{String chat(@MemoryId Long id, @UserMessage String text);}@Testpublic void test() {AiChat aiChat = AiServices.builder(AiChat.class).chatLanguageModel(qwenChatModel).chatMemoryProvider(memoryId -> MessageWindowChatMemory.builder().maxMessages(10).id(memoryId).build()).build();String response1 = aiChat.chat(1L,"我的名字是小徐");String response2 = aiChat.chat(1L,"我的名字是什么");log.info(response1);log.info(response2);log.info("======");response2 = aiChat.chat(2L,"我的名字是什么");log.info(response2);}
2025-04-19T22:39:18.264+08:00  INFO 40528 --- [           main] com.xujie.TestAi                         : 你好,小徐!很高興認識你。有什么我可以幫助你的嗎?
2025-04-19T22:39:18.264+08:00  INFO 40528 --- [           main] com.xujie.TestAi                         : 你的名字是小徐。如果有其他問題或需要幫助的地方,隨時告訴我哦!
2025-04-19T22:39:18.264+08:00  INFO 40528 --- [           main] com.xujie.TestAi                         : ======
2025-04-19T22:39:19.739+08:00  INFO 40528 --- [           main] com.xujie.TestAi                         : 您好!您并沒有告訴我您的名字,所以我無法知道您的名字是什么。如果您愿意,可以告訴我您的名字,我很樂意用您的名字來稱呼您。

可以看的兩個回話,確實是隔離了,第二個回話并不清楚我第一個回話的內容

Function Call

Function Call 就是我們提前預設一些場景,然后用戶在進行AI問答時,如果ai覺得當前對話符合某一個場景,便會去調用預設的函數,獲取函數的返回值,然后結合用戶的提問,去回答用戶
比如:我數據庫中存儲今天的香蕉價格是10元一斤
并且預設場景:水果的價格
那么用戶提問:今天的香蕉多少錢一斤
那么就會提取到水果的名稱:香蕉,去數據庫查詢香蕉的價格,為10元,然后結合用戶的提問,進行回答

 @Testpublic void testFuncCall() {class FuncCallService{final Map<String,Integer> map = Map.of("香蕉",10,"蘋果",12);@Tool("水果的價格")public Integer fruitsPrice(@P("水果名字") String fruitName) {return map.getOrDefault(fruitName,-1);}}AiChat aiChat = AiServices.builder(AiChat.class).chatLanguageModel(qwenChatModel).tools(new FuncCallService()).chatMemoryProvider(memoryId -> MessageWindowChatMemory.builder().maxMessages(10).id(memoryId).build()).build();String response1 = aiChat.chat(1L, "香蕉多少錢一斤");String response2 = aiChat.chat(2L, "蘋果多少錢一斤");String response3 = aiChat.chat(3L, "栗子多少錢一斤");log.info(response1);log.info(response2);log.info(response3);}
2025-04-19T22:49:48.799+08:00  INFO 40704 --- [           main] com.xujie.TestAi                         : 香蕉的價格是10元一斤。
2025-04-19T22:49:48.799+08:00  INFO 40704 --- [           main] com.xujie.TestAi                         : 蘋果的價格是12元一斤。
2025-04-19T22:49:48.799+08:00  INFO 40704 --- [           main] com.xujie.TestAi                         : 對不起,當前的查詢工具中沒有栗子的價格信息。我建議您可以去附近的市場或者在線購物網站上查看最新的價格。如果您需要查詢其他水果的價格,也可以告訴我,我會盡力幫您查詢。

可以看到,確實是結合我們預設的內容去執行了Func Call

綜上,結合Langchain4j確實可以很方便引入AI的功能,讓我們的應用具有AI的功能

項目實戰放在下一篇文章中

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

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

相關文章

平均池化(Average Pooling)

1. 定義與作用?? ??平均池化??是一種下采樣操作&#xff0c;通過對輸入區域的數值取??平均值??來壓縮數據空間維度。其核心作用包括&#xff1a; ??降低計算量??&#xff1a;減少特征圖尺寸&#xff0c;提升模型效率。??保留整體特征??&#xff1a;平滑局部…

【dify實戰】chatflow結合deepseek實現基于自然語言的數據庫問答、Echarts可視化展示、Excel報表下載

dify結合deepseek實現基于自然語言的數據庫問答、Echarts可視化展示、Excel報表下載 觀看視頻&#xff0c;您將學會 在dify下如何快速的構建一個chatflow&#xff0c;來完成數據分析工作&#xff1b;如何在AI的回復中展示可視化的圖表&#xff1b;如何在AI 的回復中加入Excel報…

加一:從簡單問題到復雜邊界的深度思考

加一&#xff1a;從簡單問題到復雜邊界的深度思考 引言 在算法世界里&#xff0c;有些問題看似簡單&#xff0c;實則暗藏玄機&#xff0c;其中“加一”問題就是一個典型例子。所謂“加一”&#xff0c;通常指的是給一個由數字組成的數組表示的整數加一&#xff0c;這聽起來簡…

PointCore——利用局部全局特征的高效無監督點云異常檢測器論文與算法解讀

概述 三維點云異常檢測旨在從訓練集中檢測出異常數據點&#xff0c;是工業檢測、自動駕駛等眾多應用的基礎。然而&#xff0c;現有的點云異常檢測方法通常采用多個特征存儲庫來充分保留局部和全局特征表示&#xff0c;這帶來了高昂的計算成本以及特征之間的不匹配問題。為解決…

桌面應用UI開發方案

一、基于 Web 技術的跨平臺方案 Electron Python/Go 特點&#xff1a; 技術棧&#xff1a;前端使用 HTML/CSS/JS&#xff0c;后端通過 Node.js 集成 Python/Go 模塊或服務。 跨平臺&#xff1a;支持 Windows、macOS、Linux 桌面端&#xff0c;適合開發桌面應用。 生態成熟&…

redis 配置日志和數據存儲位置

Redis配置日志和數據存儲位置 介紹 Redis是一個開源的高性能鍵值存儲數據庫&#xff0c;常用于緩存、消息隊列和實時分析等場景。在使用Redis時&#xff0c;我們需要配置日志和數據存儲位置&#xff0c;以便更好地管理和監控Redis的運行狀態。本文將介紹如何配置Redis的日志和數…

OSI七層網絡模型詳解

OSI七層網絡模型詳解 OSI&#xff08;開放系統互連&#xff09;模型是國際標準化組織&#xff08;ISO&#xff09;提出的網絡通信框架&#xff0c;旨在規范不同系統間的通信。它分為七層&#xff0c;每層承擔特定功能&#xff0c;協同實現端到端的數據傳輸。 1. 物理層&#x…

Springboot 學習 之 logback-spring.xml 日志打印

文章目錄 1. property2. springProperty3. appender4. logger4.1. 通過包路徑控制日志4.2. 通過類名控制日志4.3. 按自定義 Logger 名稱控制日志 5. root6. springProfile SpringBoot 項目中可以通過自定義 logback-spring.xml 中各項配置&#xff0c;實現日志的打印控制 1. p…

Gradle與Idea整合

文章目錄 1. Groovy 簡介2. Groovy 安裝[非必須]3. 在idea中創建java工程 1. Groovy 簡介 在某種程度上&#xff0c;Groovy可以被視為Java的一種腳本化改良版,Groovy也是運行在JVM上&#xff0c;它可以很好地與Java代碼及其相關庫進行交互操作。它是一種成熟的面向對象編程語言…

OpenFeign終極指南:超時控制、重試策略、攔截器與自定義Starter

目錄 前言 使用 引入依賴 開啟feign 編寫feign客戶端 效果 日志 超時配置 重試機制 攔截器 Fallback兜底返回 引入依賴 編寫兜底實現 連接池 引入依賴 開啟連接池 制作OpenFeign Starter 編寫配置類 自動裝配 前言 在RPC框架中&#xff0c;有openFeign和Du…

Windows桌面圖標變白的解決方案

一、問題原因 桌面圖標變白通常是由于系統圖標緩存文件&#xff08;IconCache.db&#xff09;損壞或系統圖表示現異常導致。圖標緩存是Windows用于存儲應用程序和文件夾圖標圖像的臨時文件&#xff0c;當該文件損壞或系統未正確更新緩存時&#xff0c;圖標會因無法加載原始圖像…

【mysql】Mac 通過 brew 安裝 mysql 、啟動以及密碼設置

Mac 通過 brew 安裝 mysql 、啟動以及密碼設置 使用 brew 安裝 mysqlmysql 啟動mysql密碼設置參考文章&#xff1a; 使用 brew 安裝 mysql brew install mysqlmysql 啟動 下載完畢&#xff0c;終端告訴我們mysql數據庫沒有設置密碼的&#xff0c;我們可以直接執行 mysql -u r…

Manus AI:突破多語言手寫識別技術壁壘之路

Manus AI與多語言手寫識別 討論Manus AI如何突破多語言手寫識別的技術壁壘。 寫一篇詳細的博客有重點有鏈接超詳細 Manus AI&#xff1a;突破多語言手寫識別技術壁壘之路 在人工智能領域&#xff0c;多語言手寫識別一直是極具挑戰性的難題。不同語言的字符形態、書寫規則大相…

Redis字符串類型實戰:解鎖五大高頻應用場景

精心整理了最新的面試資料和簡歷模板&#xff0c;有需要的可以自行獲取 點擊前往百度網盤獲取 點擊前往夸克網盤獲取 Redis的字符串&#xff08;String&#xff09;類型是最基礎的數據結構&#xff0c;但其靈活性和原子性操作使其成為解決高并發場景問題的利器。本文通過真實項…

邊沿耦合與寬邊耦合的串擾

邊沿耦合與寬邊耦合的串擾 我們知道&#xff0c;如果兩條走線位于同一層&#xff0c;由于耦合兩條線之間會存在串擾。如果PCB層疊中有相鄰的信號層&#xff0c;那么同樣存在耦合&#xff0c;這兩個相鄰信號層的走線之間也會存在串擾。同層走線之間的耦合稱為邊沿耦合&#xff0…

B端可視化像企業數據的透視鏡,看清關鍵信息

在數字化時代&#xff0c;數據已成為企業最寶貴的資產之一。然而&#xff0c;數據的價值不僅取決于其數量&#xff0c;更在于企業能否快速、準確地提取關鍵信息并據此做出決策。B端可視化技術的出現&#xff0c;為企業提供了一種強大的工具&#xff0c;它如同企業的“透視鏡”&…

蒼穹外賣項目中所涉及到的測試內容

1.使用JWT令牌封裝用戶令牌&#xff0c;并且設置相應的攔截器校驗JWT的有效性&#xff0c;從而確保了項目的安全可靠 1.基本功能測試&#xff1a; 驗證合法JWT是否能夠正常通過攔截器的校驗 驗證非法的JWT能否正常通過攔截器的校驗 2.可靠性測試&#xff1a; 3.易用性測試 …

模擬投資大師思維:AI對沖基金開源項目詳解

這里寫目錄標題 引言項目概述核心功能詳解多樣化的AI投資智能體靈活的運行模式透明的決策過程 安裝和使用教程環境要求安裝步驟基本使用方法運行對沖基金模式運行回測模式 應用場景和實際價值教育和研究價值潛在的商業應用與現有解決方案的對比局限性與發展方向 結論 引言 隨著…

YOLO拓展-錨框(anchor box)詳解

一.錨框&#xff08;anchor box&#xff09;概述 1.1什么是錨框 錨框就是一種進行預測的像素框&#xff0c;通過遍歷輸入圖像上所有可能的像素框&#xff0c;然后選出正確的目標框&#xff0c;并對位置和大小進行調整就可以完成目標檢測任務。 對于yolo錨框的建設須基于實際…

Excel自定義函數取拼音首字母

1.啟動Excel 2003&#xff08;其它版本請仿照操作&#xff09;&#xff0c;打開相應的工作表&#xff1b; 2.執行“工具 > 宏 > Visual Basic編輯器”命令&#xff08;或者直接按“AltF11”組合鍵&#xff09;&#xff0c;進入Visual Basic編輯狀態&#xff1b; 3.執行“…