当前位置: 首页 > ds >正文

AI 开发入门之 RAG 技术

目录

    • 一、从一个简单的问题开始
    • 二、语言模型“闭卷考试”的困境
    • 三、RAG 是什么—LLM 的现实世界“外挂”
    • 四、RAG 的七步流程
      • 第一步:加载数据(Load)
      • 第二步:切分文本(Chunking)
      • 第三步:向量化(Embedding)
        • 向量化:把句子变成“可以计算距离”的坐标点
        • 向量化模型做了啥?
        • 相似度怎么计算?
        • 总结一下
      • 第四步:存入向量数据库(Vector Store)
      • 第五步:接收用户问题(Query)
      • 第六步:检索相关文段(Retrieve)
      • 第七步:组织 Prompt,交给大模型生成回答(Generate)
    • 总结

如果关注 AI 领域,那么 RAG 这个名词你肯定不陌生,这篇文章,我们就来揭开它的神秘面纱。为什么需要 RAG,它到底是什么,能解决什么问题。

一、从一个简单的问题开始

假设你在和一个 AI 聊天助手对话,你问它:

“北京到上海高铁多久?”

这看起来像个非常简单的问题,但它考验的却是 AI 模型的知识广度知识时效性

你希望它能回答类似这样:

“大约 4.5 到 6 小时,具体取决于车次。”

但是,假设这个 AI 模型训练得比较早,它可能回答是——

“我不知道。”

或者:

“我认为北京和上海之间目前没有高铁。”(因为它只看到了 2010 年以前的数据)

这就暴露出一个大语言模型的通病

训练完就定格了,它不会自己更新知识。


二、语言模型“闭卷考试”的困境

所有的大语言模型(如 GPT、Claude、Gemini)在训练时都要读取大量文本,比如:

  • 维基百科
  • 新闻网站
  • Reddit 论坛
  • Github 代码
  • 开放书籍、论文

训练结束后,它就像一个“背书高手”,记住了大量的知识。但这也意味着一但遇到新知识实时内容你私有的数据,它就歇菜了。

所以问题就来了:怎么让模型既有“语言能力”,又能随时“看资料再回答”呢?

这时候就该 RAG 登场了!


三、RAG 是什么—LLM 的现实世界“外挂”

RAG,全称是 Retrieval-Augmented Generation,翻译为“检索增强生成”。

通过字面意思也能看出来它的核心作用,通过检索来增强生成(废话)

用通俗话来讲:
它让 AI 在回答之前,先“查资料”,再用大模型来“组织语言”。

就像你考试的时候如果不确定答案,那就翻课本,然后用自己的话组织一段回答。

想象一个真实的场景,比如你在一家 SaaS 公司,客户经常问你:

  • “你们的产品怎么绑定企业微信?”
  • “有没有 API 文档?”
  • “怎么开具发票?”

这些内容,可能都写在:

  • 帮助中心文档
  • FAQ 文档
  • 客服聊天记录
  • 内部知识库

而传统的 ChatGPT 模型对这些你们内部的这些专属知识一无所知

这时候你就可以用 RAG,它的基本流程是:

  1. 用户提问
  2. 在你的知识库里“检索”相关文档段落(比如找到 API 文档那一段)检索
  3. 把这些内容和用户问题一起送进语言模型 增强
  4. 生成一个有针对性的、个性化的回答。生成

这样的系统既懂你公司,又能写好回答

所以 RAG 的核心优势显而易见:

优点解释
实时更新你改了文档,模型就能学会新内容,不需要重新训练
私有知识可以在不暴露给外部模型的前提下使用公司内部数据
可控性强检索什么,传给模型什么,你可以干预整个过程
更少幻觉模型参考真实资料后,不容易瞎编

所以,总的来说,大语言模型就像是通用的大脑,RAG 则让它接入你自己的知识RAG 不是让模型更“聪明”,而是让它更“有见识”。

通过上面的描述,RAG 听起来很简单嘛。

但真正的 RAG 系统背后可是有很多技术细节:

  • 文档如何分段(chunking)
  • 怎样计算用户问题和文档的“语义相似度”(向量检索)
  • 检索出几条内容?怎么拼接 Prompt?
  • 模型是否支持多轮记忆和上下文压缩?
  • 如何缓存和优化响应速度?

等等,这些都会影响最终效果。

四、RAG 的七步流程

我们已经大致了解了 RAG 的原理,现在我们就从宏观视角来看看 RAG 的全流程是怎么样的。

第一步:加载数据(Load)

RAG 的第一步,就是从你现有的资料中**“把内容读进来”**。比如我们加载一份 FAQ 文档:

import { TextLoader } from "langchain/document_loaders/fs/text";const loader = new TextLoader("docs/faq.txt");
const rawDocs = await loader.load();

输出结果是一个标准格式:

[{pageContent: "退订说明:用户如需退订,请登录控制台,点击账户管理。",metadata: { source: "faq.txt" }},...
]

这就像是把原始文档清洗成结构化文本,供后续使用。

第二步:切分文本(Chunking)

为什么要切分?因为文档太大了,大模型一次吃不下。

我们需要把文档拆成段落级别的小块(chunk),通常每块控制在几百字以内。

切分工具(在 langchain.js 中):

import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";const splitter = new RecursiveCharacterTextSplitter({chunkSize: 500,chunkOverlap: 50
});
const docs = await splitter.splitDocuments(rawDocs);

第三步:向量化(Embedding)

现在我们已经把文档切分了,但是有一个问题:

计算机如何知道,两个句子意思相近?

比如下面这两个问法:

  • “怎么取消订阅?”
  • “我不想继续用了,怎么退?”

我们人类一看就知道是同一个意思。可对计算机来说,它只看到一串字符,完全不懂“语义”。

那怎么办?

我们需要给它一种能“看出意思相似”的方式,这就是向量化。

向量化:把句子变成“可以计算距离”的坐标点

你可以把“向量化”想象成这样的过程:

我们给每个句子分配一个“坐标点”,让相近意思的句子靠得近,差很多的句子离得远。

比如:

句子向量(简化表示)
“怎么退订服务?”[0.9, 0.1, 0.4]
“不想用了怎么办?”[0.88, 0.12, 0.45]
“产品价格是多少?”[0.1, 0.8, 0.9]

你可以把每个向量想象成一个坐标点在三维空间中:

  • 第一个句子和第二个句子很靠近(表示意思差不多)
  • 第三个句子在远处(表示是完全不同的问题)

于是我们就可以计算两个句子之间的“距离”,这个距离越近,它们的意思就越像。

这就是所谓的**“语义相似度计算”**。


向量化模型做了啥?

现在的语言模型已经很强大,它们会从大量语料中学会如何把意思相近的词语、句子放到更接近的坐标位置上

你只要给它一句话,它就会返回一个长长的向量,比如:

[0.12, -0.03, 0.77, ..., 0.01]  // 长度可能是 1536 维

虽然我们看不懂这个向量长啥样,但这没关系——我们只需要知道:它可以拿来计算“相似度”


相似度怎么计算?

最常用的方式就是:

计算两个向量的夹角是否接近(余弦相似度)

可以理解为:

  • 两个方向完全一样的箭头,表示“非常相似”
  • 两个方向差很多,说明“几乎没关系”

总结一下
概念通俗理解
向量把一个句子的意思表示成一组数字坐标
向量化把句子转成向量(embedding 模型来做)
相似度比较两个向量距离近不近,距离越近意思越相近

所以,向量化的本质就是:把语言变成“可以比较距离的东西”,让计算机能看出语义像不像。


第四步:存入向量数据库(Vector Store)

我们把每段文本 + 它的向量都存到一个数据库里,方便后续检索。

可用的数据库有:

  • FAISS(本地)
  • Pinecone / Weaviate / Chroma(云服务)
  • Milvus(工业级)

示例(用 FAISS):

import { FaissStore } from "langchain/vectorstores/faiss";const store = await FaissStore.fromDocuments(docs, embeddings);

现在,你就有了一个可以按语义相似度查内容的数据库了。


第五步:接收用户问题(Query)

终于轮到用户提问了,比如:

“怎么退订你们的服务?”

这个问题会经过同样的向量化过程,再去数据库中查最接近的问题片段。


第六步:检索相关文段(Retrieve)

将用户问题的向量丢进数据库,找出前几段最相似的内容(通常是 top-3 或 top-5):

const results = await store.similaritySearch("怎么退订服务?", 3);

返回类似:

["退订说明:请登录控制台,点击账户管理页面...","退订功能位于控制台左侧菜单栏...",...
]

这就是查资料的部分。


第七步:组织 Prompt,交给大模型生成回答(Generate)

最后,我们把:

  • 用户问题
  • 检索到的文档片段

组织成一个 Prompt,交给 LLM:

const prompt = `
你是一个客服助手,请参考以下内容回答用户问题:资料:
---
1. ${results[0]}
2. ${results[1]}
3. ${results[2]}
---用户提问:
怎么退订服务?请根据资料,用简洁的语言回答:
`;

然后喂给 OpenAI 或其他模型:

const res = await llm.call(prompt);

得到最终回答:

“您好,您可以登录控制台,进入‘账户管理’,点击‘退订管理’即可操作退订。”

至此,一个完整的 RAG 流程就完成了。

当然这只是最简单笼统的流程介绍,具体的每个环节都是很复杂的,比如算法的选取以及参数的调整等等等等…


总结

RAG = 查文档 + 用大模型答题,RAG 本质上让 LLM 具备了实时访问企业知识库的能力,既规避了幻觉,又能针对性回答个性化问题。

http://www.xdnf.cn/news/1889.html

相关文章:

  • 解析Mqtt 消息服务质量Qos
  • 2025最新软件测试面试八股文(答案+文档+视频讲解)
  • linux 桌面环境
  • 如何用大模型技术重塑物流供应链
  • 【C++基础知识】C++类型特征组合:`disjunction_v` 和 `conjunction_v` 深度解析
  • linux centOS7.9 No package docker-ce available
  • 解决 Windows10 下 UWP 应用无法使用本地代理
  • Python实现技能记录系统
  • 建筑安全员考试科目有哪些
  • 从梯度消失到百层网络:ResNet 是如何改变深度学习成为经典的?
  • 三维扫描|用高精度3D数据驱动制造企业降本增效
  • 循环神经网络RNN(示例代码LSTM预测股价示例)
  • 【硬核干货】SonarQube安全功能
  • 上篇:深入剖析 BLE 底层物理层与链路层(约5000字)
  • FreeRTOS【2】任务、优先级知识重点
  • 【C语言】C语言结构体:从基础到高级特性
  • 深入解析 doas:有望替代 sudo 的极简权限管理工具
  • Dify快速入门之发布应用
  • Trae 编程工具 Cline 插件安装与 Claude 3.7 API Key 自定义配置详解
  • 修改RK3568 UBUNTU开机画面
  • C++ Lambda 表达式
  • 黑马点评商户查询缓存--缓存更新策略
  • shell练习(2)
  • github 简单访问方法(无魔法)
  • 数据库-数据类型、约束 和 DQL语言
  • QComboBox自适应下拉展开区域宽度但控件本身限制宽度
  • leetcode刷题日记——有效的括号
  • IOMUXC_SetPinMux的0,1参数解释
  • Java集合框架解析
  • 【TS入门笔记1---初识TS】