【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的功能
项目实战放在下一篇文章中
相关文章:
【langchain4j】Springboot如何接入大模型以及实战开发-AI问答助手(一)
langchain4j介绍 官网地址:https://docs.langchain4j.dev/get-started langchain4j可以说是java和spring的关系,spring让我们开发java应用非常简单,那么langchain4j对应的就是java开发ai的 “Spring” 他集成了AI应用的多种场景,…...
解决Windows update服务启动拒绝访问的问题 | wuauserv 注册表拒绝访问的方法
在某些情况下,为了配置系统更新相关服务(例如禁用 Windows 自动更新),我们需要更改注册表中 wuauserv 项的权限。本教程将带你一步步操作,成功获取并修改权限。 修改注册表路径: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\wuauserv 步骤一:打开注册表编辑…...
精益数据分析(5/126):解锁创业成功的关键密码
精益数据分析(5/126):解锁创业成功的关键密码 大家好!我一直坚信在技术与商业不断融合的当下,持续学习是保持进步的唯一途径。之前我们一起探讨了《精益数据分析》的部分内容,今天咱们接着深入学习&#x…...
Cribl 优化EC2 ip-host-region 数据
We’ve seen examples of using the magical powers of regex to customize Functions, extract fields, and filter events in real time. In this section, we’ll show you how to sprinkle your Lookups with regex magic. Lets walk through a Pipeline that demonstrates…...
【java实现+4种变体完整例子】排序算法中【桶排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格
以下是桶排序的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格: 一、桶排序基础实现 原理 将数据分到有限数量的桶中,每个桶内部使用其他排序算法(如插入排序或快速排序)…...
栈(c++)
今天介绍两种在c中写“栈”方法 1. #include <bits/stdc.h> using namespace std;class mystack { private:int a[1000];int curr -1; public:void push(int);void pop();int top();bool empyt();int size(); };int main() {mystack n;while(true){int a;cout<<&…...
GraphRAG与RAG的区别和原理简介
第一章 图谱与向量的共生逻辑 1.1 知识载体的局限性 向量空间模型虽能高效捕捉文本语义相似性,却无法解析知识的深层关联。例如,当用户询问“特斯拉4680电池与续航里程的关系”,向量检索可能仅返回技术参数片段,而无法解释化学成…...
vue2技术练习-开发了一个宠物相关的前端静态商城网站-宠物商城网站
为了尽快学习掌握相关的前端技术,最近又实用 vue2做了一个宠物行业的前端静态网站商城。还是先给大家看一下相关的网站效果: 所以大家如果想快速的学习或者掌握一门编程语言,最好的方案就是通过学习了基础编程知识后,就开始利用…...
[每周一更]-(第140期):sync.Pool 使用详解:性能优化的利器
文章目录 一、什么是 sync.Pool?二、sync.Pool 的基本作用三、sync.Pool 的主要方法四、sync.Pool 的内部工作原理五、sync.Pool 适用场景六、使用示例示例 1:基本使用输出示例:示例 2:并发使用 七、一个基于 sync.Pool 的 **Benc…...
Prompt-Tuning 提示词微调
1. Hard Prompt 定义: Hard prompt 是一种更为具体和明确的提示,要求模型按照给定的信息生成精确的结果,通常用于需要模型提供准确答案的任务. 原理: Prompt Tuning原理如下图所示:冻结主模型全部参数,在…...
sqli-labs之Less-7 GET注入写shell
验证注入点:单引号报错,)) 根据提示,是想让我们试试写shell 第一个条件 secure_file_priv 写shell即MySQL需要对外写文件,但默认MySQL是不允许outfile来导出数据的,先动手在MySQL确认一下。 MySQL特性,se…...
数据库基础-B+树
查询类型 全表扫描,不提供索引,扫描所有集合中的数据。根据指定key值查询指定点范围查询,在指定区间内查询 有很多方法能够进行快速扫面数据,但是再快复杂度也是O(N),我们的目标是想办法将查询复杂度降低到O(logN)。…...
智能语音备忘录:SpeechRecognition与gTTS的奇妙融合
引言:智能语音备忘录的时代已经到来 在这个信息爆炸的时代,我们每天需要处理大量的事务和信息。传统的文字记录方式虽然可靠,但在效率上往往难以满足快节奏生活的需求。想象一下,如果你能在驾车、散步或是灵感突现的任何时刻&…...
C++项目 —— 基于多设计模式下的同步异步日志系统(3)(日志器类)
C项目 —— 基于多设计模式下的同步&异步日志系统(3)(日志器类) 整体思想设计日志消息的构造C语言式的不定参函数的作用函数的具体实现逻辑1. 日志等级检查2. 初始化可变参数列表3. 格式化日志消息4. 释放参数列表5. 序列化和…...
2025/4/19 数据库的流程控制函数
单行函数_流程函数 要点: 流程处理函数可以根据不同的条件 执行不同的处理流程 可以在SQL语句中实现不同的条件选择,MySQL中的流程处理函数主要包括if() ifnull() 和 case() 函数 多行函数_聚合函数 和单行函数的区别: 单行函数是作用在每一行 最终结果可能是多行结果 多行…...
代码随想录打家劫舍+树形DP入门
动态规划part07 198.打家劫舍 视频讲解:https://www.bilibili.com/video/BV1Te411N7SX https://programmercarl.com/0198.%E6%89%93%E5%AE%B6%E5%8A%AB%E8%88%8D.html dp数组:进入房屋i能够偷得得最大金额dp[i]递推公式:根据不相邻原则…...
Http基础
目录 定义 一、请求部分(Request) 1. 请求行(Request Line) 常见请求方法: 2. 请求头(Request Headers) 3. 请求体(Request Body) 二、响应部分(Respo…...
【Unity】bug记录——部分物体突然不受animator控制
博主烘焙完灯光后突然发现有的物体的动画失效了,不会动,测试发现是因为勾了static(但是有些勾了static的物体就没事),修改static为Contribute GI Static(只针对光照静态)就行...
Zephyr、FreeRTOS、RT-Thread 邮箱(Mailbox)对比分析
一、核心特性对比 特性ZephyrFreeRTOSRT-Thread消息类型支持指针或4字节数据(依赖架构)仅支持指针传递支持任意数据类型(需指定消息长度)容量固定容量(静态初始化配置)动态容量(基于队列长度&a…...
xilinx fpga中pll与mmcm的区别
Xilinx中的PLL(锁相环)和MMCM(混合模式时钟管理器)都是用于时钟管理的关键组件,但它们之间存在一些显著的区别。以下是对两者的详细比较: 1. 功能特性 PLL(锁相环): 主…...
Python语法系列博客 · 第8期[特殊字符] Lambda函数与高阶函数:函数式编程初体验
上一期小练习解答(第7期回顾) ✅ 练习1:找出1~100中能被3或5整除的数 result [x for x in range(1, 101) if x % 3 0 or x % 5 0]✅ 练习2:生成字符串长度字典 words ["apple", "banana", "grape…...
黑马商城(五)微服务保护和分布式事务
一、雪崩问题 二、雪崩-解决方案(服务保护方案) 请求限流: 线程隔离: 服务熔断: 服务保护组件: 三、Sentinel 引入依赖: <!--sentinel--> <dependency><groupId>com.aliba…...
Java 编译与反编译深度解析
Java 编译与反编译深度解析 1. 编译过程详解 (1) 完整编译流程 .java 文件 → 词法分析 → 语法分析 → 语义分析 → 字节码生成 → .class 文件│ │ │ │↓ ↓ ↓ ↓识别关键字 生成抽象语法树 类型…...
Java集合框架中的List、Map、Set详解
在Java开发中,集合框架是处理数据时不可或缺的工具之一。今天,我们来深入了解一下Java集合框架中的List、Map和Set,并探讨它们的常见方法操作。 目录 一、List集合 1.1 List集合介绍 1.2 List集合的常见方法 添加元素 获取元素 修改元素…...
国产的 Java Solon v3.2.0 发布(央企信创的优选)
Solon 框架! Solon 是新一代,Java 企业级应用开发框架。从零开始构建(No Java-EE),有灵活的接口规范与开放生态。采用商用友好的 Apache 2.0 开源协议,是“杭州无耳科技有限公司”开源的根级项目ÿ…...
机器学习决策树
一、何为决策树 决策树(Decision Tree)是一种分类和回归方法,是基于各种情况发生的所需条件构成决策树,以实现期望最大化的一种图解法。由于这种决策分支画成图形很像一棵树的枝干,故称决策树。它的运行机制非常通俗易…...
Java集合及面试题学习
知识来源沉默王二、小林coding、javaguide 1、ArrayList list.add("66") list.get(2) list.remove(1) list.set(1,"55") List<String> listnew ArrayList<>(); 底层是动态数组 添加元素流程:判断是否扩容…...
【内置函数】84个Python内置函数全整理
Python 内置函数全集(完整分类 参数详解 示例) 文章目录 Python 内置函数全集(完整分类 参数详解 示例)一、数值与数学函数abs(x)divmod(a, b)pow(x, y, modNone)round(number[, ndigits])sum(iterable, /, start0)hash(obj) …...
【LeetCode 热题 100】双指针 系列
📁283. 移动零 对于该题目,需要注意的是两个地方,一是保持非零元素的相对顺序,以及O(1)的空间复杂度。 采用双指针的思路,将数组划分成3个区间,。 [0 , left]:该区间内元素全是非零元素。 [left1 , right…...
实现批量图片文字识别(python+flask+EasyOCR)
话不多说,向上效果图 1)先说框架版本 为什么要先说框架版本呢,因为我在各种版本中尝试了两天,总算确定了如下版本适合我,至于其他的版本,各位自己去尝试 python 3.9.7 EasyOCR 1.7.2 flask 3.0.3 2)执行操作效果图 2.1)多选文件 2.2)图片预览 2.3)提取选中文件 2.4)提取所有文…...
[Swift]pod install成功后运行项目报错问题error: Sandbox: bash(84760) deny(1)
操作: platform :ios, 14.0target ZKMKAPP do# Comment the next line if you dont want to use dynamic frameworksuse_frameworks!# Pods for ZKMKAPPpod Moyaend pod install成功后运行报错 报错: error: Sandbox: bash(84760) deny(1) file-writ…...
文档内容提取以及合成
如何从10个左右的docx文档中抽取内容,生成新的文档,抽取内容包括源文档的文字内容、图片、表格、公式等,以及目标文档的样式排版、字体、格式,还有目标文档的语言风格、用词规范、文法习惯等等。这是一个相当复杂的需求࿰…...
[Windows] Wireshark 网络抓包工具 v4.4.6
[Windows] Wireshark 网络抓包工具 链接:https://pan.xunlei.com/s/VOODTZ7Lm2gsNLoFNcOIqflzA1?pwdf3ea# 软件说明Wireshark(前称Ethereal)是一款免费开源的网络嗅探抓包东西,世界上最流行的网络协议剖析器!网络封…...
在Ubuntu中安装hadoop的详细过程
在Ubuntu中安装hadoop的详细过程 请自行安装Ubuntu系统(可参考:在VMWare中安装Linux虚拟机Ubuntu) 一、创建hadoop用户 如果在安装 Ubuntu 的时候不是用的 “hadoop” 用户,这时需要增加一个名为 hadoop 的用户。 首先打开终端…...
NOIP2017提高组.列队
目录 *数据结构模板题目算法标签: 模拟, 线段树, 线段树动态开点, 树状数组, 平衡树思路*前置代码完整注释代码精简注释代码 *数据结构模板 题目 530. 列队 算法标签: 模拟, 线段树, 线段树动态开点, 树状数组, 平衡树 思路 首先考虑简单情况, 如果只有一行, 删除一个位置…...
PSN港服跳过生日找回密码(需要英语对话,需要注册的id)
登陆这个网站 https://www.playstation.com/en-hk/support/contact-us/?categoryAcc&subCategorypw 随便输入点名字 firstname 跟lastname 勾选,然后打开机器人聊天 然后按照提示输入邮箱跟id,输入正确之后会分配真人客服 真人客服会要求提供第一次…...
服务治理-服务注册
一个服务在真实项目部署的时候,如果压力较大,会做多实例部署。 在IDEA里面做多实例部署的话,只需要配置多个启动项。...
Jinja2模板引擎SSTI漏洞
1. 引入 再研究大模型相关应用的漏洞CVE-2025-25362时(参考1),看到作者给了比较详细的分析(参考2)。下面对这个漏洞做个介绍。 2. 漏洞类型 这个漏洞属于CWE-1336,它主要关注在使用模板引擎进行脚本化处…...
STM32单片机教程:从零开始打造智能天气时钟
STM32单片机教程:从零开始打造智能天气时钟 大家好!今天我想为大家详细介绍一下我们的STM32课程,以及如何从零基础逐步掌握单片机开发技能,最终实现一个完整的智能天气时钟项目。 课程面向人群 本课程主要面向那些已经通过野火…...
c++_csp-j算法 (1)
DFS搜索(深度优先搜索) 讲解 第一部分:DFS搜索算法简介 深度优先搜索(Depth-First Search,DFS)是一种常用的图搜索算法,用于遍历或搜索图或树的所有节点。DFS算法的核心思想是尽可能深地搜索图的分支,直…...
word选中所有的表格——宏
Sub 选中所有表格()Dim aTable As TableApplication.ScreenUpdating FalseActiveDocument.DeleteAllEditableRanges wdEditorEveryoneFor Each aTable In ActiveDocument.TablesaTable.Range.Editors.Add wdEditorEveryoneNextActiveDocument.SelectAllEditableRanges wdEdito…...
16、堆基础知识点和priority_queue的模拟实现
一、priority_queue的使用方法 priority_queue的使用方法看这篇文章 二、堆 1、介绍 堆(Heap)是一种特殊的完全二叉树数据结构,满足以下性质: 堆序性质(Heap Property): 大顶堆(…...
20250419将405的机芯由4LANE的LVDS OUT配置为8LANE的步骤
20250419将405的机芯由4LANE的LVDS OUT配置为8LANE的步骤 2025/4/19 15:38 查询格式YUV/RGB 81 09 04 24 60 FF 90 50 00 00 FF 查询辨率帧率 81 09 04 24 72 FF 90 50 01 03 FF 查询LVDS mode : Singel output/Dual output 81 09 04 24 74 FF 90 50 00 00 FF 配置405的机…...
【信息系统项目管理师】高分论文:论信息系统项目的采购管理(信息化办公系统)
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 论文1、规划采购管理2、实施采购3、管理采购论文 随着信息化技术的发展,从企业到政府,传统的办公模式正在悄然消失,信息化办公模式正成为主流。特别是国务院印发的《关于加快推广“互联网+政务服务”工作的…...
国产GPU生态现状评估:从寒武纪到壁仞的编程适配挑战
近年来,国产GPU厂商在硬件性能上持续突破,但软件生态的构建仍面临严峻挑战。本文以寒武纪、壁仞等代表性企业为例,对比分析其与CUDA生态的兼容性差异,并探讨技术突围路径。 一、编程适配的核心挑战 编程模型差异与开发成本 …...
Linux(autoDL云服务器)mamba-ssm环境安装——一次成功!
1.创建环境选择torch2.0, cuda11.8,python3.8 2.从GitHub官网下载cp38对应的,causl_conv1d,和mamba-ssm2.2.2。下载入下图所示。 3.直接用finalshell 或者xshell连接服务器上传,到根目录下面。 直接用pip install *…...
手搓LeNet-5(基础模型)实现交通标志识别
手搓LeNet-5(基础模型)实现交通标志识别 一、环境准备1. 安装Python环境2. 安装CUDA(可选,仅需GPU加速时)3. 配置虚拟环境4. 安装PyTorch核心库5. 安装辅助库6. 验证安装7. 准备数据集8.常见问题处理 二、 数据集处理三…...
TV主板的拆解学习
下面是小米的电视机主板,电源采用PFCLLC方案,主控采用电视盒子主控采用晶晨半导体T962-H,搭配2G南亚DDR3L内存和8G三星eMMC存储器。 本文用来加深对TV主板的认识,学习于充电头网,链接在文末。 两颗蓝色插件Y电容来自S…...
PH热榜 | 2025-04-19
1. Omakase.ai Voice 标语:你的语音驱动销售助手。一个链接。 介绍:Omakase.ai Voice将您的网站转变为一个语音驱动的销售助手,它可以在客户浏览时进行对话、倾听并给出推荐。聊天机器人往往效果不佳——它们无法实现销售,而这个…...
LeetCode(Hot.2)—— 49.字符异位词分组题解
Problem: 49. 字母异位词分组 字母异位词的定义是:两个单词的字母组成一样,但顺序可以不同,比如 eat、tea 和 ate 就是一个组的。 思路 将每个字符串按字母排序,把排序后的字符串作为 key,相同 key 的放在一个 list 中…...