检索与生成的技术(RAG),可以提升文本精准度与企业数据相关性
检索增强生成 (RAG) 是一种技术,它结合了检索模型和生成模型,旨在通过私有或专有的数据源来辅助文本生成。在使用大模型时,一个常见问题是模型可能会产生“幻觉”,即生成的信息可能与事实不符;此外,由于模型通常不包含企业的特定数据,其回答往往缺乏针对性和精确性。RAG 通过引入企业知识库中的信息作为上下文,使得生成的回答更加准确、相关且基于最新的企业数据,从而有效缓解了这些问题。
Spring AI Alibaba :类似Spring cloud alibaba的Spring AI最佳实践
Spring AI Alibaba 是一个专为 Java 和 Spring Boot 生态系统设计的应用框架,旨在将 Spring 的设计理念应用到人工智能领域。
Spring ai 由 Spring 官方团队维护,确保了高质量和稳定性。
其核心优势在于提供了统一的接口来标准化不同AI提供商(如OpenAI、阿里云等)的服务接入方式,使开发者能够通过简单的配置切换不同的AI实现。
此外,Spring AI Alibaba 结合了阿里云的最佳实践,特别是与百炼平台的深度集成,支持多种生成式AI能力,包括对话、文生图、文生语音等功能,极大地简化了在Spring Boot项目中引入和使用AI功能的过程。
构建RAG后端服务:从PDF到智能对话
检索增强的后端代码编写
根据提供的我了解的信息,为了通过检索增强(RAG)的方式读取一个名为专家答疑文档.pdf
的PDF文件、构建向量索引,并对外提供服务,我们需要遵循一定的步骤来完成环境准备与编码实现。首先确保你的开发环境满足以下要求:
- JDK版本:需在JDK 17或以上。
- Spring Boot版本:需要3.3.x或更高版本。
- 阿里云API Key获取:按照我了解的信息中的指引,在阿里云申请并记录下通义千问的API Key。
环境配置
配置仓库
由于Spring AI Alibaba当前使用的某些组件尚未正式发布到Maven中央仓库,你需要添加Spring官方维护的仓库到你的项目中:
<repositories>
<repository>
<id>sonatype-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots><enabled>false</enabled></snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases><enabled>false</enabled></releases>
</repository>
</repositories>
添加依赖
接下来,添加必要的依赖项以支持RAG功能以及与阿里云大模型的交互:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.4</version>
</parent>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
<version>1.0.0-M2</version>
</dependency>
<!-- 其他所需依赖 -->
</dependencies>
API Key配置
将从阿里云获得的API Key设置为环境变量或者直接在application.properties
里指定:
spring.ai.dashscope.api-key=这里填写你的API Key
RAG服务实现
创建一个名为RagService
的服务类,用于处理RAG相关的逻辑,包括初始化向量存储和文档检索器等:
public class RagService {
private final ChatClient chatClient;
private final VectorStore vectorStore;
private final DashScopeApi dashscopeApi = new DashScopeApi("这里填写你的API Key");
DocumentRetriever retriever;
public RagService(ChatClient chatClient, EmbeddingModel embeddingModel) {
this.chatClient = chatClient;
vectorStore = new DashScopeCloudStore(dashscopeApi, new DashScopeStoreOptions("专家答疑库"));
retriever = new DashScopeDocumentRetriever(dashscopeApi,
DashScopeDocumentRetrieverOptions.builder().withIndexName("专家答疑库").build());
}
public String buildIndex() {
String filePath = "专家答疑文档.doc";
DocumentReader reader = new DashScopeDocumentCloudReader(filePath, dashscopeApi, null);
List<Document> documentList = reader.get();
vectorStore.add(documentList);
return "SUCCESS";
}
public StreamResponseSpec queryWithDocumentRetrieval(String message) {
StreamResponseSpec response = chatClient.prompt()
.user(message)
.advisors(new DocumentRetrievalAdvisor(retriever, DEFAULT_USER_TEXT_ADVISE))
.stream();
return response;
}
}
其中,DEFAULT_USER_TEXT_ADVISE
应定义为包含{documents}
占位符的字符串模板,以便后续替换实际文档内容。
控制器实现
最后,创建一个控制器类,公开/buildIndex
和/steamChat
两个接口,分别对应索引构建和服务请求:
@RestController
@RequestMapping("/ai")
public class RagController {
private final RagService ragService;
public RagController(RagService ragService) {
this.ragService = ragService;
}
@GetMapping("/buildIndex")
public String buildIndex() {
return ragService.buildIndex();
}
@GetMapping("/steamChat")
public Flux<String> steamChat(@RequestParam(value = "input", required = true) String input,
HttpServletResponse httpResponse) {
httpResponse.setCharacterEncoding("UTF-8");
return ragService.queryWithDocumentRetrieval(input).content();
}
}
通过上述步骤,你已经成功搭建了一个基于Spring AI Alibaba框架的应用程序,它能够利用RAG技术从给定的PDF文件中提取信息,并通过指定的URL对外提供智能对话服务。记得首次启动应用时先访问http://localhost:8080/ai/buildIndex
来构建索引,之后就可以正常调用聊天接口了。
流式数据处理:React构建实时聊天应用教程
检索增强的前端代码编写
分析问题的原因
要基于React构建一个简单的支持流输出(如flux<String>
)的项目,首先需要确保后端接口能够以流的形式返回数据。本案例中给定的后端接口为http://localhost:8080/ai/steamChat?input=…
,它应该已经配置好能够处理请求并返回流式响应。
在React前端部分,关键在于如何正确地读取这个流,并将获取到的信息实时展示给用户。根据我了解的信息中的内容,我们可以了解到如何创建基础的React应用框架以及如何通过Fetch API与后端交互来实现这一目标。特别地,对于流式响应,我们需要使用ReadableStream
相关API来逐块接收数据,并即时更新UI。
构建并运行项目的步骤
由于我了解的信息提供了构建基本React项目的方法和所需代码,这里直接给出基于上述要求的具体实现步骤:
- 初始化新的React应用:
npx create-react-app frontend
cd frontend
npm install
- 编辑公共HTML文件 (
public/index.html
) 和入口JavaScript文件 (src/index.js
),这部分保持默认或按需修改即可。
- 开发主要组件 (
src/App.js
和src/components/ChatComponent.js
) 用于显示聊天界面及处理逻辑:
-
App.js
主要是容器作用。
-
ChatComponent.js
实现了输入消息、发送消息、清除消息的功能,特别是从服务器异步获取流数据的部分。
- 在
ChatComponent.js
中实现对流的支持,参考如下代码片段:
// ... 其他import语句
function ChatComponent() {
const [input, setInput] = useState('');
const [messages, setMessages] = useState('');
const handleSendMessage = async () => {
try {
const response = await fetch(`http://localhost:8080/ai/steamChat?input=${input}`);
if (!response.ok) throw new Error('Network response was not ok');
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
let done = false;
while (!done) {
const { value, done: isDone } = await reader.read();
done = isDone;
const chunk = decoder.decode(value, { stream: true });
setMessages(prev => prev + chunk);
}
} catch (error) {
console.error('Failed to fetch', error);
}
};
// ...其他函数定义
return (
<div>
{/* 输入框、按钮等元素 */}
<pre>{messages}</pre> {/* 显示消息区域 */}
</div>
);
}
export default ChatComponent;
- 启动应用程序:
npm start
对步骤的解释
- 步骤1至2是标准的新React项目搭建流程。
- 步骤3和4专注于聊天功能的实际实现。特别是,在处理来自服务器的流时,我们使用了
fetch
发起HTTP请求,然后利用ReadableStream
的getReader()
方法读取流中的数据块,并通过TextDecoder
将其转换成可读文本格式。每当收到新的数据块时,就更新状态变量messages
,从而触发组件重新渲染,让用户看到最新的消息。
- 最后一步启动本地开发服务器,使你可以在浏览器中查看你的工作成果。