对于这个项目的 9,586 个块,numpy 数组点积 + pickle BM25 就足够了。搜索延迟小于 100ms,内存使用量约为 29MB(嵌入 14MB + BM25 索引 7.1MB + 标记化语料库 7.6MB)。但当你扩大规模时:
| 块数 | 嵌入尺寸 (384d) | 点积搜索时间 | 问题 |
|---|---|---|---|
| 10K | 14MB | <100毫秒 | 不存在 |
| 10万 | 140MB | 〜500毫秒 | 内存压力开始 |
| 1M | 1.4GB | 〜5秒 | 内存限制、延迟容忍度 |
| 10M | 14GB | 不可能 | numpy 不可能 |
最小更改方法。 在保持当前代码结构的同时提高性能:
| 成分 | 今天 | 改变 |
|---|---|---|
| 矢量搜索 | numpy 点积 | FAISS IndexFlatIP(准确,但经过优化) |
| BM25 | Rank-bm25 泡菜 | 相同(内存中最多可达 50K) |
| 元数据 | JSONL 文件 | SQLite (chunks.db) |
| 创建嵌入 | PyTorch SentenceTransformer | ONNX转换(准备转换脚本:convert_to_onnx.py) |
期限说明:
# FAISS 적용 예시 (embed.py 변경 부분만)
import faiss
# 빌드 시
index = faiss.IndexFlatIP(384) # Inner Product = cosine (정규화 후)
index.add(embeddings)
faiss.write_index(index, "data/faiss.index")
# 검색 시
index = faiss.read_index("data/faiss.index")
scores, indices = index.search(query_embedding, top_k) # GPU도 가능
**引入近似搜索(ANN)。**牺牲一点准确性并获得大量速度:
| 成分 | 选项 A(自托管) | 选项 B(托管) |
|---|---|---|
| 矢量搜索 | FAISS IndexIVFFlat(基于集群) |
Qdrant(Docker) |
| BM25 | Elasticsearch(Docker) | OpenSearch 无服务器 |
| 元数据 | PostgreSQL | Supabase(PostgreSQL + REST API) |
| 创建嵌入 | GPU 服务器上的批处理 | OpenAI text-embedding-3-small API |
| 重新排序 | 本地 bge-reranker | Cohere 重新排序 API |
# FAISS IVF 적용 (100K+ 청크에 효과적)
nlist = 100 # 클러스터 수 (sqrt(N) 정도)
quantizer = faiss.IndexFlatIP(384)
index = faiss.IndexIVFFlat(quantizer, 384, nlist, faiss.METRIC_INNER_PRODUCT)
index.train(embeddings) # 클러스터 학습
index.add(embeddings)
index.nprobe = 10 # 검색 시 탐색할 클러스터 수 (정확도↔속도 트레이드오프)
专用向量数据库+搜索引擎集群:
| 成分 | 选项 | 特征 |
|---|---|---|
| 矢量搜索 | 松果 | 完全托管、无服务器、自动扩展 |
| 韦维阿特 | 内置混合搜索(BM25+密集单查询) | |
| 奎德兰特 | 基于 Rust 的高性能、自托管/云 | |
| pgvector + PostgreSQL | 将向量搜索添加到现有 RDB | |
| 关键词搜索 | Elasticsearch集群 | BM25 + 内置形态分析 (nori/ik) |
| 嵌入 | API服务(OpenAI/Cohere) | 无需本地 GPU,按代币收取费用 |
| 编排 | LangChain/LlamaIndex | 搜索→重新排名→LLM链自动配置 |
当前的 paraphrase-multilingual-MiniLM-L12-v2(384 尺寸)是轻量级的,但精度低于最新型号:
| 模型 | 方面 | 尺寸 | 特征 | 合适的尺寸 |
|---|---|---|---|---|
| MiniLM-L12-v2(当前) | 第384章 | 120MB | 本地运行,50 多种语言 | 〜50K |
bge-m3 (BAAI) |
1024 | 2.2GB | Dense+Sparse+ColBERT 三合一,多语言强大 | 50K~500K |
multilingual-e5-large-instruct |
1024 | 2.2GB | 针对定向查询进行了优化 | 50K~500K |
text-embedding-3-small (OpenAI) |
1536 | 应用程序编程接口 | 低成本API,优秀的多语言 | 10万+ |
embed-multilingual-v3(连贯) |
1024 | 应用程序编程接口 | 100+语言,特殊搜索 | 10万+ |
更换时影响范围:
embed.py的模型名称+调整批量大小embeddings.npy 重新生成(更改尺寸 → 增加文件大小)search.py 不需要更改(numpy 点积是无量纲的)| 方法 | 优点 | 劣势 | 适合的情况 |
|---|---|---|---|
| 全面重建 | 简单且一致 | 随着规模的增加,时间也会增加 | <50K 块,每天一次 |
| 增量添加 | 快速(仅处理更改) | 复杂的删除/编辑管理 | 50K~500K,要求实时 |
| 增量+循环重建 | 实时+质量 | 两系统管理 | 500K+,生产 |
对于此项目,完全重建 9,586 个块就足够了,因为完全重建需要 3-5 分钟。然而,超过 100K 块时,增量索引就变得至关重要。
目前,整个系统在本地运行。将其扩展到外部服务或与团队共享时,请组织每个步骤可用的选项。
| 选项 | 解释 | 合适的环境 |
|---|---|---|
| 文件系统监视 | 使用 watchdog/inotify 检测目录更改 → 自动重新处理 |
当地的、小规模的 |
| Git 网络钩子 | 推送文档存储库时自动从 CI/CD 重建 | 技术文档,IaC |
| Confluence/Notion API 同步 | 使用 REST API 检测更改的页面 → 增量处理 | 企业环境 |
| S3 事件 + Lambda | 将文档上传到 S3 时使用 Lambda 进行分块 + 嵌入 | AWS环境,无服务器 |
| 非结构化.io | PDF/DOCX/PPTX/HTML → 自动转换为结构化文本 | 各种文件格式 |
| 选项 | 解释 | 合适的环境 |
|---|---|---|
| 直接实施(当前) | chunk.py:512 个字符,尊重段落边界 |
当需要域自定义控制时 |
| LangChain 文本分割器 | RecursiveCharacterTextSplitter:Markdown标题识别、代码块保存 |
通用、快速启动 |
| LlamaIndex SentenceSplitter | 尊重句子边界,自动提取元数据 | 普遍的 |
| 非结构化.io | 自动解析文档结构,然后进行基于元素的分块(分离标题、正文、表格和图像标题) | 非结构化文档 |
| 语义分块 | 根据嵌入相似性在意义切换点进行划分 | 没有结构的长文本 |
| 选项 | 费用 | 延迟 | 合适的环境 |
|---|---|---|---|
| 本地句子转换器(当前) | 自由的 | 批量3-5分钟 | 本地开发,<100K |
| 本地ONNX(转换脚本已准备) | 自由的 | 部署约 2 分钟 | 本地、CPU 优化 |
| GPU服务器 | 实例成本 | 部署约 30 秒 | 100K+,频繁重建 |
| OpenAI 嵌入 API | 0.02 美元/100 万代币 | 即时的 | 生产经营负担↓ |
| Cohere 嵌入 API | 0.10 美元/100 万代币 | 即时的 | 多语言专业化 |
| 亚马逊基岩泰坦 | 0.02 美元/100 万代币 | 即时的 | AWS环境 |
| 选项 | BM25 | 稠密 | 杂交种 | 合适的环境 |
|---|---|---|---|---|
| 基于文件(当前) | rank-bm25 pickle(2 个文件:bm25_index + tokenized_corpus) | numpy.npy | 手动求和 | 本地,<50K |
| FAISS + Elasticsearch | 弹性搜索 | FAISS | 单独的求和逻辑 | 自托管,50K~1M |
| 偏离 | 内置BM25 | 内置 HNSW | 自动使用 alpha 参数 |
一体机,50K~10M |
| Qdrant | (需要单独的 ES) | 内置 HNSW | 快速嵌入集成 | 高性能矢量搜索 |
| 松果 | (另外需要) | 室内装饰 | 稀疏+密集支持 | 全面管理、规模化 |
| pgvector + PostgreSQL | pg_trgm/FTS | PG向量 | 使用 SQL 查询求和 | 利用现有的 RDB |
| 选项 | 费用 | 表现 | 合适的环境 |
|---|---|---|---|
| bge-reranker-v2-m3(当前) | 自由的 | 40 名候选人/500 毫秒 | 本地化、多语言 |
| 凝聚重新排名 | $2/1K 搜索 | 40 名候选人/200 毫秒 | 生产,基于 API |
| 吉娜重新排序 | 免费 ~ 付费 | 40 名候选人/300 毫秒 | 多语言、API/本地 |
| ColBERT v2 | 自由的 | 令牌单元匹配 | 长文档,精准匹配 |
| 基于LLM的重新排名 | 代币成本 | 缓慢但极其精确 | 小批量、高价值的搜索 |
使用 RAG 管理有效数据:
| 数据类型 | RAG 拟合优度 | 原因 |
|---|---|---|
| 服务计划 | 高度 | 经常更改,需要版本控制,并且在团队之间共享。 |
| API文档 | 非常高 | 需要准确的术语匹配,版本差异 |
| 入职指南 | 高度 | 解答新员工提出的各种问题 |
| 故障响应手册 | 非常高 | 紧急情况下快速搜索至关重要 |
| 代码审查指南 | 中间 | 对于代码本身,IDE 搜索更适合 |
| 诉讼程序 | 卑微 | 非结构化,仅提取决策后需要结构化 |
| 每日站立笔记 | 非常低 | 短暂的、基于 TTL 的过期处理 |
┌──────────────────────────────────────────────────┐
│ 데이터 소스 │
│ Confluence │ Notion │ Google Docs │ Git (MD) │
└──────┬───────────┬────────────┬──────────────────┘
│ │ │
▼ ▼ ▼
┌──────────────────────────────────────────────────┐
│ 수집 + 정제 레이어 │
│ - API 동기화 (변경분 감지) │
│ - HTML→Markdown 변환 │
│ - 메타데이터 추출 (작성자, 수정일, 라벨, 버전) │
│ - 이전 버전 아카이브 (검색 대상에서 제외) │
│ - 구조 정규화 (헤딩 레벨 통일, 섹션 구분선 삽입) │
└──────────────────┬───────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ 청킹 + 인덱싱 │
│ - 헤딩 기반 청킹 (## 단위로 분할) │
│ - 메타데이터 보존 (문서 제목, 스페이스, 태그) │
│ - 증분 인덱싱 (변경분만 재처리) │
│ - 하이브리드 인덱스 (BM25 + Dense) │
└──────────────────┬───────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────┐
│ 검색 + 활용 │
│ - Slack/Teams 봇: "결제 API 타임아웃 몇 초?" │
│ - AI Agent: 기획서 기반 코드 생성 │
│ - 온보딩 봇: 신규 입사자 질문 대응 │
│ - 장애 대응: 에러 메시지로 해결 방법 검색 │
└──────────────────────────────────────────────────┘
虽然项目和企业环境结构相同,但操作需求不同:
1.访问权限 (ACL)
每个文档的访问权限都不同。工程师不应搜索 HR 文件。
→ 将access_group字段添加到块元数据中,搜索时进行过滤
2.审核日志
您需要跟踪谁搜索了什么。
→ 记录搜索查询+返回结果+用户ID
3. PII(个人信息)屏蔽
计划中包含的个人信息不得因 RAG 而暴露。
→ 添加分块之前的 PII 检测 + 屏蔽管道
4.多租户
每个团队的独立语料库或每个团队结构的共享语料库+专用语料库。
→ 按命名空间分隔语料库,搜索时命名空间过滤器