【LangChain4j快速入門】5分鐘用Java玩轉GPT-4o-mini,Spring Boot整合實戰!| 附源碼

【LangChain4j快速入門】5分鐘用Java玩轉GPT-4o-mini,Spring Boot整合實戰!

前言:當Java遇上大模型

在AI浪潮席卷全球的今天,Java開發者如何快速擁抱大語言模型?LangChain4j作為專為Java打造的AI開發框架,以極簡的API設計和強大的擴展能力,讓集成ChatGPT、GPT-4o-mini等模型變得異常輕松!本文將帶你通過實戰代碼+圖文詳解,5分鐘完成Spring Boot與GPT-4o-mini的對接,開啟你的AI應用開發之旅!


一、環境準備:閃電戰配置

1.1 添加關鍵依賴

在Spring Boot項目的pom.xml中加入LangChain4j核心庫與OpenAI擴展:

<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-open-ai</artifactId><version>1.0.0-beta3</version>
</dependency>
<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j</artifactId><version>1.0.0-beta3</version>
</dependency>

1.2 申請密鑰(零門檻!)

  • 正式環境:通過OpenAI平臺獲取API Key
  • 嘗鮮體驗:直接使用官方Demo Key(配額有限,僅支持gpt-4o-mini)
// 配置類中直接使用demo密鑰
.baseUrl("http://langchain4j.dev/demo/openai/v1")
.apiKey("demo")
  • ??如果你沒有API密鑰怎么辦?

如果你沒有自己的OpenAI API密鑰,別擔心。你可以臨時使用官方免費提供的演示密鑰,用于演示目的。請注意,當使用演示密鑰時,所有對OpenAI API的請求都需要通過官方的代理服務器,該代理會在將你的請求轉發給OpenAI API之前注入真實的密鑰。官方不會以任何方式收集或使用你的數據。演示密鑰有配額限制,僅限于gpt-4o-mini模型,并且只應用于演示目的。

OpenAiChatModel model = OpenAiChatModel.builder().baseUrl("http://langchain4j.dev/demo/openai/v1").apiKey("demo").modelName("gpt-4o-mini").build();

1.3配置application.yml

spring:application:name: AIai:openai:api-key: "demo"base-url: "http://langchain4j.dev/demo/openai/v1"

二、核心實現:3步構建AI聊天接口

2.1 模型配置(智能引擎)

@Configuration
public class LangChain4jConfig {@Beanpublic ChatLanguageModel chatLanguageModel() {return OpenAiChatModel.builder().baseUrl("http://langchain4j.dev/demo/openai/v1").apiKey("demo") // 替換為真實KEY時移除baseUrl.modelName("gpt-4o-mini") // 最新輕量級模型.build();}
}

關鍵點說明

  • baseUrl僅在使用Demo Key時需要
  • modelName指定模型版本,推薦性能優異的gpt-4o-mini

2.2 聊天控制器(對話大腦)

@RestController
@RequestMapping("/ai")
public class ChatController {private final ChatLanguageModel model;private final ChatMemory chatMemory; // 自動記憶上下文@GetMapping(value = "/chat", produces = "text/plain;charset=utf-8")public Mono<String> chat(@RequestParam String message) {UserMessage userMsg = UserMessage.from("你叫小智,是一個人工智能\n" + message);chatMemory.add(userMsg);AiMessage aiMsg = model.chat(chatMemory.messages()).aiMessage();chatMemory.add(aiMsg);return Mono.just(aiMsg.text());}
}
package org.example.ai.config;import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.store.memory.chat.ChatMemoryStore;
import dev.langchain4j.store.memory.chat.InMemoryChatMemoryStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class CommonConfiguration {/*** 定義一個基于消息數量限制的 ChatMemory Bean*/@Beanpublic ChatMemory messageWindowChatMemory(ChatMemoryStore chatMemoryStore) {return MessageWindowChatMemory.builder().id("session-1") // 會話 ID.maxMessages(10) // 最大消息數量.chatMemoryStore(chatMemoryStore) // 持久化存儲.build();}/*** 定義一個簡單的內存存儲實現*/@Beanpublic ChatMemoryStore inMemoryChatMemoryStore() {return new InMemoryChatMemoryStore();}
}

亮點功能

  • ChatMemory自動維護對話上下文
  • 強制UTF-8編碼解決中文亂碼
  • 響應式編程支持(Mono)

在這里插入圖片描述
在這里插入圖片描述

三、效果驗證:你的第一個AI接口

啟動應用后訪問:

http://localhost:8080/ai/chat?message=講個程序員笑話

預期響應

好的,主人!為什么程序員總把萬圣節和圣誕節搞混?
因為 Oct 31 == Dec 25!(Octal 31 = Decimal 25)

在這里插入圖片描述
加入前端代碼

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>小智AI助手</title><script src="https://unpkg.com/vue@3/dist/vue.global.js"></script><style>/* 現代聊天界面樣式 */:root {--primary: #4CAF50;--bg: #f5f5f5;--user-bg: #e3f2fd;--ai-bg: #ffffff;}body {margin: 0;font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;background: var(--bg);}.chat-container {max-width: 800px;margin: 20px auto;border-radius: 12px;box-shadow: 0 2px 15px rgba(0,0,0,0.1);background: white;height: 90vh;display: flex;flex-direction: column;}.messages {flex: 1;overflow-y: auto;padding: 20px;display: flex;flex-direction: column;gap: 15px;}.message {max-width: 70%;padding: 12px 16px;border-radius: 18px;animation: fadeIn 0.3s ease;}.user-message {background: var(--user-bg);align-self: flex-end;border-bottom-right-radius: 4px;}.ai-message {background: var(--ai-bg);align-self: flex-start;border-bottom-left-radius: 4px;box-shadow: 0 2px 4px rgba(0,0,0,0.05);}.loading-dots {display: inline-block;font-size: 24px;}.loading-dots::after {content: '...';animation: dots 1.5s infinite;}.input-area {padding: 20px;border-top: 1px solid #eee;display: flex;gap: 10px;}input {flex: 1;padding: 12px;border: 1px solid #ddd;border-radius: 25px;font-size: 16px;outline: none;transition: 0.3s;}input:focus {border-color: var(--primary);box-shadow: 0 0 0 3px rgba(76,175,80,0.1);}button {padding: 12px 24px;background: var(--primary);border: none;border-radius: 25px;color: white;cursor: pointer;transition: 0.3s;}button:disabled {opacity: 0.7;cursor: not-allowed;}@keyframes dots {0%, 20% { content: '.'; }40% { content: '..'; }60%, 100% { content: '...'; }}@keyframes fadeIn {from { opacity: 0; transform: translateY(10px); }to { opacity: 1; transform: translateY(0); }}</style>
</head>
<body>
<div id="app"><div class="chat-container"><div class="messages"><div v-for="(msg, index) in messages":key="index":class="['message', msg.role === 'user' ? 'user-message' : 'ai-message']">{{ msg.content }}</div><div v-if="loading" class="message ai-message"><span class="loading-dots"></span></div></div><div class="input-area"><inputv-model="inputMessage"@keyup.enter="sendMessage"placeholder="和小智聊天吧~":disabled="loading"><button @click="sendMessage" :disabled="!inputMessage || loading">{{ loading ? '思考中' : '發送' }}</button></div></div>
</div><script>const { createApp } = Vue;createApp({data() {return {messages: [],inputMessage: '',loading: false}},methods: {async sendMessage() {if (!this.inputMessage.trim() || this.loading) return;const userMessage = this.inputMessage;this.messages.push({ role: 'user', content: userMessage });this.inputMessage = '';this.loading = true;try {const response = await fetch(`/ai/chat?message=${encodeURIComponent(userMessage)}`);const text = await response.text();this.messages.push({ role: 'assistant', content: text });} catch (error) {this.messages.push({role: 'assistant',content: '哎呀,小智暫時無法連接,請稍后再試~'});} finally {this.loading = false;this.scrollToBottom();}},scrollToBottom() {this.$nextTick(() => {const container = document.querySelector('.messages');container.scrollTop = container.scrollHeight;});}},mounted() {// 初始歡迎語this.messages.push({role: 'assistant',content: '你好!我是小智,有什么可以幫您的?'});}}).mount('#app');
</script>
</body>
</html>

完整代碼

package org.example.ai.config;import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class LangChain4jConfig {@Beanpublic ChatLanguageModel chatLanguageModel() {return OpenAiChatModel.builder().baseUrl("http://langchain4j.dev/demo/openai/v1").apiKey("demo").modelName("gpt-4o-mini").build();}
}
package org.example.ai.config;import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.store.memory.chat.ChatMemoryStore;
import dev.langchain4j.store.memory.chat.InMemoryChatMemoryStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class CommonConfiguration {/*** 定義一個基于消息數量限制的 ChatMemory Bean*/@Beanpublic ChatMemory messageWindowChatMemory(ChatMemoryStore chatMemoryStore) {return MessageWindowChatMemory.builder().id("session-1") // 會話 ID.maxMessages(10) // 最大消息數量.chatMemoryStore(chatMemoryStore) // 持久化存儲.build();}/*** 定義一個簡單的內存存儲實現*/@Beanpublic ChatMemoryStore inMemoryChatMemoryStore() {return new InMemoryChatMemoryStore();}
}
package org.example.ai.controller;import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;@RestController
@RequestMapping("/ai")
@RequiredArgsConstructor
public class ChatController {private final ChatLanguageModel chatLanguageModel;private final ChatMemory chatMemory;@RequestMapping (value = "/chat", produces = "text/plain;charset=utf-8")public Mono<String> chat(@RequestParam(required = false, defaultValue = "") String message) {UserMessage userMessage = UserMessage.from("你叫小智,是一個人工智能\n" + message);chatMemory.add(userMessage);AiMessage aiMessage = chatLanguageModel.chat(chatMemory.messages()).aiMessage();chatMemory.add(aiMessage);return Mono.just(aiMessage.text());}
}

在這里插入圖片描述

四、生產級優化建議

  1. 密鑰安全:通過application.yml配置,避免硬編碼
    langchain4j:openai:api-key: ${OPENAI_API_KEY}
    
  2. 限流降級:集成Resilience4j實現請求限流
  3. 性能監控:通過Micrometer對接Prometheus
  4. 上下文管理:使用PersistentChatMemory實現對話持久化

總結:為什么選擇LangChain4j?

通過本文實戰,我們體驗到了:
? 極簡集成:5行代碼對接GPT-4o-mini
? 開箱即用:自動記憶管理、流式響應支持
? 生態豐富:支持20+模型廠商,輕松切換
? Spring Boot友好:自動配置+依賴注入

下一步探索

  • 嘗試AI服務(Assistant API)實現復雜邏輯
  • 結合Embedding實現RAG知識庫
  • 使用Tools API讓模型調用外部服務

立即訪問LangChain4j官網開啟你的AI應用開發之旅!如果你在實踐過程中遇到任何問題,歡迎在評論區留言交流~

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

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

相關文章

Vue 3 reactive 和 ref 區別及 失去響應性問題

在 Vue 3 中&#xff0c;reactive 和 ref 是實現響應式數據的兩個核心 API&#xff0c;它們的設計目標和使用場景有所不同。以下是兩者的詳細對比&#xff1a; 1. 基本定義與核心功能 特性reactiveref作用創建對象類型的響應式代理&#xff08;對象、數組、Map 等&#xff09…

第一節:Vben Admin 最新 v5.0初體驗

系列文章目錄 基礎篇 第一節&#xff1a;Vben Admin介紹和初次運行 第二節&#xff1a;Vben Admin 登錄邏輯梳理和對接后端準備 第三節&#xff1a;Vben Admin登錄對接后端login接口 第四節&#xff1a;Vben Admin登錄對接后端getUserInfo接口 第五節&#xff1a;Vben Admin權…

Nginx部署spa單頁面的小bug

沒部署過&#xff0c;都是給后端干的&#xff0c;自己嘗試部署了一個下午終于成功了 我遇到的最大的bug是進入后只有首頁正常顯示 其他頁面全是404&#xff0c;于是問問問才知道&#xff0c;需要這個 location / { try_files $uri $uri/ /index.html; } 讓…

面試算法高頻08-動態規劃-01

動態規劃 遞歸知識要點 遞歸代碼模板&#xff1a;提供遞歸代碼的標準形式public void recur(int level, int param) &#xff0c;包含終止條件&#xff08;if (level> MAX_LEVEL)&#xff09;、當前層邏輯處理&#xff08;process(level, param)&#xff09;、向下一層遞歸…

若依框架前后端分離版部署全流程詳解(本地+服務器+高級配置)

若依框架前后端分離版部署全流程詳解&#xff08;本地服務器高級配置&#xff09; 若依&#xff08;RuoYi&#xff09;作為一款基于SpringBoot和Vue的權限管理系統&#xff0c;憑借其模塊化設計和開箱即用的特性廣受開發者歡迎。本文將從本地部署、服務器部署、高級配置三個維…

醫療設備預測性維護合規架構:從法規遵循到技術實現的深度解析

在醫療行業數字化轉型加速推進的當下&#xff0c;醫療設備預測性維護已成為提升設備可用性、保障醫療安全的核心技術。然而&#xff0c;該技術的有效落地必須建立在嚴格的合規框架之上。醫療設備直接關乎患者生命健康&#xff0c;其維護過程涉及醫療法規、數據安全、質量管控等…

LLMs基礎學習(七)DeepSeek專題(4)

LLMs基礎學習&#xff08;七&#xff09;DeepSeek專題&#xff08;4&#xff09; 文章目錄 LLMs基礎學習&#xff08;七&#xff09;DeepSeek專題&#xff08;4&#xff09;DeepSeek-R1 訓練過程的四個階段具體流程小結 “規則化獎勵”具體原因小結 “自我認知”&#xff08;se…

SQL 速查手冊

前言&#xff1a;SQL&#xff08;Structured Query Language&#xff09;是用于管理關系型數據庫的標準語言&#xff0c;廣泛應用于數據查詢、更新、定義和管理等操作。本文將為你提供一份詳細的 SQL 速查手冊&#xff0c;涵蓋從基礎到高級的各種 SQL 操作&#xff0c;幫助你快…

IDEA 中 Scala 項目遠程連接虛擬機 Spark 環境

IDEA 中 Scala 項目遠程連接虛擬機 Spark 環境 1. 環境準備 確保虛擬機 Spark 環境正常運行 虛擬機中已安裝并啟動 Spark記錄虛擬機的 IP 地址和 Spark 端口&#xff08;默認 7077&#xff09;確保虛擬機防火墻允許相關端口訪問 本地 IDEA 環境配置 安裝 Scala 插件安裝 Spar…

.net core 項目快速接入Coze智能體-開箱即用-全局說明

目錄 一、Coze智能體的核心價值 二、開箱即用-效果如下 三 流程與交互設計 為什么要分析意圖&#xff0c;而不是全部交由AI處理。 四 接入前的準備工作 五&#xff1a;代碼實現----字節Coze 簽署 JWT和獲取Token .net core 項目快速接入Coze智能體-開箱即用 .net core快…

網店運營精細化突破新路徑

內容概要 電商戰場越來越卷&#xff0c;單純靠低價和流量轟炸已經玩不轉了。今天想要站穩腳跟&#xff0c;精細化運營才是破局密碼——從商品怎么選、用戶怎么留&#xff0c;到供應鏈怎么跑得更快&#xff0c;每個環節都得摳細節。比如用數據給選品“開天眼”&#xff0c;把用…

數據結構學習筆記 :線性表的鏈式存儲詳解

目錄 單鏈表 1.1 無頭單鏈表 1.2 有頭單鏈表單向循環鏈表雙鏈表 3.1 雙鏈表 3.2 雙向循環鏈表總結與對比 一、單鏈表 1. 無頭單鏈表&#xff08;Headless Singly Linked List&#xff09; 定義&#xff1a;鏈表無頭結點&#xff0c;直接由頭指針指向第一個數據節點。 特點&…

數據庫10(代碼相關語句)

while循環 declare avgprice numeric(10,2) set avgprice(select avg(price)from titles) //自定義參數 while avgprice<10 //循環條件 begin update titles set priceprice*1.1 end //循環語句操作&#xff0c;當avgprice<10,所有price都加0.1 case語句 查詢authors表…

Redis 下載與安裝(Windows版)

一、下載 1、redis官網&#xff1a; https://redis.io/downloads/ 2、Github下載地址&#xff1a; https://github.com/MicrosoftArchive/redis/releases 二、安裝 1、打開一個命令窗口&#xff0c;通過 cd 命令進入到你解壓的目錄 2、輸入命令 &#xff0c;啟動 Redis&…

在高數據速度下確保信號完整性的 10 個關鍵策略

隨著越來越多的傳感器連接到系統&#xff0c;需要快速、可靠和安全地傳輸更多數據&#xff0c;對帶寬和設計復雜性的需求也在增加。優先考慮的是確保從 A 發送到 B 的信號不會失真。 確保信號完整性 對于設計依賴于持續準確數據流的數據密集型應用程序的工程師來說&#xff0c…

NAT、代理服務、內網穿透

NAT、代理服務、內網穿透 1、NAT1.1、NAT過程1.2、NAPT2、內網穿透3、內網打洞3、代理服務器3.1、正向代理3.2、反向代理1、NAT 1.1、NAT過程 之前我們討論了IPv4協議中IP地址數量不充足的問題。NAT技術是當前解決IP地址不夠用的主要手段,是路由器的一個重要功能。 NAT能夠將…

利用互斥鎖或者利用邏輯過期解決緩存擊穿問題

緩存擊穿問題概述 緩存擊穿是指某個 熱點數據緩存過期 時&#xff0c;大量并發請求直接穿透緩存&#xff0c;同時訪問數據庫&#xff0c;導致數據庫壓力驟增甚至崩潰。以下是基于 互斥鎖 和 邏輯過期 的解決方案&#xff1a; 一、緩存擊穿的核心原因 熱點數據失效&#xff1a…

Vue3組合式API內核解析:從原子狀態到企業級架構

一、組合邏輯原子化設計 1.1 狀態管理層級拓撲 1.2 組合單元類型對照表 類型典型實現適用場景復用維度UI邏輯單元useForm/useTable表單/列表交互100%跨項目復用業務邏輯單元useOrderFlow訂單流程控制同項目跨模塊設備能力單元useGeolocation地理位置獲取跨技術棧復用狀態管理…

新生宿舍管理系統

收藏關注不迷路&#xff01;&#xff01; &#x1f31f;文末獲取源碼數據庫&#x1f31f; 感興趣的可以先收藏起來&#xff0c;還有大家在畢設選題&#xff08;免費咨詢指導選題&#xff09;&#xff0c;項目以及論文編寫等相關問題都可以給我留言咨詢&#xff0c;希望幫助更多…

從零上手GUI Guider學習LVGL——Button

視頻教程請關注我b站&#xff1a;同學_好好學習&#xff0c;這里只是做相應的筆記文稿 從零上手GUI Guider學習LVGL——Buttton 前言&#xff1a; 首先我們為什么要學習LVGL設計工具呢&#xff1f; 1 降低開發難度 2 提高開發效率 所以我們需要學習一款合適的設計工具 在b站很少…