2025-07-13-Sun-T-AI-LangChain4j

news/2025/11/23 21:49:07/文章来源:https://www.cnblogs.com/fei1010/p/19261615

1. 认识AI

1.1 神经元

介绍

黑马LangChain4j入门到实战项目: 项目地址

软件架构

前端:

  • 静态页面

后端框架:

  • Springboot

  • Langchain4j + Ollama

持久化:

  • 本地文件存储对话记录 (resources/memory)
  • 用户预约信息存储在内存(map结构)
  • RAG向量存储在内存

1. 快速入门:Ollama本地部署大模型

  • 安装ollama

下载地址:Ollama

  • 运行阿里千问小小模型
ollama run qwen3:0.6b
  • POST请求ollama本地服务

参考Thinking · Ollama Blog

//http://localhost:11434/api/chat
{"model":"qwen3:0.6b","messages":[{"role":"system","content": "你是一个ai助手"},{"role": "user","content": "叫什么名字?什么是PEFT?"},{"role":"assistant","content" : "我是小小傻瓜蛋"}],"think":true,"stream":false
}

2. 整合spring-boot

2.1 引入ollama依赖

<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-ollama</artifactId><version>1.0.1-beta6</version>
</dependency>

2.2 配置模型

//Properties
package com.learning.langchain4j.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "ollama")
@Data
public class OllamaConfigProperties {private String modelName;private String baseUrl; // 本地 ollama 基础 URL
}
//Ollama 配置
package com.learning.langchain4j.config;import dev.langchain4j.model.ollama.OllamaChatModel;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.time.Duration;@Configuration
@EnableConfigurationProperties(OllamaConfigProperties.class)
public class OllamaConfig {@Beanpublic OllamaChatModel ollamaChatModel(OllamaConfigProperties ollamaConfigProperties){OllamaChatModel model = OllamaChatModel.builder().modelName(ollamaConfigProperties.getModelName()).baseUrl(ollamaConfigProperties.getBaseUrl()).timeout(Duration.ofSeconds(30)) // 超时时间.logRequests(true).logResponses(true).maxRetries(3) // 超时最大重试次数.build();return model;}}
# yaml
server:port: 8099
spring:application:name: ai-consultant
ollama:base-url:  http://localhost:11434model-name: qwen3:0.6b

2.3 编写controller

package com.learning.langchain4j;import dev.langchain4j.model.ollama.OllamaChatModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@Slf4j
public class ChatController {@Autowiredprivate OllamaChatModel ollamaChatModel;@RequestMapping("/chat")public String chat(String message) {log.info("用户: {}", message);return ollamaChatModel.generate(message);}
}

2.4 测试

http://localhost:8099/chat?message="你好"

3. 功能会话 AIServices

3. 1 引入依赖

<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-spring-boot-starter</artifactId><version>1.0.1-beta6</version>
</dependency>

3.2 Service 和Controller

// AiService
@AiService(chatModel = "ollamaChatModel",wiringMode = AiServiceWiringMode.EXPLICIT
)
public interface ConsultantService {// 用于聊天的方法,message为用户输入内容String chat(String message);
}// Controller
@Autowired
private ConsultantService consultantService;@RequestMapping("/streamChat")
public String streamChat(String message) {log.info("用户: {}", message);return consultantService.chat(message);
}

4. 流式调用

4.1 依赖

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-reactor</artifactId><version>1.0.1-beta6</version></dependency>

4.2 Config, Service, Controller

  • config
@Bean
public OllamaStreamingChatModel ollamaStreamingChatModel(OllamaConfigProperties ollamaConfigProperties){return OllamaStreamingChatModel.builder().modelName(ollamaConfigProperties.getModelName()).baseUrl(ollamaConfigProperties.getBaseUrl()).timeout(Duration.ofSeconds(ollamaConfigProperties.getTimeOut())) // 超时时间.logRequests(ollamaConfigProperties.getLogRequests()).logResponses(ollamaConfigProperties.getLogResponses()).build();
}
  • service
@AiService(chatModel = "ollamaChatModel",wiringMode = AiServiceWiringMode.EXPLICIT,streamingChatModel = "ollamaStreamingChatModel"
)
public interface ConsultantService {// 用于聊天的方法,message为用户输入内容Flux<String> chat(String message);
}
  • controller
    @Autowiredprivate ConsultantService consultantService;@RequestMapping(value = "/streamChat", produces = "text/html;charset=utf-8") // produces指定响应类型,解决响应乱码问题public Flux<String> streamChat(String message) {log.info("用户: {}", message);return consultantService.chat(message);}

5 消息会话

5.1 message注解

@AiService(chatModel = "ollamaChatModel",wiringMode = AiServiceWiringMode.EXPLICIT,streamingChatModel = "ollamaStreamingChatModel"
)
public interface ConsultantService {// 用于聊天的方法,message为用户输入内容@SystemMessage(fromResource = "system.txt")Flux<String> chat(String message);
}

5.2 会话记忆

  • config
    @Beanpublic ChatMemory chatMemory(OllamaConfigProperties ollamaConfigProperties){return MessageWindowChatMemory.builder().maxMessages(ollamaConfigProperties.getMaxMessages()).build();}
  • service
@AiService(chatModel = "ollamaChatModel",wiringMode = AiServiceWiringMode.EXPLICIT,streamingChatModel = "ollamaStreamingChatModel",chatMemory = "chatMemory"
)
public interface ConsultantService {// 用于聊天的方法,message为用户输入内容@SystemMessage(fromResource = "system.txt")Flux<String> chat(String message);
}

5.3 会话记忆隔离

  • config
    @Beanpublic ChatMemoryProvider chatMemoryProvider(OllamaConfigProperties ollamaConfigProperties){return new ChatMemoryProvider(){@Overridepublic ChatMemory get(Object o) {return MessageWindowChatMemory.builder().id(o).maxMessages(ollamaConfigProperties.getMaxMessages()).build();}};}
  • service
@AiService(chatModel = "ollamaChatModel",wiringMode = AiServiceWiringMode.EXPLICIT,streamingChatModel = "ollamaStreamingChatModel",chatMemoryProvider = "chatMemoryProvider"
)
public interface ConsultantService {// 用于聊天的方法,message为用户输入内容@SystemMessage(fromResource = "system.txt")Flux<String> chat(@MemoryId String memoryId, @UserMessage String message);
}
  • controller
    @RequestMapping(value = "/streamChat", produces = "text/html;charset=utf-8")public Flux<String> streamChat(String memoryId,String message) {log.info("用户: {}", message);return consultantService.chat(memoryId,message);}

5.4 数据持久化- 本地文件

  • repository
package com.learning.langchain4j.repository;import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.ChatMessageDeserializer;
import dev.langchain4j.data.message.ChatMessageSerializer;
import dev.langchain4j.store.memory.chat.ChatMemoryStore;
import org.springframework.stereotype.Repository;import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@Repository
public class MyChatMemoryStore implements ChatMemoryStore {// 存储路径:优先使用resource目录下的memory文件private static final Path STORAGE_PATH = Paths.get("src/main/resources/memory");private final Map<Object, String> memoryMap = new HashMap<>();public MyChatMemoryStore() {loadFromFile(); // 初始化时加载持久化数据}// 从文件加载会话记忆private synchronized void loadFromFile() {try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(STORAGE_PATH.toFile()))) {Map<Object, String> loadedMap = (Map<Object, String>) ois.readObject();memoryMap.putAll(loadedMap);} catch (FileNotFoundException e) {initStorageFile(); // 首次使用时创建文件} catch (IOException | ClassNotFoundException e) {throw new RuntimeException("Failed to load chat memory", e);}}// 初始化存储文件private void initStorageFile() {try {File file = STORAGE_PATH.toFile();if (!file.getParentFile().exists()) {file.getParentFile().mkdirs();}file.createNewFile();saveToFile(); // 创建空文件} catch (IOException e) {throw new RuntimeException("Failed to initialize storage file", e);}}// 保存会话记忆到文件private synchronized void saveToFile() {try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(STORAGE_PATH.toFile()))) {oos.writeObject(memoryMap);} catch (IOException e) {throw new RuntimeException("Failed to save chat memory", e);}}@Overridepublic List<ChatMessage> getMessages(Object memoryId) {String s = memoryMap.get(memoryId);List<ChatMessage> list = ChatMessageDeserializer.messagesFromJson(s);return list;}@Overridepublic void updateMessages(Object memoryId, List<ChatMessage> messages) {String s = ChatMessageSerializer.messagesToJson(messages);memoryMap.put(memoryId, s);saveToFile(); // 更新后立即持久化}@Overridepublic void deleteMessages(Object memoryId) {memoryMap.remove(memoryId);saveToFile(); // 删除后立即持久化}
}
  • config
@Bean
public ChatMemoryProvider chatMemoryProvider(OllamaConfigProperties ollamaConfigProperties,ChatMemoryStore myChatMemoryStore){return new ChatMemoryProvider(){@Overridepublic ChatMemory get(Object o) {return MessageWindowChatMemory.builder().id(o).maxMessages(ollamaConfigProperties.getMaxMessages()).chatMemoryStore(myChatMemoryStore).build();}};
}

6. RAG知识库

6.1 原理

  1. 知识文本通过向量模型转为向量
  2. 将向量和文本一一存储到向量数据库
  3. 用户输入时,先计算用户提问的文本对应的向量,然后再到向量数据库中去匹配,计算用户输入向量与数据库中向量余弦相似度
  4. 设定余弦相似度阈值,例如0.5,那么余弦相似度大于0.5的数据就会被提取出来,和用户提问数据一并交给大模型处理

6.2 快速入门

  • 引入依赖
    <!--RAG数据库相关依赖--><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-easy-rag</artifactId><version>1.0.1-beta6</version></dependency>
  • config
    /*** 加载文件进内存,当作RAG* @return*/@Beanpublic EmbeddingStore embeddingStore(){  // 出现重名需要重命名// 1.加载文件进内存,构建向量数据库操作对象List<Document> contents = ClassPathDocumentLoader.loadDocuments("content");InMemoryEmbeddingStore store = new InMemoryEmbeddingStore();  // 使用内存当作向量数据库// 文本切割,向量化EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder().embeddingStore(store).build();IngestionResult ingest = ingestor.ingest(contents);return store;}//构建向量数据库检索对象@Beanpublic ContentRetriever contentRetriever(EmbeddingStore embeddingStore){return EmbeddingStoreContentRetriever.builder().embeddingStore(embeddingStore).minScore(0.5).maxResults(3).build();}
  • service
@AiService(chatModel = "ollamaChatModel",wiringMode = AiServiceWiringMode.EXPLICIT,streamingChatModel = "ollamaStreamingChatModel",chatMemoryProvider = "chatMemoryProvider",contentRetriever = "contentRetriever" 
)
public interface ConsultantService {// 用于聊天的方法,message为用户输入内容@SystemMessage(fromResource = "system.txt")Flux<String> chat(@MemoryId String memoryId, @UserMessage String message);
}

6.3 核心API

1 内容加载

  • FileSystemDocumentLoader
  • ClassPathDocumentLoader
  • UrlDocumentLoader
  • ...

2 文本分割器

  • DocumentByParagraphSplitter 按照段落
  • DocumentByRegexSpliter 按照正则表达式分割
  • DocumentSplitters.recursive(...)(默认) 递归分割器,优先段落,再按照行,句子和词

3 配置自己想要的向量模型

具体操作:略,本项目采用内存向量数据库,理解即可

4 部署向量数据库

具体操作:略,本项目采用内存向量数据库,理解即可

常用向量数据库:

  • Milvus
  • Chroma
  • Pinecone
  • RedisSearch(Redis)
  • pgvector(PostgreSQL)

使用向量数据库流程

  1. 安装好向量数据库
  2. 引入maven依赖
  3. 配置向量数据库信息
  4. 注入向量数据库对象并引用

7. Tools

7.1 开发预约服务,可以读写mysql中预约表中的信息

具体操作:本项目采用Map作为数据库,理解即可

数据库准备:

  1. 准备数据库环境
  2. 引入依赖
  3. 配置连接信息
  4. 准备实体类
  5. 开发mapper
  6. 开发service
  7. 完成测试

7.2 原理

image-20250715183922428

7.3 实现

  1. 准备工具方法
  2. 配置工具方法

image-20250715184248004

  • tool配置
@Component
public class ReservationTool {@Autowiredprivate ReservationService reservationService;// 1. 工具:添加预约信息@Tool("预约志愿填报服务")public void addReservation(@P("考生姓名") String name,@P("考生性别") String gender,@P("考生电话") String phone,@P("会话时间") LocalDateTime communicationTime,@P("考生所在省份") String province,@P("考生预估分数") Integer estimateScore) {Reservation build = Reservation.builder().id(null).name(name).gender(gender).phone(phone).communicationTime(communicationTime).province(province).estimateScore(estimateScore).build();reservationService.insert(build);}// 2. 工具: 查询预约信息@Tool("根据用户手机号码查询预约单")public Reservation findReservation(@P("考生电话") String phone){return reservationService.findByPhone(phone);}
}
  • service 使用
@AiService(chatModel = "ollamaChatModel",wiringMode = AiServiceWiringMode.EXPLICIT,streamingChatModel = "ollamaStreamingChatModel",chatMemoryProvider = "chatMemoryProvider",contentRetriever = "contentRetriever",tools = {"reservationTool"}
)
public interface ConsultantService {// 用于聊天的方法,message为用户输入内容@SystemMessage(fromResource = "system.txt")Flux<String> chat(@MemoryId String memoryId, @UserMessage String message);
}

qwen3:0.6b似乎不能完成工具的调用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/974267.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P24_现有网络模型的使用及修改

P24_现有网络模型的使用及修改24.1 VGG16网络模型: (1)打开pytorch(0.9.0)—torchvision.models—VGG(2)参数点击查看代码 pretrained (bool) – If True, returns a model pre-trained on ImageNet progress (bo…

20232403 2025-2026-1 《网络与系统攻防技术》实验六实验报告

1.实验内容 主要内容:使用ARP扫描和nmap进行主机发现与端口扫描、Vsftpd后门漏洞获得root权限、Samba命令注入漏洞获取系统访问、Java RMI反序列化漏洞建立Meterpreter会话、PHP CGI参数注入漏洞。 掌握Metasploit命令…

第二讲类神经网络训练不起来

第二讲类神经网络训练不起来 一.优化失败的原因梯度为0有可能是local minima 和saddle point 因为计算优化的终止条件是梯度为0,但有可能梯度为0仅是局部最小值local minima或鞍点saddle point(多维,在某些维度是最…

【计算机网络】深入浅出DNS:网络世界的地址簿与导航系统 - 教程

【计算机网络】深入浅出DNS:网络世界的地址簿与导航系统 - 教程2025-11-23 21:39 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !imp…

2025-01-24-Fri-T-如何做一个开源项目

创建和维护一个开源项目是一个非常有意义的工作,它可以帮助你与全球开发者合作,同时建立个人或团队的影响力。以下是详细步骤,帮你从零开始创建一个成功的开源项目。 1. 确定项目目标 解决实际问题:选择一个对你或…

利用大语言模型分析技术支持诈骗Facebook群组的网络犯罪研究

本文介绍了一项利用大语言模型分析Facebook上技术支持诈骗群组的研究,涉及38万条帖子的分类分析,揭示了网络犯罪服务的运作模式和最新趋势。网络犯罪与刑罚:我们在APWG eCrimes会议上关于技术支持诈骗Facebook群组的…

一些唐话

学OI学的言论均为转载 不保证言论可读你干嘛直接放 *3500 啊?!正经比赛里不是这样的!你应该先放两个简单签到,然后提升我的心态。偶尔给我送送强点的大样例,然后在那个我上厕所的时候跟我有神秘互动。最后在某个我…

2025-05-29-Thu-T-设计模式

目录1. 设计模式相关内容介绍1.1 设计模式概述1.2 UML类图类的表示方式类之间的关系表示方法1.3 软件设计原则1.1 开闭原则1.2 里氏代换原则1.3 依赖倒转/依赖倒置原则1.4 接口隔离原则1.5 迪米特法则1.6 合成复用原则…

2025-05-27-Tue-T-JVM

目录1 JVM与Java体系结构1.1 JVM 结构简图1.2 Java代码执行流程1.3 JVM的架构模型1.4 JVM的生命周期一、内存结构1. 程序计数器2. 虚拟机栈2.1 定义2.2 栈内存溢出2.3 线程运行诊断3. 本地方法栈4. 堆4.1 定义4.2 堆内…

11-28

今日掌握了 HashMap 的常用方法(put ()、get ()、containsKey ()),理解了键的唯一性,学会了遍历 Map 集合的两种方式(keySet、entrySet)。 明日计划学习多线程编程,重点理解线程的概念、创建方式(继承 Thread …

20232421 2025-2026-1 《网络与系统攻防技术》实验六实验报告

1.实践内容前期渗透主机发现 端口扫描 选做:也可以扫系统版本、漏洞等。Vsftpd源码包后门漏洞(21端口) SambaMS-RPC Shell命令注入漏洞(139端口) Java RMI SERVER命令执行漏洞(1099端口) PHP CGI参数执行注入漏…

20232315 2025-2026-1 《网络与系统攻防技术》实验六实验报告

20232315 2025-2026-1 《网络与系统攻防技术》实验六实验报告20232315 2025-2026-1 《网络与系统攻防技术》实验六实验报告 目录一、实验基本信息二、实验内容及要求三、实验过程3.1 前期渗透3.2 漏洞利用四、问题及解…

[CISCN 2022 华东北]duck WP

[CISCN 2022 华东北]duck WP[CISCN 2022 华东北]duck 一、题目来源 NSSCTF-Pwn-[CISCN 2022 华东北]duck二、信息搜集 通过 file 命令查看文件类型:通过 checksec 命令查看文件开启的保护机制:题目把 libc 文件和链接…

20232320 2025-2026-1 《网络与系统攻防技术》实验六实验报告

1.实验内容 总结一下本周学习内容,不要复制粘贴 2.实验过程 (1)前期渗透 ①主机发现(可用Aux中的arp_sweep,search一下就可以use) ②端口扫描:可以直接用nmap,也可以用Aux中的portscan/tcp等。 ③选做:也可以…

2025-01-14-Tue-T-实体关系图ERD

实体关系图(ERD)指南 什么是实体关系图(ERD)? 数据库是软件系统中不可或缺的一个组成部分,若能在数据库工程中好好利用 ER 图,便能让您生成高质量的数据库设计,用于数据库创建,管理和维护,也为人员间的交流提供…

《Either Way》

누가 내 말투가 재수없대 有人说我语气很讨人厌 잘난 척만 한대 有人说我自以为是 또 누구는 내가 너무 착하대 还有人说是我太善良 바보같을 정도래 以至于像个傻瓜 가끔은 이해조차 안 되는 시선들 有些时候 被投来不…

20232424 2025-2026-1 《网络与系统攻防技术》实验六实验报告

20232424 2025-2026-1 《网络与系统攻防技术》实验六实验报告 1.实验内容 总结一下本周学习内容,不要复制粘贴 2.实验过程 3.问题及解决方案问题1:XXXXXX 问题1解决方案:XXXXXX 问题2:XXXXXX 问题2解决方案:XXXXX…

2024-11-26-Tue-T-SSM

SSM SSM三者的关系1 Spring IoC容器 父子工程 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w…

HTML游戏创建:利用视频作为特效自动播放的方法

HTML游戏创建:利用视频作为特效自动播放的方法pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

第四章-Tomcat线程模型与运行方式 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …