探索大模型世界_什么是大模型

大模型(Large Model),通常是指参数量非常庞大的深度学习模型,特别是在自然语言处理(NLP)、计算机视觉(CV)等领域中,模型参数数量达到数十亿甚至数千亿的规模。
大模型的特点

特点
- 庞大的参数量
- 海量的数据训练
- 强大的计算能力

大模型的分类

- 语言大模型:专注于解析和理解文本
- 视觉大模型:擅长图像识别和分析
- 多模态大模型:则能够综合处理包括文本、图像和音频在内的多种数据类型
按照应用领域的不同,大模型主要可以分为 L0、L1、L2 三个层级

L0(高中生):通用模型,知识面广,但不够深入,能做基础工作。
L1(大学生):行业模型,针对某个领域有深入理解,能解决更复杂的问题,但还有限制。
L2(研究生):垂直模型,专注于一个领域,深度专业,能够处理高难度、细节化的问题。
大语言模型LLM的应用场景
-
智能客服与聊天机器人
-
内容创作与生成
-
翻译与多语言处理
-
文档摘要与信息提取
-
搜索与推荐系统
-
情感分析与情感计算
-
代码自动化与开发辅助
探索大模型世界_AI会替代程序员吗
替代的是搜索引擎不是程序员
编程的魅力:不仅仅是写代码
无法被 AI 取代的部分,主要有几方面:
- 需要大量沟通理解的领域模型和业务逻辑,我们不能指望 AI 和人聊后,把业务逻辑梳理清楚。
- 对可用性质量要求比较高的部分,例如调度系统、中间件、存储核心系统。
- 其实也就是暗含在 2 中的,就是逻辑极度复杂的场景,短期模型能力好像还不够。
复杂绕口的业务逻辑:
其中用户首先需要通过多重身份验证访问一个分层的决策树。每个节点代表不同的决策路径,取决于用户的历史行为、实时数据分析和外部市场波动。例如,如果用户在节点A选择了路径1,系统需要立即调用一个外部API获取实时数据,然后根据该数据及用户的地理位置、时间戳和最近的购买历史,再决定是否允许其进入节点B。若进入,节点B的逻辑会涉及到与供应链管理系统的交互,以实时调整产品可用性,进而影响下一步的推荐算法,从而实现个性化推荐,最终将用户引导至一个动态生成的、可能与其过往行为完全无关的新产品展示界面。这一过程必须在毫秒级响应内完成,以保证用户体验的流畅性。
探索大模型世界_Java AI 开发工具
为了弥补Java开发者在AI领域的工具短板,市面上已经出现了几款针对Java的AI开发工具。
LangChain4J
- 提供标准化API,支持超过15个主流大模型提供商和嵌入存储,
- 提供工具箱,从低级提示词模板到高级AI服务,适合构建聊天机器人和检索增强生成(RAG)管道。
- 社区支持活跃,能够快速整合最新的AI技术,便于Java开发者将AI功能集成到现有项目中。
Spring Al
- 深度集成到Spring框架中,Java开发者可以轻松将AI功能嵌入到现有Spring项目中。
- 尽管Spring Al仍处于发展阶段,尚未发布正式版本,但其凭借Spring生态系统,具备了极强的扩展性和集成能力。
Spring AI Alibaba
- 提供多种大模型服务对接能力,包括主流开源与阿里云通义大模型服务(百炼)等
- 支持的模型类型包括聊天、文生图、音频转录、文生语音等

对比
| LangChain4J | Spring AI | Spring AI Alibaba | |
|---|---|---|---|
| 功能成熟度 | 功能全面,适合大规模AI应用 | 发展中,功能有待完善 | 功能全面,适合大规模AI应用 |
| 集成能力 | 支持多种LLM和嵌入存储,适合多样化场景 | 集成到Spring项目中,扩展性强 | 集成到Spring项目中,扩展性强 |
| 社区支持 | 社区活跃,反馈迅速 | 项目正在成长,API变更较大 | 社区活跃 |
| 兼容性 | Java8 + | Java17 + SpringBoot3 | JDK 要求 17 及以上版本 |
Java AI 开发工具_介绍LangChain4j

介绍
LangChain4j 是一个专为Java开发者设计的开源库,旨在简化将大型语言模型(LLM)集成到Java应用程序中的过程。它于2023年初开发,灵感来源于Python和JavaScript的LLM库,特别是为了填补Java领域在这一方面的空白。
LangChain4j 的核心功能
- 统一API:LangChain4j 提供统一 API,避免了学习和实现每个 API 的特定 API。
- 全面的工具箱:该框架包含多种工具,从低级的提示模板、聊天记忆管理到高级模式(如AI服务和RAG)。
- 大量的示例:LangChain4j提供大量的使用示例,与 Quarkus 和 Spring Boot 的集成等。
能干什么
- 集成了 15+个 语言大模型 15+ LLM providers
- 集成了 15+个 向量数据库 15+ embedding (vector) stores
- 集成了 10+个 嵌入模型 10+ embedding models
- 集成了 4个 图片大模型 4 cloud and local image generation models
- 集成了 2个 评分重排名模型 2 scoring (re-ranking) models
- 集成 1个 OpenAI 审核模型(检测prompt与响应是否有有害内容)
- 支持文本和图像作为输入(多模态)
- 更高层次的抽象,针对复杂的场景更方便集成。 AI Services
- 支持提示词模板、聊天记忆、聊天持久化、聊天记忆淘汰算法(消息窗口和令牌窗口) chat memory
- 支持同步/流式响应,支持常见 Java 类型和自定义 POJO 的输出解析器
- 支持工具(函数调用)Tools (function calling), 动态工具(执行动态生成LLM的代码)
- 支持检索增强生成技术 RAG (Retrieval-Augmented-Generation)

LangChain4j支持的LLMs

Java AI 开发工具_Langchain4j入门示例
介绍
如何通过低级 API 接入阿里百炼平台的通义模型 qwen-max。通过使用 LangChain4j 框架,开发者可以轻松调用该模型并集成到 Java 应用中。

Maven 依赖配置
首先,需要在项目中引入以下 Maven 依赖,用于集成 LangChain4j 与 DashScope:
XML
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<!-- 加载bom 后,所有langchain4j引用不需要加版本号 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-bom</artifactId>
<version>0.35.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
YML 配置文件
在项目的 application.yml 中设置所使用的通义模型 qwen-max,以下是示例配置:
XML
langchain4j:
open-ai:
chat-model:
# 课程测试 KEY,需要更换为实际可用 KEY
api-key: sk-xx
model-name: qwen-xxx
# 百炼兼容OpenAI接口规范,base_url为https://dashscope.aliyuncs.com/compatible-mode/v1
base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
代码实现
使用以下代码,快速启动一个基于 LangChain4j 和 Spring Boot 的 Java 应用,集成并调用阿里百炼平台的通义大语言模型。
java
/**
* 用于处理与通义模型的交互请求测试。
*/
@RestController
public class ChatController {
@Autowired
private ChatLanguageModel chatLanguageModel;
/**
* 聊天
* @param message
* @return
*/
@GetMapping("/ai/generate")
public String testChat(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message){
String generate = chatLanguageModel.generate(message);
return generate;
}
}
Java AI 开发工具_LangChain4j 高级API
创建子项目模块
创建子模块langchain4j_chatapi

Maven 依赖配置
在pom.xml中添加以下依赖:
XML
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
配置模型元信息
新建LLMConfig文件,配置 ChatLanguageModel 提供模型元信息。
java
@Bean
public ChatLanguageModel chatLanguageModel() {
return OpenAiChatModel.builder()
.apiKey(System.getenv("DASHSCOPE_KEY"))
.modelName("qwen-turbo")
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
.build();
}
编写控制器
java
@RestController
public class ChatController {
@Autowired
ChatLanguageModel chatLanguageModel;
@GetMapping("/ai/generate")
public String testChat(String msg){
String generate = chatLanguageModel.generate(msg);
System.out.println(generate);
return generate;
}
}
Java AI 开发工具__LangChain4j 高级LLM API
为了简化开发,LangChain4j提供了高层API,使开发者能够更专注于业务逻辑,而无需关注底层实现细节。高层API中,AiService 用于定义一个集成大模型的服务。
定义AI Service
java
/**
* AI 助手接口
*/
public interface ChatAssistant {
/**
* 聊天
* @param message
* @return {@link String}
*/
String chat(String message);
}
注入模型
java
/**
* 大模型配置
*/
@Configuration(proxyBeanMethods = false)
public class LLMConfig
{
@Bean
public ChatLanguageModel chatLanguageModel() {
return OpenAiChatModel.builder()
// .apiKey(System.getenv("sk-46aeef92a70d4a86bc04e6c9d04d9db1"))
.apiKey("sk-46aeef92a70d4a86bc04e6c9d04d9db1")
.modelName("qwen-plus")
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
.build();
}
@Bean
public ChatAssistant chatAssistant() {
return AiServices.builder(ChatAssistant.class)
.chatLanguageModel(chatLanguageModel())
.build();
}
}
测试功能
java
@RestController
public class ChatController {
@Autowired
private ChatAssistant chatAssistant;
/**
* 测试高级LLM API
* @param msg
* @return
*/
@GetMapping("/ai/chatassistant")
public String testChat2(String msg){
String response = chatAssistant.chat(msg);
return response;
}
}
Java AI 开发工具_LangChain4j日志配置
日志配置 (Logging)
LangChain4j 使用 SLF4J 作为日志接口,支持集成各种日志后端,如 Logback 或 Log4j。
Spring Boot 环境
在 Spring Boot 集成时,可以通过 application.yml 文件配置日志级别:
langchain4j.open-ai.chat-model.log-requests = true
langchain4j.open-ai.chat-model.log-responses = true
logging.level.dev.langchain4j = DEBUG
logging.level.dev.ai4j.openai4j = DEBUG
监控
LangChain4j 提供了一些语言模型(如 ChatLanguageModel 和 StreamingChatLanguageModel),支持通过 ChatModelListener 监听以下事件:
- 请求到达 LLM
- LLM 返回的响应
- 错误处理
事件监听:
java
package com.itbaizhan.config;
import dev.langchain4j.model.chat.listener.*;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
/**
* 测试大模型调用监听器
*/
@Slf4j
public class TestChatModelListener implements ChatModelListener {
@Override
public void onRequest(ChatModelRequestContext requestContext) {
ChatModelRequest request = requestContext.request();
Map<Object, Object> attributes = requestContext.attributes();
log.info("请求参数:{}", requestContext);
}
@Override
public void onResponse(ChatModelResponseContext responseContext) {
ChatModelResponse response = responseContext.response();
ChatModelRequest request = responseContext.request();
Map<Object, Object> attributes = responseContext.attributes();
log.info("返回结果:{}", attributes);
}
@Override
public void onError(ChatModelErrorContext errorContext) {
Throwable error = errorContext.error();
ChatModelRequest request = errorContext.request();
ChatModelResponse partialResponse = errorContext.partialResponse();
Map<Object, Object> attributes = errorContext.attributes();
// 记录错误
log.error("请求异常:{}", errorContext);
}
}
重试机制 (Retry Configuration)
LangChain4j 支持重试配置,可用于处理失败的请求。可以通过 maxRetries 来配置重试逻辑,指定重试次数和延迟等参数:
ChatLanguageModel model = OpenAiChatModel.builder()
.maxRetries(5) // 设置重试策略
.build();
超时配置 (Timeout Configuration)
对于超时配置,可以通过 timeout 设置请求的超时时间:
ChatLanguageModel model = OpenAiChatModel.builder()
.timeout(Duration.ofSeconds(10)) // 设置10秒超时
.build();
最终配置
java
package com.itbaizhan.config;
import com.itbaizhan.service.ChatAssistant;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.Duration;
import java.util.List;
/**
* 大模型配置
*/
@Configuration(proxyBeanMethods = false)
public class LLMConfig
{
@Bean
public ChatLanguageModel chatLanguageModel() {
return OpenAiChatModel.builder()
.apiKey("sk-46aeef92a70d4a86bc04e6c9d04d9db1")
.logRequests(true)
.logResponses(true)
// 设置重试策略
.maxRetries(1)
//设置10秒超时
.timeout(Duration.ofSeconds(100))
.listeners(List.of(new TestChatModelListener()))
.modelName("qwen-plus")
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
.build();
}
@Bean
public ChatAssistant chatAssistant() {
return AiServices.builder(ChatAssistant.class)
.chatLanguageModel(chatLanguageModel())
.build();
}
}
Java AI 开发工具_流式输出

介绍
LLM 每次生成一个标记,因此许多 LLM 提供商都提供逐个标记流式传输响应的方法,而不是等待生成整个文本。这显著改善了用户体验,因为用户无需等待未知的时间,几乎可以立即开始阅读响应。
流式响应处理
StreamingResponseHandler 接口流式响应的关键接口是 StreamingResponseHandler。它允许开发者定义在响应生成过程中的各个事件的处理逻辑。
Maven 依赖配置
XML
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-reactor</artifactId>
<version>0.35.0</version>
</dependency>
</dependencies>
编写配置文件
流式要使用到:StreamingChatLanguageModel和OpenAiStreamingChatModel
java
package com.itbaizhan.config;
import com.itbaizhan.service.ChatAssistant;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.StreamingChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import dev.langchain4j.service.AiServices;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.Duration;
/**
* 大模型配置
*/
@Configuration(proxyBeanMethods = false)
public class LLMConfig
{
@Bean
public ChatLanguageModel chatLanguageModel() {
return OpenAiChatModel.builder()
.apiKey("sk-xxxxxx")
.modelName("qwen-plus")
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
.build();
}
/**
* 流返回
* @return
*/
@Bean
public StreamingChatLanguageModel streamingChatLanguageModel(){
return OpenAiStreamingChatModel.builder()
.apiKey("sk-xxxxxx")
.modelName("qwen-plus")
.timeout(Duration.ofSeconds(10))
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
.build();
}
@Bean
public ChatAssistant chatAssistant(StreamingChatLanguageModel streamingChatLanguageModel){
return AiServices.create(ChatAssistant.class, streamingChatLanguageModel);
}
}
定义AI Service(返回值要使用Flux<>)
java
/**
* @author itbaizhan
*/
public interface ChatAssistant {
/**
* 聊天
*
* @param message 消息
* @return {@link Flux }<{@link String }>
*/
Flux<String> chat(String message);
}
编写控制层代码
java
@RestController
public class ChatController {
@Autowired
private ChatAssistant chatAssistant;
/**
* 聊天
* @param message 内容
* @return
*/
@GetMapping("/ai/generate")
public Flux<String> chat(@RequestParam("message") String message) {
return chatAssistant.chat(message);
}
}
Java AI 开发工具_视觉理解
创建子模块
langchain-4j_image

Maven依赖
XML
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
构建大模型客户端
java
@Bean
public ChatLanguageModel chatLanguageModel() {
return OpenAiChatModel.builder()
.apiKey(System.getenv("DASHSCOPE_KEY"))
.modelName("qwen-vl-max") // 设置使用的模型名称
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
.build();
}
构建 ImageController
java
/**
* 视觉理解示例 - 通过Dashscope进行图像分析
*/
@RestController
public class ImageController {
@Autowired
private ChatLanguageModel chatLanguageModel;
/**
* 视觉理解
* @param msg
* @param file
* @return
* @throws IOException
*/
@PostMapping("/identify")
public String chatLanguageModel(String msg,MultipartFile file) throws IOException {
InputStream inputStream = file.getInputStream();//得到输入流
byte[] byteArray = inputStream.readAllBytes();//转为byte数组
String encodeToString = Base64.getEncoder().encodeToString(byteArray);//再转为Base64 //也可以传入其他的
UserMessage userMessage = UserMessage.from(
TextContent.from(msg),
ImageContent.from(encodeToString, "https://www.itbaizhan.com/wiki/image/png")
);//使用UserMessage来传入参数
Response<AiMessage> response = chatLanguageModel.generate(userMessage);
return response.content().text();
}
}
编写配置application
设置文件上传最大值
java
spring:
servlet:
multipart:
max-file-size: 5MB
max-request-size: 5MB
测试

Java AI 开发工具_文生图
创建子模块
langchain4j-05-generateimage

智谱生成apikey

然后使用的是ImageModel来使用的

Java AI 开发工具_ChatMemory聊天记忆

为什么需要ChatMemory
实现聊天记忆实现起来非常简单,就是把用户所有的提问、大模型回答/产生的内容,放在一个List<ChatMessage>中,随着用户提问将List一并发送给大模型,让大模型具备了聊天记忆功能。
问题:
- 随着提问不断增多,上下文会变的很长,很快超出大模型的上下文token限制。
- 如果多人同时使用大模型,如何隔离不同用户的上下文信息。
手动维护和管理 ChatMessage 很麻烦。因此,LangChain4j 提供了一个 ChatMemory 抽象以及多个开箱即用的实现。ChatMemory 可以用作独立的低级组件,也可以用作高级组件(如 AI Services)的一部分。
ChatMemory实现什么能力
- 容器管理机制,充当ChatMessage容器,对ChatMessage进行管理。
- 淘汰机制(Eviction policy),为保证ChatMessage不会过多。
- 持久化机制(Persistence),防止聊天上下文丢失的问题。
- 消息特殊处理机制 SystemMessage特殊处理。 函数调用返回消息特殊处理。
淘汰机制(Eviction policy)
- 适应 LLM的上下文窗口: 一次LLM可以处理的token数量是有上限的。
- 控制成本: 每个token都有成本,这使得每次调用LLM越来越昂贵。逐出不必要的token可降低成本。
- 控制延迟: 发送到 LLM的token越多,处理它们所需的时间就越多。
实现流程

流程:
- 用户发起提示词 prompt 提问;
- 根据chatMemoryId 查询历史回话,并返回;
- 通过提示词模板将 prompt 和 history messages 组合成一个提示词发送给大模型;
- 大模型根据提示词进行回答,将prompt + AiMessages同时放入到ChatMemory中;
- 最后将大模型生成的结果返回给用户
Java AI 开发工具_ChatMemory聊天记忆实现
创建子模块
创建子模块langchain4j-chatmemory

Maven依赖
XML
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
Ai Services 定义
java
public interface ChatAssistant {
/**
* 聊天
*
* @param userId 用户 ID (根据ID隔离记忆)
* @param message 消息
* @return {@link String }
* 前面参数前的注解也是必须要加上的
*/
String chat(@MemoryId Long userId, @UserMessage String message);
}
编写配置文件生成元数据信息
java
@Configuration(proxyBeanMethods = false)
public class LLMConfig {
@Bean
public ChatLanguageModel chatLanguageModel() {
return OpenAiChatModel.builder()
.apiKey(System.getenv("DASHSCOPE_KEY"))
.modelName("qwen-long") // 设置使用的模型名称
.logRequests(true)
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
.build();
}
@Bean
public AiAssistant aiAssistant(ChatLanguageModel chatLanguageModel) {
return AiServices.builder(AiAssistant.class)
.chatLanguageModel(chatLanguageModel)
//这里是使用了chatMemory的生产者去使用一个类似于滑动窗口的 也就是使用最近的10条消息
.chatMemoryProvider(memoryId -> MessageWindowChatMemory.withMaxMessages(10))
.build()
;
}
}
编写控制层
java
@RestController
public class ChatMemoryController {
@Autowired
private AiAssistant aiAssistant;
/**
* 聊天记忆练习
* @return
*/
@GetMapping("/chat")
public String chat(){
aiAssistant.chat(1L, "你好!我的名字是小王");
aiAssistant.chat(2L, "你好!我的名字是小刘");
String chat = aiAssistant.chat(2L, "我的名字是什么");
return chat;
}
}
Java AI 开发工具_ChatMemory聊天记忆自定义持久化-MapDB嵌入数据库

MapDB简介
MapDB是一个轻量级的Java嵌入式数据库引擎,它支持在JVM中直接运行,无需外部服务器。MapDB提供了基于磁盘或堆外存储的并发的Maps、Sets、Lists、Queues等数据结构,使得开发者可以像使用Java集合一样轻松地使用MapDB。此外,MapDB还支持ACID事务、MVCC(多版本并发控制)等特性,确保数据的完整性和一致性。
MapDB的特点
- 高性能:MapDB经过优化和重写,性能出色,可以在多核环境中实现线性扩展。
- 轻量级:MapDB的jar包体积较小,且没有其他依赖项,非常适合嵌入式系统或内存数据库的应用场景。
- 易用性:MapDB提供了基于Java集合的API,使得开发者可以轻松地进行数据存储和检索操作。
- ACID事务支持:MapDB支持ACID事务,确保数据的一致性和隔离性。
- 模块化设计:MapDB采用模块化的架构设计,易于扩展和定制。
如何引入 MapDB
要开始使用 MapDB,首先需要将其添加到你的项目中。如果你使用的是 Maven,可以在项目的 pom.xml 文件中添加以下依赖:
XML
<dependency>
<groupId>org.mapdb</groupId>
<artifactId>mapdb</artifactId>
<version>3.0.10</version>
</dependency>
MapDB 使用示例
1、简单的键值存储与检索
MapDB 提供了简单的键值存储机制,类似于 Java 的 HashMap。下面是一个基本的示例,展示如何创建一个数据库,添加、检索和删除记录。
java
import org.mapdb.*;
public class MapDBExample {
public static void main(String[] args) {
// 创建或打开一个DB文件
File dbFile = new File("mydb");
DB db = DBMaker.newFileDB(dbFile)
.make();
// 创建一个HashMap并设置名称
ConcurrentHashMap<String, String> map = db.getHashMap("myMap");
// 在Map中存储数据
map.put("key1", "value1");
map.put("key2", "value2");
// 提交事务以确保数据被持久化到磁盘
db.commit();
// 关闭数据库连接
db.close();
// 重新打开数据库以检索数据
db = DBMaker.newFileDB(dbFile)
.make();
// 从Map中检索数据
String value1 = map.get("key1");
String value2 = map.get("key2");
System.out.println("Value for key1: " + value1);
System.out.println("Value for key2: " + value2);
// 关闭数据库连接
db.close();
}
}
Java AI 开发工具_ChatMemory聊天记忆自定义持久化实现
自定义持久化
java
/**
* 自定义的持久化聊天存储器
*/
public class PersistentChatMemoryStore implements ChatMemoryStore {
private final DB db = DBMaker.fileDB("./chat-memory1.db").transactionEnable().make();
private final Map<Integer, String> map = db.hashMap("messages", INTEGER, STRING).createOrOpen();
@Override
public List<ChatMessage> getMessages(Object memoryId) {
String json = map.get((int) memoryId);
return messagesFromJson(json);
}
@Override
public void updateMessages(Object memoryId, List<ChatMessage> messages) {
String json = messagesToJson(messages);
map.put((int) memoryId, json);
db.commit();
}
@Override
public void deleteMessages(Object memoryId) {
map.remove((int) memoryId);
db.commit();
}
}
配置元信息
java
/**
* ai 配置
*/
@Configuration
public class ChatConfig {
/**
* 流返回
* @return
*/
@Bean
public StreamingChatLanguageModel streamingChatLanguageModel(){
return OpenAiStreamingChatModel.builder()
.apiKey("sk-46aeef92a70d4a86bc04e6c9d04d9db1")
.modelName("qwen-max")
.timeout(Duration.ofSeconds(10))
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
.build();
}
@Bean
public ChatMemoryProvider chatMemoryProvider() {
return memoryId -> MessageWindowChatMemory.builder()
// 设置消息窗口 ID
.id(memoryId)
// 设置消息最大条数,默认为 10
.maxMessages(10)
.chatMemoryStore(chatMemoryStore())
.build();
}
@Bean
public ChatMemoryStore chatMemoryStore() {
return new PersistentChatMemoryStore();
}
@Bean
public Assistant chatAssistant(StreamingChatLanguageModel streamingChatLanguageModel){
return AiServices.builder(Assistant.class)
.streamingChatLanguageModel( streamingChatLanguageModel )
.chatMemoryProvider(memoryId -> MessageWindowChatMemory.withMaxMessages(10))
.build();
}
}
Java AI 开发工具_prompt提示词工程重要性

什么是提示词
当我们想用大语言模型开发具有独特功能的产品时,通常需要通过提示词模板让大语言模型显示出独特的技能。
创作提示词的万能模板
掌握提示词,是用好AI的关键!
- Role:分析用户的Prompt,思考最适合扮演的1个或多个角色,该角色是这个领域最资深的专家,也最适合解决问题。 - Background:分析用户的Prompt,思考用户为什么会提出这个问题,陈述用户提出这个问题的原因、背景、上下文。 - Profile:基于这个新提示词应扮演的角色,描述该角色,以及该角色的特征和属性。 - Skills:考虑到这个提示词中应扮演的角色,思考完成任务所需的关键能力。 - Goals:分析这个新提示词角色应当扮演的部分,考虑用户希望通过这个新提示词实现的目标任务。思考哪些任务列表,如果被完成,就能够针对性地解决用户面临的问题。 - Constrains:若适用,基于此prompt扮演的角色,思考该角色应该遵守的规则,确保角色能够出色的完成任务。 - OutputFormat:若适用,预想生成的内容形式,考虑输出应采取何种格式。 -Workflow:若适用,基于此扮演的角色,拆解该角色执行任务时的工作流,生成不低于3个步骤 -Examples:若适用,给出几个例子作为few-shots -Initalization:基于此扮演的角色,给出一个初始化的欢迎语和使用引导
问题
相信很多自媒体创作者都有个头疼的问题,就是觉得自己的文章明明内容做的很好,为什么浏览量和传播量这么低呢?


如果你去看那些10W+的文章,内容好是一部分,但是人家的标题也起得是真好啊!有种看见了不点进去心里就吃亏的感觉!所以,这里确定的需求就是为文章取爆款标题。
创作爆款标题Prompt
这里有个小技巧,就是我们需要让AI 把我们的需求用提示词模板的框架表述出来,所以在这里刚开始的时候,需要为AI赋予一个角色,那就是提示词工程师,让它知道自己的任务是什么。
所以,我设计的提示词如下:
你是一位提示词工程师,你需要根据我提供的内容1,按照提示词模板,为我生成可重复使用的“文章爆款标题大师”结构化提示词。 这是内容1: --- 你是一位公众号爆款标题创作大师,你创作了无数吸引眼球的爆款标题,用户一旦看见你的标题一定会阅读文章。 --- 这是提示词模板: --- #Role:[请填写你想定义的角色名称] ##Profile: -Author:itbaizhan -Version:0.1 -Language:中文 - Description:[你是一名[角色名称],具有[核心能力]。擅长[核心方法],能够帮助用户[用户需求]。在[专业细节]方面有深入的了解,能够[具体细节],尽量50字以内] ##Background: [请描述角色的背景信息,例如其历史、来源或特定的知识背景] ##Preferences: [请描述角色的偏好或特定风格,例如对某种设计或文化的偏好] ##Goals: [请列出该角色的主要目标1] [请列出该角色的主要目标2] ... ##Constrains: [请列出该角色在互动中必须遵循的限制条件1] [请列出该角色在互动中必须遵循的限制条件2] ... ##Skills: [为了在限制条件下实现目标,该角色需要拥有的技能1] [为了在限制条件下实现目标,该角色需要拥有的技能2] ... ##Examples: [提供一个输出示例1,展示角色的可能回答或行为] [提供一个输出示例2] ... ##OutputFormat: [请描述该角色的工作流程的第一步] [请描述该角色的工作流程的第二步] ... ## Initialization :作为[角色名称], 拥有[技能], 严格遵守[限制条件], 使用[选择语言]与用户对话,友好的欢迎用户,并提示用户输入。 ---
测试:
这里打开ChatGPT进行测试,当然,这样生成的提示词只是初稿,我们还需要进行优化。AI可以完成80%的工作,剩下的20%需要我们自己完成,毕竟AI只是辅助,我们才是最终决策者。
通过你给出的提示词,我发现了以下问题: --- 一.在Examples里,示例标题太过简短,且没有说明为什么好的原因,所以我提供了一些标题,供你参考,在下次迭代提示词时加入。 1、制造反差。 人类的大脑对于反差的信息会更加关注。 范例:我被裁员了,但我更快乐了。 2、巧用数字。 数字标题给人清晰、具体、易操作的感觉,能快速吸引读者的注意力 范例:父母做到这3点,孩子更自信。 3、制造悬念。 就像没有人不爱看悬疑小说一样,悬念能够很好的激发好奇心。 范例:看了这本书以后,90后的我彻底不想奋斗了 4、名人效应。 名人之所以是名人,就是因为他们自带流量,适当蹭一蹭,可以提升你的打开率。 范例:马云,刘强东都在用的时间管理方法! 5、提出痛点问题。 范例:那些喜欢熬夜的人,多久会死? --- 二、在Outputformat里,只需要第一步引导输入主题或者关键词即可,然后第二步输出10个符合要求的爆款标题 --- 三、在Initialization里,只需要说“作为[Role],仅输出“你好,我是:公众号爆款标题创作大师,请告诉我文章主题或者关键词,我将为你提供10个引人注目的爆款标题” --- 请按照以上问题优化提示词
请按照以上问题优化提示词
然后,拿到这版提示词之后,我们一定要打开一个新窗口进行测试,看看效果如何。

是不是一下子我们的选择就变多了呢,你若想达到更好的效果,对于其他部分,我们也可以返回到最初页面进行优化,当然这个问题因人而异,能达到自己的目标就行。
Java AI 开发工具_prompt提示词工程实现
角色设定
角色设定是指导大语言模型(LLM)行为的重要手段。通过明确定义AI助手的身份和能力范围,我们可以使其更专注于特定领域的任务。
在LangChain4j中,我们主要利用SystemMessage来实现这一点。
SystemMessage具有高优先级,能有效地指导模型的整体行为。@SystemMessage("你好,我是:公众号爆款标题创作大师,请告诉我文章主题或者关键词,我将为你提供10个引人注目的爆款标题。")
提示词模板:精确控制输入输出
LangChain4j提供了多种方式来使用提示词模板,让我们能够灵活地构造输入并控制输出。以下是几种常用的方法:
1. 使用 @UserMessage 和 @V 注解:
java
public interface AiAssistant {
@SystemMessage("你好,我是:公众号爆款标题创作大师,请告诉我文章主题或者关键词,我将为你提供10个引人注目的爆款标题。")
@UserMessage("请回答以下问题:{{question}}")
String answerLegalQuestion(@V("question") String question);
}
2. 使用 PromptTemplate 渲染:
java
@GetMapping("/prompt1")
public String prompt1(){
String chat = legalAssistant.chat("资深java程序员不知道的6个小技巧?");
return chat;
}
Java AI 开发工具_JSON 结构化输出
大模型精准化输出
在利用大模型构建自己的应用时,需要每次调用大模型都能稳定的返回固定的字段,如果输出结果不是指定JSON格式,不一定能做到。
使用JSON结构化输出的优势
- 精确控制大模型输出字段 使大模型每次都精确稳定的返回指定的输出字段;
- 易于大模型对输出格式的理解;
- JSON格式方便应用端解析;
- JSON格式方便应用端对数据的利用:应用端可以根据自身需求对各字段的UI展示。
示例
下面是一个要求大模型设计语文阅读题并设计相应的选择题的例子,原来的提示词如下:
"""
假设你是一个中国大陆的初中生老师,你擅长设计初中语文的阅读题。 请以"聚会和休闲活动(亲朋好友聚会、看电影、去公园、参加音乐会等)"为主题,设计一篇250字左右的汉语阅读内容,然后根据阅读内容,出三个单选选择题,每个选择题包含四个选项,并给出每个选择题的正确答案。要求这个阅读题的难度是中等, 阅读题的段落过度要自然、逻辑清晰,不要使用"首先、其次、再次、然后、最后"这些副词和过渡词。
输出的内容包括:
设计的阅读题内容。
阅读题的主题。
阅读题对应的三个单选选择题。
每个题目的四个选项(A、B、C、D)。
每个题目的正确答案(A、B、C、D中的一个),必须避免三个选择题的答案都是相同(即不要都是同一个字母)。
每个题目的正确答案的解释(为什么是这个选项)。
该阅读理解的难度。
"""
大模型返回的结果如下:
阅读题内容:
在一个阳光明媚的周末,小明一家决定去郊外的公园享受休闲时光。他们早早地起床,准备了野餐篮,里面装满了小明最爱的三明治和水果。到达公园后,他们选择了一片树荫下的草地,铺开了野餐垫。孩子们在草地上追逐嬉戏,而大人们则坐在垫子上,享受着美食和阳光。午后,他们决定去附近的电影院看一场期待已久的电影。电影院里,灯光昏暗,气氛温馨,大家都沉浸在电影的情节中。傍晚时分,一家人又去了一个小型音乐会,现场的音乐让人心旷神怡。这一天,小明一家在聚会和休闲活动中度过了一个愉快的周末。
阅读题的主题:
聚会和休闲活动
单选选择题:
- 小明一家选择在哪个地方野餐?
A. 电影院
B. 公园的树荫下
C. 小型音乐会现场
D. 家中
- 他们野餐时,孩子们在做什么?
A. 看电影
B. 听音乐会
C. 追逐嬉戏
D. 准备食物
- 小明一家在音乐会上的感受是什么?
A. 紧张刺激
B. 心旷神怡
C. 疲惫不堪
D. 兴奋不已
正确答案:
B
C
B
上面的输出结果有几个问题:解析不方便;
应用使用数据不方便:比如应用要展示某个选择题的某个选项,需要做多次的解析;
非结构化的输出,模型不一定能保证每次都输出相同的稳定的字段。
如何实现JSON结构化输出
下面的提示词将前面的例子要求转为结构化输出:
假设你是一个中国大陆的初中生老师,你擅长设计初中语文的阅读题。 请以"聚会和休闲活动(亲朋好友聚会、看电影、去公园、参加音乐会等)"为主题,设计一篇250字左右的汉语阅读内容,然后根据阅读内容,出三个单选选择题,每个选择题包含四个选项,并给出每个选择题的正确答案。要求这个阅读题的难度是中等, 阅读题的段落过度要自然、逻辑清晰,不要使用"首先、其次、再次、然后、最后"这些副词和过渡词。
输出的格式要求如下:
The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "```json" and "```":
```json
{
"content": "设计的阅读题内容", //使用汉语,控制在250个汉字左右
"theme": "",
"choices": [{ //出的3选择题内容
"question": "题目内容" //根据阅读题内容出的单选题, 使用汉字,控制在100个汉字以内
"options": [
"A_option": "A选项内容", //使用汉语,控制在20个汉字以内
"B_option": "B选项内容" //使用汉语,控制在20个汉字以内
"C_option": "C选项内容" //使用汉语,控制在20个汉字以内
"D_option": "D选项内容" //使用汉语,控制在20个汉字以内
"correct_option": "该题目的答案选项" //该题目的正确选项,内容为'A','B','C','D'中的一个
"correct_option_reason": "解释答案的原因" //使用汉语,控制在100个汉字以内
]
}],
"difficulty": "设计的阅读理解的难度" //分"容易"、"中等"、"难"
}
大模型返回结果如下:
{
"content": "周末的午后,阳光明媚,小明和朋友们约定在公园里举行野餐。他们带来了各种美食,有香甜的蛋糕、新鲜的水果和美味的三明治。在树荫下,大家围坐在一起,边品尝美食边聊天,享受着轻松愉快的时光。随后,他们决定去划船,湖面上波光粼粼,船桨激起层层涟漪。傍晚时分,他们又一起去了电影院,观看了一部期待已久的电影。这一天,小明和朋友们的聚会充满了欢声笑语,留下了美好的回忆。",
"theme": "聚会和休闲活动",
"choices": [
{
"question": "小明和朋友们在哪里举行了野餐活动?",
"options": {
"A_option": "电影院",
"B_option": "公园",
"C_option": "湖边",
"D_option": "家里",
"correct_option": "B",
"correct_option_reason": "根据阅读内容,小明和朋友们是在公园里举行野餐。"
}
},
{
"question": "他们野餐时享受了哪些活动?",
"options": {
"A_option": "划船",
"B_option": "看电影",
"C_option": "品尝美食和聊天",
"D_option": "参加音乐会",
"correct_option": "C",
"correct_option_reason": "阅读内容提到他们在野餐时品尝美食并聊天。"
}
},
{
"question": "小明和朋友们的聚会在一天中的哪个时间段结束?",
"options": {
"A_option": "中午",
"B_option": "傍晚",
"C_option": "晚上",
"D_option": "早晨",
"correct_option": "B",
"correct_option_reason": "根据阅读内容,他们傍晚时分去电影院观看电影,说明聚会在傍晚结束。"
}
}
],
"difficulty": "中等"
}
Java AI 开发工具_结构化输出
如果要从 LLM接收结构化输出,可以将 AI Service 方法的返回类型更改为 String 或其他。
支持类型
- 字符串 String。
- 基本类型 boolean/byte/short/int/long/float/double。
- 对象类型 Boolean/Byte/Short/Integer/Long/Float/Double/BigDecimal。
- 时间类型 Date/LocalDate/LocalTime/LocalDateTime。
- 集合类型 List/Set。
- 枚举类型 Enum。
- 自定义 POJO。
- 自定义 Result 。
- 大模型回复消息 AiMessage。
创建子模块

结构化输出示例
数字类型
java
public interface SentimentAnalyzer {
@UserMessage("Does {{it}} have positive sentiment?")
boolean isPositive(String text);
@UserMessage("Analyze sentiment of {{it}}")
Sentiment analyzeSentimentOf(String text);
enum Sentiment {
POSITIVE, NEGATIVE, NEUTRAL
}
}
配置元数据
java
@Bean
public SentimentAnalyzer personExtractor(ChatLanguageModel chatLanguageModel) {
return AiServices.create(SentimentAnalyzer.class, chatLanguageModel);
}
配置控制器
java
@RestController
public class ChatController {
@Autowired
private SentimentAnalyzer personExtractor;
/**
* 聊天
* @param message
* @return
*/
@GetMapping("/chat")
public boolean chat(String message){
return personExtractor.isPositive(message);
}
}
数字类型
java
@AiService
public interface NumberExtractor {
@UserMessage("从{{it}}中提取一个数字")
int extractInt(String text);
@UserMessage("从{{it}}中提取一个长数字")
long extractLong(String text);
@UserMessage("从{{it}}中提取一个大整数")
BigInteger extractBigInteger(String text);
@UserMessage("从{{it}}中提取浮点数")
float extractFloat(String text);
@UserMessage("从{{it}}中提取一个双精度数")
double extractDouble(String text);
@UserMessage("从{{it}}中提取一个大小数")
BigDecimal extractBigDecimal(String text);
}
Bean POJO
java
package org.ivy.chatmemory.service;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.spring.AiService;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.time.LocalDate;
@AiService
public interface PojoExtractor {
@UserMessage("从{{it}}中提取有关某人的信息")
Person extractPerson(String text);
@Data
@ToString
class Person{
// 名字
private String name;
// 年龄
private int age;
// 出生日期
private LocalDate birthDate;
}
}
Java AI 开发工具_funcation函数调用!!
在人工智能的世界里,大语言模型(LLMs)不仅仅是文本生成的能手,它们还能触发实际的操作。这种能力,我们称之为函数调用或函数调用。
案列
有无工具时的效果
Request:
messages:
UserMessage:
text: 475695037565的平方根是多少?
Response:
AiMessage:
text: 475695037565的平方根约为689710。
使用一下工具的消息
public class NumberHandler {
/**
* 返回给定数字的平方根
* @param number
* @return
*/
@Tool("返回给定数字的平方根")
public double square(double number) {
return Math.sqrt(number);
}
}
函数调用的应用场景
- 触发外部操作:如发送邮件、控制智能家居设备等。
- 实时数据获取:解决 LLM 知识更新滞后的问题,如进行实时搜索或数据库查询。
- 复杂逻辑处理:处理 LLM 难以直接计算的复杂数据运算问题。

经验法则
为了增加LLM调用正确工具和参数的几率,我们应该提供清晰且明确的:
- 工具名称
- 工具的功能描述以及何时使用
- 每个工具参数的描述
一个好的经验法则是:
如果人类能理解工具的用途和如何使用,那么LLM也能理解。
注意:
工具/函数调用与JSON模式不同。
Java AI 开发工具_动态函数调用
引言
在现代软件开发中,代码执行引擎的应用场景日益广泛。LangChain4j框架通过集成多种代码执行引擎,为开发者提供了强大的工具支持。
执行流程

在大模型执行function calling的流程中:
- 大模型首先返回可直接运行的脚本语言代码
- LangChain4j接收到这段可运行代码后,调用
CodeExecutionEngine执行- 执行结果返回给大模型
LangChain4j支持的执行引擎
LangChain4j目前支持两种主要的代码执行引擎:
-
GraalVM
- Polyglot: 允许在同一应用中无缝使用多种编程语言
- Truffle: 用于构建语言引擎的框架,支持轻松添加新语言
-
Judge0
- 开源代码执行引擎,支持多种编程语言(C, C++, Java, Python, Ruby等)
- 被誉为"世界上最先进的开源在线代码执行系统"
执行引擎测试
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-code-execution-engine-graalvm-polyglot</artifactId>
</dependency>
调用 js 版本斐波那契数列
java
CodeExecutionEngine engine = new GraalVmJavaScriptExecutionEngine();
String code = """
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
fibonacci(10)
""";
String result = engine.execute(code);
动态函数示例
1. 配置类
ChatAssistant assistant = AiServices.builder(ChatAssistant.class) .chatLanguageModel(chatLanguageModel) .tools(new GraalVmJavaScriptExecutionTool()) .build();
2. AI Service 定义
public interface Assistant {
String chat(String message);
}
3. 测试
String chat = chatAssistant.chat("What is the square root of 485906798473894056 in scientific notation?");
System.out.println(chat);
Java AI 开发工具_函数增强搜索

网址:https://www.perplexity.ai/search/jin-tian-shang-zheng-zhi-shu-s-kvEtItD9TvaTH1rzDD_CFA
什么是 Web Search API?
Web Search API 是一种接口,允许开发者通过程序化的方式实时搜索互联网,并从搜索引擎中提取结构化数据,可用于大模型、AI应用进行后续的处理与分析。
为什么需要Web Search API?
各类AI Native应用、RAG应用、AI Agent智能体在开发过程都会遇到联网获取互联网网页信息的需求,此时需要得到原始网页链接以及文本摘要,以用于给workflow中的大模型作为上下文总结使用。
Langchain4j 支持的搜索引擎
| SearchApi 引擎 | 是否支持 |
|---|---|
| Google Web Search | ✅ |
| Google News | ✅ |
| Bing | ✅ |
| Bing News | ✅ |
| Baidu | ✅ |
申请密钥
1、打开SearchAPI网站

2、获取 API KEY

Java AI 开发工具_函数增强搜索实现
在你的项目 pom.xml 中添加以下依赖:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-web-search-engine-searchapi</artifactId>
</dependency>
定义 Ai Service
java
public interface ChatAssistant {
@SystemMessage("""
1. 搜索支持:你的职责是为用户提供基于网络搜索的支持。
2. 事件验证:如果用户提到的事件尚未发生或信息不明确,你需要通过网络搜索确认或查找相关信息。
3. 网络搜索请求:使用用户的查询创建网络搜索请求,并通过网络搜索工具进行实际查询。
4. 引用来源:在最终回应中,必须包括搜索到的来源链接,以确保信息的准确性和可验证性。
""")
String chat(String message);
}
注入 web search

测试

LangChain4j_向量数据库介绍

什么是向量数据库?
向量数据库,顾名思义,它以高维向量的形式存储数据。这些向量是一串数字,代表了某个对象的特征或属性。每一个向量都对应着一个独一无二的实体,比如一段文字、一张图片或一段视频。

为什么选择向量呢?
向量的魅力在于它们能够精准捕捉到数据的语义含义和相似度。
向量数据库核心!!!
向量数据库的核心在于相似性搜索(Similarity Search)。将文本转换成向量,然后将向量存储在数据库中,当用户输入问题时,将问题转换成向量,然后在数据库中搜索最相似的向量和上下文,最后将文本返回给用户。
我们先思考一个问题?为什么我们在生活中区分不同的物品和事物?

然而单靠一个体型大小的特征并不够,像照片中哈士奇、金毛和拉布拉多的体型就非常接近,我们无法区分。所以我们会继续观察其它的特征,例如毛发的长短。

为何向量数据库受到青睐?
近年来,随着机器学习和人工智能领域的迅速发展,向量数据库的需求日益增加。AI 和 ML 模型需要处理的非结构化数据量巨大,这就需要一种有效的存储、检索和搜索方法。
重点:
采用了专门的搜索和索引算法,能够迅速地在数十亿条数据中找到相似的向量。
向量数据库的应用场景
向量数据库的出现极大地扩展了 AI 和 ML 应用的可能性。

一些典型的应用场景包括:
- RAG 系统:将向量数据库与大型语言模型结合,可构建出基于知识的语言 AI 应用。
- 推荐系统:利用向量数据库构建个性化推荐引擎,通过向量来表示用户偏好和商品特性。
- 基于内容的检索:向量数据库能够搜索视觉上相似的图像或视频,彻底改变了内容检索方式。
- 自然语言处理:通过将文本转换为向量,向量数据库支持语义搜索、主题建模和文档分类。
- 欺诈检测:向量数据库能够帮助识别金融交易中的异常模式和趋势。
LangChain4j_Qdrant向量数据库

目前常见的向量数据库有 Qdrant, Milvus, Faiss 等等。
什么是Qdrant
"Qdrant "是一个向量相似性搜索引擎,提供生产就绪的服务,并配有方便的 API,用于存储、搜索和管理点(即向量)以及附加的有效负载。" 你可以将有效负载视为额外的信息片段,这些信息可以帮助你优化搜索,并向用户提供有用的信息。
由 Rust 编写的向量数据库, 在性能上自然是第一梯队的。
LangChain4j支持的向量数据库
LangChain支持多种向量数据库,每种数据库具有不同的特性。以下是部分支持的向量数据库及其功能:
| 向量存储 | 存储元数据 | 按元数据过滤 | 移除向量 |
|---|---|---|---|
| 内存存储 | ✅ | ✅ | ✅ |
| Astra DB | ✅ | ||
| Azure AI Search | ✅ | ✅ | ✅ |
| Azure CosmosDB Mongo vCore | ✅ | ||
| Azure CosmosDB NoSQL | ✅ | ||
| Cassandra | ✅ | ||
| Chroma | ✅ | ✅ | ✅ |
| Couchbase | ✅ | ✅ | |
| Elasticsearch | ✅ | ✅ | ✅ |
| Infinispan | ✅ | ||
| Milvus | ✅ | ✅ | ✅ |
| MongoDB Atlas | ✅ | 仅支持原生过滤 | |
| Neo4j | ✅ | ||
| OpenSearch | ✅ | ||
| Oracle | ✅ | ✅ | ✅ |
| PGVector | ✅ | ✅ | ✅ |
| Pinecone | ✅ | ✅ | ✅ |
| Qdrant | ✅ | ✅ | |
| Redis | ✅ | ||
| Tablestore | ✅ | ✅ | ✅ |
| Vearch | ✅ | ||
| Vespa | |||
| Weaviate | ✅ | ✅ |
Qdrant 目前实现了 4 种距离算法
• 余弦相似度:适用于比较向量的方向,而不考虑向量的大小. 比如文本相似度, 信息检索等.
• 欧氏距离:适用于度量两点之间的直线距离,考虑向量的大小和方向. 用于几何计算, 图像处理等.
• 点积:适用于度量向量的相对位置和方向. 常用于线性代数和信号处理等离散数据计算.
• 曼哈顿距离:适用于度量两点之间的网格距离,适合网格状或离散空间. 用于路径规划, 特征工程等.
Qdrant 架构概览

概念:
- 集合 (collections): 可以类比为 MySQL 中的表, 里边存储了一条条的记录
- Points: 这个结构类似 MySQL 中的一条记录, 这是一个实体, 由三部分组成
- • 唯一 ID
- • vector: 固定长度的向量, 在创建集合的时候, 就已经确定好的
- • payload: 记录里携带的 json 对象, 我们也是我们要利用的核心数据
- Storage: 向量的存储方式, 向量和 payload 会分开存储, 通过 payload 索引进行关联, 为了保证数据完整,
LangChain4j_Qdrant向量库安装

Qdrant是一个高性能的向量数据库,用于存储嵌入并进行快速的向量搜索。
配置镜像加速器
您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://dockerhub.xianfish.site","https://docker.m.daocloud.io"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
安装Qdrant
使用Docker安装Qdrant:
docker run --name myqdrant -d -p 6333:6333 -p 6334:6334 qdrant/qdrant
参数说明:
- 端口6333:用于HTTP API
- 端口6334:用于gRPC API

访问
http://192.168.47.120:6333/dashboard#/welcome
192这个要换成自己的

LangChain4j_集成LangChain4j与Qdrant
添加Maven依赖
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-qdrant</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-zhipu-ai</artifactId>
<version>0.35.0</version>
</dependency>
创建Qdrant客户端
@Bean
public QdrantClient qdrantClient() {
QdrantGrpcClient.Builder grpcClientBuilder = QdrantGrpcClient.newBuilder("192.168.66.120", 6334, false);
return new QdrantClient(grpcClientBuilder.build());
}
创建索引
var vectorParams = Collections.VectorParams.newBuilder()
.setDistance(Collections.Distance.Cosine)
.setSize(1024)
.build();
qdrantClient.createCollectionAsync("testv", vectorParams);
配置Qdrant Embedding Store
/**
* 存储向量地方
* @return
*/
@Bean
public EmbeddingStore<TextSegment> embeddingStore(){
return QdrantEmbeddingStore.builder()
.host("192.168.47.120")
.port(6334)
.collectionName("itbaizhan")
.build();
}
配置向量模型
java
/**
* Embedding Model 向量模型,机器学习模型,核心功能 将高维数据映射到低维空间的技术。
* 离散的,稀疏的数据转换连续的、密集的向量表示
* Duration callTimeout,
* Duration connectTimeout,
* Duration readTimeout,
* Duration writeTimeout
* @return
*/
@Bean
public EmbeddingModel embeddingModel(){
return ZhipuAiEmbeddingModel.builder()
.apiKey("842df645f867724dddfbdd1145162a03.VlzbHzSVUg5y0Q9r")
.callTimeout(Duration.ofSeconds(1000))
.connectTimeout(Duration.ofSeconds(1000))
.readTimeout(Duration.ofSeconds(1000))
.writeTimeout(Duration.ofSeconds(1000))
.build();
}
文本生成与存储
java
/**
* 存储文本到向量数据库
*/
@Test
public void saveText(){
TextSegment from1 = TextSegment.from("客服的电话是400-3464563");
TextSegment from2 = TextSegment.from("客服工作时间是周一到周五");
TextSegment from3 = TextSegment.from("客服的投诉电话是400-123456");
TextSegment from4 = TextSegment.from("客服的人数是245");
// 转换向量
Embedding content1 = embeddingModel.embed(from1).content();
Embedding content2 = embeddingModel.embed(from2).content();
Embedding content3 = embeddingModel.embed(from3).content();
Embedding content4 = embeddingModel.embed(from4).content();
// 存储入向量数据库
embeddingStore.add(content1,from1);
embeddingStore.add(content2,from2);
embeddingStore.add(content3,from3);
embeddingStore.add(content4,from4);
}
向量查询与过滤
- 基本向量查询:
java
/**
* 向量查询与过滤
*/
@Test
public void search(){
// 问题
String msg = "你们公司客服的人数是多少";
// 问题向量
Embedding embedding = embeddingModel.embed(msg).content();
// 搜索
EmbeddingSearchRequest request = EmbeddingSearchRequest.builder()
.maxResults(1)
.queryEmbedding(embedding)
.build();
EmbeddingSearchResult search = embeddingStore.search(request);
System.out.println(search.matches().get(0));
}
/**
* 向量查询与过滤 元数据
*/
@Test
public void datameate(){
TextSegment from1 = TextSegment.from("客服的女生人数是67人");
from1.metadata().put("author","lisi");
// 转换向量
Embedding content1 = embeddingModel.embed(from1).content();
// 存储入向量数据库
embeddingStore.add(content1,from1);
// 问题
String msg = "你们公司客服有多少女生";
// 问题向量
Embedding embedding = embeddingModel.embed(msg).content();
// 搜索
EmbeddingSearchRequest request = EmbeddingSearchRequest.builder()
.maxResults(1)
// 过滤
.filter(metadataKey("author").isEqualTo("lisi"))
.queryEmbedding(embedding)
.build();
EmbeddingSearchResult search = embeddingStore.search(request);
if (!CollectionUtils.isEmpty(search.matches())){
List matches = search.matches();
for (Object match : matches) {
System.out.println(match);
}
}
}
常用过滤器:
| Filter名称 | 功能 | 使用示例 |
|---|---|---|
| And | 同时满足多个条件 | Filter.and(condition1, condition2) |
| Or | 满足其中任意一个条件 | Filter.or(condition1, condition2) |
| Not | 不满足条件 | Filter.not(condition) |
| IsEqualTo | 等于 | new IsEqualTo("field", "value") |
| IsGreaterThan | 大于 | new IsGreaterThan("field", value) |
| IsLessThan | 小于 | new IsLessThan("field", value) |
| IsIn | 在列表内 | new IsIn("field", listOfValues) |
LangChain4j_内容审查助手

敏感词过滤的应用场景
- 社交网络:实时监控聊天记录,防止不当言论传播。
- 在线评论系统:过滤用户评论中的敏感词,保护品牌声誉。
- 用户注册:验证用户名和简介,确保符合社区准则。
- 邮件系统:检测垃圾邮件,保障用户信息安全。
Sensitive-Word 简介
sensitive-word 是一个 Java 编写的敏感词过滤工具包,可以用于对文本中的敏感词进行过滤。该工具包提供了多种敏感词匹配算法,并支持自定义敏感词库和替换策略。使用该工具包可以有效地保护用户隐私,防止不良信息的传播。
主要功能和特点
- 高性能:能够处理大量关键词集,并在极短的时间内完成文本扫描。
- 灵活配置:支持多种配置方式,包括动态加载敏感词字典。
- 易于扩展:提供插件架构,方便添加新的过滤规则和替换策略。
- 全面文档:拥有详细的使用文档和示例代码,帮助开发者快速上手。
1. 通过Maven引入依赖
<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>sensitive-word</artifactId>
<version>0.21.0</version>
</dependency>
2. 基本使用示例
java
@Test
void testWord() {
String text = "五星红旗迎风飘扬,毛主席的画像屹立在天安门前。";
//输出是否包含敏感词
System.out.println(SensitiveWordHelper.contains(text));
//默认替换为*
System.out.println(SensitiveWordHelper.replace(text));
System.out.println(SensitiveWordHelper.replace(text, '0'));
//查找出第一个敏感词
System.out.println(SensitiveWordHelper.findFirst(text));
System.out.println(SensitiveWordHelper.findFirst(text, WordResultHandlers.word()));
System.out.println(SensitiveWordHelper.findFirst(text, WordResultHandlers.raw()));
//查找全部的敏感词
System.out.println(SensitiveWordHelper.findAll(text));
System.out.println(SensitiveWordHelper.findAll(text, WordResultHandlers.word()));
System.out.println(SensitiveWordHelper.findAll(text, WordResultHandlers.raw()));
}