我在gitee上有整体的项目示例,有兴趣的可以拉下来看看:https://gitee.com/JR542784/langchain4j-test,如果不知道怎么部署milvus可以从我的主页走索milvus有相关的说明
POM相关依赖
xml
<properties>
<java.version>21</java.version>
<junit.platform.version>1.9.2</junit.platform.version>
<junit.jupiter.version>5.9.2</junit.jupiter.version>
<langchain4j.version>0.36.2</langchain4j.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-milvus-spring-boot-starter</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- Source: https://mvnrepository.com/artifact/dev.langchain4j/langchain4j-spring-boot-starter -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<!-- 4.0.x 已经没有 vintage,可省略 exclusion -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
配置AiService
java
import com.ai.langchain.langchain4jtest.service.AiHelperService;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.service.AiServices;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author JR
* @version 1.0
* @description:
* @date 2026年05月25日 17:39
*/
@Configuration
public class AiServiceConfig {
@Resource
private ChatLanguageModel qwenChatModel;
@Resource
private ContentRetriever contentRetriever;
/**
* 加入RAG检索增强生成
* @return
*/
@Bean
public AiHelperService aiHelperService() {
ChatMemory messageWindowChatMemory = MessageWindowChatMemory.withMaxMessages(10);
return AiServices.builder(AiHelperService.class)
.chatLanguageModel(qwenChatModel)
.chatMemory(messageWindowChatMemory)
.chatMemoryProvider(memoryId -> messageWindowChatMemory)
.contentRetriever(contentRetriever)
.tools()
.build();
}
}
RAG的相关配置
java
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.store.embedding.EmbeddingStore;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author JR
* @version 1.0
* @description:
* @date 2026年05月25日 18:45
*/
@Configuration
public class AiRagConfig {
@Resource
private EmbeddingModel qwenEmbeddingModel;
// EmbeddingStore 的作用是什么?
@Resource(name = "milvusEmbeddingStore")
private EmbeddingStore<TextSegment> embeddingStore;
/**
* 检索器Bean:用于问答时从Milvus检索向量,不负责入库
*/
@Bean
public ContentRetriever contentRetriever() {
return EmbeddingStoreContentRetriever.builder()
.embeddingStore(embeddingStore)
.embeddingModel(qwenEmbeddingModel)
.maxResults(5) // 召回top5
.minScore(0.75) // 相似度阈值过滤低相关
.build();
}
}
AiService的接口
java
/**
* @author JR
* @version 1.0
* @description:
* @date 2026年05月25日 17:35
*/
public interface AiHelperService {
@SystemMessage(fromResource = "Prompt.txt")
String chat(String userMessage);
@SystemMessage(fromResource = "Prompt.txt")
Report chatReport(String userMessage);
record Report(String name, List<String> suggetionList){}
}
不同调用方式的调用
java
import com.ai.langchain.langchain4jtest.service.ChatService;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.request.ChatRequest;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.store.embedding.EmbeddingStore;
import io.milvus.client.MilvusClient;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author JR
* @version 1.0
* @description:
* @date 2026年05月25日 10:09
*/
@Slf4j
@Service
public class ChatServiceImpl implements ChatService {
private static final String COLLECTION_NAME = "test_collection";
@Resource
private ChatLanguageModel qwenChatModel;
private String SYSTEM_MESSAGE= """
你是AI面试助手**小光**,专注面试题库检索、答案整理与分类工作。
1. 接收用户面试相关提问,精准检索对应面试题目、标准答案与解题思路
2. 按**技术方向、难度等级、题型类别**规整划分内容
3. 排版清晰简洁,题目与答案分区展示,冗余信息剔除
4. 主动区分基础题、进阶题、实操题、问答论述题,按需归类输出
5. 严格围绕面试考点作答,不偏离求职面试场景
""";
@Override
public String chat(String messageChat) {
// 1. 组装消息
UserMessage userMsg = UserMessage.from("你的提问内容");
ChatRequest chatRequest = ChatRequest.builder().messages(userMsg).build();
ChatResponse response = qwenChatModel.chat(chatRequest);
AiMessage aiMessage = response.aiMessage();
log.info("ai message:{}",aiMessage.toString());
return aiMessage.text();
}
@Override
public String chatUserMessage(UserMessage userMessage) {
ChatRequest chatRequest = ChatRequest.builder().messages(userMessage).build();
ChatResponse response = qwenChatModel.chat(chatRequest);
AiMessage aiMessage = response.aiMessage();
log.info("ai message:{}",aiMessage.toString());
return aiMessage.text();
}
@Override
public String chatPrompt(String message) {
SystemMessage systemMessage = new SystemMessage(SYSTEM_MESSAGE);
UserMessage userMessage = UserMessage.from(message);
ChatRequest chatRequest = ChatRequest.builder().messages(systemMessage,userMessage).build();
ChatResponse response = qwenChatModel.chat(chatRequest);
AiMessage aiMessage = response.aiMessage();
log.info("ai message:{}",aiMessage.toString());
return aiMessage.text();
}
}
单元测试
java
import com.ai.langchain.langchain4jtest.service.AiHelperService;
import com.ai.langchain.langchain4jtest.service.ChatService;
import com.ai.langchain.langchain4jtest.service.MilvusVectorIngestService;
import dev.langchain4j.data.message.ImageContent;
import dev.langchain4j.data.message.TextContent;
import dev.langchain4j.data.message.UserMessage;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Langchain4jTestApplicationTests {
@Resource
private ChatService chatService;
@Resource
private AiHelperService aiHelperService;
@Test
public void baseChat() {
// 普通文本处理模型,在yml中进行配置
String responseMessage = chatService.chat("你好,我是安多尼");
System.out.println(responseMessage);
}
@Test
public void chatImageHandel() {
// 需要使用多模态的模型,在yml中进行配置
// 还可以处理其他文件,相关的对象有:
// AudioContent VideoContent PdfFileContent TextContent ImageContent
// 音频,视频,pdf,文本,图片
UserMessage userMessage = new UserMessage(
TextContent.from("这张图片的内容是什么"),
ImageContent.from("https://tse4.mm.bing.net/th/id/OIP.bl-kQplMxE9HV27SrrmekAHaLn?r=0&rs=1&pid=ImgDetMain&o=7&rm=3")
);
String responseMessage = chatService.chatUserMessage(userMessage);
System.out.println(responseMessage);
}
/**
* 系统预设提示词,可以指定ai的身份作用等等
*/
@Test
public void chatPrompt() {
// 需要使用多模态的模型,在yml中进行配置
// 还可以处理其他文件,相关的对象有:
// AudioContent VideoContent PdfFileContent TextContent ImageContent
// 音频,视频,pdf,文本,图片
String responseMessage = chatService.chatPrompt("你是谁?你的功能是什么?");
System.out.println(responseMessage);
}
/**
* 通过aiService实现ai的调用(无会话记忆)
*/
@Test
public void chatPromptAiService() {
// 需要使用多模态的模型,在yml中进行配置
// 还可以处理其他文件,相关的对象有:
// AudioContent VideoContent PdfFileContent TextContent ImageContent
// 音频,视频,pdf,文本,图片
String responseMessage = aiHelperService.chat("你是谁?你的功能是什么?");
System.out.println(responseMessage);
}
@Test
public void chatPromptMemoryAiService() {
String responseMessage = aiHelperService.chat("现在是那年哪月那日,星期几");
System.out.println("AI第一次回答:"+responseMessage);
responseMessage = aiHelperService.chat("我刚刚问了你什么问题,你怎么回答的");
System.out.println("AI第二次回答:"+responseMessage);
}
/**
* 以Json scheam的方式返回数据
*/
@Test
public void chatJsonScheam() {
AiHelperService.Report report = aiHelperService.chatReport("给我几条学习建议,规划一些学习目标");
System.out.println(report);
System.out.println(report.suggetionList().size());
}
@Resource
private MilvusVectorIngestService milvusVectorIngestService;
@Test
public void chatRag() {
// RAG相关配置需要查看AiRagConfig中的contentRetriever
String responseMessage = aiHelperService.chat("JDK命令行工具有哪些");
System.out.println(responseMessage);
}
/**
* 加载文档并向量化后存入milvus(向量数据库)中
*/
@Test
public void loadDocsToMilvus() {
milvusVectorIngestService.loadDocsToMilvus();
}
}