☰
RAG 知识库
2026/10/20 5:37:52 网站建设 项目流程

知识库搭建增加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() 都能复用。
2. application.yml 的上传大小限制要调大:现在是 max-file-size: 20MB,既然要"大文件",按实际需求调,比如 500MB。
3. "先中转后演进"的预留:MinioService 里先把 presignedUrl() 方法留好,UploadController 的存储调用抽象在 MinioService 内部——以后切预签名直传时,Controller
只多一个 POST /presign 接口,消费链路完全不动。
4. 幂等要双重保证:DB 层用 uk_file_id 唯一键 + 消费前 isSuccess 判断;Chroma 侧给切片打 fileId metadata,若底层 API 支持按 id 覆盖则更好(Spring AI 2.0 的
VectorStore.add 具体幂等能力需验证)。
5. 环境依赖: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对象

2. 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. 三种向量库对比

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

2. 各自特点与适用场景

Chroma
- 一个命令装好就能跑,API 极简,内置持久化(默认 SQLite)。
- 适合:原型验证、demo、个人项目、小团队 MVP,数据量不大但想快速上线。
- 缺点:不是为高并发/海量数据设计的,规模上去了通常要换。

PGVector
- 最大优势是**"向量 + 关系数据"一体化**:你不需要再维护一个独立的向量库,业务数据和向量数据在同一张表、同一个事务里。例如 SELECT * FROM docs ORDER BY
embedding <=> :q LIMIT 5。
- 适合:已经用 PostgreSQL 的团队、需要强一致性和复杂过滤(向量 + 结构化条件混合查询)的场景。
- 缺点:性能天花板受单机 PG 限制,海量向量规模(亿级)不如专用分布式库。

Milvus
- 功能最全、性能最强:多索引类型、分区、数据分片、流式/批式写入、GPU 加速等。
- 适合:数据量亿级、高并发 QPS、需要水平扩展的生产级系统(如大型知识库、电商以图搜图、推荐系统)。

3. 选型建议

- 快速起步 / 原型 → 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。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询