手动创建AIservice类
arduino
package com.ai.aiService;
public interface ConsultantService {
public String chat(String message);//用于聊天的方法 使用aiservice的chat方法进行返回结果
}
less
@Autowired
private ConsultantService consultantService;
@RequestMapping("/chat2")
public String chat2(@RequestParam("message") String message) {
return consultantService.chat(message);
}//但是这个是通过手动的取创建aiservice
java
//为aiService接口创建一个实现类,并将其注册为Spring Bean,以便在应用程序中使用
// 创建一个动态代理对象,代理对象实现了ConsultantService接口,
// 并将chatModel注入到代理对象中,以便在调用chat方法时能够使用chatModel进行聊天交互
@Autowired
private OpenAiChatModel model;
@Bean
public ConsultantService consultantService() {
ConsultantService consultantService = AiServices.builder(ConsultantService.class)
.chatModel(model)
.build();
return consultantService;
}//手动进行创建AIservice类
显示调用AiService类
typescript
@AiService(
wiringMode = AiServiceWiringMode.EXPLICIT,//手动装配
chatModel = "openAiChatModel"//指定模型
)//使用AiService注解将ConsultantService2接口标记为一个AI服务,并指定其聊天模型为openAiChatModel
//自动的将chatmodel注入到ConsultantService2接口的实现类中,
// 以便在调用chat方法时能够使用chatModel进行聊天交互
public interface ConsultantService2 {
public String chat(String message);
}
js
less
@Autowired
private ConsultantService consultantService2;
@RequestMapping("/chat3")//这个是aiService声明式使用
public String chat3(@RequestParam("message") String message) {
return consultantService2.chat(message);
}
通过阻塞式调用等进行创建aiservice类
less
package com.ai.aiService;
import dev.langchain4j.service.MemoryId;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import dev.langchain4j.service.spring.AiService;
import dev.langchain4j.service.spring.AiServiceWiringMode;
import reactor.core.publisher.Flux;
@AiService(
wiringMode = AiServiceWiringMode.EXPLICIT,
chatModel = "openAiChatModel",
streamingChatModel = "openAiStreamingChatModel",
// chatMemory = "chatMemory",//指定会话记忆对象 这个对象在bean配置类中进行创建并配置了会话记忆的相关参数
chatMemoryProvider = "chatMemoryProvider",//指定会话记忆提供者 这个对象在bean配置类中进行创建并配置了会话记忆提供者的相关参数
contentRetriever = "contentRetriever",//指定内容检索器 这个对象在bean配置类中进行创建并配置了内容检索器的相关参数
tools = "reservationTool"//指定工具 这个对象在bean配置类中进行创建并配置了工具的相关参数
)//进行创建流式调用对象
public interface ConsultantService3 {
//消息注解 设置聊天背景和角色
//@SystemMessage("你是东哥的小助手,协助东哥解答问题,提供帮助。")//系统消息,设置聊天的背景和角色
@SystemMessage(fromResource = "system.txt")//从资源文件中加载系统消息,设置聊天的背景和角色
// @UserMessage("请你以东哥的小助手的身份,协助东哥解答问题,提供帮助。{{msg}}")
//这两个注解区别是前者是系统消息,设置聊天的背景和角色,后者是用户消息,表示用户输入的消息内容,其中{{msg}}是一个占位符,用于在调用chat方法时动态传入用户输入的消息内容
public Flux<String> chat(@MemoryId String memoryId, @UserMessage String message);
}
typescript
@Repository
public class RedisChatMemoryStore implements ChatMemoryStore {
//进行重写store接口中的方法,来实现对聊天记录的存储和管理
//将其存放到redis中,来实现聊天记录的持久化和共享
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public List<ChatMessage> getMessages(Object memoryId) {
//获取会话消息
String json = stringRedisTemplate.opsForValue().get(memoryId);
//把json数据转换成list
List<ChatMessage> list = ChatMessageDeserializer.messagesFromJson(json);
return list;
}
@Override
public void updateMessages(Object memoryId, List<ChatMessage> list) {
//更新会话消息
//把list转换成json数据
String json = ChatMessageSerializer.messagesToJson(list);
//将json数据存储到redis中
stringRedisTemplate.opsForValue().set(memoryId.toString(),json, Duration.ofDays(1));
}
@Override
public void deleteMessages(Object memoryId) {
stringRedisTemplate.delete(memoryId.toString());
}
}
typescript
//构建chatMemoryProvider对象
@Bean
public ChatMemoryProvider chatMemoryProvider() {
ChatMemoryProvider chatMemoryProvider = new ChatMemoryProvider() {
//chatMemoryProvider接口是一个提供会话记忆对象的接口,定义了一个get方法,用于根据传入的参数获取对应的ChatMemory对象
@Override
public ChatMemory get(Object memoryId) {
//根据传入的参数o来获取对应的ChatMemory对象
//可以根据o的类型或者值来决定返回哪个ChatMemory对象
//例如,如果o是一个用户ID,可以根据用户ID来获取对应的ChatMemory对象
//如果o是一个会话ID,可以根据会话ID来获取对应的ChatMemory对象
//这里可以根据实际需求进行实现,返回一个ChatMemory对象
MessageWindowChatMemory build = MessageWindowChatMemory.builder()
.id(memoryId)
.maxMessages(20)
.chatMemoryStore(chatMemoryStore)
.build();
return build;
}
};
return chatMemoryProvider;
}
scss
//构建向量数据库操作对象
@Bean
public EmbeddingStore store() {
//加载文档进内存
// List<Document> content = ClassPathDocumentLoader.loadDocuments("content");
List<Document> content = ClassPathDocumentLoader.loadDocuments("content", new ApachePdfBoxDocumentParser());//加载pdf文档
//List<Document> content = FileSystemDocumentLoader.loadDocuments("D:\ideaproject\java-ai\src\main\resources\content");
//构建向量数据库操作对象 操作的是内存版本的向量数据库
//InMemoryEmbeddingStore Store = new InMemoryEmbeddingStore();
//构建文档分割器对象
DocumentSplitter recursive = DocumentSplitters.recursive(500, 100);
//构建embeddingStoreIngestor对象 完成数据切割向量化,存储到向量数据库中
EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
//.embeddingStore(Store)
.embeddingStore(RedisEmbeddingStore)//使用redis作为向量数据库
.documentSplitter(recursive)
.embeddingModel(embeddingModel)
.build();
//将文档转换成向量并存储到向量数据库中
ingestor.ingest(content);
return RedisEmbeddingStore;
}
//构建向量数据库检索对象
@Bean
public ContentRetriever contentRetriever(/*EmbeddingStore store*/) {//构建向量数据库检索对象 注意名字是store 不是默认的embeddingStore
return EmbeddingStoreContentRetriever.builder()
.embeddingStore(RedisEmbeddingStore)
.minScore(0.5)
.maxResults(3)
.embeddingModel(embeddingModel)
.build();
}
less
@Component
public class ReservationTool {
@Autowired
private reservationService reservationService;
//工具方法 添加预约信息
@Tool("预约志愿填报服务")//使用Tool注解将addReservation方法标记为一个工具方法,并指定其名称为"预约志愿填报服务"
public void addReservation(@P("考生姓名") String name,
@P("考生性别") String gender,
@P("考生手机号") String phone,
@P("预约沟通时间 格式 yyyy-MM-dd'T'HH:mm") String communicationTime,
@P("考生所在省份") String province,
@P("考生预估分数") Integer estimatedScore
) {//创建预约对象
Reservation reservation = new Reservation(null,name,gender,phone,java.time.LocalDateTime.parse(communicationTime),province,estimatedScore);
//调用service方法添加预约信息
reservationService.addReservation(reservation);
}
//查询预约信息
@Tool("根据考生手机号查询预约单")
public Reservation getReservationByPhone(@P("考生手机号") String phone) {
//调用service方法查询预约信息
return reservationService.getReservationByPhone(phone);
}
}