【MY_TRUCK - AI 应用】RAG 与 LangChain 入门:检索增强生成、向量检索与链式编排


从 RAG 公式与工作流讲到向量/嵌入与余弦相似度,覆盖 LangChain Models、Prompt、Chain、Memory、文档分割与 Chroma 检索,并给出完整 RAG 开发步骤总结。

本文承接「提示词工程」笔记,面向要在业务里用 外部知识库 给大模型「补课」、减少幻觉并接入 私有/实时数据 的读者。内容包含 RAG 定义与标准流程向量与嵌入LangChain 组件(Models / Prompt / Chain / Memory / Loader / 向量库)完整 RAG 开发步骤 。读完后能够复述离线/在线两条链路,并理解链式调用 prompt | model | parser 与向量检索在整体中的位置。

⚡ 快速参考

  • 适用场景:领域知识不在预训练权重里、需要基于文档回答、要降低幻觉并控制数据边界(内网文档、手册、工单等)。
  • 核心结论RAG = 检索技术 + LLM 提示 ;标准路径为 Indexing(切分→嵌入→入库)→ Retrieval(query 转向量→Top-K)→ Generation(上下文+问题→生成) ;LangChain 负责 组件编排(不造模型)。
  • 最短步骤 :准备文档 → 加载与 chunk 分割Embedding 写入向量库 → 用户提问 相似度检索Prompt 融合检索片段Chat/LLM 生成 →(可选)流式与 会话记忆
  • 常用命令/代码 :环境安装与各组件示例见 第三节 ;向量检索典型调用:vector_store.similarity_search("问题", k=4)(笔记原文)。
  • 避坑提醒 :嵌入 维度越高语义越细但开销越大chunk_size / overlap 直接影响召回与上下文长度;临时记忆 重启即丢,持久化需自行按 session 落盘。

📚 学习目标

  1. 掌握 RAG 离线/在线流程Indexing---Retrieval---Generation 三阶段对应关系。
  2. 能独立完成 DashScope / Ollama 三类模型调用PromptTemplate / ChatPromptTemplate 基础写法,以及 Chroma + DashScopeEmbeddings 的入库与检索代码骨架。
  3. 能说出 invokestream 的差异余弦相似度在检索中的作用 ,以及 | 组合数据流 的面试级表述。

一、基础概念

1.1 什么是 RAG

RAG(Retrieval-Augmented Generation)检索增强生成公式:RAG = 检索技术 + LLM 提示

解决大模型 4 大问题:

  • 知识过时(无实时数据)
  • 领域知识不足(无私有数据)
  • 幻觉(编造答案)
  • 数据安全性

1.2RAG 核心价值

  • 用外部文档 / 私有知识库给模型 "补课"
  • 回答基于事实,减少幻觉
  • 无需重新训练模型,成本低、更新快
  • 支持实时数据接入

1.3 RAG 标准工作流程

RAG 分两条线:

离线流程(构建知识库)

  • 文档加载 → 文本分割 → 向量化 → 存入向量数据库

在线流程(用户提问)

  • 用户问题向量化 → 向量检索 → 提示词融合 → 模型生成答案

三阶段标准流程:

  • 索引 Indexing:文档切分 chunk → 嵌入向量 → 存入向量库
  • 检索 Retrieval:用户 query 转向量 → 相似度匹配 Top-K
  • 生成 Generation:检索内容 + 问题 → 输入模型 → 精准回答

1.4 向量与嵌入基础

向量是什么

  • 向量 = 文本的数学身份证:把文字语义转为固定长度数字序列,让计算机能计算相似度。

向量嵌入

  • 使用文本嵌入模型(如 text-embedding-v1)生成向量。维度越高,语义越精准,但性能开销越大。常用:1536 维

余弦相似度

  • 判断两个向量方向是否相近:
    • 夹角越小 → 越相似
    • 只看方向,不看长度
  • 公式:余弦相似度 = 点积 / (模长A × 模长B)

1.5 LangChain 是什么

LangChain 是什么

  • LLM 应用开发框架,不造模型,只做组件编排。把模型、提示词、记忆、检索、文档、链、智能体全部打通。

LangChain 核心功能(原始笔记)

  • Prompts:提示词工程
  • Models:模型调用
  • History:对话记忆
  • Indexes:文档 / 向量库管理
  • Chains:执行链路
  • Agent:智能体

1.6 LangChain Models:三类模型

  • LLMs:文本生成
  • Chat Models:多轮对话
  • Embeddings Models:文本转向量

1.7 核心术语对比

术语 含义 典型用途 常见误区
Indexing 文档切块、嵌入、入库 构建可检索知识库 切块过大导致噪声多;过小丢语义
Retrieval query 与向量库相似度匹配 取 Top-K 片段作上下文 k 过大稀释主题;过小漏证据
Generation 将检索片段与问题拼入提示再生成 最终回答用户 不把检索结果写入提示仍易幻觉
Embedding 文本→稠密向量 检索、聚类、去重 混用不同嵌入模型导致向量空间不一致
Chain(链) 用 ` ` 串联组件 `prompt

二、原理详解

2.1 为什么用 RAG 而不是只堆提示词(归纳)

原始笔记从四个痛点出发:时效、私域、幻觉、安全 。RAG 通过 可更新的外部知识 让生成锚定在检索到的证据上,成本低于重训,适合文档迭代频繁的场景。

2.2 离线 vs 在线:数据流(对应原始笔记两条线)

text 复制代码
离线:文档 -> Loader -> Split -> Embed -> VectorStore 持久化
在线:用户问题 -> Embed -> similarity_search(Top-K) -> Prompt 融合 -> LLM -> 回答

2.3 余弦相似度为何常用

高维向量下,方向一致往往比绝对长度更能表达「语义相近」。余弦相似度对向量长度缩放相对不敏感,适合文案级别语义检索(笔记:只看方向,不看长度)。

2.4 LangChain 「链」的本质

什么是链

  • | 把组件串起来,上一个输出 = 下一个输入。
text 复制代码
chain = prompt | model | parser

2.5 RAG 检索流程复述

  • 加载文档 → 分割 → 向量化 → 入库
  • 用户问题 → 向量化 → 相似度检索
  • 检索结果 + 问题 → 提示词 → 模型回答

三、完整实战代码

3.1 环境安装

bash 复制代码
pip install langchain langchain-community langchain-ollama langchain-chroma dashscope chromadb bs4 jq

3.2 阿里云通义千问调用

python 复制代码
# LLM 模型
from langchain_community.llms.tongyi import Tongyi
llm = Tongyi(model="qwen-max")
res = llm.invoke("讲个笑话")

# 聊天模型
from langchain_community.chat_models.tongyi import ChatTongyi
chat = ChatTongyi(model="qwen3-max")

3.3 Ollama 本地模型

python 复制代码
from langchain_ollama import OllamaLLM
model = OllamaLLM(model="qwen3:4b")

3.4 嵌入模型

python 复制代码
# 阿里云
from langchain_community.embeddings import DashScopeEmbeddings
embed = DashScopeEmbeddings()

# Ollama
from langchain_ollama import OllamaEmbeddings
embed = OllamaEmbeddings(model="qwen3-embedding")

3.5 两种调用方式

  • .invoke():一次性返回
  • .stream():流式输出

3.6 LangChain 提示词模板

通用模板 PromptTemplate

python 复制代码
from langchain_core.prompts import PromptTemplate
prompt = PromptTemplate.from_template("给{lastname}家{gender}起名")

少样本模板 FewShotPromptTemplate

python 复制代码
from langchain_core.prompts import FewShotPromptTemplate

参数:

  • examples:示例列表
  • example_prompt:示例模板
  • prefix:前缀说明
  • suffix:后缀问题
  • input_variables:变量

聊天模板 ChatPromptTemplate

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是诗人"),
    ("human", "{question}")
])

支持动态历史:MessagesPlaceholder("history")

3.7 LangChain Chain 链式调用

必须会的解析器(原始笔记)

  • StrOutputParser:AIMessage → 字符串
  • JsonOutputParser:AIMessage → JSON 字典
python 复制代码
chain = prompt | model | parser

自定义函数入链

python 复制代码
from langchain_core.runnables import RunnableLambda
chain = prompt | model | RunnableLambda(lambda x: {"name": x.content})

或直接写函数:

python 复制代码
chain = prompt | model | (lambda x: {"name": x.content})

3.8 LangChain 记忆 Memory

临时记忆(内存)

  • InMemoryChatMessageHistory:重启程序丢失。

长期记忆(文件持久化)

  • 自定义 FileChatMessageHistory
  • session_id 存文件
  • 重启程序仍可读取历史

带记忆的链

python 复制代码
from langchain_core.runnables.history import RunnableWithMessageHistory
chain = RunnableWithMessageHistory(
    base_chain,
    get_session_history,
    input_messages_key="input",
    history_messages_key="chat_history"
)

3.9 文档加载与分割

文档加载器 Document Loader

统一返回 Document 对象:

  • page_content:内容
  • metadata:元信息

常用 Loader(原始笔记):

  • CSVLoader:加载 CSV
  • JSONLoader:加载 JSON(依赖 jq)
  • PyPDFLoader:加载 PDF(依赖 pypdf)
  • TextLoader:加载文本

文档分割(关键)

RecursiveCharacterTextSplitter(官方推荐)

python 复制代码
from langchain_text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50,
    separators=["\n\n","\n","。","!","?"," "]
)

3.10 向量数据库与检索

向量库类型

  • InMemoryVectorStore:内存版
  • Chroma:本地轻量级向量库

基本使用

python 复制代码
from langchain_chroma import Chroma
from langchain_community.embeddings import DashScopeEmbeddings

vector_store = Chroma(
    embedding_function=DashScopeEmbeddings(),
    persist_directory="./chroma_db"
)

# 添加
vector_store.add_documents(docs)

# 检索
vector_store.similarity_search("问题", k=4)

四、开发避坑总结

4.1 典型问题清单

  1. 检索命中差或答非所问
    原因chunk_size / chunk_overlap 与文档结构不匹配;分隔符未覆盖实际标点习惯(笔记强调分割关键)。
    解决 :按文档类型调参;优先 RecursiveCharacterTextSplitter 并从日志中抽查若干 chunk 语义完整性。

  2. 同一库多次试验结果漂移
    原因 :嵌入模型更换或混用(笔记:维度与模型差异带来向量空间不一致)。
    解决 :同一业务固定同一 Embeddings 实现;重建索引后再对比指标。

  3. 多轮对话「失忆」或上下文爆炸
    原因 :仅用内存历史或未限制 history 长度(笔记:InMemoryChatMessageHistory 重启丢失;长期需 FileChatMessageHistory + session)。
    解决:明确 session 边界;对历史做裁剪/摘要并与 RAG 检索片段分工(事实来自库,偏好来自对话)。

4.2 最佳实践

  • 检索侧:固定 Top-K 策略并记录每次检索片段,便于回归与风控审计。
  • 生成侧:提示中要求引用或摘录检索内容,与笔记「绑定参考文本」思路一致。
  • 工程侧:persist_directory 与嵌入模型版本写入配置或元数据,避免「同一目录混模型」。

五、面试考点

5.1 高频问题

  • Q1:用一句话解释 RAG。
    A检索增强生成 ,先用检索从向量库取相关片段,再把片段与问题交给 LLM 生成,公式上即 检索 + 提示 + 生成

  • Q2:Indexing、Retrieval、Generation 各做什么?
    A:Indexing 把文档切块并嵌入入库;Retrieval 把 query 转向量并做相似度 Top-K;Generation 把检索内容与问题融合后由模型输出答案。

  • Q3:LangChain 里 prompt | model | parser 表达什么?
    A :链式组合 runnable:前一组件输出作为后一组件输入;parser 负责把消息解析成字符串或 JSON(笔记 StrOutputParser / JsonOutputParser)。

5.2 进阶追问

  • 余弦相似度为何「只看方向」仍适合语义检索? → 高维语义向量往往更强调方向一致性;对长度缩放相对稳健。
  • LLM、Chat Model、Embeddings 三类分工? → 生成/对话/转向量三类接口,RAG 至少用到 Embeddings + Chat 或 LLM。

本文为MY_TRUCK原创实战学习笔记,持续更新Java后端与AI应用领域干货,问题欢迎评论区交流。

相关推荐
theaiera1 小时前
用 Tauri 写一个 AI Chat:3MB 的桌面应用干翻 Electron 100MB
人工智能
scglwsj1 小时前
Spec:让 AI 在实现前真正理解问题
人工智能
狐狐生风1 小时前
LangGraph 核心概念全解笔记
人工智能·python·langchain·prompt·langgraph
EAIReport1 小时前
深度拆解WorkBuddy技术实现:腾讯云全场景AI智能体的架构设计与核心逻辑
人工智能·云计算·腾讯云
美狐美颜SDK开放平台1 小时前
什么是美颜SDK?高并发场景下的企业级美颜SDK如何开发?
android·人工智能·ios·美颜sdk·第三方美颜sdk·视频美颜sdk
Westward-sun.1 小时前
Claude Code 接入 DeepSeek V4 Pro:从 npm 安装到 CC Switch 配置完整记录
网络·人工智能
项目題供诗1 小时前
STM32-对射式红外传感器计次&旋转编码器计次(九)
人工智能·stm32·嵌入式硬件
灵机一物1 小时前
灵机一物AI原生电商小程序、PC端(已上线)-黄仁勋 CNBC 对话全文解析:AI 算力、芯片出口、安全开源与产业生态核心观点
人工智能
叶子Talk1 小时前
AI终端国标发布:你的手机/眼镜是L几?
人工智能·ai·智能手机·国家标准·智能终端·工信部