如果备课就是提出一个问题,然后在几秒钟内拿到对应教学大纲中的正确段落,并且附带出处,会怎样?

这正是 wag.titcheur.fr 的设想:一个面向法国中等教育大纲和课程标准的语义搜索引擎,覆盖初中、普通与技术高中以及职业方向。

问题所在

官方教学大纲是公开的,却分散在 5680 份 PDF 文档中,共 4.9 GB 文本、数千页、几十个学科。想找到"八年级数学大纲里关于毕达哥拉斯定理是怎么说的",几乎是一项壮举。传统搜索引擎只匹配词语,它们并不理解问题。

30 秒看懂原理

这个工具不靠关键词匹配,而是理解语义

每份文档被切成约 700 个字符的小块(带重叠)。一个法英双语 AI 模型(bilingual-embedding-large,5.59 亿参数)把每个小块转换成一个 1024 个数字组成的向量,就像是语义地图中的一组坐标:谈论同一件事的两段文字会落在同一个位置,哪怕表述完全不同。

你的问题经过同样的转换。系统再在 234893 个已索引小块中寻找最近的邻居:检索变成了简单的距离计算。结果是:一句自然法语查询,无论有没有错别字,都会返回相关的官方段落,按语义接近程度排序,并附上源 PDF 的直接链接。

再加上"Élaborer",第二个模型会只依据检索到的摘录撰写结构化回答,出处标注在括号里。

用基准测试挑选正确的"大脑"

语义引擎的成色取决于其嵌入模型。我没有跟风,也没有照搬博客文章,而是实测

我搭建了一个隔离的基准测试装置(500 份文档,22393 个小块,30 个手工改写的问题,8 个按学科分类的问题),让三个模型同场竞技:

模型 召回率@10 学科纯度 延迟
bilingual-embedding-large(法/英,5.59 亿参数) 0.867 0.900 56 毫秒
multilingual-e5-base(2.78 亿参数,旧模型) 0.800 0.825 33 毫秒
gte-multilingual-base(3.05 亿参数) 0.767 0.862 40 毫秒

嵌入模型基准测试:召回率@10、学科纯度与延迟(500 份文档,22393 个小块)

结论:法英双语模型 bilingual-embedding-large 在学科纯度上高出 7.5 分,召回率高出 6.7 分。道理很明白:在法语语料上,一个为法语训练的模型可以击败通用多语言模型。切换已经完成。但更换模型意味着改变向量维度:整座数据库将变得无法读取。这次迁移的故事值得单开一章。

岔路口:一个晚上在"一次性"集群上算完 23.4 万个小块

换模型等于换向量几何(768 → 1024 维)。现有数据库无法兼容:没有增量迁移的可能,所有小块都必须重新编码:23.4 万个。

我的笔记本(Apple Silicon M2/16)上的初步估算:一开始约 2 秒/文档,遇到大 PDF 变成 9 到 10 秒/文档。外推结果是:要跑一整夜,机器完全被占用

转机在于:Azure 上一个现成的 k3s 集群:4 个节点、32 个 vCPU、没有 GPU,一个本就在跑其他实验的免费层级。无需创建任何基础设施。大约 1 小时内的配方:

  1. 导出状态,而不是从零开始:5 GB PDF + SQLite 数据库 + 已算好的部分索引(约 900 MB)传上集群。任务是可续跑的:它精确地从中断处继续;笔记本上约 2 小时的计算没有白费。
  2. 把语料分片成 4 个带重叠的区间,每个节点一个,并行索引。
  3. 用 upsert 合并分片(重叠部分自动去重),回传最终索引,原子切换,随时可以回滚。

成果:

  • 约 4 小时分布式计算重编码 234893 个小块,而单机要一整夜
  • 总成本:不到 10 美元,按分钟计费,任务一结束 4 台虚拟机立即释放
  • 整个计算期间生产服务无中断;公共搜索一直用旧索引在线服务,直到切换
  • 顺手排掉了三个 ChromaDB 的坑(读取分页、单次插入 5461 条的限制、按文档的原子性),已修复并纳入版本管理

我得到的教训:一个设计良好的批处理任务(状态可移植、可续跑、分片、合并)是数据,不是流程。它可以在一小时内从笔记本搬到集群,一个小块都不丢,也不用为 99% 时间闲置的专用基础设施买单。

技术栈

  • Python / FastAPI 提供 API,界面是纯净 JS 的简洁网页
  • ChromaDB(HNSW,余弦空间)作为向量数据库
  • Sentence-Transformers 生成嵌入(bilingual-embedding-large,1024 维),一个关键细节:模型要求的 passage: / query: 前缀,缺了它们质量会断崖式下跌
  • DeepSeek 通过 API 做摘要;检索本身100% 本地、即时(< 1 秒)
  • Docker 非 root(cap_drop: ALL)、nginx + Let's EncryptGitLab CI/CD(SAST 和密钥检测),以及凌晨 3 点的夜间循环:重新爬取源、索引新内容、轮换数据库但不抹掉旧库
  • Azure 上的 k3s(4 节点,32 vCPU,无 GPU)跑一次性批处理任务:一个晚上完成全量重索引,任务结束虚拟机立即释放

这次工程教会我的事(工程师关心的部分)

  1. 向量数据库的后置过滤是个陷阱:在 ANN 检索之后过滤,会以看不见的方式截断结果。我为此花了一整天,附上了对比测试。
  2. 公共引擎一旦引入 LLM,每次请求都在花钱:按 IP 限流(6 请求/分钟)+ 自动封禁(fail2ban),否则账单会遭殃。
  3. 暴露服务的每一点安全都靠小动作累积:元数据 XSS 转义、收紧 CORS、只用 SSH 密钥、最小化防火墙,以及一份已经记录到暴力破解尝试的认证日志。
  4. 数据优先于代码:向量数据库 staging/live 轮换,新索引不响应就自动回滚,绝不在线热覆盖。
  5. 用你自己的数据做基准:公开排行榜(MTEB)不能说明一切。在 500 份真实文档上,两个有说服力的模型差距高达 7 分。正是这些分数,把有用的工具和玩具区分开来。

这一切都能在页面上实时看到:一个小图表展示索引夜复一夜的增量演进。

它为什么有用

对老师来说:"高中一年级的条件概率" → 大纲中的内容、预期能力与演示,精确的摘录和原始 PDF。对培训师、督学、好奇的家长来说:同一扇门,通向机构真正所说的内容。

而这只是开始:这个引擎被设计为可以吞下其他语料,小学、高等教育、法规文本……


试试看https://wag.titcheur.fr,免费、无需注册,用法语回答

有问题、反馈或语料创意?wag@titcheur.fr


为 199A Consulting 开发的项目:端到端的摄取、索引、加固与自动化。

RAG #SemanticSearch #EdTech #AI #Python #ChromaDB #FastAPI #GitLabCI #Benchmark #Kubernetes #Cloud #EdTechInnovation #TechForEducation