游乐游手机版
首页/AI教程/文章详情

LangChain.js RAG实战:爬取掘金文章消除LLM幻觉

时间:2026-07-14 15:13
基于LangChain js实现RAG(检索增强生成)链路,通过CheerioWebBaseLoader爬取网页内容,使用RecursiveCharacterTextSplitter进行智能文本切片,利用OpenAIEmbeddings进行向量化,借助MemoryVectorStore进行存储和检索,将检索结果增强至Prompt中,提供给大语言模型生成回答,

从零实现 RAG:爬取掘金文章,让 LLM 帮你读懂任何网页

如果你一直在关注大模型落地,应该对“RAG”这个词不陌生。它被公认为解决 LLM 幻觉问题最实用的方案之一。但到底怎么用?代码怎么写?今天这篇文章就从一个最基础的案例开始,一步步带你跑通完整的 RAG 链路——从手工知识库,到自动爬取网页并问答,让你真正掌握检索增强生成的核心实践。

什么是 RAG?

RAG(Retrieval-Augmented Generation,检索增强生成)的核心思路其实很简单:LLM 的训练数据是有限的,你问它训练集之外的问题(比如一篇昨天刚发布的文章),它很可能“认认真真地胡说八道”——这就是幻觉。RAG 的做法是:先检索相关知识,再让 LLM 基于这些知识回答,确保输出的内容有据可查。这种“先检索后生成”的模式,正成为大模型应用开发中的主流方案。

LangChain.js RAG 实战:爬取掘金文章,让 LLM 告别幻觉

流程可以概括为:

用户提问 → 向量检索 → 找到相关文档片段 → 拼入 Prompt → LLM 生成回答

下面通过两个递进的实战案例,带你完整走通这条链路。先从最简单的场景开始。

案例一:手工知识库 RAG

我们手动编写一个关于“光光和东东”的友情故事,让 LLM 基于这个故事回答问题。这个案例虽然简单,但能让你看清 RAG 的核心构件,包括文档切分、向量化、检索与生成的全流程。

核心代码结构

import { ChatOpenAI, OpenAIEmbeddings } from "@langchain/openai";
import { Document } from "@langchain/core/documents";
import { MemoryVectorStore } from "@langchain/classic/vectorstores/memory";

// 1. 手动构造知识库(7个Document)
const documents = [
  new Document({
    pageContent: `光光是一个活泼开朗的小男孩...`,
    metadata: { chapter: 1, character: "光光", type: "角色介绍", mood: "活泼" },
  }),
  // ... 共7段故事
];

// 2. 向量化并存入内存
const vectorStore = await MemoryVectorStore.fromDocuments(documents, embeddings);

// 3. 构建检索器
const retriever = vectorStore.asRetriever({ k: 3 });

// 4. 提问 → 检索 → 增强Prompt → 生成回答
const retrievedDocs = await retriever.invoke("光光和东东各自擅长什么?");
const context = retrievedDocs.map((doc, i) => `[片段${i+1}]\n${doc.pageContent}`).join("\n\n----\n\n");
const prompt = `基于以下故事片段回答问题:\n${context}\n\n问题:${question}\n回答:`;
const response = await model.invoke(prompt);

这段代码里最核心的数据结构就是 Document。每个 Document 代表知识库中的一个片段(chunk),包含两个关键字段:

字段作用
pageContent存储实际文本,会被 embedding 成向量参与语义搜索
metadata附加标签(章节、角色、类型等),不参与向量计算,可用于过滤检索

在 RAG 全流程中,Document 是贯穿始终的统一数据格式:

原始文本切片 → Document[] → Embedding 向量化 → 存入向量库 → 检索返回 Document[] → 提取内容拼入 Prompt

案例二:自动爬虫 RAG(loader-and-splitter.mjs)

手工编写知识库毕竟不现实。真正的 RAG 需要自动从各种来源加载文档、自动切片、自动向量化。这个案例实现的是:爬取一篇掘金文章 → 自动切片 → 向量化 → LLM 问答,让大模型能够读懂线上的任意技术文章。

完整流程图

掘金文章 URL
  → CheerioWebBaseLoader(爬取+解析)
  → RecursiveCharacterTextSplitter(智能切片)
  → OpenAIEmbeddings(向量化)
  → MemoryVectorStore(存入内存向量库)
  → retriever(检索)
  → LLM(生成回答)

三个核心 API 详解

1. CheerioWebBaseLoader — 网页加载器

import { CheerioWebBaseLoader } from "@langchain/community/document_loaders/web/cheerio";

const loader = new CheerioWebBaseLoader(
  "https://juejin.cn/post/7233327509919547452",
  { selector: '.main-area p' }  // CSS选择器,只提取正文段落
);
const documents = await loader.load();

底层原理:使用 cheerio(服务端的 jQuery)解析 HTML,你可以像操作前端 DOM 一样用 CSS 选择器精确定位要提取的内容。关键配置 selector 决定了抓取哪些 DOM 节点,这里 .main-area p 只取文章正文区的

标签,自动过滤掉导航栏、评论区等噪音,确保获取的是高质量正文。这个加载器是 LangChain 中处理网页文档的常用工具。

2. RecursiveCharacterTextSplitter — 递归文本切片器

import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";

const splitter = new RecursiveCharacterTextSplitter({
  chunkSize: 400,       // 每个chunk最大字符数
  chunkOverlap: 50,     // 相邻chunk重叠字符数
  separators: ['。', ',', '!', '?']  // 分隔符优先级
});
const chunks = await splitter.splitDocuments(documents);

三个参数的作用:

  • chunkSize:每个文本块的最大字符数(上限,不是固定值)
  • chunkOverlap:相邻块之间重叠的字符数。比如 chunk1 末尾 50 字和 chunk2 开头 50 字相同,防止关键信息在切割边界处被“腰斩”
  • separators:按优先级排序的分隔符。优先在句号处切,其次是逗号,再次是感叹号、问号,保证切分尽量发生在自然语义边界

分隔符和 chunkSize 会冲突吗?不会。RecursiveCharacterTextSplitter 采用“先全切再合并”的策略:先用 把所有句子切开,然后贪心合并,几个句子加起来不超过 400 字就继续加,直到某句超了 400 就停止,这个 chunk 完成。最终一个 chunk 里可能包含 2-4 个完整句子,大小接近但不超 400 字。这种智能切分方式能很好地保留语义完整性,是 LangChain 中最推荐的文本分割器。

3. MemoryVectorStore — 内存向量数据库

import { MemoryVectorStore } from "@langchain/classic/vectorstores/memory";

const vectorStore = await MemoryVectorStore.fromDocuments(splitDocuments, embeddings);
const retriever = vectorStore.asRetriever({ k: 2 });

MemoryVectorStore 把所有向量数据存在内存中,适合学习和原型验证。两个核心方法:

方法作用
fromDocuments(docs, embeddings)将文档列表 embedding 后存入内存
asRetriever({ k: 2 })将向量库包装成检索器,k=每次返回几个结果

检索时实际发生的是:用户问题 → embedding → 问题向量;问题向量与库中所有文档向量做余弦相似度计算,余弦值越接近 1 表示语义越相似,越接近 0 表示不相关;按相似度排序,返回 Top K 个 Document。这种向量检索方式保证了即使问题与文档关键词不完全匹配,也能找到语义相关的内容。

LangChain 常见 Splitter 行为对比

不同的 Splitter 切割策略差异很大,选对工具很重要:

Splitter策略特点
RecursiveCharacterTextSplitter按分隔符优先级递归切割,贪心合并凑近 chunkSize保持句子完整性,最常用
CharacterTextSplitter按固定字符数 + 滑动窗口切割简单粗暴,可能截断句子
TokenTextSplitter按 token 数切割精确控制 token 消耗,但不关心语义边界
MarkdownHeaderTextSplitter按 Markdown 标题层级切割适合结构化文档
HTMLHeaderTextSplitter按 HTML 标题标签切割适合网页文档

关键区别:只有 RecursiveCharacterTextSplitter 是“先全部按分隔符切开,再贪心合并凑满 chunkSize”,其他都是一刀一刀按固定窗口切。所以 Recursive 的 chunk 质量通常最高,也是 RAG 项目中优先选用的切分方式。

构建 Prompt 与 LLM 调用

检索到相关文档后,将其拼入 Prompt:

const context = retrievedDocs.map((doc, i) => `[片段${i+1}]\n${doc.pageContent}`).join("\n\n----\n\n");
const prompt = `你是一个文章辅助阅读助手,根据文章内容来解答:
文章内容:${context}
问题:${question}
回答:`;
const response = await model.invoke(prompt);

这就是 RAG 中 Augmented(增强)的核心:给 LLM 的 Prompt 不只是用户问题,还追加了检索到的相关上下文。通过这种方式,大模型能够基于真实文档生成有据可查的回答,有效避免幻觉,显著提升回答的准确性和可靠性。

关于国内模型的兼容性

代码中使用的是 @langchain/openai,但实际调用的可能是通义千问(Qwen)或 DeepSeek 等国内模型。关键在于:

const model = new ChatOpenAI({
  apiKey: process.env.OPENAI_API_KEY,        // 国内模型的 API Key
  configuration: {
    baseURL: process.env.OPENAI_BASE_URL    // 国内模型的 API 地址
  },
});

国内主流大模型(阿里 Qwen、DeepSeek、智谱 GLM、月之暗面 Kimi、零一万物 Yi 等)都提供 OpenAI 兼容接口,只需要改 baseURLapiKey,代码不用动。这意味着本教程的 RAG 实现可以无缝适配国内各大模型,非常适合在国内部署环境使用。

总结

从两个案例可以看到 RAG 的完整链路:

  1. Loader:从各种来源加载文档(网页、PDF、数据库…)
  2. Splitter:将长文档智能切片成 chunks
  3. Embedding:将每个 chunk 转为向量
  4. VectorStore:存储向量,支持相似度检索
  5. Retriever:根据用户问题检索最相关的 chunks
  6. Augmented Prompt:将检索结果拼入 Prompt
  7. Generation:LLM 基于增强后的 Prompt 生成准确回答

掌握了这个流程,你就能让 LLM 读懂任意文档,从“通用聊天机器人”升级为“领域知识专家”。无论是用于知识问答、文档分析还是智能客服,RAG 都是大模型落地的必备技能,值得每一个开发者深入掌握。

来源:https://juejin.cn/post/7661830907990442024
上一篇系统化调试技能深度解析全攻略 下一篇Claude Code渐进式披露:初始阶段避免上下文塞满
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
MyShell发布开源AI语音克隆工具OpenVoice,瞄准语音模仿领域
AI教程 · 2026-07-14

MyShell发布开源AI语音克隆工具OpenVoice,瞄准语音模仿领域

MyShell最新推出的开源语音克隆工具OpenVoice引起了广泛关注。这一创新产品由麻省理工学院(MIT)、清华大学以及加拿大人工智能初创公司MyShell合作开发。OpenVoice采用了一种概念简单但高效的方法,可几乎即时克隆用户的语音,并使用明显更少的计算资源。该工具不仅具备语音克隆的基本

Open Voice:轻松克隆任何声音,免费开源的AI语音克隆项目
AI教程 · 2026-07-14

Open Voice:轻松克隆任何声音,免费开源的AI语音克隆项目

Open Voice是由MyShell推出的一个免费开源的AI即时语音克隆项目,相较于其他的语音克隆技术,OpenVoice的优势在于仅需一段简短的音频,便能以惊人的准确度复刻说话者的音色,创造出让人信以为真的自然语音。除开复制和参考说话者的音色之外,OpenVoice还可以对语音风格进行精细控制,

VoiceCanvas-AI语音克隆 & TTS工具 | 40+种语言语音合成
AI教程 · 2026-07-14

VoiceCanvas-AI语音克隆 & TTS工具 | 40+种语言语音合成

VoiceCanvas是什么?VoiceCanvas是由先进AI驱动的语音克隆与文本转语音工具,支持40+种语言的即时语音合成。其核心能力包括:高质量语音合成:具有自然语调和节奏的清晰人声个性化语音克隆:通过3-10秒语音样本创建专属AI声纹多语言支持:覆盖全球主流语种的男 女声选择进阶调控功能:语

Github爆火AI语音克隆项目OpenVoice,精准进行声音复刻
AI教程 · 2026-07-14

Github爆火AI语音克隆项目OpenVoice,精准进行声音复刻

最近,Github上的一个名为OpenVoice的AI语音克隆项目爆火,该项目由myshell-ai开源,仅开源了不到三周,就有了6 1k的star。OpenVoice仅需参考说话者的短音频片段,即可复制其声音并生成多种语言的语音。这一技术不仅实现了对音色的准确克隆,还在语音生成过程中提供了对情感、

Free Voice Cloning-免费AI语音克隆工具 | 5秒生成你的数字声音
AI教程 · 2026-07-14

Free Voice Cloning-免费AI语音克隆工具 | 5秒生成你的数字声音

Free Voice Cloning,一款真正0成本、无限制、跨语言的高质量AI语音克隆平台。适合内容创作者、教育者、AI开发者、播客人群等所有想要“复制自己的声音”并进行语音合成的用户。?️ Free Voice Cloning 是什么?Free Voice Cloning 是一个基于先进AI语音