Spring AI Alibaba基础概念
- [1.对话模型(Chat Model)](#1.对话模型(Chat Model))
- 2.ChatClient:
-
- 2.1概念
- [2.2创建 ChatClient](#2.2创建 ChatClient)
- [2.3处理 ChatClient 响应](#2.3处理 ChatClient 响应)
- [2.4call() 返回值](#2.4call() 返回值)
- [2.5stream() 返回值](#2.5stream() 返回值)
- 3.Advisors
- 4.检索增强生成(RAG)
- 5.聊天记忆
- 6.嵌入模型 (Embedding Model)
- [7.工具(Function Calling)](#7.工具(Function Calling))
- 8.提示词 (Prompt)
- 9.文档检索 (Document Retriever)
- [10.向量存储(Vector Store)](#10.向量存储(Vector Store))
1.对话模型(Chat Model)
1.1概念
- 对话模型(Chat Model)接收一系列消息(Message)作为输入,与模型 LLM 服务进行交互,并接收返回的聊天消息(Chat Message)作为输出。
java
@Autowired
private ChatModel chatModel;
/**
* 通过ChatModel调用
*/
@GetMapping("/test2")
public String test2(String userInput) {
ChatClient.Builder builder = ChatClient.builder(chatModel);
ChatClient chatClient = builder.build();
return chatClient.prompt()
.user(userInput)
.call()
.content();
}
1.2模型分类
- ChatModel:文本聊天交互模型,支持纯文本格式作为输入,并将模型的输出以格式化文本形式返回,使用 Prompt 作为输入,使用 ChatResponse 作为输出
- ImageModel:接收用户文本输入,并将模型生成的图片作为输出返回,ImageModel 的入参为包装类型 ImagePrompt,输出类型为 ImageResponse
- AudioModel:接收用户文本输入,并将模型合成的语音作为输出返回
2.ChatClient:
2.1概念
- 与 ChatModel、Message、ChatMemory 等原子 API 相比,使用 ChatClient 可以将与 LLM 及其他组件交互的复杂性隐藏在背后,因为基于 LLM 的应用程序通常要多个组件协同工作(例如,提示词模板、聊天记忆、LLM Model、输出解析器、RAG 组件:嵌入模型和存储),并且通常涉及多个交互,因此协调它们会让编码变得繁琐
2.2创建 ChatClient
- 自动配置的 ChatClient.Builder
- 以编程方式创建 ChatClient
java
private final ChatClient chatClient;
public ChatController(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.defaultAdvisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory())).build();
}
/**
* 通过chatClient调用
*/
@GetMapping("/test1")
public String test1(String userInput) {
return this.chatClient.prompt()
.user(userInput)
.call()
.content();
}
2.3处理 ChatClient 响应
- 返回 ChatResponse
- 返回实体类(Entity)
- 流式响应
java
/**
* 返回entity
*/
@GetMapping("/entity")
public ActorFilms entity() {
return this.chatClient.prompt()
.user("给我周星驰的三部电影信息")
.call()
.entity(ActorFilms.class);
}
2.4call() 返回值
ChatClient.call() 方法支持几种不同类型的响应格式。
- String content():返回响应的字符串内容
- ChatResponse chatResponse():返回ChatResponse包含多个代以及有关响应的元数据的对象,例如,使用了多少个令牌来创建响应。
- entity 返回 Java 类型
3.1 entity(ParameterizedTypeReference type):用于返回实体类型的集合。
3.2 entity(Class type): 用于返回特定的实体类型。
3.3 entity(StructuredOutputConverter structuredOutputConverter): 用于指定一个实例 StructuredOutputConverter,将 String 转换为实体类型。
2.5stream() 返回值
您还可以调用该stream方法而call不是,在指定stream方法后ChatClient,响应类型有几个选项:
- Flux content():返回由AI模型生成的字符串的Flux。
- Flux chatResponse():返回对象的 Flux ChatResponse,其中包含有关响应的附加元数据。
java
/**
* 流式响应
*/
@GetMapping(value = "/streamChat", produces = "text/html;charset=UTF-8")
public Flux<String> streamChat() {
return chatClient
.prompt()
.user("你是谁")
.stream()
.content();
}
3.Advisors
3.1概念
在使用用户输入文本构建 Prompt 调用 AI 模型时,一个常见模式是使用上下文数据附加或扩充 Prompt,最终使用扩充后的 Prompt 与模型交互。
3.2常见类型
- 您自己的数据:这是 AI 模型尚未训练过的数据,如特定领域知识、产品文档等,即使模型已经看到过类似的数据,附加的上下文数据也会优先生成响应。
- 对话历史记录:聊天模型的 API 是无状态的,如果您告诉 AI 模型您的姓名,它不会在后续交互中记住它,每次请求都必须发送对话历史记录,以确保在生成响应时考虑到先前的交互
3.3示例
- SimpleLoggerAdvisor 是一个用于记录 ChatClient 的 request 和 response 数据 Advisor,这对于调试和监控您的 AI 交互非常有用
java
/**
* 使用advisor
*/
@GetMapping("/advisor")
public String advisor(String userInput) {
ChatClient.Builder builder = ChatClient.builder(chatModel);
ChatClient chatClient = builder
.defaultAdvisors(new MyCallAroundAdvisor())
.build();
return chatClient.prompt()
.user(userInput)
.call()
.content();
}
4.检索增强生成(RAG)
4.1概念
- 向量数据库存储的是 AI 模型不知道的数据,当用户问题被发送到 AI 模型时,QuestionAnswerAdvisor 会在向量数据库中查询与用户问题相关的文档。
4.2原理
- 使用它们时的第一步是将您的数据加载到矢量数据库中。然后,当要将用户查询发送到 AI 模型时,首先检索一组相似文档。然后,这些文档作为用户问题的上下文,并与用户的查询一起发送到 AI 模型。
5.聊天记忆
5.1概念
- 大模型本身的对话是无状态的,此机制使得大模型不仅能够响应即时的输入请求,还能基于之前的交流内容能够在对话中记住先前的对话内容,并根据这些信息进行后续的响应。这种记忆机制使得模型能够在对话中持续跟踪和理解用户的意图和上下文,从而实现更自然和连贯的对话
5.2分类
- ChatMemory 接口表示聊天对话历史记录的存储,它提供向对话添加消息、从对话中检索消息以及清除对话历史记录的方法。
- InMemoryChatMemory:聊天对话历史记录提供内存存储
- CassandraChatMemory:time-to-live 类型的持久存储
java
/**
* 会话记忆功能
*/
@GetMapping("/chatMemoryChat")
public String chatMemoryChat(@RequestParam("chatId") String chatId, @RequestParam("message") String message) {
return chatClient
.prompt()
.advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId))
.user(message)
.call()
.content();
}
6.嵌入模型 (Embedding Model)
6.1概念
嵌入模型(EmbeddingModel)是嵌入过程中采用的模型。当前EmbeddingModel的接口主要用于将文本转换为数值向量
6.2原理
嵌入(Embedding)的工作原理是将文本、图像和视频转换为称为向量(Vectors)的浮点数数组。这些向量旨在捕捉文本、图像和视频的含义。嵌入数组的长度称为向量的维度(Dimensionality)
6.3代码示例
java
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
@RestController
public class EmbeddingController {
private final ChatClient chatClient;
public EmbeddingController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@Autowired
private EmbeddingModel embeddingModel;
@GetMapping("/embedding")
public float[] embedding(@RequestParam String message) {
return embeddingModel.embed(message);
}
@Autowired
private DocumentService documentService;
@GetMapping("/documentEmbedding")
public List<Document> documentEmbedding() {
return documentService.loadText();
}
/**
* 相似度查询
*/
@GetMapping("/documentSearch")
public List<Document> documentSearch(@RequestParam String message) {
return documentService.search(message);
}
/**
* RAG调用
*/
@GetMapping("/ragChat")
public String ragChat(@RequestParam String message) {
// 向量搜索
List<Document> documentList = documentService.search(message);
// 提示词模板
PromptTemplate promptTemplate = new PromptTemplate("{userMessage}\n\n 用以下信息回答问题:\n {contents}");
// 组装提示词
Prompt prompt = promptTemplate.create(Map.of("userMessage", message, "contents", documentList));
// 调用大模型
return chatClient.prompt(prompt).call().content();
}
@Autowired
private VectorStore vectorStore;
@GetMapping("/qa")
public String qa(@RequestParam String message) {
return chatClient
.prompt()
.advisors(new QuestionAnswerAdvisor(vectorStore))
.advisors(c->c.param("question", message))
.user(message)
.call()
.content();
}
}
7.工具(Function Calling)
7.1概念
"工具(Tool)"或"功能调用(Function Calling)"允许大型语言模型(LLM)在必要时调用一个或多个可用的工具,这些工具通常由开发者定义。工具可以是任何东西:网页搜索、对外部 API 的调用,或特定代码的执行等。LLM 本身不能实际调用工具;相反,它们会在响应中表达调用特定工具的意图(而不是以纯文本回应)。然后,我们应用程序应该执行这个工具,并报告工具执行的结果给模型
对话记忆
8.提示词 (Prompt)
- Prompt 是引导 AI 模型生成特定输出的输入格式,Prompt 的设计和措辞会显著影响模型的响应。
- 每条消息都分配有特定的角色,这些角色对消息进行分类,明确 AI 模型提示的每个部分的上下文和目的
- Prompt 中的主要角色(Role)包括:
3.1 系统角色(System Role):指导 AI 的行为和响应方式,设置 AI 如何解释和回复输入的参数或规则。这类似于在发起对话之前向 AI 提供说明。
3.2 用户角色(User Role):代表用户的输入 - 他们向 AI 提出的问题、命令或陈述。这个角色至关重要,因为它构成了 AI 响应的基础。
3.3 助手角色(Assistant Role):AI 对用户输入的响应。这不仅仅是一个答案或反应,它对于保持对话的流畅性至关重要。通过跟踪 AI 之前的响应(其"助手角色"消息),系统可确保连贯且上下文相关的交互。助手消息也可能包含功能工具调用请求信息。它就像 AI 中的一个特殊功能,在需要执行特定功能(例如计算、获取数据或不仅仅是说话)时使用。
3.4 工具/功能角色(Tool/Function Role):工具/功能角色专注于响应工具调用助手消息返回附加信息。
9.文档检索 (Document Retriever)
DocumentRetriever通常基于向量搜索。它将用户的查询问题(query)转化为Embeddings后,在存储文档中进行相似性搜索,返回相关的片段。片段的用途之一是作为提示词(prompt)的一部分,发送给大模型(LLM)汇总处理后,作为答案呈现给用户。
10.向量存储(Vector Store)
10.1概念
向量存储(VectorStore)是一种用于存储和检索高维向量数据的数据库或存储解决方案,它特别适用于处理那些经过嵌入模型转化后的数据。在 VectorStore 中,查询与传统关系数据库不同。它们执行相似性搜索,而不是精确匹配。当给定一个向量作为查询时,VectorStore 返回与查询向量"相似"的向量。
10.2原理
在将文本内容插入 VectorStore 时,使用 EmbeddingModel 将文本内容转换为数值数组或float[],这一步称为向量 Embedding。EmbeddingModel 用于将单词、句子或段落转换为这些向量 Embeddings。
10.3相似性搜索:
接口中的similaritySearch方法允许检索与给定查询字符串相似的文档,你可以微调相似性搜索的这些参数:
- k:一个整数,指定要返回的相似文档的最大数量。这通常被称为 "top K" 搜索或 "K最近邻"(KNN)。
- threshold:一个值从 0 到 1 的双精度数,接近1的值表示更高的相似性。默认情况下,如果您设置了阈值为0.75,那么只有相似度超过此值的文档才会被返回。
- Filter.Expression:一个用于传递流畅 DSL(特定域语言)表达式的类,其功能类似于 SQL 中的 "where"子句,但它仅适用于Document的元数据键值对。
- filterExpression:基于 ANTLR4 的外部 DSL,接受字符串形式的过滤表达式。例如,对于元数据键如country、year 和isActive,您可以使用如下表达式:country == 'UK' && year >= 2020 && isActive == true。