Web开发者实战LangChain RAG:构建企业级知识库问答系统
在Web开发中,我们熟悉“数据 → 处理 → 展示”的经典流程:从前端表单收集用户输入,后端查询数据库,再将结果渲染成页面。而如今,当企业希望用自然语言查询内部文档(如产品手册、技术规范、HR政策),这套逻辑依然成立——只是“数据库”换成了向量数据库,“SQL查询”换成了语义搜索。这就是 RAG(Retrieval-Augmented Generation) 的核心思想:先从海量文档中检索出与问题
图片来源网络,侵权联系删。

文章目录
1. 引言
在Web开发中,我们熟悉“数据 → 处理 → 展示”的经典流程:从前端表单收集用户输入,后端查询数据库,再将结果渲染成页面。而如今,当企业希望用自然语言查询内部文档(如产品手册、技术规范、HR政策),这套逻辑依然成立——只是“数据库”换成了向量数据库,“SQL查询”换成了语义搜索。
这就是 RAG(Retrieval-Augmented Generation) 的核心思想:
先从海量文档中检索出与问题最相关的片段,再将这些片段作为上下文喂给大模型,生成精准回答。
对于Web开发者而言,RAG 并非全新范式,而是你熟悉的 “搜索 + 渲染”模式的AI升级版。本文将从Web工程视角出发,详解 LangChain 中 RAG 的完整链路,并通过一个 Node.js + React + Pinecone 的企业知识库项目,带你从零实现可落地的RAG应用。
2. RAG核心组件解析(Web类比)

| RAG 组件 | Web 类比 | 作用 |
|---|---|---|
| 文档加载器(Document Loaders) | 文件上传解析器(如 multer + pdf-parse) | 将PDF/Word/网页等转为纯文本 |
| 文本分割器(Text Splitters) | 分页器(Pagination) | 将长文档切分为小块,适配模型上下文 |
| 嵌入模型(Embedding Model) | 搜索引擎的倒排索引构建器 | 将文本转为高维向量(语义指纹) |
| 向量数据库(Vector DB) | Elasticsearch / MySQL全文索引 | 存储向量并支持相似度搜索 |
| 检索器(Retriever) | 搜索API(/api/search?q=…) | 根据问题向量召回相关文档 |
| LLM + Prompt | 模板引擎(Handlebars/EJS) | 将检索结果+问题组合成最终回答 |
整个流程如同构建一个“智能搜索引擎”:
用户提问 → 语义搜索 → 召回相关段落 → 注入提示词 → 生成答案
3. 文档处理:从原始文件到结构化文本

3.1 文档加载(Document Loading)
LangChain 提供多种加载器,覆盖常见格式:
// 加载本地PDF
import { PDFLoader } from "@langchain/community/document_loaders/fs/pdf";
const loader = new PDFLoader("./docs/product_manual.pdf");
const docs = await loader.load();
// 加载网页
import { PuppeteerWebBaseLoader } from "@langchain/community/document_loaders/web/puppeteer";
const webLoader = new PuppeteerWebBaseLoader("https://example.com/kb");
const webDocs = await webLoader.load();
💡 Web类比:这就像你用
pdf-parse或cheerio解析文件内容。
3.2 文本分割(Document Transformation)
大模型有上下文长度限制(如GPT-4o最多128K),需将长文档切块:
import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
const splitter = new RecursiveCharacterTextSplitter({
chunkSize: 1000, // 每块约1000字符
chunkOverlap: 200 // 相邻块重叠200字符,防断句
});
const splitDocs = await splitter.splitDocuments(docs);
// 输出: [Document(pageContent="...", metadata={source: "manual.pdf", ...}), ...]
✅ 关键点:
metadata字段保留来源信息(文件名、URL、章节),便于溯源。
4. 向量化与存储:构建语义索引

4.1 嵌入模型(Embedding Model)
将文本转为向量。推荐使用开源且高效的 OpenAI Embeddings 或 HuggingFace Sentence Transformers:
import { OpenAIEmbeddings } from "@langchain/openai";
const embeddings = new OpenAIEmbeddings({
apiKey: process.env.OPENAI_API_KEY,
modelName: "text-embedding-3-small" // 成本低、性能好
});
4.2 向量数据库选型
| 数据库 | Web部署友好度 | 适用场景 |
|---|---|---|
| Pinecone | ⭐⭐⭐⭐(全托管) | 快速上线、无需运维 |
| Chroma | ⭐⭐⭐(嵌入式) | 本地开发、轻量级 |
| Weaviate | ⭐⭐(需Docker) | 需要混合搜索(关键词+向量) |
| PostgreSQL + pgvector | ⭐⭐⭐⭐ | 已有PostgreSQL、希望统一存储 |
本文以 Pinecone 为例(免费 tier 足够演示)。
4.3 构建向量索引
import { Pinecone } from "@pinecone-database/pinecone";
import { PineconeStore } from "@langchain/pinecone";
// 初始化Pinecone
const pc = new Pinecone({ apiKey: process.env.PINECONE_API_KEY });
const index = pc.Index("company-kb");
// 创建向量存储
const vectorStore = await PineconeStore.fromDocuments(
splitDocs, // 切分后的文档
embeddings, // 嵌入模型
{ pineconeIndex: index }
);
🔧 注意:首次运行会自动计算所有文档的向量并存入Pinecone。
5. 检索与生成:RAG链的核心逻辑

5.1 创建检索器(Retriever)
// 从向量库创建检索器,返回最相关的4个片段
const retriever = vectorStore.asRetriever({
k: 4,
searchType: "similarity"
});
5.2 构建RAG链(LCEL风格)
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { ChatOpenAI } from "@langchain/openai";
import { createStuffDocumentsChain } from "langchain/chains/combine_documents";
import { createRetrievalChain } from "langchain/chains/retrieval";
const llm = new ChatOpenAI({ model: "gpt-4o" });
// 定义提示词模板
const prompt = ChatPromptTemplate.fromTemplate(`
你是一个企业知识库助手,请基于以下上下文回答问题。
如果不知道答案,请说“根据现有资料无法回答”。
上下文:
{context}
问题:{input}
`);
// 组合文档链
const combineDocsChain = createStuffDocumentsChain({
llm,
prompt,
});
// 创建完整RAG链
const ragChain = createRetrievalChain({
retriever,
combineDocsChain,
});
5.3 调用RAG链
const response = await ragChain.invoke({
input: "我们的产品退货政策是什么?"
});
console.log(response.answer);
// 输出: "根据公司政策,商品在签收后7天内可无理由退货..."
console.log(response.context); // 返回检索到的原始文档片段
6. 应用实战:企业知识库问答系统

6.1 项目架构
enterprise-rag/
├── backend/
│ ├── ingestion/ # 文档预处理
│ │ └── ingest.js # 加载+切分+存向量库
│ ├── chains/
│ │ └── ragChain.js # RAG链定义
│ └── routes/
│ └── ask.js # /api/ask 接口
└── frontend/ # React搜索界面
6.2 后端API(Express)
// backend/routes/ask.js
import { ragChain } from "../chains/ragChain.js";
router.post("/ask", async (req, res) => {
try {
const { question } = req.body;
const result = await ragChain.invoke({ input: question });
// 返回答案 + 溯源(用于前端展示来源)
res.json({
answer: result.answer,
sources: result.context.map(doc => ({
content: doc.pageContent,
source: doc.metadata.source
}))
});
} catch (err) {
res.status(500).json({ error: err.message });
}
});
6.3 前端界面(React)
// 展示答案和来源
function Answer({ answer, sources }) {
return (
<div>
<div className="answer">{answer}</div>
<div className="sources">
<h4>参考来源:</h4>
{sources.map((src, i) => (
<div key={i} className="source-card">
<p>{src.content.substring(0, 100)}...</p>
<small>来自: {src.source}</small>
</div>
))}
</div>
</div>
);
}
6.4 效果演示
用户问:“如何申请年假?”
系统回答:“员工需提前3天在HR系统提交申请…”
并附上《员工手册_v2.pdf》第12页的原文片段 —— 可解释、可溯源!
7. 优化与生产建议
7.1 提升检索精度
- 使用 HyDE(假设性文档嵌入):先让LLM生成假设答案,再用该答案去检索
- 混合搜索:结合关键词(BM25) + 向量搜索(如Weaviate)
- 元数据过滤:只检索特定部门/产品的文档(
retriever.getRelevantDocuments(query, { filter: { department: "IT" } }))
7.2 降低成本
- 使用
text-embedding-3-small而非 large - 缓存高频问题的答案(Redis)
- 限制上下文长度,避免Token浪费
7.3 安全与权限
- 在
metadata中记录文档权限级别 - 检索时传入用户角色,过滤无权访问的文档
- 敏感内容脱敏后再存入向量库
8. 总结与学习路径
RAG 不是魔法,而是一套可工程化的信息检索增强方案。作为Web开发者,你已具备构建它的全部能力:
- 文件处理 → 用过 multer / pdf-parse
- 搜索系统 → 熟悉 Elasticsearch / SQL LIKE
- API设计 → 知道如何封装 /ask 接口
下一步
-
动手实践
- 用公司内部文档(如Confluence导出PDF)搭建知识库
- 尝试不同向量数据库(Chroma本地跑,Pinecone上云)
-
深入优化
- 实现多轮RAG(追问时保留上下文)
- 加入评分机制:让用户对答案点赞/点踩,反馈优化检索
-
推荐资源
- 官方指南:LangChain RAG Tutorial
- 开源项目:langchain-ai/chat-langchain(含完整RAG实现)
结语:未来的内部工具,不再是复杂的表单和菜单,而是一个“懂你”的对话入口。作为Web开发者,你站在构建这一未来的最前线——用RAG,把知识变成服务。
更多推荐


所有评论(0)