大型语言模型懂很多东西,但它们不会自动知道我们私有文件、公司文档、笔记或最近写的文章里有什么。这正是检索增强生成(RAG)派上用场的时候。在这个项目里,我搭了一个小型的 RAG 应用,它能读入文本文档,把文档拆成更小的段落,将这些段落转化为一种叫“嵌入”的数值表示,然后存入 Pinecone。当用户提问时,它会找到最相关的段落,把它们交给 AI 模型,让模型给出一个“有根据”的答案——也就是基于检索到的源材料来回答。
我用了 Python 来写这个应用,用 LangChain 连接各个步骤,用 OpenAI 的嵌入模型把文字变成数字,用 Pinecone 存储和搜索这些嵌入,还用 uv 管理整个 Python 项目和依赖。这篇文章我会解释这个应用是怎么运作的,各个组件怎么配合,以及我在调试过程中学到了什么。
想象一下你在参加一场开卷考试。没有书的时候,你只能凭记忆作答。你可能知道答案,但也可能忘掉点什么,或者给出错误的信息。有了开卷资格,你可以先读题,翻到相关的那一页,然后用那上面的内容来写答案。RAG 应用的工作原理与此类似:语言模型就是答题的人,向量数据库就像一本可以搜索的书。在回答之前,应用会找到最相关的信息交给模型,模型不需要记住整份文档,它只收到那些可能包含答案的片段。
一个基本的 RAG 应用有两个阶段。第一阶段是“摄取”,也就是把文档准备好,让它们以后能被搜索到。流程是:加载文档,切成小块,每块转成一个嵌入,然后把这些嵌入存进 Pinecone。这个过程通常在添加或更新文档时运行。第二阶段是“检索与答案生成”,在用户提问时触发:先把问题转成嵌入,到 Pinecone 里搜出相似的文档块,把这些块放进提示词里,最后让语言模型作答。把这两个阶段分开,整个应用就更容易理解——摄取负责整理知识,检索负责用上这些知识。
计算机不能像人那样直接比较句子之间的意思。嵌入模型的作用就是把文字转换成一串数字,也就是向量。比如“如何重置我的密码”和“我忘了密码该怎么办”意思很接近,它们对应的向量在数值空间中也会挨得很近。这样,通过比较向量,系统就能找到语义上相关的段落,哪怕用词不完全一样。
调试的时候我用上了 LangSmith,它能让我看到每个步骤的输入输出,帮我定位问题。比如,有一次我发现检索到的段落和问题根本不沾边,通过追踪才发现是文档切分的粒度不对,导致关键信息被切散。改了切分策略之后,检索质量明显提升。RAG 确实能减少没有根据的回答,但它并不能保证每一次回复都正确。模型仍然可能误解上下文,或者把检索到的信息拼凑得看似合理却偏离事实。这就是这个应用留下的一个需要持续留意的地方。
热门跟贴