LangChain4j 入门(二)
LangChain 整合 SpringBoot
下述代码均使用 阿里云百炼平台 提供的模型。
创建项目,引入依赖
- 通过
IDEA创建SpringBoot项目,并引入Spring Web依赖,SpringBoot推荐使用 3.x 版本。


- 引入 LangChain4j 和 WebFlux 依赖
<!--阿里云 DashScope API(通义大模型)的 Spring Boot Starter 依赖-->
<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId><version>1.0.0-beta2</version>
</dependency>
<!--LangChain4j 的核心库-->
<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j</artifactId><version>1.0.0-beta2</version>
</dependency>
<!--Spring WebFlux 依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
案例一 — 普通对话
该示例为整体返回,即等待模型回复完成后,一起进行返回。
- 配置 yaml
langchain4j:community:dashscope:chat-model:api-key: 个人 api-keymodel-name: qwen-max
- 创建
ChatController,并编写相关接口
@RestController
@RequestMapping("/chat")
public class ChatController {@Autowiredprivate ChatLanguageModel chatLanguageModel;@RequestMapping("/test1")public String test1(@RequestParam(defaultValue = "你好") String message) {String response = chatLanguageModel.chat(message);return response;}
}
- 测试接口响应
浏览器中访问:http://localhost:8080/chat/test1?message=你好,你是谁,如果有响应类似下述内容,则说明成功。

案例二 — 流式对话
上述示例用户体验并不好,本示例采用流式返回
- 配置 yaml
langchain4j:community:dashscope:streaming-chat-model:model-name: qwen-maxapi-key: 个人 api-key
- 编写相关接口
@Autowired
private StreamingChatLanguageModel streamingChatLanguageModel;// 指定 produces,否则会出现乱码情况
@RequestMapping(value = "/test2", produces = "text/stream;charset=UTF-8")
public Flux<String> test2(@RequestParam(defaultValue = "你好") String message) {Flux<String> flux = Flux.create(sink -> {streamingChatLanguageModel.chat(message, new StreamingChatResponseHandler() {@Overridepublic void onPartialResponse(String partialResponse) {sink.next(partialResponse);}@Overridepublic void onCompleteResponse(ChatResponse completeResponse) {sink.complete();}@Overridepublic void onError(Throwable error) {sink.error(error);}});});return flux;
}
- 测试接口响应
浏览器中访问:http://localhost:8080/chat/test2?message=你好,你是谁,如果有响应类似下述内容,则说明成功。
本案例与案例一的区别为输出方式不同,一种是整体输出,一种是流式输出。

案例三 — 图片生成
百炼平台提供500张图片的免费额度用于学习。
本案例采用同步的方式获取图片,也可以按照官方文档采用异步方式进行图片获取。
- 配置yaml
gen-img:api-key: 个人 api-keymodel-name: wanx2.1-t2i-turbo
- 配置
WanxImageModel,编写相关接口
@Configuration
public class AIConfig {@Value("${gen-img.api-key}")private String genImgApiKey;@Value("${gen-img.model-name}")private String genImgModelName;@Bean/*** 图片绘制模型*/public WanxImageModel wanxImageModel() {return WanxImageModel.builder().apiKey(genImgApiKey).modelName(genImgModelName).build();}
}
@Autowired
private WanxImageModel wanxImageModel;@RequestMapping("/test3")
public String test3(@RequestParam(defaultValue = "午后的公园") String message) {Response<Image> generate = wanxImageModel.generate(message);// 具体返回结构可查看官方定义,这里只获取图片的 urlreturn generate.content().url().toString();
}
- 测试接口响应
在浏览器中输入:http://localhost:8080/chat/test3?message=雨后的公园
下图中返回数据为生成图片的 url,使用浏览器访问该 url,可以在浏览器中下载生成后的图片。

生成的图片如下:

案例四 — 记忆对话
- 配置
AiService相关对象
// 定义聊天助手接口
public interface MyAssistant {String chat(String message);TokenStream stream(String message);
}@Bean
public MyAssistant assistant(ChatLanguageModel qwenChatModel, StreamingChatLanguageModel qwenStreamingChatModel) {MyAssistant assistant = AiServices.builder(MyAssistant.class).chatLanguageModel(qwenChatModel).streamingChatLanguageModel(qwenStreamingChatModel).chatMemory(MessageWindowChatMemory.withMaxMessages(20))// 自定义对话存储方式
// .chatMemoryProvider(memoryId -> MessageWindowChatMemory
// .builder()
// .chatMemoryStore(new ChatMemoryStore() {
// @Override
// public List<ChatMessage> getMessages(Object memoryId) {
// return null;
// }
//
// @Override
// public void updateMessages(Object memoryId, List<ChatMessage> messages) {
//
// }
//
// @Override
// public void deleteMessages(Object memoryId) {
//
// }
// }
// ).build()).build();return assistant;
}
- 编写接口,采用流式返回
@Autowired
private AIConfig.MyAssistant assistant;@RequestMapping(value = "/test4", produces = "text/stream;charset=UTF-8")
public Flux<String> test4(@RequestParam(defaultValue = "你好") String message) {TokenStream stream = assistant.stream(message);return Flux.create(sink -> {stream.onPartialResponse(sink::next).onCompleteResponse(c -> sink.complete()).onError(sink::error).start();});
}
- 测试接口响应
-
直接进行询问

-
通过接口给模型写入记忆

-
根据写入记忆,进行对话

-
上述聊天信息默认存储在内存中,程序重启后会丢失记忆,可以重写被注释掉的内容,将信息存储到 mysql、redis等存储容器中。
案例五 — 记忆对话,数据隔离
上述案例中,所有的问答都是混合到一起的,即 A 对模型输入的信息,B 也可以读取到,本案例将通过 memoryId 对记忆数据进行隔离。
- 配置
AiService相关对象
public interface MyAssistantIsolate {String chat(@MemoryId String memoryId, @UserMessage String message);TokenStream stream(@MemoryId String memoryId, @UserMessage String message);
}@Bean
public MyAssistantIsolate myAssistantMemory(ChatLanguageModel qwenChatModel, StreamingChatLanguageModel qwenStreamingChatModel) {ChatMemoryProvider chatMemoryProvider = memoryId -> MessageWindowChatMemory.builder().id(memoryId).maxMessages(20)// 自定义对话存储方式
// .chatMemoryStore(new ChatMemoryStore() {
// @Override
// public List<ChatMessage> getMessages(Object memoryId) {
// return null;
// }
//
// @Override
// public void updateMessages(Object memoryId, List<ChatMessage> messages) {
//
// }
//
// @Override
// public void deleteMessages(Object memoryId) {
//
// }
// }).build();MyAssistantIsolate assistant = AiServices.builder(MyAssistantIsolate.class).chatLanguageModel(qwenChatModel).streamingChatLanguageModel(qwenStreamingChatModel).chatMemoryProvider(chatMemoryProvider).build();return assistant;
}
- 编写接口
@Autowired
private AIConfig.MyAssistantIsolate myAssistantIsolate;@RequestMapping(value = "/test5", produces = "text/stream;charset=UTF-8")
// 通过不同的 memoryId 对记忆进行分割,memoryId 可以使用 userId 或 uuid
public Flux<String> test5(String memoryId, String message) {TokenStream stream = myAssistantIsolate.stream(memoryId, message);return Flux.create(sink -> {stream.onPartialResponse(sink::next).onCompleteResponse(c -> sink.complete()).onError(sink::error).start();});
}
- 测试接口响应
- 给 memoryId = 1,设置记忆信息

- 通过 memoryId = 1,查询记忆信息

- 通过 memoryId = 2,查询记忆信息

- 给 memoryId = 1,设置记忆信息
上述内容为 LangChain4j 整合 SpringBoot 的基本示例。
相关文章:
LangChain4j 入门(二)
LangChain 整合 SpringBoot 下述代码均使用 阿里云百炼平台 提供的模型。 创建项目,引入依赖 通过 IDEA 创建 SpringBoot 项目,并引入 Spring Web 依赖,SpringBoot 推荐使用 3.x 版本。 引入 LangChain4j 和 WebFlux 依赖 <!--阿里云 D…...
小智机器人关键函数解析:MqttProtocol::SendAudio()对输入的音频数据进行加密处理,通过UDP发送加密后的音频数据
MqttProtocol::SendAudio()对输入的音频数据进行加密处理,通过UDP发送加密后的音频数据。 源码: void MqttProtocol::SendAudio(const std::vector<uint8_t>& data) {// 使用互斥锁保护临界区,确保同一时间只有一个线程可以访问该…...
npm i 失败
当npm i 失败 且提示下面的错误 尝试降低npm 的版本 npm install npm6.14.15 -g...
音视频基础(音视频的录制和播放原理)
文章目录 一、录制原理**1. 音视频数据解析****2. 音频处理流程****3. 视频处理流程****4. 同步控制****5. 关键技术点****总结** 二、播放原理**1. 音视频数据解析****2. 音频处理流程****3. 视频处理流程****4. 同步控制****5. 关键技术点****总结** 一、录制原理 这张图展示…...
CoAP Shell 笔记
CoAP Shell 笔记 1. 概述 CoAP (Constrained Application Protocol) 是一种专为物联网 (IoT) 中资源受限的节点和网络设计的 RESTful Web 传输协议。CoAP Shell 是一个基于命令行的交互式工具,用于与支持 CoAP 的服务器进行交互。 2. 主要功能 协议支持ÿ…...
回溯(子集型):分割回文串
一、多维递归 -> 回溯 1.1:17. 电话号码的字母组合(力扣hot100) 代码: mapping ["","", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv&qu…...
2022年蓝桥杯第十三届CC++大学B组真题及代码
目录 1A:九进制转十进制 2B:顺子日期(存在争议) 3C:刷题统计 解析代码(模拟) 4D:修剪灌木 解析代码(找规律) 5E:X进制减法 解析代码1&…...
1.oracle修改配置文件
1.找到oracle的安装路径 D:\app\baozi\product\11.2.0\dbhome_1\NETWORK\ADMIN ,修改下面的两个文件。如果提示没有权限,可以先把这两个文件复制到桌面,修改完后,在复制回来。 2.查看自己电脑的主机名, 右击 - 此电脑 …...
通义万相2.1 你的视频创作之路
通义万相2.1的全面介绍 一、核心功能与技术特点 通义万相2.1是阿里巴巴达摩院研发的多模态生成式AI模型,以视频生成为核心,同时支持图像、3D内容及中英文文字特效生成。其核心能力包括: 复杂动作与物理规律建模 能够稳定生成包含人体旋转、…...
Muduo网络库实现 [四] - Channel模块
设计思路 具体来说每一个套接字都会对应一个 Channel 对象,用于对它的事件进行管理。可以对于描述符的监控事件在用户态更容易维护,以及触发事件后的操作流程更加的清晰 Channel模块是用于对一个描述符所需要监控的事件以及事件触发之后要执行的回调函…...
“自动驾驶背后的数学” 专栏导读
专栏链接: 自动驾驶背后的数学 专栏以“自动驾驶背后的数学”为主题,从基础到深入,再到实际应用和未来展望,全面解析自动驾驶技术中的数学原理。开篇用基础数学工具搭建自动驾驶的整体框架,吸引儿童培养兴趣࿰…...
XSS 攻击(详细)
目录 引言 一、XSS 攻击简介 二、XSS 攻击类型 1.反射型 XSS 2.存储型 XSS 3.基于 DOM 的 XSS 4.Self - XSS 三、XSS 攻击技巧 1.基本变形 2.事件处理程序 3.JS 伪协议 4.编码绕过 5.绕过长度限制 6.使用标签 四、XSS 攻击工具与平台 1.XSS 攻击平台 2.BEEF 五…...
K8s负载均衡全解析:从入门到实战的完整指南
Kubernetes(K8s)作为容器编排的标准,其负载均衡机制是构建高可用、高弹性应用的关键。本文将全面介绍K8s负载均衡的核心概念、实现方式及最佳实践,帮助开发者和运维人员构建稳定高效的云原生应用。 一、K8s负载均衡的基础概念 在Kubernetes生态系统中,负载均衡是指将工作负…...
《ZooKeeper Zab协议深度剖析:构建高可用分布式系统的基石》
《ZooKeeper Zab协议深度剖析:构建高可用分布式系统的基石》 一、分布式协调的挑战与ZooKeeper的解决方案 1.1 分布式系统一致性难题 #mermaid-svg-iigak7YlgEw7o6lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-sv…...
OpenCV 图形API(6)将一个矩阵(或图像)与一个标量值相加的函数addC()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 addC 函数将给定的标量值加到给定矩阵的每个元素上。该功能可以用矩阵表达式替换: dst src1 c \texttt{dst} \texttt{src1} \te…...
同步SVPWM调制策略的初步学习记录
最近项目需要用到一些同步调制SVPWM相关的内容(现在的我基本都是项目驱动了),因此对该内容进行一定的学习。 1 同步SVPWM调制的背景 我们熟知的一些知识是:SVPWM(空间矢量脉宽调制)是一种用于逆变器的调制…...
六十天Linux从0到项目搭建(第十五天)(程序替换、exec流程示意图、核心特性)
1 为什么要有程序替换? 程序替换(Process Replacement)是操作系统中一个关键机制,它的核心目的是:让一个正在运行的进程(通常是子进程)停止执行当前代码,转而加载并执行一个全新的程…...
排序算法3-交换排序
目录 1.常见排序算法 2.排序算法的预定函数 2.1交换函数 2.2测试算法运行时间的函数 2.3已经实现过的排序算法 3.交换排序的实现 3.1冒泡排序 3.2快速排序 3.2.1递归的快速排序 3.2.1.1hoare版本的排序 3.2.1.2挖坑法 3.2.1.3lomuto前后指针法 3.2.2非递归版本的快…...
【Qt】数据库管理
数据库查询工具开发学习笔记 一、项目背景与目标 背景:频繁编写数据库查询语句,希望通过工具简化操作,提升效率。 二、总体设计思路 1. 架构设计 MVC模式:通过Qt控件实现视图(UI),业务逻辑…...
Ant Design Vue 中的table表格高度塌陷,造成行与行不齐的问题
前言: Ant Design Vue: 1.7.2 Vue2 less 问题描述: 在通过下拉框选择之后,在获取接口数据,第一列使用了fixed:left,就碰到了高度塌陷,查看元素的样式结果高度不一致,如&#x…...
面经-项目
项目 项目(重点)问题1:描述在网页中题目点击提交后到题目结果出现的一系列后台反应【1】如何获取到用户提交的代码的?【2】_1. 题目细节都有哪些?【2】_2. 题目信息怎么存储的?【3】负载均衡算法的实现?【4】oj_server怎么连接对应的compile_server(编译主机)的?【5】oj_…...
Win10安装Linux的三种方法
通过 Windows 子系统 for Linux(WSL)安装 启用 “适用于 Linux 的 Windows 子系统” 可选功能: 图形界面方式:在【设置 -> 更新与安全 -> 开发者选项】中开启【开发人员模式】;在【程序和功能 -> 启用或关闭…...
【qt】文件类(QFile)
很高兴你能看到这篇文章,同时我的语雀文档也更新了许多嵌入式系列的学习笔记希望能帮到你 : https://www.yuque.com/alive-m4b9n 目录 QFile 主要功能QFile 操作步骤QFile 其他常用函数案例分析及实现功能一实现:打开文件并显示功能二实现:另…...
力扣hot100——最长连续序列(哈希unordered_set)
题目链接:最长连续序列 1、错解:数组做哈希表(内存超出限制) int longestConsecutive(vector<int>& nums) {vector<bool> hash(20000000010, false);for(int i0; i<nums.size();i){hash[1000000000nums[i]]t…...
3. 实战(一):Spring AI Trae ,助力开发微信小程序
1、前言 前面介绍了Spring boot快速集成Spring AI实现简单的Chat聊天模式。今天立马来实战一番,通过Trae这个火爆全网的工具,来写一个微信小程序。照理说,我们只是极少量的编码应该就可以完成这项工作。开撸~ 2、需求描述 微信小程序实现一…...
MySQL高级语句深度解析与应用实践
一、窗口函数:数据分析的利器 1. 窗口函数基础概念 窗口函数(Window Function)是MySQL 8.0引入的强大特性,它可以在不减少行数的情况下对数据进行聚合计算和分析 SELECT employee_name,department,salary,RANK() OVER (PARTITION BY department ORDER…...
SSE服务器主动推送至浏览器客户端,让你不再需要websocket
Server-Sent Events(SSE)是一种服务器向客户端推送实时更新的技术,基于HTTP协议。客户端通过EventSource API来接收事件流,而服务器则保持一个长连接,持续发送数据。这与传统的请求-响应模式不同,允许服务器…...
UE5新材质系统效果Demo展示
1、玉质材质,透明玻璃材质,不同透射和散射。 2、浅水地面,地面层,水层,地面湿度,水面高度,水下扰动,水下浇洒,水下折射 Substrate-Water Substrate-Water-CodeV2...
wps 怎么显示隐藏文字
wps 怎么显示隐藏文字 》文件》选项》视图》勾选“隐藏文字” wps怎么设置隐藏文字 wps怎么设置隐藏文字...
解决 macOS (M1 Pro) 上使用 Vite 进行 Build 打包时 Node 进程内存溢出的问题
解决 macOS (M1 Pro) 上使用 Vite 进行 Build 打包时 Node 进程内存溢出的问题 在搭载 M1 Pro 芯片的 macOS 系统上,使用 Vite 进行项目构建(build)时,您可能会遇到 Node 进程内存溢出的错误。特别是在使用较新版本的 Node.js&am…...
