百度SEO

百度SEO

Products

当前位置:首页 > 百度SEO >

LangChain RAG:如何让生成更精准?

96SEO 2026-05-06 20:59 25


我们常常会遇到两个让人抓狂的问题:要么是模型一本正经地胡说八道,要么就是它对你的私有数据一问三不知。想象一下你费尽心思搭建了一个客服机器人,结果它连自己公司的退货政策dou搞不清楚,这岂不是hen尴尬?

LangChain RAG:如何让生成geng精准?

这时候,RAG 就像是一根救命稻草出现了。简单来说RAG 就是给大模型外挂了一个“知识库”,让它在回答问题之前,先去翻翻书,kankan资料里是怎么说的。今天我们就结合 LangChain,来深入探讨一下如何构建一个高质量的 RAG 系统,让 AI 的生成结果不再“飘”在空中,而是脚踏实地。

一、为什么我们需要 RAG?

大模型虽然聪明,但有两个天然的“硬伤”:

1. 知识盲区: 模型的训练数据是有截止日期的。Ru果你问它“今年的诺贝尔文学奖得主是谁?”,它大概率会一脸懵圈,因为它根本没学过新发生的事。

// 用户问:"2024年诺贝尔文学奖得主是谁?"
// LLM 回答:"抱歉,我的训练数据截止到 2023 年..."

2. 幻觉问题: 有时候为了“讨好”用户,模型会编造一些听起来hen合理但完全错误的信息。特别是在处理企业内部文档、医疗记录或法律条款时这种胡编乱造是绝对不Neng容忍的。

RAG 的核心思路非常直观:在提问时先从知识库里找到Zui相关的内容,再把它作为上下文提供给模型,让模型“带着资料”回答。这就像考试从“闭卷”变成了“开卷”,答案自然geng准确、geng可靠。

二、RAG 的核心工作流

一个完整的 RAG 系统其实并不神秘,它主要分为两个大的阶段:索引阶段检索生成阶段。我们Ke以通过下面的流程图来直观地理解这个过程:

flowchart TB
    subgraph Indexing
        L --> S
        S --> EM
        EM --> VS
    end
    subgraph Retrieval
        Q --> QE
        QE --> SR
        VS --> SR
        SR --> Docs
    end
    subgraph Generation
        Docs --> Prompt
        Q --> Prompt
        Prompt --> LLM
        LLM --> Answer
    end
    style Indexing fill:#e8f4fd,stroke:#1890ff,stroke-width:2px
    style Retrieval fill:#fff7e6,stroke:#fa8c16,stroke-width:2px
    style Generation fill:#f6ffed,stroke:#52c41a,stroke-width:2px

接下来我们就把这个流程拆解开,一步步kankan如何用代码实现,以及其中有哪些不为人知的细节和坑。

三、阶段 1:文档加载

万事开头难,RAG 的第一步就是把你的数据“喂”给系统。这些数据可Neng散落在 PDF、Word、网页甚至是 GitHub 仓库里。LangChain 提供了非常丰富的文档加载器,帮我们把各种格式的文件转换成统一的 Document 对象。

一个标准的 Document 对象长这样:

{
  pageContent: "产品的保修期为一年...",
  metadata: {
    source: "./docs/warranty.pdf",
    page: 5,
    author: "TechCorp"
  }
}
1. 常见文档加载器实战

假设你有一个 100 页的产品手册,我们来kankan怎么加载它:

PDF 文档

PDF 是企业知识库中Zui常见的格式,处理起来也Zui麻烦。

import { PDFLoader } from "@langchain/community/document_loaders/fs/pdf";
const pdfLoader = new PDFLoader;
const pdfDocs = await pdfLoader.load;
console.log;
// 每个页面对应一个 Document 对象

Word 文档

import { DocxLoader } from "@langchain/community/document_loaders/fs/docx";
const docxLoader = new DocxLoader;
const docxDoms = await docxLoader.load;

CSV 表格

import { CSVLoader } from "@langchain/community/document_loaders/fs/csv";
const csvLoader = new CSVLoader;
const csvDocs = await csvLoader.load;
// 每行数据转换为一个 Document
// pageContent: "产品名称: iPhone 15, 价格: 5999"
// metadata: { row: 0 }

网页内容

import { CheerioWebBaseLoader } from "@langchain/community/document_loaders/web/cheerio";
const webLoader = new CheerioWebBaseLoader;
const webDocs = await webLoader.load;
// 自动提取网页的文本内容,去除 HTML 标签

GitHub 仓库

这对于构建代码问答机器人非常有用。

import { GithubRepoLoader } from "@langchain/community/document_loaders/web/github";
const githubLoader = new GithubRepoLoader(
  "https://github.com/langchain-ai/langchainjs",
  { 
    branch: "main",
    recursive: false,  // 是否递归加载子目录
    unknown: "warn"    // 遇到未知文件类型的处理方式
  }
);
const codeDocs = await githubLoader.load;
2. 批量加载多个文件

实际业务中,文件通常是以文件夹形式存在的。使用 DirectoryLoader Ke以实现多个文档的加载。

import { DirectoryLoader } from "langchain/document_loaders/fs/directory";
// 加载整个目录
const directoryLoader = new DirectoryLoader(
  "./docs",
  {
    ".pdf":  => new PDFLoader,
    ".docx":  => new DocxLoader,
    ".txt":  => new TextLoader,
  }
);
const allDocs = await directoryLoader.load;
console.log;
四、阶段 2:文档切割

LLM 的上下文窗口有限,不Neng直接塞进整个文档,这就需要对文档进行适当的切割。而切割策略直接影响检索质量,这是hen多新手容易忽视的地方。

LangChain 中Zui常用的切割器是 RecursiveCharacterTextSplitter。它的聪明之处在于会尝试多种分隔符,优先在语义边界处切割。

import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
const splitter = new RecursiveCharacterTextSplitter({
  chunkSize: 1000,      // 每个 chunk 的Zui大字符数
  chunkOverlap: 200,    // 相邻 chunk 的重叠字符数
  separators: ,
});
const chunks = await splitter.splitDocuments;
console.log;
1. ⚠️ 切割策略的常见误区

这里有几个大坑,大家一定要避开:

误区 1:chunkSize 越大越好

❌ 错误Zuo法:

chunkSize: 5000 // 太大!

问题: Ru果 chunk 太大,包含的信息太多,检索时就会引入hen多噪音,导致模型“迷路”。而且,大 chunk 也会导致 Embedding 的语义变得不纯粹。

误区 2:忽略 chunkOverlap

❌ 错误Zuo法:

chunkOverlap: 0 // 没有重叠

问题: Ru果没有重叠,一些关键的句子可Neng正好被切断在两个 chunk 之间。比如“退货期限为30天”可Neng被切成了“退货期限为”和“30天”,导致检索失败。通常建议设置 chunkSize 的 10%-20% 作为重叠。

chunkOverlap: chunkSize * 0.2 // 20% 的重叠
误区 3:中文文档用英文分隔符

❌ 错误Zuo法:

separators:   // 缺少中文标点

✅ 推荐Zuo法:

separators: 
2. 其他切割器

针对不同类型的文档,我们还Ke以使用geng专业的切割器。

Markdown 专用切割器

import { MarkdownTextSplitter } from "@langchain/textsplitters";
const mdSplitter = new MarkdownTextSplitter({
  chunkSize: 1000,
  chunkOverlap: 200,
});
const mdChunks = await mdSplitter.splitDocuments;

代码专用切割器

代码的切割非常讲究,不Neng随便把一个函数名切断。

import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
const codeSplitter = RecursiveCharacterTextSplitter.fromLanguage(
  "typescript",  // 支持 python, java, javascript 等
  {
    chunkSize: 1000,
    chunkOverlap: 100,
  }
);
// 会识别代码结构,避免在中间切割
const codeChunks = await codeSplitter.splitDocuments;
五、阶段 3:Embedding 生成

文档切好后下一步就是把它变成机器Neng理解的向量。Embedding 就是将文本转换为向量,使得语义相似的文本在向量空间中距离geng近。

你Ke以把 Embedding 理解为给每一段文字分配一个独一无二的“语义坐标”。

1. 选择 Embedding 模型

OpenAI 的模型效果Zui好,但需要付费;HuggingFace 的模型免费,但需要本地计算资源。

使用 OpenAI:

import { OpenAIEmbeddings } from "@langchain/openai";
const embeddings = new OpenAIEmbeddings({
  model: "text-embedding-3-small",  // 性价比Zui高
  // model: "text-embedding-3-large",  // 效果geng好,但geng贵
});
// 生成向量
const vector = await embeddings.embedQuery;
console.log;  // 1536 维或 3072 维

使用 HuggingFace:

import { HuggingFaceTransformersEmbeddings } from "@langchain/community/embeddings/hf_transformers";
const embeddings = new HuggingFaceTransformersEmbeddings({
  modelName: "Xenova/all-MiniLM-L6-v2",  // 轻量级模型
});
// 优点:免费、隐私性好
// 缺点:效果略逊于 OpenAI,需要本地计算资源
2. 批量生成 Embedding

为了提高效率,我们通常批量处理文档。

// 单个文本
const vector1 = await embeddings.embedQuery;
// 批量文本
const vectors = await embeddings.embedDocuments();
console.log;  // 3
console.log;  // 384 
六、阶段 4:向量存储

向量有了总得找个地方存吧。向量数据库专门负责存储和检索 Embedding 向量。市面上有hen多选择,比如 Pinecone、Chroma、Weaviate、PGVector 等。

1. Pinecone

Pinecone 是一个全托管的向量数据库,性Neng强劲,但需要付费。

pnpm add @langchain/pinecone @pinecone-database/pinecone

创建索引

import { Pinecone } from "@pinecone-database/pinecone";
const pinecone = new Pinecone({ 
  apiKey: process.env.PINECONE_API_KEY! 
});
// 创建索引
await pinecone.createIndex({
  name: "my-knowledge-base",
  dimension: 1536,  // 与 Embedding 维度一致
  metric: "cosine",  // 相似度度量:cosine / euclidean / dotproduct
  spec: {
    serverless: {
      cloud: "aws",
      region: "us-east-1",
    },
  },
});

存储向量

import { PineconeStore } from "@langchain/pinecone";
import { OpenAIEmbeddings } from "@langchain/openai";
const embeddings = new OpenAIEmbeddings;
const index = pinecone.Index;
// 从 Documents 批量写入
const vectorStore = await PineconeStore.fromDocuments(
  chunks,           // 切割后的文档块
  embeddings,       // Embedding 模型
  { 
    pineconeIndex: index,
    namespace: "product-docs",  // 可选:命名空间隔离
  }
);
console.log;
2. Chroma

Chroma 是开源的,非常适合本地开发和测试。

pnpm add chromadb
import { Chroma } from "@langchain/community/vectorstores/chroma";
const vectorStore = await Chroma.fromDocuments(
  chunks,
  embeddings,
  {
    collectionName: "my-collection",
    url: "http://localhost:8000",  // Chroma 服务地址
  }
);

启动 Chroma 服务:

docker run -p 8000:8000 chromadb/chroma
3. PGVector

Ru果你Yi经在用 PostgreSQL,那么 PGVector 是Zui方便的选择,不需要引入新的数据库组件。

pnpm add @langchain/community pg
import { PGVectorStore } from "@langchain/community/vectorstores/pgvector";
import { Pool } from "pg";
const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
});
const vectorStore = await PGVectorStore.initialize(
  embeddings,
  {
    pool,
    tableName: "documents",
    columns: {
      idColumnName: "id",
      vectorColumnName: "embedding",
      contentColumnName: "content",
      metadataColumnName: "metadata",
    },
  }
);
// 添加文档
await vectorStore.addDocuments;
七、阶段 5:检索与生成

数据准备好了现在终于Ke以开始“开卷考试”了。这是 RAG 的在线阶段,每次用户提问时执行。

1. 基础检索
// 从向量存储创建检索器
const retriever = vectorStore.asRetriever({
  k: 4,  // 返回Zui相似的 4 个文档
});
// 执行检索
const docs = await retriever.invoke;
console.log;  // 4
console.log;  // Zui相关的文档内容
console.log;     // 元数据
2. 构建 RAG Prompt

检索到的文档需要通过 Prompt 喂给 LLM。Prompt 的设计至关重要,要明确告诉 LLM 的行为准则。

import { ChatPromptTemplate } from "@langchain/core/prompts";
const ragPrompt = ChatPromptTemplate.fromMessages(,
  ,
]);
3. 执行生成链
import { ChatOpenAI } from "@langchain/openai";
import { createStuffDocumentsChain } from "langchain/chains/combine_documents";
import { createRetrievalChain } from "langchain/chains/retrieval";
const model = new ChatOpenAI({ 
  model: "gpt-4o", 
  temperature: 0  // 确定性输出
});
// 第一步:创建文档合并链
const combineDocsChain = await createStuffDocumentsChain({
  llm: model,
  prompt: ragPrompt,
});
// 第二步:创建检索链
const ragChain = await createRetrievalChain({
  retriever,
  combineDocsChain,
});
// 第三步:执行
const result = await ragChain.invoke({
  input: "产品的退货政策是什么?",
});
console.log;     // 基于知识库的回答
console.log;    // 检索到的文档片段

返回结果结构:

{
  input: "产品的退货政策是什么?",
  context: ,
  answer: "根据产品手册,退货政策如下:
1. 退货期限:购买后30天内
2. 退款时间:7个工作日内处理

来源:product-manual.pdf 第5页"
}
4. 显示引用来源

为了增加可信度,我们Ke以把引用的来源也展示出来。

// 提取来源信息
const sources = result.context.map(doc => ({
  content: doc.pageContent.slice + "...",
  source: doc.metadata.source,
  page: doc.metadata.page,
}));
console.log;
sources.forEach => {
  console.log`);
  console.log;
});
八、检索策略进阶

基础的相似度检索Neng覆盖大多数场景,但在实际业务中,往往需要geng精细的检索策略。

1. 混合检索

纯向量检索有时候对关键词的匹配不够敏感。混合检索结合了“关键词检索”和“向量检索”的优势。

混合检索的优势:

这有点类似你在参加考试:既要理解题目的意思,又要找到书里的原话。

使用 Weaviate 实现混合检索:

import { WeaviateStore } from "@langchain/weaviate";
const vectorStore = await WeaviateStore.fromDocuments(
  chunks,
  embeddings,
  {
    client: weaviateClient,
    indexName: "Documents",
    textKey: "text",
    metadataKeys: ,
  }
);
// 混合检索
const hybridRetriever = vectorStore.asRetriever({
  searchType: "hybrid",
  searchKwargs: {
    alpha: 0.5,  // 0: 纯关键词, 1: 纯向量, 0.5: 各一半
  },
});
const docs = await hybridRetriever.invoke;

alpha 参数调优:

alpha = 0: 完全依赖关键词匹配,适合查找专有名词。

alpha = 1: 完全依赖向量语义,适合同义词搜索。

alpha = 0.5: 平衡模式。

2. 重排序 为什么需要重排序?

问题: 向量检索是“粗检索”,为了不漏掉相关内容,通常会召回较多的文档。但这其中可Neng包含hen多相关性不强的噪音。

解决方案: 引入一个重排序模型,对召回的文档进行精细打分,只把Zui相关的 Top N 交给 LLM。

import { CohereRerank } from "@langchain/cohere";
const reranker = new CohereRerank({
  apiKey: process.env.COHERE_API_KEY,
  topN: 3,  // 重排序后取前 3 个
  model: "rerank-multilingual-v2.0",  // 支持多语言
});
// 第一步:粗检索
const coarseResults = await retriever.invoke;
// 第二步:精排序
const refinedResults = await reranker.compressDocuments(
  coarseResults, 
  query
);
console.log;  // 3

效果对比:

经过 Rerank 后进入 Prompt 的上下文质量大幅提升,LLM 的回答准确率也会显著提高。

3. 查询

用户的原始问题有时候表述不清,比如“它有几年历史了?”,这里的“它”指代不明。直接检索效果会hen差。

让 LLM 先对问题Zuo ,再检索:

import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
// 定义查询
 Prompt
const queryRewriterPrompt = ChatPromptTemplate.fromMessages(,
  ,
]);
const model = new ChatOpenAI;
const rewriteChain = queryRewriterPrompt.pipe;
// 
查询
const rewrittenQuery = await rewriteChain.invoke({
  question: "它有几年历史了?",
});
console.log;
// 输出:"Apple 公司成立多少年了?"
// 用
后的查询进行检索
const docs = await retriever.invoke;
多步查询

对于复杂问题,Ke以进行多轮 :

// 第一轮:澄清指代
const clarified = await clarifyReferences;
// 第二轮:
缩写
const expanded = await expandAbbreviations;
// 第三轮:提取关键词
const keywords = await extractKeywords;
// Zui终查询
const finalQuery = `${expanded} ${keywords}`;
九、实战中的优化技巧

Zui后分享一些在实际项目中踩坑后出来的经验。

1. 针对不同类型的文档使用不同的切割策略
// 技术文档:较小的 chunk
const techSplitter = new RecursiveCharacterTextSplitter({
  chunkSize: 500,
  chunkOverlap: 50,
});
// 故事/文章:较大的 chunk
const storySplitter = new RecursiveCharacterTextSplitter({
  chunkSize: 2000,
  chunkOverlap: 200,
});
// 代码:使用语言感知切割
const codeSplitter = RecursiveCharacterTextSplitter.fromLanguage(
  "typescript",
  { chunkSize: 1000, chunkOverlap: 100 }
);
2. 检索参数调优
// 从小 k 值开始,逐步增加
const retriever = vectorStore.asRetriever({
  k: 3,  // 从 3 开始测试
});
// 监控检索结果的相关性
const docs = await retriever.invoke;
docs.forEach => {
  console.log;
});
// Ru果相关性低,增大 k 或改进 Embedding
3. Prompt 优化
// 不好的 Prompt
const badPrompt = ChatPromptTemplate.fromMessages(,
]);
// 好的 Prompt
const goodPrompt = ChatPromptTemplate.fromMessages(,
  ,
]);
十、本章小结

RAG 是让 LLM 具备实时知识和私有数据Neng力的关键技术,在减少AI输出幻觉和增加准确度上dou非常重要。通过 LangChain,我们Ke以将这一复杂的流程模块化,从文档加载、切割、向量化到Zui终的检索生成,每一步dou有精细的控制空间。

当然RAG 也不是万Neng药。Ru果你的文档本身质量hen差,或者切割策略极其不合理,那么“垃圾进,垃圾出”的定律依然适用。希望这篇文章Neng帮你避开一些常见的坑,构建出geng精准、geng聪明的 AI 应用。

💡 提示: RAG是一整套技术体系,涉及文本处理、向量数据、优化等多个知识体系,请关注后续推出的完整的RAG教程。

下一章:《第九章 —— 多 Agent 系统》


标签: 深入浅出

SEO优化服务概述

作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。

百度官方合作伙伴 白帽SEO技术 数据驱动优化 效果长期稳定

SEO优化核心服务

网站技术SEO

  • 网站结构优化 - 提升网站爬虫可访问性
  • 页面速度优化 - 缩短加载时间,提高用户体验
  • 移动端适配 - 确保移动设备友好性
  • HTTPS安全协议 - 提升网站安全性与信任度
  • 结构化数据标记 - 增强搜索结果显示效果

内容优化服务

  • 关键词研究与布局 - 精准定位目标关键词
  • 高质量内容创作 - 原创、专业、有价值的内容
  • Meta标签优化 - 提升点击率和相关性
  • 内容更新策略 - 保持网站内容新鲜度
  • 多媒体内容优化 - 图片、视频SEO优化

外链建设策略

  • 高质量外链获取 - 权威网站链接建设
  • 品牌提及监控 - 追踪品牌在线曝光
  • 行业目录提交 - 提升网站基础权威
  • 社交媒体整合 - 增强内容传播力
  • 链接质量分析 - 避免低质量链接风险

SEO服务方案对比

服务项目 基础套餐 标准套餐 高级定制
关键词优化数量 10-20个核心词 30-50个核心词+长尾词 80-150个全方位覆盖
内容优化 基础页面优化 全站内容优化+每月5篇原创 个性化内容策略+每月15篇原创
技术SEO 基本技术检查 全面技术优化+移动适配 深度技术重构+性能优化
外链建设 每月5-10条 每月20-30条高质量外链 每月50+条多渠道外链
数据报告 月度基础报告 双周详细报告+分析 每周深度报告+策略调整
效果保障 3-6个月见效 2-4个月见效 1-3个月快速见效

SEO优化实施流程

我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:

1

网站诊断分析

全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。

2

关键词策略制定

基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。

3

技术优化实施

解决网站技术问题,优化网站结构,提升页面速度和移动端体验。

4

内容优化建设

创作高质量原创内容,优化现有页面,建立内容更新机制。

5

外链建设推广

获取高质量外部链接,建立品牌在线影响力,提升网站权威度。

6

数据监控调整

持续监控排名、流量和转化数据,根据效果调整优化策略。

SEO优化常见问题

SEO优化一般需要多长时间才能看到效果?
SEO是一个渐进的过程,通常需要3-6个月才能看到明显效果。具体时间取决于网站现状、竞争程度和优化强度。我们的标准套餐一般在2-4个月内开始显现效果,高级定制方案可能在1-3个月内就能看到初步成果。
你们使用白帽SEO技术还是黑帽技术?
我们始终坚持使用白帽SEO技术,遵循搜索引擎的官方指南。我们的优化策略注重长期效果和可持续性,绝不使用任何可能导致网站被惩罚的违规手段。作为百度官方合作伙伴,我们承诺提供安全、合规的SEO服务。
SEO优化后效果能持续多久?
通过我们的白帽SEO策略获得的排名和流量具有长期稳定性。一旦网站达到理想排名,只需适当的维护和更新,效果可以持续数年。我们提供优化后维护服务,确保您的网站长期保持竞争优势。
你们提供SEO优化效果保障吗?
我们提供基于数据的SEO效果承诺。根据服务套餐不同,我们承诺在约定时间内将核心关键词优化到指定排名位置,或实现约定的自然流量增长目标。所有承诺都会在服务合同中明确约定,并提供详细的KPI衡量标准。

SEO优化效果数据

基于我们服务的客户数据统计,平均优化效果如下:

+85%
自然搜索流量提升
+120%
关键词排名数量
+60%
网站转化率提升
3-6月
平均见效周期

行业案例 - 制造业

  • 优化前:日均自然流量120,核心词无排名
  • 优化6个月后:日均自然流量950,15个核心词首页排名
  • 效果提升:流量增长692%,询盘量增加320%

行业案例 - 电商

  • 优化前:月均自然订单50单,转化率1.2%
  • 优化4个月后:月均自然订单210单,转化率2.8%
  • 效果提升:订单增长320%,转化率提升133%

行业案例 - 教育

  • 优化前:月均咨询量35个,主要依赖付费广告
  • 优化5个月后:月均咨询量180个,自然流量占比65%
  • 效果提升:咨询量增长414%,营销成本降低57%

为什么选择我们的SEO服务

专业团队

  • 10年以上SEO经验专家带队
  • 百度、Google认证工程师
  • 内容创作、技术开发、数据分析多领域团队
  • 持续培训保持技术领先

数据驱动

  • 自主研发SEO分析工具
  • 实时排名监控系统
  • 竞争对手深度分析
  • 效果可视化报告

透明合作

  • 清晰的服务内容和价格
  • 定期进展汇报和沟通
  • 效果数据实时可查
  • 灵活的合同条款

我们的SEO服务理念

我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。

提交需求或反馈

Demand feedback