大模型应用之使用LangChain实现RAG(一)

LangChain介绍

2022年10月LangChain由 Lson Chase 创建,LangChain围绕 LLMs(大语言模型)建立,为各种 LLMs 实现通用接口,简化 LLMs 相关开发,方便开发者快速构建复杂的 LLMs 应用。

LangChain 是一个用于开发大语言模型(LLM)相关应用的 Python 第三方库 ,它是一个 集大成者/主力框架 ,提供了构建复杂LLM应用所需的各种功能组件和API。核心目标是让开发者能够便捷地调用 LLM 的全部能力 。后续学习与开发 RAG(检索增强生成) 应用的主力框架

环境设置

shell 复制代码
pip install langchain langchain-community langchain-ollama dashscope chromadb -i https://pypi.tuna.tsinghua.edu.cn/simple
  • langchain:LangChain 框架的核心主包,提供了基础架构和核心组件。
  • langchain-community: 社区支持包,集成了大量第三方模型、工具和功能,极大地扩展了 LangChain 的能力
  • langchain-ollama : 专门用于支持调用 Ollama 框架托管部署的本地大语言模型
  • dashscope : 阿里云 通义千问 大模型的官方 Python SDK。用于通过 LangChain 调用阿里云的模型服务。
  • chromadb: LangChain 兼容多种向量数据库如chromadb,用于实现文档的存储、检索与分析,这是构建 RAG 应用的关键组件

RAG介绍

RAG主要针对大语言模型固有的以下四个关键问题:

  • 领域知识缺乏:LLM的训练数据主要来自公开的互联网和开源数据集,缺乏特定领域(如企业、专业)的私有知识。
  • 知识过时:模型训练完成后知识即固化,无法自动更新,导致信息滞后。
  • 幻觉问题:模型可能生成看似合理但实际错误或虚构的信息。
  • 安全与可控性:难以控制模型生成内容的范围和准确性。

RAG通过引入外部知识检索,RAG能够:

  • 补充领域知识和私有数据

  • 整合实时数据

  • 减少生成的不确定性(缓解幻觉)

  • 增强数据安全与可控性

  • 无需重新训练模型,相比微调(Fine-tuning),RAG只需更新知识库,成本更低,效率更高

    RAG 标准流程由索引(Indexing)、检索(Retriever)和生成(Generation)三个核心阶段组成。

  • 索引阶段

    ,通过处理多种来源多种格式的文档提取其中文本,将其切分为标准长度的文本块(chunk),并进行嵌入向量化(embedding),向量存储在向量数据库(vector database)中。

    • 加载文件
    • 内容提取
    • 文本分割,形成 chunk
    • 文本向量化
    • 存向量数据库
  • 检索阶段

    用户输入的查询(query)被转化为向量表示,通过相似度匹配从向量数据库中检索出最相关的文本块。

    • query 向量化
    • 在文本向量中匹配出与问句向量相似的 top_k 个
  • 生成阶段

    ,检索到的相关文本与原始查询共同构成提示词(Prompt),输入大语言模型(LLM),生成精确且具备上下文关联的回答。

    • 匹配出的文本作为上下文和问题一起添加到 prompt 中
    • 提交给 LLM 生成答案:

简单来说,RAG分两条线:离线流程、在线流程

基础调用阿里云通义千问大模型

1、介绍

LangChain模型组件集成了多种模型,并为所有模型提供统一的精简接口。目前支持以下三类模型:

  • LLMs(大语言模型):技术范畴统称,基于大参数量、海量文本训练的Transformer架构模型。主要理解和生成自然语言。服务于文本生成场景。
  • Chat Models(聊天模型):专为对话场景优化的LLMs。模拟人类对话的轮次交互。主要服务于聊天场景。
  • Text Embeddings Models(文本嵌入模型):接收文本输入,输出文本的向量表示。

阿里云通义千问系列主要来源于langchain_community包。

2、调用LLMs示例

LangChain 调用阿里云通义千问示例

python 复制代码
from langchain_community.llms.tongyi import Tongyi

# 实例化模型
llm = Tongyi(model='qwen-max')

# 模型推理
res = llm.invoke("帮我讲个笑话吧")
print(res)

通过 langchain_ollama 包导入 OllamaLLM 类,即可调用本地已启动的 Ollama 模型。

(确保 Ollama 服务已启动。已提前通过 Ollama 下载好需要使用的模型。)

python 复制代码
from langchain_ollama import OllamaLLM

# 实例化模型,指定模型名称(例如:"qwen3:4b")
model = OllamaLLM(model="qwen3:4b")

# 通过 invoke 方法调用模型
res = model.invoke(input="你是谁呀能做什么?")
print(res)

3、调用聊天模型示例

在聊天模型中,消息通常分为以下三种类型,使用时需按约定传入对应的值:

消息类型 说明 对应 OpenAI 库中的角色
AIMessage AI 输出的消息,即模型对问题的回答或生成的响应。 assistant 角色
HumanMessage 用户向模型发送的提示信息,例如问题、指令等。 user 角色
SystemMessage 用于设定模型的上下文环境、角色或任务背景,如系统指令、角色扮演设定、输出格式要求等。 system 角色

通义千问示例

python 复制代码
from langchain_community.chat_models.tongyi import ChatTongyi
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage

# 使用聊天模型
model = ChatTongyi(model="qwen3-max")

messages = [
    SystemMessage(content="你是一个边塞诗人"),
    HumanMessage(content="写一首唐诗"),
    AIMessage(content="锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦。"),
    HumanMessage(content="按照你上一个回复的格式,在写一首唐诗")
]

res = model.stream(input=messages)

for chunk in res:
    print(chunk.content, end="",flush=True)

ollama本地调用示例

python 复制代码
from langchain_community.chat_models.ollama import ChatOllama
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage

# 使用聊天模型
model = ChatOllama(model="qwen3:4b")

messages = [
    SystemMessage(content="你是一个边塞诗人"),
    HumanMessage(content="写一首唐诗"),
    AIMessage(content="锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦。"),
    HumanMessage(content="按照你上一个回复的格式,在写一首唐诗")
]

res = model.stream(input=messages)

for chunk in res:
    print(chunk.content, end="",flush=True)

4、调用文本嵌入模型

Embeddings Models 嵌入模型的特点:将字符串作为输入,返回一个浮点数的列表(向量)。

在 NLP 中,Embedding 的作用就是将数据进行文本向量化。

调用阿里

复制代码
from langchain_community.embeddings import DashScopeEmbeddings

# 通过阿里的DashScopeEmbeddings默认使用text-embeddings-v1 文本嵌入模型
model = DashScopeEmbeddings()

# 文本向量化
print(model.embed_query("在哪里"))
# 批量文本向量化
print(model.embed_documents(["你好","吃什么饭"]))

调用本地Ollama

复制代码
from langchain_ollama import OllamaEmbeddings

# 通过阿里的DashScopeEmbeddings默认使用text-embeddings-v1 文本嵌入模型
model = OllamaEmbeddings(model="qwen3-embedding:0.6b")

# 文本向量化
print(model.embed_query("在哪里"))
# 批量文本向量化
print(model.embed_documents(["你好","吃什么饭"]))

提示词prompt

1、zero-shot的提示词

提示词优化在模型应用中非常重要,LangChain提供了PromptTemplate类,用来协助优化提示词。

PromptTemplate 表示提示词模板,可以构建一个自定义的基础提示词模板,支持变量的注入,最终生成所需的提示词。

python 复制代码
from langchain_community.llms.tongyi import Tongyi
from langchain_core.prompts import PromptTemplate

# 没有任何提示,即zero-shot思想
prompt_template = PromptTemplate.from_template(
    "我到邻居姓{lastname},刚生了{gender},你帮我起个名字"
)

# 因为Tongyi属于llms包下的需要使用大语言模型,不能用其他类型模型如聊天模型qwen3-max
model = Tongyi(model="qwen-max")

# 填充提示词模板,像LLM模型提问
# template_format = prompt_template.format(lastname="张", gender="女儿")
# res = model.invoke(input=template_format)
# print(res)


# 通过框架里的链式写法,(注意:字符串无法加入链式写法)
chain = prompt_template | model
res = chain.invoke({"lastname": "张", "gender": "女儿"})
print(res)

2、few-shot的提示词

FewShotPromptTemplate: 支持基于模板注入任意数量的示例信息。

python 复制代码
from langchain_community.llms.tongyi import Tongyi
from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate

# 示例的模板
example_template = PromptTemplate.from_template("单词: {word},反义词: {antonym}")

# 示例的动态数据注入,要求是list内部套字典
examples_data = [
    {"word": "大", "antonym": "小"},
    {"word": "上", "antonym": "下"}
]

few_shot_template = FewShotPromptTemplate(
    example_prompt=example_template,  # 示例数据的模板
    examples=examples_data,           # 示例的数据(用来注入动态数据的),list内套字典
    prefix="告知我单词的反义词,我提供如下的示例:",      # 示例之前的提示词
    suffix="基于前面的示例告知我,{input_word}的反义词是?",  # 示例之后的提示词
    input_variables=['input_word']    # 声明在前缀或后缀中所需注入的变量名
)

# 生成最终提示词
prompt_text = few_shot_template.invoke(input={"input_word": "左"}).to_string()
print(prompt_text)

tongyi = Tongyi(model="qwen-max")
print(tongyi.invoke(input(prompt_text)))

3、历史会话的提示词

ChatPromptTemplate: 支持注入任意数量的历史会话信息。

python 复制代码
from langchain_community.chat_models import ChatTongyi
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

# 获取历史提示词
history_chat = [
    ("human", "请来一首唐诗"),
    ("ai", "白日依山尽,黄河入海流。欲穷千里目,更上一层楼。"),
    ("human", "请再来一首唐诗"),
    ("ai", "锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦。"),
]
chat_message = ChatPromptTemplate.from_messages(
    [
        ("system", "你是一个边塞诗人,可以作诗"),
        MessagesPlaceholder("history_chat"),
        ("human", "请再来一首唐诗"),
    ]
)
prompt_txt = chat_message.invoke({"history_chat": history_chat}).to_string()

# 提问AI
tongyi = ChatTongyi(model="qwen3-max")
res = tongyi.invoke(prompt_txt)
print(res.content)

Chain链式调用

「将组件串联,上一个组件的输出作为下一个组件的输入」是 LangChain 链(尤其是 | 管道链)的核心工作原理,这也是链式调用的核心价值:实现数据的自动化流转与组件的协同工作,如下。

chain = prompt_template | model

核心前提:即Runnable子类对象才能入链(以及Callable、Mapping接口子类对象也可加入(后续了解用的不多))。我们目前所学习到的组件,均是Runnable接口的子类,如下类的继承关系:

python 复制代码
from langchain_community.chat_models import ChatTongyi
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnableSerializable

chat_prompt_template = ChatPromptTemplate.from_messages([
    ("system", "你是一个边塞诗人,可以作诗。"),
    MessagesPlaceholder("history"),
    ("human", "请再来一首唐诗"),
])

history_data = [
    ("human", "你来写一个唐诗"),
    ("ai", "床前明月光,疑是地上霜。举头望明月,低头思故乡"),
    ("human", "好诗再来一个"),
    ("ai", "锄禾日当午,汗滴禾下土。谁知盘中餐,粒粒皆辛苦")
]

model = ChatTongyi(model="qwen3-max")

# 组成链,要求每一个组件都是Runnable接口的子类
chain: RunnableSerializable = chat_prompt_template | model

# 通过链去调用invoke或stream
# res = chain.invoke({"history": history_data})
# print(res.content)

for chunk in chain.stream({"history": history_data}):
    print(chunk.content,end="",flush= True)
  • 通过 | 链接提示词模板对象和模型对象
  • 返回值 chain 对象是 RunnableSerializable对象
    • 是 Runnable接口的直接子类
    • 也是绝大多数组件的父类
  • 通过 invoke或stream进行阻塞执行或流式执行

组成的链在执行上有 | 上一个组件的输出作为下一个组件的输入的特性。

所以有如下执行流程:

相关推荐
小天呐5 小时前
08—langchain Retrieval
langchain
laplace01237 小时前
mcp和skills区别
agent·rag·mcp·skills
Dontla9 小时前
黑马大模型RAG与Agent智能体实战教程LangChain提示词——6、提示词工程(提示词优化、few-shot、金融文本信息抽取案例、金融文本匹配案例)
redis·金融·langchain
JaydenAI9 小时前
[LangChain之链]LangChain的Chain——由Runnable构建的管道
python·langchain
草帽lufei9 小时前
LangChain 框架核心向量存储
langchain
猫头虎9 小时前
如何使用Docker部署OpenClaw汉化中文版?
运维·人工智能·docker·容器·langchain·开源·aigc
qq_54702617910 小时前
LangChain 1.0 核心概念
运维·服务器·langchain
uXrvbWJGleS10 小时前
三相两电平整流器Simulink仿真探究
langchain
猫头虎11 小时前
手动部署开源OpenClaw汉化中文版过程中常见问题排查手册
人工智能·langchain·开源·github·aigc·agi·openclaw