AI 满嘴跑火车怎么办?给它配个"小抄"

第 1 课:RAG 是什么?给小帅的 AI 配个"小抄"

学完这一节,你能带走什么

  • 一句话说清 RAG 是干嘛的:先查资料,再回答问题。
  • 知道它治的是 AI 的什么病:不知道还硬编,也就是"幻觉"。
  • 分得清三种方案各自什么时候用:RAG、微调、长上下文。
  • 亲手跑通一个最小版 RAG:建资料柜 → 找小抄 → 递给 AI → 照着答。

开头:小帅的 AI 店员,开业第一天就翻车

楼下开面馆的小帅最近迷上了 AI。他花五分钟接上了一个大模型,给自己的店做了个"AI 店员",挂进微信里。心里想的是从此不用回顾客消息,躺着赚钱。

结果开业第一天就翻车了,连翻三次。

顾客问:"你家牛肉面辣吗?" AI 店员秒回:"我们的牛肉面选用澳洲和牛,微辣回甘,入口即化。"小帅看完血压上来了,他家用的明明是本地黄牛肉,牛肉面根本不辣

顾客又问:"你们营业到几点?" AI 店员自信满满:"本店 24 小时营业,深夜也可下单。"小帅差点把手机扔了,他每天九点准时关门,回家打游戏。

最离谱的是顾客问:"明天会不会下雨?" AI 店员一本正经:"明天多云转晴,适合来店里吃面。"好家伙,它连天气预报都敢编。

小帅崩溃了:"这 AI 怎么满嘴跑火车啊!"

真相是:AI 没撒谎,它是真不知道,但又不好意思说不知道。 它就像一个读书很多、从没进过小帅店里的路人,突然被拉来当店员,只能靠猜,而且猜得比谁都自信。

它的三个"难言之隐"

  • 店里的资料它一眼没看过。菜单、会员规则、营业时间,这些是小帅的"私有资料",大模型训练的时候压根没见过。
  • 脑子里的信息停在某一天。它的知识有截止日期,之后发生的事一概不知。
  • 不知道就硬编。这是大模型的职业病,学名叫"幻觉",编得越细,越像真的。

小帅的三个办法

小帅开始想办法,路人告诉他三条路。

办法一:把店规刻进它脑子(微调) 相当于给员工做脑部手术,把菜单刻进去。贵,慢,还得准备一堆数据。最要命的是,下个月小帅换了新菜单,又得开一次刀。❌

办法二:每次把整本店手册塞给它(长上下文) 300 页手册直接全塞。结果它只看进去了第一页和最后一页,还特别费钱费时间。❌

办法三:给它配个小抄(RAG) ✅ 不动脑子,也不塞全书。顾客问啥,就先帮它翻到对应的那页,递到眼前:"来,看着这页回答。"

那 RAG 到底是个啥?

RAG 全称是 Retrieval-Augmented Generation,翻译过来叫"检索增强生成"。名字唬人,拆开就是三个动作:

  • R · 找小抄(检索):顾客问"牛肉面辣不辣",系统冲进店里的资料柜,翻出菜单页。
  • A · 递小抄(增强):把菜单页和顾客的问题打包在一起,递给 AI。
  • G · 照着答(生成):AI 看着菜单回答:"牛肉面不辣,可以单独加辣。"

一句话:RAG 不是一个新模型,也不是训练方法,它是"先查资料,再回答问题"的工作流程。 大模型还是那个大模型,只是从闭卷考试换成了开卷考试。

完整流程:顾客问"会员怎么打折?"

flowchart LR A[&#34;顾客问:会员怎么打折?&#34;] --> B[&#34;找小抄:去店里资料库<br/>翻出最相关的几页&#34;] B --> C[&#34;递小抄:资料+问题<br/>打包成一份提示词&#34;] C --> D[&#34;照着答:AI 看着资料<br/>写出回答&#34;] D --> E[&#34;带出处的回答&#34;]

一步步看:

  1. 顾客提问,系统不急着问 AI
  2. 系统去店里的"数字档案柜"翻出最相关的三页:《会员章程》第 3 条、最近的满减活动海报、店长上周的通知。数字档案柜是什么,后面会学到,它有个正经名字叫向量数据库。
  3. 把这三页加上顾客的问题,打包成一份"小抄"。
  4. AI 看着小抄回答:"根据《会员章程》第 3 条,会员周三全场 8.8 折......(来源:会员章程.pdf)"
  5. 要是啥也没翻到,AI 老老实实说:"这个我不太清楚,建议您直接问店长。"

这里藏着整节课最值钱的一句话:大模型擅长照着资料写总结,不擅长把资料全背下来。 RAG 就是扬长避短,不逼它背,让它抄,但抄得有凭有据。

为什么这招能治"跑火车"?

  • 有凭据:回答基于翻到的原文,不是瞎猜。
  • 能追责:每条回答都标了出处,错了知道是谁的锅。
  • 好更新:菜单换了,把资料柜里的旧页换掉就行,模型一个字不用改。
  • 能保密:店里的机密资料不交给模型训练,只在回答问题那一刻临时翻一眼。

丑话说在前头:RAG 不是万能药

  • 小抄没翻对页,后面答得再漂亮也是错的。所以接下来的课程,我们会死磕"怎么翻得准"。
  • 小抄本身写错了,AI 会一本正经地跟着错。垃圾进,垃圾出。
  • 想让 AI 学会新本事,比如用方言回顾客、写打油诗?那是微调的活,RAG 不接。

判断口诀

菜单常改、要注明出处、资料要保密 → 用 RAG 想改 AI 的性格和本领 → 用微调 偶尔查一两页小资料 → 直接塞长上下文


动手环节:给小帅的店跑通最小版 RAG

光说不练假把式。接下来用一个文件、几十行代码,给小帅的店做出一个最小版 RAG。不装框架,不用向量数据库,所有零件手工搭,目的就是让你看清里面到底发生了什么。

先搭台子

bash 复制代码
mkdir my-rag-demo
cd my-rag-demo
npm init -y
npm install openai

再看代码

新建 minimal-rag.mjs,把下面代码粘进去:

javascript 复制代码
import OpenAI from "openai";

// 接上大模型:换成你的 Key 和服务商地址(DeepSeek、通义、智谱等都行)
const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: process.env.OPENAI_BASE_URL || "https://api.openai.com/v1",
});

// 两个模型各司其职:一个管"说话",一个管"把文字变成数字"
const CHAT_MODEL = "gpt-4o-mini";           // 对话模型,换成你用的
const EMBED_MODEL = "text-embedding-3-small"; // 向量模型,换成你用的

// ── 第 1 步:准备"小抄"(小帅店里的资料) ──
const menuDocs = [
  "牛肉面:本地黄牛肉,不辣,可以单独加辣,28 元一碗。",
  "营业时间:每天 10:00 到 21:00,周二休息。",
  "会员规则:会员周三全场 8.8 折,生日当天免费送煎蛋。",
  "地址:幸福路 88 号,地铁 3 号线幸福站 B 口出来左转。",
];

// ── 第 2 步:把每条资料变成向量,存进"资料柜" ──
async function buildStore() {
  const res = await client.embeddings.create({
    model: EMBED_MODEL,
    input: menuDocs,
  });
  return res.data.map((item, i) => ({
    text: menuDocs[i],
    vector: item.embedding,
  }));
}

// ── 第 3 步:余弦相似度------量一量两个向量有多"像"(可以不用纠结公式, 有现成的向量数据库可以使用不用自己算) ──
function cosineSimilarity(a, b) {
  let dot = 0, normA = 0, normB = 0;
  for (let i = 0; i < a.length; i++) {
    dot += a[i] * b[i];
    normA += a[i] * a[i];
    normB += b[i] * b[i];
  }
  return dot / (Math.sqrt(normA) * Math.sqrt(normB));
}

// ── 第 4 步:找小抄------把问题也变成向量,挑出最像的两条资料 ──
async function findNotes(question, store) {
  const res = await client.embeddings.create({
    model: EMBED_MODEL,
    input: question,
  });
  const questionVector = res.data[0].embedding;
  return store
    .map((doc) => ({
      text: doc.text,
      score: cosineSimilarity(questionVector, doc.vector),
    }))
    .sort((a, b) => b.score - a.score)
    .slice(0, 2)
    .map((doc) => doc.text);
}

// ── 第 5 步:递小抄 + 照着答------资料和问题打包一起放到Prompt中并且要求AI 照着说 ──
async function askAI(question) {
  const store = await buildStore();
  const notes = await findNotes(question, store);

  const res = await client.chat.completions.create({
    model: CHAT_MODEL,
    messages: [
      {
        role: "system",
        content:
          "你是小帅面馆的店员。只能根据下面的资料回答顾客问题。" +
          "资料里没有的内容,一律回答『这个我不太清楚』,不许瞎编。\n\n" +
          "【店内资料】\n" + notes.join("\n"),
      },
      { role: "user", content: question },
    ],
  });

  console.log("顾客问:", question);
  console.log("店员答:", res.choices[0].message.content);
}

// 试两个问题:一个店里答得上,一个店里答不上
await askAI("牛肉面辣吗?");
await askAI("明天会下雨吗?");

填上钥匙,跑起来

powershell 复制代码
$env:OPENAI_API_KEY = "你的API Key"
$env:OPENAI_BASE_URL = "https://api.openai.com/v1"
node minimal-rag.mjs

国内的同学推荐用硅基流动(SiliconFlow),一个 Key 同时搞定对话和向量,把环境变量换成:

powershell 复制代码
$env:OPENAI_BASE_URL = "https://api.siliconflow.cn/v1"
# CHAT_MODEL  换成 "deepseek-ai/DeepSeek-V3"
# EMBED_MODEL 换成 "BAAI/bge-m3"

跑起来大概是这样:

复制代码
顾客问: 牛肉面辣吗?
店员答: 牛肉面不辣,是本地黄牛肉,如果想加辣可以单独加辣,28 元一碗。

顾客问: 明天会下雨吗?
店员答: 这个我不太清楚,我没有相关资料。

看见没?第一个问题它翻到了菜单页,照着答。第二个问题资料柜里根本没有,它就老实闭嘴了。跑火车治好了。

这几十行代码里到底发生了什么

  • buildStore:把四条店规一条条变成向量(一串数字),相当于给每页资料拍一张数字照片,存档。
  • findNotes:把顾客的问题也变成向量,和柜子里的照片比"像不像"(相似度),挑最像的两条。这就是 R 和 A 的前半段。
  • askAI:把挑出来的资料塞进 system 提示词,等于把"小抄"递到 AI 眼前,再让它回答。这就是 A 的后半段和 G。
  • 防瞎编的秘诀:system 提示词里那句"不许瞎编"不是魔法。真正的底气是,相关资料根本没进提示词,AI 想编都没素材。

这个版本刻意做得很糙:没切块、没真向量库、资料写死在代码里、每次提问都重新建库。别急,这些"糙"正是后面课程 3 到 6 要逐个升级的地方。现在你已经亲眼见过 RAG 的完整骨架了。

本课小结

  • RAG 就是先查资料再回答,三个动作:找小抄 → 递小抄 → 照着答
  • 它治的是"不知道"和"瞎编",不是"不够聪明"。
  • 它不训练模型,只是给 AI 配了个随身小抄。
  • RAG 能答多好,天花板由"找小抄"决定,翻得准,才答得好。
  • 今天已经跑通最小版闭环:建资料柜 → 找小抄 → 打包 → 回答。

预告一句:从下一节开始,我们要给小帅的店做一个完整的 RAG 问数程序。它不光能翻资料回答问题,还能自己写 SQL 去数据库里查数,你问"上个月卖了多少碗牛肉面",它就真去账本里把数字算出来。今天这节课是地基,后面的每一块砖都压在它上面。

课后小练习

  • 用一句话跟完全不碰电脑的朋友解释 RAG。
  • menuDocs 换成你自己的四条信息,比如作息、爱好、家乡,再问 AI 三个问题,看看它答得准不准。
  • 试着把"明天会下雨吗"换成"你们店里卖奶茶吗",观察它这次会怎么回答,想想为什么。
  • 预习:下一节开始给小帅的店做完整的 RAG 问数程序,AI 不光能翻资料,还会自己写 SQL 查数据库。
相关推荐
计算机魔术师1 小时前
AI 权力集中辩论实录:从「token 工厂」到「唯一幸存者」
前端
Full Stack Developme1 小时前
跨站请求伪造 (CSRF) 是什么 设计及工作原理
前端·okhttp·csrf
MoSTChillax1 小时前
UI规范设计:从视觉到交互的全面指南
前端·ui·产品经理·设计规范·vibecoding
雪碧聊技术2 小时前
Vue + Element Plus 实现文本溢出显示省略号及悬浮提示
前端·javascript·css·vue.js·文本溢出省略
eric-sjq2 小时前
0.6B 前端生成模型本地部署实战:消费级显卡跑通 WanlyFrontend 全流程
前端·本地部署
kaliarch2 小时前
WorkBuddy 不是 Chat:从对话到可交付 Agent 工作台
aigc·ai编程
小妖6663 小时前
设置了 box-sizing: border-box; 不管用,下边框还是被挤压没了
前端·css·html
雪隐3 小时前
个人电脑玩AI-16让5060 Ti给你打工——5060Ti 16G 跑 MiniMax-Music-3:从下载到 60s 出歌的全流程
前端·人工智能·后端
CAD老兵4 小时前
让 AI Coding Agent 直接访问 CAD 文档:GitMCP 实战指南
前端·人工智能·github