【LangChain4j快速入门】5分钟用Java接入AI大模型,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")
复制代码
如果你没有本身的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: AI
- ai:
- openai:
- api-key: "demo"
- base-url: "http://langchain4j.dev/demo/openai/v1"
复制代码 二、核心实现:3步构建AI谈天接口
2.1 模型设置(智能引擎)
- @Configuration
- public class LangChain4jConfig {
- @Bean
- public 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
- */
- @Bean
- public ChatMemory messageWindowChatMemory(ChatMemoryStore chatMemoryStore) {
- return MessageWindowChatMemory.builder()
- .id("session-1") // 会话 ID
- .maxMessages(10) // 最大消息数量
- .chatMemoryStore(chatMemoryStore) // 持久化存储
- .build();
- }
- /**
- * 定义一个简单的内存存储实现
- */
- @Bean
- public 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">
- <input
- v-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 {
- @Bean
- public 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
- */
- @Bean
- public ChatMemory messageWindowChatMemory(ChatMemoryStore chatMemoryStore) {
- return MessageWindowChatMemory.builder()
- .id("session-1") // 会话 ID
- .maxMessages(10) // 最大消息数量
- .chatMemoryStore(chatMemoryStore) // 持久化存储
- .build();
- }
- /**
- * 定义一个简单的内存存储实现
- */
- @Bean
- public 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());
- }
- }
复制代码
四、生产级优化发起
- 密钥安全:通过application.yml设置,制止硬编码
- langchain4j:
- openai:
- api-key: ${OPENAI_API_KEY}
复制代码 - 限流降级:集成Resilience4j实现请求限流
- 性能监控
:通过Micrometer对接Prometheus
- 上下文管理:利用PersistentChatMemory实现对话长期化
总结:为什么选择LangChain4j?
通过本文实战,我们体验到了:
✅ 极简集成:5行代码对接GPT-4o-mini
✅ 开箱即用:自动影象管理、流式相应支持
✅ 生态丰富:支持20+模型厂商,轻松切换
✅ Spring Boot友爱:自动设置+依靠注入
下一步探索:
- 实验AI服务(Assistant API)实现复杂逻辑
- 结合Embedding实现RAG知识库
- 利用Tools API让模型调用外部服务
立刻访问LangChain4j官网开启你的AI应用开辟之旅!如果你在实践过程中碰到任何题目,欢迎在品评区留言交换~
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
|