SpringAI实现AI应用-搭建知识库

SpringAI实战链接

1.SpringAl实现AI应用-快速搭建-CSDN博客

2.SpringAI实现AI应用-搭建知识库-CSDN博客

概述

想要使用SpringAI搭建知识库,就要使用SpringAI中的TikaDocumentReader,它属于ETL(提取、转换、加载)框架中的提取(Extract)阶段。

作用

TikaDocumentReader是Spring AI提供的一个文档读取器,它基于Apache Tika技术实现,能够读取并解析多种格式的文档,包括但不限于PDF、DOC/DOCX、PPT/PPTX和HTML等。这使得TikaDocumentReader成为一个非常灵活和强大的工具,适用于构建知识库或处理各种文档数据。

使用场景

TikaDocumentReader的使用场景非常广泛,包括但不限于:

构建知识库:在构建知识库时,需要从各种格式的文档中提取文本内容。TikaDocumentReader能够轻松地读取这些文档,并将其转换为统一的格式,以便后续的处理和存储。
文档处理:在处理大量文档时,如文档分类、摘要生成等任务中,TikaDocumentReader可以作为一个预处理步骤,将文档内容提取出来,为后续的处理提供便利。
数据清洗:在数据清洗过程中,有时需要从非结构化的文档中提取关键信息。TikaDocumentReader能够读取这些文档,并将其转换为结构化的数据格式,以便进行后续的数据清洗和分析。

准备工作一

在制作本地知识库的时候,还需要安装矢量数据库并下载插件vector,下载矢量化模型

矢量数据库(PostgreSQL)下载地址:EDB: Open-Source, Enterprise Postgres Database Management

插件vector下载地址:vector: Open-source vector similarity search for Postgres / PostgreSQL Extension Network

矢量化模型下载地址:text2vec-base-chinese · 模型库

遇到的问题

问题一

安装完成PostgreSQL之后,想用自带的管理器(pgAdmin4),但是报错,解决了半天没成功,直接改用navicat进行连接,但是连接的时报错(datlastsysoid does not exist),是因为Postgres 15 从pg_database表中删除了 datlastsysoid 字段引发此错误。(我安装的是PostgreSQL17)

解决方式

方法一:升级navicat

方法二:安装Postgres 15以下

方法三:修改navicat的dll文件

详述方法三:找到navicat安装的位置

找到libcc.dll文件(最好进行备份)

使用在线十六进制编辑器打开文件,在线地址:HexEd.it — 基于浏览器的十六进制编辑器

在文件中搜索“SELECT DISTINCT datlastsysoid”,并将其替换为“SELECT DISTINCT dattablespace”

最后另存并替换原来的文件,重启navicat就可以使用了

问题二

安装vector插件的时候遇到的问题,网上也有很多方法,自己百度吧,(真的是一步一个坑)我参考的是:Windows 安装 PostgreSQL 并安装 vector 扩展_win10上安装postgresql的 vector扩展-CSDN博客

问题三

下载矢量化模型

准备工作二

PostgreSQL和插件vector都安装好之后,创建矢量表

CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS hstore;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";CREATE TABLE IF NOT EXISTS vector_store (id uuid DEFAULT uuid_generate_v4() PRIMARY KEY,content text,metadata json,embedding vector(768)
);CREATE INDEX ON vector_store USING HNSW (embedding vector_cosine_ops);

搭建工程

通过第一篇帖子,已经可以创建一个SpringAI的demo了,现在需要将矢量化模型放在resources下

修改pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>SpringAI_Demo</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.5</version><relativePath/> <!-- lookup parent from repository --></parent><properties><java.version>17</java.version><spring-ai.version>1.0.0-M6</spring-ai.version><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><version>${spring-ai.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><!--    常规jar--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--    springAI--><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-openai-spring-boot-starter</artifactId></dependency><!--    向量存储引擎--><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-pgvector-store-spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-transformers-spring-boot-starter</artifactId></dependency><!--   向量库--><dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId></dependency><!--    文档解析器--><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-tika-document-reader</artifactId></dependency><!--    lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><build><resources><resource><directory>src/main/java</directory><!--所在的目录--><includes><!--包括目录下的.properties,.xml 文件都会被扫描到--><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource><resource><directory>src/main/resources</directory><includes><include>**/*.*</include></includes></resource></resources><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>3.2.5</version></plugin></plugins></build><repositories><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository></repositories>
</project>

与第一篇相比,多了如下依赖

每个依赖的作用也已经在文件中加了注释

修改application.yml

server:port: 3210spring:#向量库datasource:url: jdbc:postgresql://localhost:5432/postgresusername: postgrespassword: #数据库密码driver-class-name: org.postgresql.Driverai:#调用ai大模型(可使用本地化部署模型,也可以使用线上的)openai:base-url: https://api.siliconflow.cnapi-key: #你自己申请的keychat:options:model: deepseek-ai/DeepSeek-R1-Distill-Qwen-7B#调用矢量化模型embedding:transformer:onnx:modelUri: classpath:/text2vec-base-chinese/onnx/model.onnxtokenizer:uri: classpath:/text2vec-base-chinese/onnx/tokenizer.json#矢量化配置vectorstore:pgvector:index-type: HNSWdistance-type: COSINE_DISTANCEdimensions: 768

EmbeddingController(矢量化接口)

import org.springframework.ai.document.Document;
import org.springframework.ai.reader.tika.TikaDocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.util.List;import static java.util.stream.Collectors.toList;/*** @Author majinzhong* @Date 2025/4/30 14:00* @Version 1.0*/
@RestController
public class EmbeddingController {@AutowiredVectorStore vectorStore;@PostMapping("/ai/vectorStore")public List<String> vectorStore(@RequestParam(name = "file") MultipartFile file) throws Exception {// 从IO流中读取文件TikaDocumentReader tikaDocumentReader = new TikaDocumentReader(new InputStreamResource(file.getInputStream()));// 将文本内容划分成更小的块List<Document> splitDocuments = new TokenTextSplitter().apply(tikaDocumentReader.read());// 存入向量数据库,这个过程会自动调用embeddingModel,将文本变成向量再存入。vectorStore.add(splitDocuments);return splitDocuments.stream().map(Document::getText).collect(toList());}@GetMapping("/ai/vectorSearch")public List<String> vectorSearch(@RequestParam(name = "text") String text) {List<Document> documents = vectorStore.similaritySearch(SearchRequest.builder().query(text).topK(1).build());return documents.stream().map(Document::getText).collect(toList());}
}

修改SimpleAiController(AI接口)

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;import java.util.List;
import java.util.Map;/*** @Author majinzhong* @Date 2025/4/28 10:37* @Version 1.0* SpringAI对话样例*/
@CrossOrigin
@RestController
public class SimpleAiController {@AutowiredVectorStore vectorStore;// 负责处理OpenAI的bean,所需参数来自properties文件private final ChatClient chatClient;//对话记忆private final InMemoryChatMemory inMemoryChatMemory;public SimpleAiController(ChatClient chatClient,InMemoryChatMemory inMemoryChatMemory) {this.chatClient = chatClient;this.inMemoryChatMemory = inMemoryChatMemory;}/*** 根据消息直接输出回答* @param map* @return*/@PostMapping("/ai/call")public String call(@RequestBody Map<String,String> map) {String message = map.get("message");return chatClient.prompt().user(message).call().content().trim();}/*** 根据消息采用流式输出* @param message* @return*/@PostMapping(value = "/ai/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public Flux<ServerSentEvent<String>> streamChat(@RequestParam(value = "message", defaultValue = "Hello!") String message) {return chatClient.prompt(message).stream().content().map(content -> ServerSentEvent.builder(content).event("message").build())//问题回答结速标识,以便前端消息展示处理.concatWithValues(ServerSentEvent.builder("").build()).onErrorResume(e -> Flux.just(ServerSentEvent.builder("Error: " + e.getMessage()).event("error").build()));}/*** 对话记忆(多轮对话)* @param message* @return* @throws InterruptedException*/@GetMapping(value = "/ai/streamresp", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public Flux<ServerSentEvent<String>> streamResp(@RequestParam(value = "message", defaultValue = "Hello!") String message){Flux<ServerSentEvent<String>> serverSentEventFlux = chatClient.prompt(message).advisors(new MessageChatMemoryAdvisor(inMemoryChatMemory, "123", 10), new SimpleLoggerAdvisor()).stream().content().map(content -> ServerSentEvent.builder(content).event("message").build())//问题回答结速标识,以便前端消息展示处理.concatWithValues(ServerSentEvent.builder("").build()).onErrorResume(e -> Flux.just(ServerSentEvent.builder("Error: " + e.getMessage()).event("error").build()));return serverSentEventFlux;}/*** 整合知识库和自己提问的问题一块向AI提问* @param message* @return*/@GetMapping("/ai/vectorStoreChat")public Flux<String> ollamaApi(@RequestParam(value = "message") String message) {//从知识库检索相关信息,再将检索得到的信息同用户的输入一起构建一个prompt,最后调用ollama apiList<Document> documents = vectorStore.similaritySearch(SearchRequest.builder().query(message).topK(1).build());String targetMessage = String.format("已知信息:%s\n 用户提问:%s\n", documents.get(0).getText(), message);return chatClient.prompt(targetMessage).stream().content();}
}

与第一篇相比,多了如下代码

测试

首先测试上传文件到矢量库

上传成功之后,查看数据库已经有数据了

然后测试查询矢量库

最后测试矢量库和AI统一的接口

再来看一下如果只通过AI进行查询会返回什么(没有矢量库)

如此看来,本地化知识库成功,接下来就剩往里面一直添数据了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/903875.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

内网服务器映射到公网上怎么做?网络将内网服务转换到公网上

如何将内网映射到公网&#xff1f;本地局域网的网络下部署的内网服务地址转换到公网上连接访问是大家比较关注的问题&#xff0c;特别是在无公网IP使用的情况下&#xff0c;很多人不知道怎么做。 在没有公网 IP 的情况下&#xff0c;要将内网映射到公网&#xff0c;以便外网能…

intellij idea最新版git开启Local Changes

习惯了在idea的git插件里&#xff0c;查看项目已修改的文件&#xff0c;但是新版idea默认不展示了&#xff0c;用起来很难受。 参考网上教程开启方法如下&#xff1a; 1. 确保安装Git Modal Commit Interface插件并开启该插件 2. 在Advanced Settings开启Use Modal Commit In…

​​智能制造中的预测性维护:基于深度学习的设备故障预测​​

智能制造中的预测性维护:基于深度学习的设备故障预测 引言 在智能制造领域,设备突发故障可能导致巨大的经济损失。传统维护方式(如定期检修或事后维修)往往效率低下且成本高昂。预测性维护(Predictive Maintenance, PdM)通过实时监测设备状态并预测潜在故障,能够显著减…

DeepSeek+即梦:AI视频创作从0到1全突破

目录 一、开启 AI 视频创作大门&#xff1a;前期准备1.1 注册与登录1.2 熟悉工具界面1.3 硬件与网络要求 二、用 DeepSeek 构思视频脚本2.1 明确创作主题与目标2.2 编写优质提示词2.3 生成并优化脚本 三、即梦 AI 实现画面生成3.1 文生图基础操作3.2 调整参数提升画质3.3 保持人…

初始化列表详解

1.类中包含以下成员&#xff0c;必须放在初始化列表位置进行初始化&#xff1a; 1. 引用成员变量 2.const成员变量 3. 自定义类型成员(且该类没有默认构造函数时 ) 2. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序&#xff0c;与其在初始化列表中的先后次序无关…

基于建造者模式的信号量与理解建造者模式

信号量是什么&#xff1f; AI解释&#xff1a;信号量&#xff08;Semaphore&#xff09;是操作系统中用于 进程同步与互斥 的经典工具&#xff0c;由荷兰计算机科学家 Edsger Dijkstra 在 1965 年提出。它本质上是一个 非负整数变量&#xff0c;通过原子操作&#xff08;P 操作…

开闭原则(OCP)

非常棒的问题&#xff01;&#x1f50d; 开闭原则&#xff08;OCP, Open/Closed Principle&#xff09;是软件设计的核心原则之一&#xff0c;下面我将从定义、意义、优劣分析、Python示例和结构图五个方面完整解析给你。 &#x1f9e0; 什么是开闭原则&#xff1f; 开闭原则&a…

python数据分析(七):Pandas 数据变形与重塑

Pandas 数据变形与重塑全面指南 1. 引言 在数据分析过程中&#xff0c;我们经常需要将数据从一种结构转换为另一种结构&#xff0c;以适应不同的分析需求。Pandas 提供了丰富的数据变形与重塑功能&#xff0c;包括旋转(pivot)、堆叠(stack)、融合(melt)等多种操作。本文将详细…

Android学习总结之jetpack组件间的联系

在传统安卓开发中&#xff0c;UI 组件&#xff08;Activity/Fragment&#xff09;常面临三个核心问题&#xff1a; 生命周期混乱&#xff1a;手动管理 UI 与数据的绑定 / 解绑&#xff0c;易导致内存泄漏&#xff08;如 Activity 销毁后回调仍在触发&#xff09;。数据断层&am…

C++初阶:类和对象(二)

大家好&#xff0c;我是小卡皮巴拉 文章目录 目录 一.运算符重载 1.1 基本概念 定义 参数规则 特性 选择原则 重载要点 二.类的默认成员函数 2.1 构造函数 构造函数的特点 2.2 析构函数 析构函数的特点 2.3 拷贝构造函数 拷贝构造的特点 2.4 拷贝赋值运算符重…

【c++】【STL】priority_queue详解

目录 priority_queue的作用priority_queue的接口构造函数emptysizetoppushpopswap priority_queue的实现仿函数&#xff08;函数对象&#xff09;是什么&#xff1f;向上调整算法&#xff08;adjustup&#xff09;向下调整算法&#xff08;adjustdown&#xff09;迭代器构造pus…

测试——用例篇

目录 1. 测试用例 1.1 概念 2. 设计测试用例的万能公式 2.1 常规思考逆向思维发散性思维 2.2 万能公式 3. 设计测试用例例的方法 3.1 基于需求的设计方法 ​编辑 3.2 具体的设计方法 3.2.1 等价类 3.2.2 边界值 3.2.3 正交法 3.2.4 判定表法 3.2.5 场景法 3.2.6…

销售总监求职简历模板

模板信息 简历范文名称&#xff1a;销售总监求职简历模板&#xff0c;所属行业&#xff1a;其他 | 职位&#xff0c;模板编号&#xff1a;KREUNY 专业的个人简历模板&#xff0c;逻辑清晰&#xff0c;排版简洁美观&#xff0c;让你的个人简历显得更专业&#xff0c;找到好工作…

AE脚本 关键帧缓入缓出曲线调节工具 Flow v1.5.0 Win/Mac

Flow是一个非常好用的After Effects脚本,它可以让你更加轻松自如地调整关键帧的速度曲线,无需触碰老旧复杂的图形编辑器。 AE脚本介绍 Flow为After Effects带来了一个简洁的界面,使自定义动画曲线变得十分容易,无需深入研究速度和影响力这些让人困惑的概念 - 只需绘制一个曲线…

ACGRIME:用于全局优化和特征选择的自适应混沌高斯RIME优化器,附完整版免费代码

自然现象中&#xff0c;软冰的形成过程由 Set al. [42] 提出&#xff0c;软冰是空气中的过冷水滴在接触固体物体并冻结时形成的。这种现象发生在特定的气候条件下&#xff0c;当水蒸气尚未凝结时&#xff0c;导致冰覆盖的表面呈现出独特的树枝状和叶子状景观。它在软冰的生长和…

大模型开发学习笔记

文章目录 大模型基础大模型的使用大模型训练的阶段大模型的特点及分类大模型的工作流程分词化(tokenization)与词表映射 大模型的应用 进阶agent的组成和概念planning规划子任务分解ReAct框架 memory记忆Tools工具\工具集的使用langchain认知框架ReAct框架plan-and-Execute计划…

4.27-5.4学习周报

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract一、方法介绍2.Rainbow Memory(RM)2.1多样性感知内存更新2.2通过数据增强增强样本多样性(DA) 二、使用步骤1.实验概况2.RM核心代码 总结 摘要 本博客概…

AI Rack架构高速互连的挑战:损耗设计与信号完整性的设计框架

在AI驱动的时代&#xff0c;系统设计已经从单一PCB的视角&#xff0c;逐步转向以整个rack为单位来考量。 对于信号完整性而言&#xff0c;焦点以不再局限于单一PCB上的损耗&#xff0c;而是扩展到芯片与芯片之间的端到端互连损耗&#xff08;end-to-end interconnect loss&…

杭电oj(1180、1181)题解

目录 1180 题目 思路 问题概述 代码思路分析 1. 数据结构与全局变量 2. BFS 函数 bfs 3. 主函数 main 总结 代码 1181 题目 思路 1. 全局变量的定义 2. 深度优先搜索函数 dfs 3. 主函数 main 总结 代码 1180 题目 思路 注&#xff1a;当走的方向和楼梯方向一…

软件测试概念

这里写目录标题 需求开发模型软件生命周期瀑布模型螺旋模型增量模型、迭代模型敏捷模型Scrum 测试模型V模型W模型&#xff08;双V模型&#xff09; 需求 用户需求&#xff1a;没有经过合理的评估&#xff0c;通常就是一句话 软件需求&#xff1a;是开发人员和测试人员执行工作…