Spring AI(11) :ChatPDF-向量数据库、PDF处理、向量写入和向量搜索
本章代码已分享至Gitee:https://gitee.com/lengcz/ai-study.git文章目录向量数据库Spring AI 支持的向量数据库有哪些Spring AI 中如何使用向量数据呢(以redis stack为例安装redis stack引入依赖配置文件如何使用配置SimpleVectorStore(简单的内存向量模型)文档处理和向量写入读取完成文档拆分这个Document有什么组成PDF Reader(示例)向量搜索按照文本的向量搜索增加配置的向量搜索向量数据库向量数据库的核心作用是‌实现语义层面的相似性检索‌区别于传统数据库的字面精确匹配能快速找到“含义最贴近”的数据是AI时代的关键基础设施。核心基础能力‌它可将文本、图片、音视频等非结构化数据转化为高维向量通过余弦相似度、欧氏距离计算向量间的接近程度完成高效的相似性匹配检索支持亿级规模向量的毫秒级查询。主流落地场景‌支撑RAG检索增强生成为大模型对接外部知识库大幅缓解大模型“幻觉”问题提升回答的准确性和时效性。应用于推荐系统基于用户兴趣向量实现精准的内容、商品匹配推送。落地以图搜图、语音/视频内容检索、异常检测等场景完成多模态数据的快速相似查找。Spring AI 支持的向量数据库有哪些官网文档地址 https://docs.spring.io/spring-ai/reference/1.0/api/vectordbs.htmlVectorStore 的实现Spring AI支持以下向量数据库数据库名称官方描述数据库类型适用场景 / 特点Azure Vector SearchThe Azure vector store.云服务全托管深度集成Azure生态适合微软云用户Apache CassandraThe Apache Cassandra vector store.NoSQL宽列高可用、大规模分布式写入适合海量数据ChromaThe Chroma vector store.专用向量数据库轻量级、开源适合本地开发和原型验证ElasticsearchThe Elasticsearch vector store.搜索引擎已有ES集群需同时支持全文检索向量检索GemFireThe GemFire vector store.企业级内存数据库VMware生态高性能缓存与实时计算场景MariaDBThe MariaDB vector store.关系型 (SQL)基于MySQL分支适合小型到中型数据量MilvusThe Milvus vector store.专用向量数据库高性能、分布式适合大规模生产环境MongoDB AtlasThe MongoDB Atlas vector store.NoSQL文档JSON文档存储与向量检索结合灵活易用Neo4jThe Neo4j vector store.NoSQL图数据库需同时处理知识图谱/关系网络与向量检索OpenSearchThe OpenSearch vector store.搜索引擎AWS开源版ES适合云上与全文检索融合OracleThe Oracle Database vector store.关系型 (SQL)企业级重型数据库适合已有Oracle栈的客户PgVectorThe PostgreSQL/PGVector vector store.关系型 (SQL)Postgres扩展最适合已用PG的技术栈PineconeThe PineCone vector store.专用向量数据库云原生全托管、低延迟适合SaaS和Serverless应用QdrantThe Qdrant vector store.专用向量数据库高性能、Rust编写支持过滤和Payload丰富RedisThe Redis vector store.NoSQL键值/缓存实时性要求极高需结合缓存与向量检索SAP HanaThe SAP HANA vector store.企业级内存列式数据库已有SAP生态需进行实时分析和向量融合TypesenseThe Typesense vector store.搜索引擎轻量、易用追求开箱即用的搜索体验WeaviateThe Weaviate vector store.专用向量数据库内置GraphQL支持混合搜索和自动向量化SimpleVectorStoreA simple implementation… good only for testing.内存级测试实现仅限开发/单元测试不适用于生产Spring AI 中如何使用向量数据呢(以redis stack为例注意这里的redis 不是指redis缓存服务器是指redis stack。官网文档地址: https://docs.spring.io/spring-ai/reference/1.0/api/vectordbs/redis.html安装redis stack这里为了方便提供docker命令安装dockerrun-d--nameredis-stack-p6379:6379-p8001:8001 redis/redis-stack:latest引入依赖dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-vector-store-redis/artifactId/dependency配置文件spring:data:redis:url:127.0.0.1:6379ai:vectorstore:redis:initialize-schema:true#向量库索引名index-name:my_doc_ai_index#是否初始化向量向量索引结构prefix:doc:#向量库key浅醉如何使用Spring AI已经为所有向量数据库统一了一套接口都实现了VectorStore各向量数据库除了依赖和配置有差异外使用方式都相同。以下是 VectorStore接口的定义/** * 向量存储接口用于管理文档的向量化表示及其持久化。 * 提供添加、删除以及基于向量相似度的检索能力。 * 继承自 {link DocumentWriter}支持文档写入操作。 */publicinterfaceVectorStoreextendsDocumentWriter{/** * 获取当前向量存储实例的名称。 * 默认实现返回类的简单名称不含包路径。 * * return 存储实例的名称默认使用类名 */defaultStringgetName(){returnthis.getClass().getSimpleName();}/** * 批量添加文档到向量存储中。 * 实现类需将文档内容转换为向量表示并存储同时保存元数据以便后续检索。 * * param documents 要添加的文档列表不能为空 */voidadd(ListDocumentdocuments);/** * 根据文档 ID 列表批量删除文档。 * * param idList 要删除的文档 ID 列表 */voiddelete(ListStringidList);/** * 根据过滤表达式删除符合条件的文档。 * 使用结构化过滤表达式如字段比较、逻辑组合进行条件删除。 * * param filterExpression 过滤表达式定义删除条件 */voiddelete(Filter.ExpressionfilterExpression);/** * 根据字符串形式的过滤表达式删除文档默认实现。 * 提供一种便捷的字符串表达式解析方式具体语法由子类实现。 * 默认实现抛出 {link UnsupportedOperationException}建议子类覆写。 * * param filterExpression 字符串形式的过滤表达式 */defaultvoiddelete(StringfilterExpression){// 默认实现为空或抛出异常这里以省略号表示原有逻辑thrownewUnsupportedOperationException(String filter expression not supported by default.);}/** * 执行基于向量相似度的搜索使用默认的查询向量由 query 字符串生成。 * 返回与查询最相似的文档列表通常按相似度降序排列。 * * param query 查询文本将自动转换为向量 * return 与查询相似的文档列表 */ListDocumentsimilaritySearch(Stringquery);/** * 执行基于向量相似度的搜索支持丰富的搜索参数。 * 可以通过 {link SearchRequest} 指定查询向量、返回数量、过滤条件、相似度阈值等。 * * param request 搜索请求对象封装所有检索参数 * return 符合搜索条件的文档列表 */ListDocumentsimilaritySearch(SearchRequestrequest);/** * 获取底层原生客户端的可选实例。 * 当向量存储基于某个第三方库如 Elasticsearch、Pinecone 等实现时 * 可通过此方法暴露原始客户端以便进行高级操作。 * 默认返回 {link Optional#empty()}表示不支持或无需暴露。 * * param T 原生客户端类型 * return 包含原生客户端的 Optional若不存在则为空 */defaultTOptionalTgetNativeClient(){returnOptional.empty();}}配置SimpleVectorStore(简单的内存向量模型)SimpleVectorStore 仅用于学习请勿用于生产和测试引入依赖dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-vector-store/artifactIdversion${spring-ai.version}/version!-- 请使用实际的 Spring AI 版本 --/dependency配置SimpleVectorStoreBeanpublicVectorStorevectorStore(OpenAiEmbeddingModelmodel){returnSimpleVectorStore.builder(model).build();}文档处理和向量写入读取完成文档拆分这里文档需要经过读取转换写入 三个操作实现文档写入到向量数据库。这个Document有什么组成Document的组成id: 文档的idcontent: 内容metadata: 元数据文件名文件大小创建时间修改时间等Media: 媒体就是音频视频等文件而针对Document Reader 文档读取过程spring-ai已经提供了很多相关的Reader支持不同文件类型的读取解析。JSONTextMarkdownPDF PagePDF ParagraphTika(DOCXPPTHTML…PDF Reader(示例)其他Document Reader 请参考官网文档https://docs.spring.io/spring-ai/reference/1.0/api/etl-pipeline.html#page-titlespring ai 提供了针对不同文件类型的Document Reader根据不同文档类型引入不同的依赖PDF 这里引入的依赖!--Document Reader 针对Pdf 的reader--dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-pdf-document-reader/artifactId/dependency读取并写入到向量数据库TestvoidwriteFileToVectorStore(){// 1. 准备 PDF 资源从 classpath 加载ResourcepdfResourcenewClassPathResource(40、狂神说Docker.pdf);// 2. 配置 PDF 读取器可选PdfDocumentReaderConfigconfigPdfDocumentReaderConfig.builder().withPageExtractedTextFormatter(ExtractedTextFormatter.defaults())// 每页最大词数.withPagesPerDocument(1)//每1页作为一个Document.build();// 3. 创建 PagePdfDocumentReader 实例PagePdfDocumentReaderpdfReadernewPagePdfDocumentReader(pdfResource,config);// 4. 读取 PDF 文档返回 Document 列表Listorg.springframework.ai.document.DocumentdocumentspdfReader.get();// 或使用 pdfReader.read()// 5. 验证读取结果System.out.println(读取到 documents.size() 页文档);// 7. 写入向量数据库vectorStore.add(documents);// 8. 验证写入结果System.out.println(成功写入 documents.size() 个文档块到向量数据库);ListDocumentresultvectorStore.similaritySearch(谁创办了Docker);if(nullresult){System.out.println(没有找到结果);return;}System.out.println(搜索结果);result.forEach(c-{System.out.println(c.getId());System.out.println(c.getScore());System.out.println(c.getText());});}测试用例运行结果PDF 除了按页读取的PagePdfDocumentReader 还有ParagraphPdfDocumentReader 按大纲读取但是很多PDF文件不规范没有大纲标题会导致读取失败。向量搜索按照文本的向量搜索ListDocumentresultvectorStore.similaritySearch(谁创办了Docker);if(nullresult){System.out.println(没有找到结果);return;}System.out.println(搜索结果);result.forEach(c-{System.out.println(c.getId());System.out.println(c.getScore());System.out.println(c.getText());});这里搜出了4页但是实际上一些结果并不相关我们并不想要关联度不是很高的结果。增加配置的向量搜索 使用vectorStore我们已经配置了向量模型故在写向量和搜索向量时并不需要我们显式的进行向量化操作而是由其内部完成向量化转换。// 8. 验证写入结果System.out.println(成功写入 documents.size() 个文档块到向量数据库);SearchRequestrequestSearchRequest.builder().query(谁创办了Docker)//匹配关键词.topK(2)//相似度最高的前几名.similarityThreshold(0.7)//相似度阈值.filterExpression(file_name 40、狂神说Docker.pdf)//过滤项目,表示搜索元数据里面文件名是40、狂神说Docker.pdf的文档.build();// ListDocument result vectorStore.similaritySearch(谁创办了Docker);ListDocumentresultvectorStore.similaritySearch(request);if(nullresult){System.out.println(没有找到结果);return;}System.out.println(搜索结果);result.forEach(c-{System.out.println(c.getId());System.out.println(c.getScore());System.out.println(c.getText());});经过这些过滤条件我们可以看到只搜索到一条记录。

相关新闻

Unity转微信小游戏:从WebGL打包到真机性能优化的完整避坑指南

Unity转微信小游戏:从WebGL打包到真机性能优化的完整避坑指南

1. 项目概述:Unity转微信小游戏的必经之路 如果你是一个Unity开发者,想把辛苦开发的项目搬到微信小游戏上,那你大概率已经听过“WebGL打包”和“真机调试”这两个词了。这听起来像是一条标准流水线:Unity导出WebGL,然后…

2026/10/13 13:26:02 阅读更多 →
AI Skills生态:从工具调用到智能体开发的核心实践

AI Skills生态:从工具调用到智能体开发的核心实践

1. 项目概述:当AI需要“工具箱”最近和几个做AI应用开发的朋友聊天,发现一个挺有意思的现象:大家手里的模型,无论是GPT-4、Claude还是国内的一些大模型,能力都很强,但真要用它们去解决一个具体的、复杂的业…

2026/10/8 21:36:34 阅读更多 →
GitHub趋势榜深度解析:从AI调试到云原生开发,2026年2月十大热门项目

GitHub趋势榜深度解析:从AI调试到云原生开发,2026年2月十大热门项目

1. 榜单背后的风向标:为什么开发者都在关注GitHub趋势?每个月月初,GitHub Trending页面的更新总能吸引全球开发者的目光。这不仅仅是一个简单的项目热度排行榜,更像是一份由全球数百万开发者共同投票产生的“技术雷达”。它实时反…

2026/10/2 3:23:44 阅读更多 →

最新新闻

全国省县界线shp数据处理:坐标系、属性表与拓扑避坑指南

全国省县界线shp数据处理:坐标系、属性表与拓扑避坑指南

简介:这份全国省、县界线shp格式矢量图面向地理信息、城乡规划、地图可视化及空间数据分析方向的从业者与学习者,精确到县区域,可用于行政区划底图制作、专题制图、区域统计与GIS空间叠加分析等场景,省界与县界两级数据可满足从宏…

2026/10/13 13:25:59 阅读更多 →
Kafka Exactly-Once 实战:幂等生产者与事务如何实现消息不重不漏?

Kafka Exactly-Once 实战:幂等生产者与事务如何实现消息不重不漏?

做后端和中间件这几年,最头疼的问题之一就是“消息不重不漏”。尤其当你处理的账务数据、商品库存、用户积分直接和真金白银挂钩时,一条消息重复消费和丢失消费,后果截然不同,轻则数据对不上,重则出现资损事故。Kafka …

2026/10/13 13:25:59 阅读更多 →
增量小样本目标检测iFSOD:特征校准与分类器扩展实战解析

增量小样本目标检测iFSOD:特征校准与分类器扩展实战解析

1. 为什么增量小样本目标检测值得单独写一篇笔记目标检测这个方向,常规套路已经相当成熟了。你拿一个 backbone,接上检测头,准备一批标注数据,训上几十上百个 epoch,基本都能拿到一个能用的模型。但现实场景很少这么理…

2026/10/13 13:25:59 阅读更多 →
基于Python的B站热门视频数据分析与可视化系统

基于Python的B站热门视频数据分析与可视化系统

做内容数据研究的人,最忌讳的就是只盯着榜单表面的数字——榜首播放量1000万,第十名300万,这种结论谁都看得见。真正有价值的信息藏在数字背后:同样是百万播放,为什么有的视频评论区热闹得像过年,有的却冷冷…

2026/10/13 13:25:59 阅读更多 →
堆叠注入原理与实战:从SQLi-Labs看多语句执行的本质

堆叠注入原理与实战:从SQLi-Labs看多语句执行的本质

1. 为什么堆叠注入是SQLi-Labs里最被低估的“实战分水岭”在某高校网络安全实训课上,我带过一批刚学完基础联合查询和报错注入的学生。当他们第一次打开Sqli-Labs的Less38页面,看到那个看似普通的id1参数时,几乎所有人都下意识地输入1 and 11…

2026/10/13 13:24:58 阅读更多 →
人体姿态估计Stacked Hourglass调优实战:堆叠、监督与热图后处理

人体姿态估计Stacked Hourglass调优实战:堆叠、监督与热图后处理

做人体姿态估计的项目久了,你会发现一个挺有意思的现象:很多人在跑通 Stacked Hourglass 之后,第一反应是“哦,就是把多个沙漏模块串起来”,但真到调优的时候就懵了——为什么堆叠数量增加,精度提升却不成比…

2026/10/13 13:24:58 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →