核心理念:先手动造轮子(去框架化),深度理解数据流转全流程,再谈工程优化。
实验目标
- 完全脱离框架,从零搭建一个可工作的 RAG 系统
- 理解数据流转链路:Text → Embedding → Vector Store → Retrieval → Prompt → Generation
- 掌握核心组件:Embedding模型、向量数据库、LLM API调用
- 培养问题定位能力:当检索效果不佳时,能分析是哪个环节出了问题
实验环境准备
安装依赖
环境测试
✅ 环境测试通过!
sentence-transformers 版本: 5.1.2
FAISS 版本: 1.13.0
NumPy 版本: 2.2.5实验一:数据切分与向量化
实验目标:
将文档切分成可管理的文本块(Chunks),并转换为向量表示。
理论基础
1. 为什么要切分?
- 上下文窗口限制:LLM的输入有长度限制(GPT-4约32K tokens,Claude约200K tokens)
- 检索效率:小块更容易找到精确匹配
- 成本控制:小块减少token数量,降低API调用成本
2. 切分策略
| 策略 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 固定长度 | 简单快速 | 可能切断语义 | 日志、代码 |
| 语义切分 | 保持语义完整 | 实现复杂 | 文档、论文 |
| 递归切分 | 平衡速度与质量 | 需要调参 | 通用场景 |
实验步骤
Step 1: 基础文本切分
原始文本长度: 244
切分成 4 个片段:--- 片段 1 ---
长度: 100人工智能(Artificial Intelligence,AI)是计算机科学的一个分支,
它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器。
包括机器人、语言识别、图像--- 片段 2 ---
--- 片段 3 ---
--- 片段 4 ---
长度: 4
过程。Step 2: 高级语义切分(进阶)
语义切分成 2 个片段--- 片段 1 ---
--- 片段 2 ---
Step 3: 文本向量化
文本块数量: 4
向量维度: (4, 384)
向量类型: <class 'numpy.ndarray'>第一个向量 (前5维): [ 0.01680778 0.04001119 -0.03224989 -0.01100226 -0.02571571]
实验一练习题
- 动手实践:将《西游记》前三回内容(可以从网络获取txt文件)切分成200字符的块,重叠50字符,统计切分结果。
原始文本长度: 22856
切分成 286 个片段:--- 片段 1 ---
--- 片段 2 ---
- 对比实验:使用固定长度切分和语义切分对比,分析哪个在保持语义完整性方面更好。
语义切分成 254 个片段--- 片段 1 ---
--- 片段 2 ---
--- 片段 3 ---
可以发现语义切分在保持语义完整性方面更好。
这不是废话吗qwq
- 思考题:如果chunksize设置过大(如2000字符),会导致什么问题?过小(如50字符)又会导致什么问题?
- chunk
- chunk_size过小:上下文信息丢失,语义不完整,检索结果碎片化,可能影响回答准确性,但检索速度更快、内存占用更低。
- 需要根据实际场景权衡检索质量、性能和成本,合理设置chunk_size和overlap参数。
实验二:向量存储与检索
实验目标:
将向量存储到数据库,实现高效的相似度搜索。
理论基础
1. 向量数据库 vs 传统数据库
| 特性 | 传统数据库 | 向量数据库 |
|---|---|---|
| 索引类型 | B-Tree, Hash | HNSW, IVF, LSH |
| 查询方式 | 精确匹配 | 相似度计算 |
| 距离度量 | =, >, < | 余弦相似度、欧氏距离 |
| 应用场景 | 结构化数据 | 文本、图像、音频等非结构化数据 |
2. 距离度量
- 余弦相似度 (Cosine Similarity):最常用,关注角度而非绝对值
- 欧氏距离 (Euclidean Distance):关注绝对差值
- 点积 (Dot Product):计算速度快,介于两者之间
实验步骤
Step 1: 使用 Faiss 构建简单向量数据库
查询: 什么是深度学习?Top-3 检索结果:
结果 1:
相似度分数: 0.6253
距离: 0.5991
文本: 机器学习是人工智能的子集结果 2:
相似度分数: 0.6068
距离: 0.6480
文本: 深度学习使用多层神经网络结果 3:
相似度分数: 0.5897
距离: 0.6957
文本: 人工智能是计算机科学的重要分支Step 2: 性能对比实验
=== 检索性能基准测试 ===
平均延迟: 0.02 ms
P95 延迟: 0.00 ms
P99 延迟: 0.61 ms
最小延迟: 0.00 ms
最大延迟: 1.00 ms实验二练习题
数据规模实验:分别存储100、1000、10000个文档,测试检索延迟的变化趋势。
Top-K 实验:对同一个查询,分别设置k=1, 3, 5, 10,分析结果质量的变化。
检索质量评估:手动准备10个问题和标准答案,测试你的向量数据库能否返回正确内容。
查询: Claude是哪个公司开发的?Top-3 检索结果:
结果 2:
结果 3:
查询: Anthropic创始人是谁?Top-3 检索结果:
结果 2:
结果 3:
实验三:Prompt 拼接与答案生成
实验目标
将检索到的内容与用户问题拼接,构建完整的Prompt发送给LLM。
理论基础
Prompt 工程核心原则
- 明确性:清晰指定角色和任务
- 结构化:使用格式化的模板
- 约束性:限制回答范围在检索内容内
- 示例驱动:提供Few-shot示例
典型 RAG Prompt 模板
实验步骤
Step 1: 基础 Prompt 拼接
检索到的文档:
文档 1 (相似度: 0.8471):
人工智能是计算机科学的重要分支文档 2 (相似度: 0.6984):
机器学习是人工智能的子集================
================
Step 2: 高级 Prompt 优化
检索到的文档:
人工智能是计算机科学的重要分支
机器学习是人工智能的子集================
================
参考文档: [1][2]
实验三练习题
Prompt A/B 测试:设计两个不同的Prompt模板,对比回答质量。
上下文长度实验:测试不同maxcontextlength对回答质量的影响。
拒绝能力测试:提出一个文档中不存在的问题,检查模型是否诚实回答。
综合实验:完整 RAG 系统
实验目标
整合前三个实验,构建一个完整、可用的RAG系统。
实验任务
任务描述
构建一个小说知识问答系统,能够回答关于《红楼梦》人物关系、情节发展等问题。
数据准备
开始实验
# 实验
rag = NovelRAGSystem()
rag.preprocess_and_index(rag.load_novel_data('hlm.txt'))
-索引完成!
- 总chunk数: 3307
- 向量维度: 384检索到的块:
================
[片段2] 文。及至第三出,只见金童玉女,旗旛宝幢,引着一个霓裳羽衣的小旦,头上披着一条黑帕,唱了几句儿进去了。众皆不知。听见外面人说:“这是新打的蕊珠记里的“冥升”。小旦扮的是嫦娥,前因堕落人寰,几乎给人为配;幸亏观音点化,他就未嫁而逝。此时升引月宫。不听见里头唱的:“人间只道风情好,那知道秋月春花容易抛?几乎不把广寒宫忘却了!””第四出是“吃糠”。第五出是“达摩带着徒弟过江回去”。正扮出些海市蜃楼,好不热闹。
[片段3] 的躺下了。原来宝钗袭人因昨夜不曾睡,又兼日间劳乏了一天,所以睡去,都不曾听见他们说话,此时院中一响,猛然惊醒,听了听,也无动静。宝玉此时躺在床上,心里疑惑:“莫非林妹妹来了,听见我和五儿说话,故意吓我们的?……”翻来覆去,胡思乱想,五更以后,才朦胧睡去。
[片段4] 笑嘻嘻的问道:“你和晴雯姐姐好不是啊?”
[片段5] 五祖宏忍在黄梅,他便充作火头僧。五祖欲求法嗣,令诸僧各出一偈。座神秀说道:“身是菩提树,心如明镜台。时时勤拂拭,莫使有尘埃。”惠能在厨房舂米,听了,道:“美则美矣,了则未了,”因自念一偈曰:“菩提本非树,明镜亦非台。本来无一物,何处染尘埃?”五祖便将衣钵传给了他。今儿这偈语,亦同此意了。只是方才这句机锋,尚未完全了结,这便丢开手不成?”黛玉笑道:“他不能答,就算输了。这会子答上了,也不为出奇了。只是以后再不许谈禅了。连我们两个所知所能的,你还不知不能呢,还去参什么禅呢!”
================
《五美吟》的由来:宝玉看了黛玉的诗后,赞不绝口,并建议将五首诗命名为《五美吟》(片段1中:“恰好只做了五首,何不就命曰《五美吟》?”)。
部分诗句内容:片段1中直接引用了《五美吟》中的两首诗:
- 红拂:诗句为“长剑雄谈态自殊,美人巨眼识穷途。尸居余气杨公幕,岂得羁縻女丈夫?”
- 另一首(未明确人名):前两句为“娇娆?都缘顽福前生造,更有同归慰寂寥。”(从上下文推断,这应属于五首之一,但具体人物未说明)。
其他信息:宝钗在片段1中评论黛玉的诗“命意新奇,别开生面”,并提及前人咏昭君的诗作,但未涉及《五美吟》其他三首诗的具体内容。
结论:基于提供的片段,《五美吟》的内容仅知包括咏红拂和另一未指名女性的诗,其余三首的具体诗句和人物均未出现。片段中无《五美吟》完整内容的描述。
评估指标
# TODO
扩展阅读
必读资源
Faiss 官方指南
- Faiss Wiki - Getting Started
- 理解不同索引类型的适用场景
Sentence-Transformers 文档
- 官方文档
- 学习如何选择合适的预训练模型
RAG 原始论文
进阶资源
Dense Passage Retrieval (DPR)
- DPR Paper
- 学习更好的密集检索方法
HyDE: Hypothetical Document Embeddings
- HyDE Paper
- 了解查询改写技术
向量数据库对比
- Pinecone: Vector Database Guide
- 了解不同向量数据库的特点