RAG 知识库

知识库搭建增加kafka+minio+mysql异步解析上传文件到chroma

一. 注意的坑

  1. 大文件 OOM:PDFBox 千万别 loadPDF(file.getBytes()),要流式读取;MinIO 下载也别整读内存。

  2. 幂等:Kafka at-least-once 会重复投递,消费者用 fileId 做去重(Redis SETNX 或查状态),否则同一文件入库两次。

  3. Chroma 幂等:vectorStore.add() 最好能按 fileId 标识切片(metadata 或 Document id),重复消费时覆盖而非重复插入------具体 API 需要在 Spring AI 2.0 里确认。

  4. 消息堆积:大文件解析慢,消费者加并发、必要时拆 topic,别让大文件拖垮队列。

  5. 失败可观测:死信 topic + 状态 FAILED + 错误信息,否则文件"静默丢失"很难排查。

二. 落地顺序建议

  1. 先起 MinIO + Kafka 环境,引入依赖,跑通「存 MinIO → 发 Kafka → 消费打印日志」。

  2. 把解析/切片/入库逻辑从 Controller 迁到 Consumer。

  3. 加状态追踪 + 轮询接口,前端改异步。

  4. 最后补幂等、重试、死信、大文件分片等加固项。

(

  1. 起 MinIO + Kafka + MySQL,引入依赖,MinioService 流式上传/下载跑通。

  2. 建 ingest_task 表 + JPA 实体/仓库/Service。

  3. 改造 UploadController:存 MinIO → 插表 → 发 Kafka;PdfService 改流式。

  4. 写 DocumentConsumer 消费编排,手动 ack + 幂等 + 重试 + 死信。

  5. 加状态查询接口,前端 index.html 改为「上传 → 拿 fileId → 轮询状态」。

  6. 最后补大文件压测、死信监控、失败重投工具。

)

三. 落地建议

  1. PdfService 要加 InputStream 重载:现在它是 readPdf(MultipartFile),内部 Loader.loadPDF(file.getBytes()) 整读内存,大文件会 OOM。改成

readPdf(InputStream) 流式解析,MultipartFile.getInputStream() 和 minioService.download() 都能复用。

  1. application.yml 的上传大小限制要调大:现在是 max-file-size: 20MB,既然要"大文件",按实际需求调,比如 500MB。

  2. "先中转后演进"的预留:MinioService 里先把 presignedUrl() 方法留好,UploadController 的存储调用抽象在 MinioService 内部------以后切预签名直传时,Controller

只多一个 POST /presign 接口,消费链路完全不动。

  1. 幂等要双重保证:DB 层用 uk_file_id 唯一键 + 消费前 isSuccess 判断;Chroma 侧给切片打 fileId metadata,若底层 API 支持按 id 覆盖则更好(Spring AI 2.0 的

VectorStore.add 具体幂等能力需验证)。

  1. 环境依赖:MinIO、Kafka、MySQL 三个中间件要先起起来;Ollama + Chroma 沿用现状。

四. 防止Claude Code卡住,对应的prompt优化

不要继续大范围分析项目,也不要重新设计架构。

连接信息已经确认:

MinIO:

http://8.x.237.x:9000

Kafka:

localhost:9092

MySQL:

localhost:3306

username=root

password=root

现在直接开始第 1 步开发:

  1. 检查 pom.xml 和 application.yml

  2. 配置 MinIO、Kafka、MySQL

  3. 检查并实现 MinioService

  4. 不要安装或下载 MinIO

  5. 不要修改 Docker 中已经运行的 MinIO

  6. 不要重新设计现有 RAG 架构

请边检查边修改代码。

每完成一个小步骤就运行编译/测试验证,不要花几分钟继续思考整个项目。

如果发现配置有问题,直接修复并继续。

现在开始实际编码。

五. MinIo

docker inspect minio | grep -E 'MINIO_ROOT_USER|MINIO_ROOT_PASSWORD'

"MINIO_ROOT_USER=admin",

"MINIO_ROOT_PASSWORD=admin123456",

"MINIO_ROOT_USER_FILE=access_key",

"MINIO_ROOT_PASSWORD_FILE=secret_key",

服务器

┌───────────┴───────────┐

│ │

9000 9001

│ │

↓ ↓

MinIO API MinIO Console

Docker

minio

六. Kafka总结

  1. 为啥Producer和Consumer的key和value都需要序列化?

由于kafka的broker端存的是byte\[\],而不是java对象。

生产者:

Producer:

Java对象

Serializer

byte\[\]

Kafka

消费者:

Kafka

byte\[\]

Deserializer

Java对象

  1. auto-offset-reset: earliest含义?

这个配置和消费者第一次读取 Kafka 消息时从哪里开始读有关。

如果这个消费者组没有找到已经提交的 offset,那么从最早的消息开始消费。

消息:

Kafka:

0 PDF-A
1 PDF-B
2 PDF-C
3 PDF-D
4 PDF-E

七. Chroma / Milvus / PGVector 这三种向量库的区别和联系

  1. 三种向量库对比
Chroma Milvus pgvector
本质 AI/RAG 向量数据库 专业、高性能向量数据库 PostgreSQL 扩展
上手难度 ⭐⭐⭐⭐ ⭐⭐
小型 RAG 非常适合 可以 适合
大规模向量 一般/可扩展 非常强 中大型可用
分布式 支持云/服务化部署 强项 PostgreSQL 集群能力为主
业务数据 JOIN 一般 不是强项 非常强
SQL 不以 SQL 为核心 自己的查询 API 标准 SQL
事务/ACID 不以此为核心 不以此为核心 PostgreSQL 原生能力
Java 后端 可以 很好 很好
RAG 学习 非常推荐 推荐 推荐
企业业务系统 看场景 大规模 AI 场景 业务数据+向量一体化
  1. 各自特点与适用场景

Chroma

  • 一个命令装好就能跑,API 极简,内置持久化(默认 SQLite)。

  • 适合:原型验证、demo、个人项目、小团队 MVP,数据量不大但想快速上线。

  • 缺点:不是为高并发/海量数据设计的,规模上去了通常要换。

PGVector

  • 最大优势是**"向量 + 关系数据"一体化**:你不需要再维护一个独立的向量库,业务数据和向量数据在同一张表、同一个事务里。例如 SELECT * FROM docs ORDER BY

embedding <=> :q LIMIT 5。

  • 适合:已经用 PostgreSQL 的团队、需要强一致性和复杂过滤(向量 + 结构化条件混合查询)的场景。

  • 缺点:性能天花板受单机 PG 限制,海量向量规模(亿级)不如专用分布式库。

Milvus

  • 功能最全、性能最强:多索引类型、分区、数据分片、流式/批式写入、GPU 加速等。

  • 适合:数据量亿级、高并发 QPS、需要水平扩展的生产级系统(如大型知识库、电商以图搜图、推荐系统)。

  1. 选型建议
  • 快速起步 / 原型 → Chroma

  • 已经有 PostgreSQL / 想少维护一套系统 → PGVector

  • 海量数据 + 高并发 + 生产级 → Milvus

一个常见的演进路径是:先用 Chroma 或 PGVector 跑通 → 数据量和 QPS 上来了 → 迁移到 Milvus。

第一种: Chroma

Chroma

专门帮你保存:

vector

text

metadata

Java开发规范.pdf:

切成:

chunk1

chunk2

chunk3

...

chunk100

Embedding:

chunk1 → 0.12, 0.38, ...

chunk2 → 0.25, 0.11, ...

Kafka消费者如何提交offset?

转成向量:query → 0.13, 0.39, ...

Chroma 找最相似的:

chunk17

chunk31

chunk72

然后交给 LLM。

Chroma 官方目前也支持 metadata filtering、dense/sparse/hybrid search 等能力。

第二种:Milvus:专业的向量数据库

官方文档现在把 Milvus 的部署从本地原型一直覆盖到 Kubernetes 大规模分布式系统,并支持 HNSW、IVF、DiskANN 等多种索引和大规模扩展。

比如:

100万向量

1000万向量

1亿向量

10亿向量

这种情况下,Milvus 的优势越来越明显。

架构可能变成:

它本身就是围绕向量检索设计的。

第三种: pgvector

pgvector 和前两个最大的区别是:

它不是一个独立的向量数据库产品,而是 PostgreSQL 的一个扩展。

例如:CREATE EXTENSION vector;

然后:

CREATE TABLE document_chunk (

id BIGSERIAL PRIMARY KEY,

content TEXT,

embedding VECTOR(1536)

);

于是 PostgreSQL 就可以直接存:

普通数据

向量

pgvector 支持精确搜索和近似最近邻搜索,并支持 HNSW、IVFFlat 等索引;同时你还能继续使用 PostgreSQL 的 JOIN、事务、备份等能力。

pgvector 最大的优势:

业务数据和向量可以放一起

比如:

document


id

name

category

tenant_id

created_at

然后:

document_chunk


id

document_id

content

embedding

那么你可以直接:

SELECT *

FROM document_chunk

WHERE tenant_id = 100

ORDER BY embedding <=> '...'

LIMIT 10;

甚至:

文档

JOIN

用户权限

分类

向量相似度

这对企业知识库特别有意义。

pgvector 官方也明确支持和 PostgreSQL 全文搜索一起实现 hybrid search。

相关推荐
全栈弄潮儿3 小时前
AI 生成的代码为什么会“看着对,其实错”
aigc·openai·ai编程
潘锦3 小时前
AI 时代,让自己慢下来
ai编程
小磊哥er4 小时前
深入解构Claude Code - 第 5 篇 · 每次提问都给 AI 塞了什么资料
javascript·ai编程
小磊哥er4 小时前
深入解构Claude Code - 第 4 篇 · 工具:AI 的手
javascript·ai编程
coft5 小时前
Pi Agent 架构与关键功能全解析
ai·ai编程
小磊哥er5 小时前
深入解构Claude Code - 第 3 篇 · 一问一答怎么转起来
javascript·ai编程
小磊哥er5 小时前
深入解构Claude Code - 第 2 篇 · 启动的秘密
javascript·ai编程
Patrick_Wilson8 小时前
Superpowers 与 Codex Harness:冲突分析与治理提示词
agent·ai编程·cursor
小磊哥er9 小时前
深入解构Claude Code - 第 1 篇 · 先认识它
javascript·ai编程