开始前,会这些就够了
- 会在终端运行 Python 文件
- 了解字符串、列表和字典
遇到不熟悉的词,先看这 2 个解释
- RAG(检索增强生成)
- 先从外部材料中检索有关内容,再让生成模型结合这些内容回答的做法。它把找到资料与组织答案连接起来,便于利用可更新的材料,无需把每次更新都训练进参数。
- 引用
- 在生成答案的具体说法旁标出依据,让读者能返回原文检查。有效引用需要对应真实来源、相关段落和所支持的结论,不能只给一个看起来权威的链接。
假设你要从几份学习规则里查“借阅期限”。系统找到两句话:一份说十四天,另一份说二十一天。两句都很像问题,也都有日期。接下来真正需要检查的是:它找到了哪些原文,为什么排序靠前,以及这些材料是否足够支持一个结论。
这个微项目把过程缩小到八份明确虚构的材料,用本地程序返回匹配片段。它不调用大模型、接口或网络,也不生成回答。你可以看清每一分来自哪个词项,再观察近义词、否定句和版本冲突为什么不能只靠字面匹配解决。
把例子带到自己的电脑上
下载完整练习包
需要 Python 3.10 或更新版本。使用标准库,不需要安装第三方包。下载 ZIP 后选择“全部提取”,进入能看到 README.md 的文件夹。
下载 ZIP · 4 个文件包里有什么
- search.py:本地词项检索
- verify.py:自动验证
- notes.json:八份虚构材料
- README.md:中文操作步骤
在这个文件夹打开 PowerShell,逐行运行
python --version
python search.py "借阅期限"
python verify.py先预测会找到哪份材料,再运行查询并核对原文。这个练习不调用大模型、不生成回答;命中分数只用来观察字面匹配。
找不到命令或文件时,先按 README 检查环境和所在目录。文中标出的阅读时间只估算文章篇幅,安装环境和动手练习可按自己的节奏进行。
先写预测,再启动程序
下载并解压后,确认 search.py、verify.py、notes.json 和 README.md 位于同一文件夹。打开 Windows PowerShell,从它的上一级运行 Set-Location .\workshop-retrieval,再运行 python --version,确认使用 Python 3.10 或更高版本;不需要安装第三方库。
先不要急着打开结果。写下三个预测:搜索“借阅期限”会返回哪份材料,搜索“借书”能否找到同义内容,搜索“允许携带饮料”会不会排除否定句。然后运行 python .\search.py "借阅期限",把引号里的文字替换成另外两个查询,逐一对照自己的判断。
- 使用 python .\
search.py"PYTHON 练习" 观察中英文混合查询。 - 使用 python .\
search.py"火星气候" 观察没有命中的情况。 - 使用 python .\
search.py"借阅期限" --json 查看原文位置和完整结构。
每一分都能指出出处
程序给查询和正文使用同一套切分规则:英文按连续字母或数字组成的整词,中文按相邻两个基本汉字组成词项。例如“借阅期限”得到“借阅”“阅期”“期限”。这里的词项只是这个检索器的单位,不是某个语言模型的 Token,也不表示它懂中文分词。
匹配前,程序在文字副本上统一兼容字符与大小写,因此全角大写的 LIBRARY 可以找到原文中的 Library。原文没有被改写。孤立的一个汉字无法组成二元组,会提示补充查询;英文单复数、带重音字母和其他文字也没有完整的语言处理。
正文按少量标点切成片段,命中一种不同查询词项记一分,重复输入同一个词不会多得分。每份文档只保留最高分的一段,同分保留先出现的片段;文档之间同分按编号排。因此三分只表示命中三种词项,不是三成概率或可靠程度。
找到原句只是核对的开始
每条结果显示文档编号、标题、日期、原始片段和命中的词项。JSON 还记录片段在正文中的起止位置。验证程序会回到相同编号的正文,检查相应位置是否恰好等于返回片段,避免出现引用编号与文字各自看似合理、实际却没有对应的情况。
这项检查证明的是“摘录来自哪里”,还没有证明“这句话支持什么结论”。只截取一段可能漏掉后面的条件,所以要打开完整正文继续读。日期也只是材料字段;新版是否适用、旧版是否废止,需要修订记录等依据,不能由排序程序擅自决定。
把失败也当成可观察的结果
“借书”和“借阅”在日常交流中接近,但这里没有相同二元组就可能查不到。反过来,“允许携带饮料”与“不允许携带饮料”含有同样的查询词项,会得到相同分数。两个例子说明,字面重合与语义一致没有必然对应关系,得分高也可能把否定含义带进来。
查“火星气候”时,材料没有匹配项,程序明确返回未找到和空结果,不补出一个听起来合理的答案。空查询也有单独提示。没有结果不证明现实中不存在答案,只表示当前材料与当前规则没有找到匹配;此时应记录缺口,再决定是否补材料或改查询。
验证规则,再做一次小改动
运行 python .\verify.py,十四项检查覆盖中英文、空输入、无匹配、稳定排序、引用对应、日期和否定等边界。本次已在 Python 3.14.0 运行通过,所用语法和接口兼容 Python 3.10;这不等于已经在所有版本实测。看到 OK,也只说明这些既定检查通过。
继续练习时,可以只增加一组近义词映射,先预测哪些结果会改变,再运行旧测试并补充新检查。这个项目没有语义向量、复杂排序或生成步骤,也没有实现完整 RAG。它的用途是把“先找资料”拆成能解释、能核对的小过程,为以后学习更复杂系统保留比较起点。
记住这三点
- 查询与材料使用相同切分规则,分数可以逐项追溯到原文中的命中词项。
- 引用确实来自原文、内容与查询相似、结论正确,是需要分别检查的事情。
- 无匹配、版本冲突和否定句同分都要如实暴露,不能用一段流畅回答掩盖缺口。
别把例子用过头
- 中文二元组和英文整词不理解近义、语法或否定,也不覆盖所有 Unicode 文字。
- 日期较新不自动代表适用,词项分数不是概率;片段之外还可能有决定含义的条件。
- 短语料的粗分句可能切错英文缩写或小数;十四项测试通过不能证明生产环境检索质量。
自己试一小步
为“借书”增加一组显式近义词映射后,怎样证明你只改变了预期行为?
- 先记录原查询的词项、结果和无匹配状态,再写出预期变化。
- 明确映射作用于查询还是文档,保持返回的引用仍是原始正文。
- 运行已有检查,并加入能观察新映射效果及误匹配风险的例子。
做到这些,就算完成
- 能否解释新增命中的原因,并指出它来自哪个原始片段?
- 映射是否意外改变英文、否定句或无关问题的结果?
- 是否仍然保留日期边界、空结果与不生成答案的行为?
查原始资料
想确认一个细节,先看这份资料对应的部分,不必从头读完所有文档。
- Introduction to Information Retrieval:Tokenization (新标签页)↗
查询与文档一致处理、词项与字符切分区别、中文字符 k-gram 的选择。
- Python 3.10:Unicode HOWTO (新标签页)↗
字符串、casefold 与规范化;匹配副本和原始引用分开保存。
- Python 3.10:re (新标签页)↗
findall
/finditer与Match.start/end对应原始字符串位置。 - Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks (新标签页)↗
检索与生成的组合概念,说明本项目只实现检索观察步骤。
找一份资料继续练
先选一项,按下面的范围继续学;不必从头读完整门课程。
动手学知识库问答:先找资料,再让模型回答 (新标签页)↗
只读知识库检索与评估部分,把本地词项匹配的结果同向量检索流程作概念对照,仍逐条检查找回的原文。
查看学习准备与访问说明 →Microsoft Learn:文档切块怎样保住上下文 (新标签页)↗
只读分块方式与内容重叠的注意事项,选本地材料中的一条限制条件,检查切开后还能否一并取回。
查看学习准备与访问说明 →