1.任务要求
| 任务信息 | 截止时间 | 任务明细 |
|---|---|---|
| Task 4: - 开发者篇 D2:统一 AI Native 数据层实战 - 产业应用篇 I3:SQL × AI —— AI Functions 的设计与执行 | 截止时间 09 月 26 日 03:00 | 任务: 1. 通过阅读并跑通 code/D2目录下的d2_1到d2_5示例代码,体验 Data 在 AI 应用里是如何被承载(向量化、存储、查询)的,体验 AI 系统中的混合搜索。2. 通过 pyseekdb向量数据库,执行 AI Function,了解在数据库系统中调用 AI 的方式。 |
2.任务笔记
本节的主要要求是通过阅读并跑通code/D2目录下的d2_1到d2_5示例代码,体验 Data 在 AI 应用里是如何被承载(向量化、存储、查询)的,体验 AI 系统中的混合搜索;以及通过pyseekdb向量数据库,执行 AI Function,了解在数据库系统中调用 AI 的方式。
2.1 DATA在AI应用中如何被承载
到此章,有些疑问还没完全清楚。整理如下:
2.1.1.问题1:为什么要向量化,向量化之后如何查询?
相关回答记录整理为:
1. 为什么要向量化?
传统关键词检索的问题:
- 搜“怎么请年假”,文档里写“休假申请流程”,关键词对不上,但意思一样。
- 搜“苹果手机”,可能命中“苹果种植”,因为都有“苹果”。
- 同义词、缩写、改写、多语言很难靠关键词覆盖。
向量化后: - “怎么请年假”和“休假申请流程”会被映射到相近的向量位置。
- 可以按语义检索、聚类、推荐、去重、分类。
核心价值是:从“字面匹配”升级为“语义匹配”。
2. 一个文档如何向量化?
通常不是把整篇文档变成一个向量,而是切成小块(chunk)后分别向量化。
步骤
① 解析文档
把 PDF、Word、HTML、Markdown 等解析成纯文本,去掉页眉页脚、乱码、广告等。
② 切块 chunking
因为 embedding 模型有输入长度限制,且整篇文档一个向量会丢失细节。常见做法:
- 按标题、段落、语义切分;
- 或按固定长度切,如 300~800 token;
- 块之间加 10%~20% 重叠,避免句子被截断。
例如《员工手册》切成:
- 年假制度
- 报销流程
- 考勤规则
- 加班调休
③ 选择 embedding 模型
常见有:
- OpenAI text-embedding-3
- BGE、M3E、GTE、Jina
- Cohere Embed
- Sentence-BERT 类模型
中文场景常用 BGE、M3E、GTE。要注意:查询和文档必须用同一个模型、同一版本、同一归一化方式。
④ 生成向量
每个 chunk 输入模型,经过 tokenizer、Transformer 编码、池化、归一化,输出一个固定维度向量,比如 768 维、1024 维、1536 维。
例如:
“员工连续工作满一年可享受5天年假,需在OA提交申请。”
→ [0.12, -0.87, 0.33, ..., 0.05]
⑤ 存入向量数据库
保存三部分:
- 向量:用于相似度检索;
- 原文 chunk:命中后返回或喂给大模型;
- 元数据:doc_id、chunk_id、标题、来源、权限、时间等。
常用向量库:FAISS、Milvus、Qdrant、Weaviate、Chroma、Pinecone、pgvector。
向量化之后如何查询命中?
查询流程和文档向量化类似,但对象是用户问题。
① 查询向量化
用户输入:
“年假怎么请?”
用同一个 embedding 模型生成查询向量。
② 相似度计算
在向量库中找和查询向量最接近的文档向量。常用:
- 余弦相似度:越大越相似;
- 点积:归一化后等价于余弦;
- 欧氏距离:越小越相似。
公式:
cos(q, d) = q · d / (|q| * |d|)
③ 近似最近邻检索 ANN
如果文档几百万条,逐条算太慢。向量库会用索引加速:
- HNSW:图索引,快;
- IVF:倒排索引;
- PQ:量化压缩,省内存。
然后返回 top-k,比如最相似的 5~10 个 chunk。
④ 元数据过滤
可以加条件:
只搜“人事制度”分类
只搜用户有权限的文档
只搜 2024 年后的版本
⑤ 重排 rerank
向量召回可能不够准,可以用 cross-encoder 或 reranker 对 top-k 精排,把最相关的排前面。
⑥ 阈值与命中判断
如果最高相似度低于阈值,比如 0.65,就认为“没有命中”,避免强行回答。
⑦ 返回或生成
命中后:
- 直接返回原文片段;
- 或把 top chunks 拼成上下文,交给大模型生成答案。
例如命中:
“员工连续工作满一年可享受5天年假,需在OA提交申请,经主管审批。”
虽然原文没有“怎么请”三个字,但语义匹配成功。
实践建议
- 切块质量决定检索上限:块太大噪声多,太小语义不完整。
- 向量检索 + 关键词检索混合:BM25 + 向量 + RRF 融合,效果通常更好。
- 加 rerank:召回靠向量,精排靠 reranker。
- 保留元数据:权限、来源、时间、标题,查询时可过滤。
- 查询和文档同模型:否则向量空间不一致,相似度无意义。
- 向量化只负责“找”,不负责“答”:生成答案通常由 LLM 完成。
总结成一条链路:
文档 → 解析 → 切块 → Embedding → 向量库
查询 → Embedding → 相似度检索 → 过滤/重排 → 命中片段 → 返回或交给LLM
2.1.2.向量化过程注意事项
向量化过程可以按固定分块,也可按一定策略处理,进阶策略包括:语义分块、动态OVERLAP、父子Chunk等,原因是通过直接分块的方式对文本进行切割不准确,更好的做法是可以用语义进行分割。分割的阈值可以根据文档类型进行调参。相对的,入库成本更高,需要调用Embedding API进行处理。
语义分块适用于结构不清晰、话题跳跃的长文,作为「基础分块效果不够好」时的优化手段。
向量化过程可以采用不同的策略进行处理,不同的输入场景可以选择不同的处理策略。实用策略表为:
| 你的情况 | 推荐策略 | 理由 |
|---|---|---|
| 刚起步 / 文档量小 | 固定 overlap(d2_1 默认方案) | 简单、零额外成本、足够跑通 |
| Markdown / API 文档 / 结构清晰 | 固定 overlap + 按标题预切 | 结构信号比语义 Embedding 更可靠 |
| 边界处经常丢上下文 | 动态 overlap | 成本最低的有效升级 |
| 话题跳跃的无结构长文 | 语义分块 | 按语义边界切,避免硬切 |
| 检索准但 LLM 答不全 | 父子 chunk | 小块检索 + 大块生成 |
| 多种文档类型混合 | 按文档类型路由不同策略 | 异构语料没有 one-size-fits-all |
2.1.3 Embedding 模型选型
做 RAG 检索时,重点看 Retrieval 子任务的得分,不要只看总分。可以参考MTEB 排行榜(Massive Text Embedding Benchmark)选型。MTEB 局限:它主要测纯文本、短文本,不覆盖多模态检索、跨语言检索、维度压缩(MRL)和长文档大海捞针等生产场景。
Recall@K 对比是更贴近业务的验证方式。做法是:准备 20–50 条真实业务查询,标注每条查询应该命中的文档(Ground Truth),分别用不同 Embedding 模型做检索,看正确答案出现在前 K 条结果里的比例。
MTEB 反映的是通用能力,Recall@K 反映的是业务数据上的实际效果。
确定评测方法后,还需要从中英文能力、多模态支持、成本、延迟四个维度缩小候选范围。
注意事项:
1. 入库和查询必须用同一个模型。换模型意味着全量 re-index
2. 查询和文档的编码方式可能不同。
3.bge-m3自带三种检索模式。
4. Embedding 负责初筛,Reranker 负责精排。工业级 RAG 的常见架构是:Embedding 召回 Top-50~100 候选,再用 Reranker 模型(如BAAI/bge-reranker-v2-m3)精排到 Top-10。Embedding 选型解决的是找得到的问题,Reranker 解决的是排得准的问题。
5. 缓存和批量处理能省 80% 的成本。
2.2 混合搜索
混合搜索(Hybrid Search)的核心逻辑:
- 向量搜索负责语义理解:“找意思最接近的内容”
- 全文搜索负责关键词匹配:“找包含这个确切词的内容”
- 关系过滤负责结构化条件:“只在最近更新的文档中找”“只在产品 A 的文档中找”