为文档集建立索引
为每个分块生成嵌入并将向量存入索引,这是任何 RAG 系统的离线准备步骤。
为文档集建立索引 是 CoddyKit 上的免费 AI Agents 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Agents 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Agents 课程共包含 4 节课。
数据摄取流程
离线 RAG 流程包含四个步骤:
- 加载文档(PDF、HTML、MD)
- 分块每份文档
- 生成嵌入每个分块
- 存储向量和元数据到索引中
第 1 步:加载文档
针对不同格式使用专用加载器:
# PDFs
from pypdf import PdfReader
text = ''
for page in PdfReader('doc.pdf').pages:
text += page.extract_text()
# HTML
from bs4 import BeautifulSoup
text = BeautifulSoup(html, 'html.parser').get_text()
# Markdown — just read the file
text = open('doc.md').read()第 2 步:分块
使用上一课中的拆分器:
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(chunk_size=800, chunk_overlap=100)
chunks = splitter.split_text(text)第 3 步:批量生成嵌入
每次 API 调用生成多个分块的嵌入:
from openai import OpenAI
client = OpenAI()
def embed_batch(texts, batch_size=100):
vectors = []
for i in range(0, len(texts), batch_size):
batch = texts[i:i + batch_size]
resp = client.embeddings.create(model='text-embedding-3-small', input=batch)
vectors.extend(d.embedding for d in resp.data)
return vectors第 4 步:存储
对于 1 万到 5 万个分块,FAISS 或 Chroma 就足够了:
import chromadb
client = chromadb.Client()
collection = client.create_collection('docs')
collection.add(
ids=[f'doc-{i}' for i in range(len(chunks))],
embeddings=vectors,
documents=chunks,
metadatas=[{'source': 'doc.pdf', 'page': i} for i in range(len(chunks))]
)幂等数据摄取
确保数据摄取可以安全地重复运行。使用确定性的标识符(内容的哈希值),这样重复运行就不会产生重复数据:
import hashlib
def chunk_id(source, text):
h = hashlib.sha256(text.encode()).hexdigest()[:16]
return f'{source}:{h}'
print(chunk_id('handbook.pdf', 'Employees get 20 vacation days per year.'))
print(chunk_id('handbook.pdf', 'Employees get 20 vacation days per year.'))
增量更新
当文档发生变化时:
- 计算新的分块
- 将其与现有标识符进行差异比较
- 删除已移除的内容,add 新内容,保留未更改的内容
朴素的方法(全部删除后重新插入)适用于小型语料库,但会浪费嵌入 API 调用。
用于过滤的元数据
包含今后可能需要用于过滤的所有字段:
metadata = {
'source': '/docs/handbook.pdf',
'page': 42,
'department': 'engineering',
'updated_at': '2024-08-12',
'access_level': 'internal'
}
for k, v in metadata.items():
print(f"{k}: {v}")
进度与检查点
对于大型数据摄取任务,请记录进度并创建检查点:
for i, batch in enumerate(batches):
embed_and_store(batch)
if i % 10 == 0:
save_checkpoint(i)
print(f'Processed {i * 100} chunks')速率限制
OpenAI 嵌入 API 的速率限制很高,但确实存在。请使用信号量或 `tenacity` 重试:
from asyncio import Semaphore
sem = Semaphore(10) # 10 concurrent embed calls max
async def safe_embed(batch):
async with sem:
return await client.embeddings.create(...)检查索引是否正常
数据摄取完成后,运行几次测试查询并手动检查结果。如果没有返回任何相关内容,说明您的分块或嵌入过程存在问题——请在用户发现之前找出原因。
索引版本管理
为索引设置版本,这样您就可以在不中断服务的情况下切换到新的分块方式或嵌入模型:
collection = client.create_collection(f'docs-v2-{date.today()}')
# old collection stays live until new one is validated幂等标识符
为什么要使用内容哈希作为分块标识符?
回顾
加载 -> 分块 -> 生成嵌入 -> 存储,并使用幂等标识符和元数据。索引是所有后续检索步骤的基础。
常见问题解答
「为文档集建立索引」课时是免费的吗?
是的 — 「为文档集建立索引」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Agents 课程的其余内容,请升级到 CoddyKit PRO。 AI Agents 课程共包含 4 节课。
「为文档集建立索引」这节课中我会学到什么?
为每个分块生成嵌入并将向量存入索引,这是任何 RAG 系统的离线准备步骤。 你通过在浏览器中直接运行的动手代码来练习 AI Agents,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 AI Agents 需要有经验吗?
无需任何先前经验。CoddyKit 上的 AI Agents 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「为文档集建立索引」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 AI Agents 课中编写并运行代码吗?
能。每节 AI Agents 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。