引言

       LangChain是一个强大的框架,旨在帮助开发者更高效地构建基于大语言模型(LLM)的应用。无论是构建聊天机器人、自动化文档处理,还是开发复杂的问答系统,LangChain都提供了丰富的工具和模块。本文将带你深入了解LangChain的核心功能,并通过实际示例展示如何应用它。

一、LangChain简介

       LangChain是一个开源框架,专注于将大语言模型(如GPT、LLaMA等)与其他工具和数据源结合,构建端到端的应用。

       核心功能:链(Chains)将多个任务串联成高效的工作流;代理(Agents)使模型能够动态选择工具完成任务;记忆(Memory)支持上下文记忆,实现流畅的多轮对话;数据加载(Data Loaders)从多种数据源加载数据,确保信息来源丰富多样;提示模板(Prompt Templates)则标准化提示词设计,提升模型输出的准确性和一致性。这些功能共同构成了 LangChain 强大的开发框架,助力开发者高效构建基于大型语言模型的应用。

       适用场景:聊天机器人、文档问答系统、自动化数据处理、知识库构建等。

二、LangChain的核心模块快速概览

1、 模型调用: 

       首先安装必要的库,这里默认安装最新版:

!pip install langchain  # 安装 LangChain 框架本身
!pip install openai  # 安装 OpenAI 的 Python SDK(软件开发工具包)
!pip install langchain-openai  # 安装 LangChain 的 OpenAI 集成包

       安装完成后,需要使用 OpenAI 的模型,从环境变量中获取你的 OpenAI API 密钥,调用ChatOpenAI()进行连接后就可以进行提问。

import os
import openai
from langchain.chat_models import ChatOpenAI

# 从环境变量中读取 API 密钥和基础 URL
openai.api_key = os.environ.get('OPENAI_API_KEY')  # 环境变量中储存 API 密钥
openai.api_base = os.environ.get('OPENAI_API_BASE')  # 环境变量中储存基础 URL

# 创建 ChatOpenAI 实例
llm = ChatOpenAI()  # 默认使用'gpt-3.5-turbo'模型

# 直接提供问题,并调用 llm
response = llm.invoke("你是什么模型")

 2、prompt template的使用

       我们可以创建prompt template, 并引入一些变量到prompt template中,这样在应用的时候更加灵活。from_messages 是一个类方法,用于从一组消息中创建一个聊天提示模板。这些消息可以是系统消息(system)或用户消息(user),它们定义了聊天的上下文和用户输入。

from langchain_core.prompts import ChatPromptTemplate  # 用于构建聊天提示模板的工具

# 创建一个聊天提示模板,定义了聊天的上下文和用户输入
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are the technical writer"),  # 系统消息,定义聊天机器人的角色为“技术作家”
    ("user", "{input}")  # 用户消息,其中"{input}"是一个变量占位符,用于动态插入用户输入的内容
])

# 我们可以把prompt和具体llm的调用和在一起
chain = prompt | llm  # 使用管道操作符(|)将prompt和llm连接起来,形成一个链式调用
chain.invoke({"input": "你是什么模型?"})  # # 调用chain,并传入具体的用户输入

       我们也可以在链式调用(chain)中加入一个输出解析器(output_parser),以确保最终的输出格式。

from langchain_core.output_parsers import StrOutputParser  # 一个输出解析器,用于将语言模型的输出解析为字符串格式。

output_parser = StrOutputParser()  # 创建一个字符串输出解析器
chain = prompt | llm | output_parser  # 将prompt、llm和output_parser连接起来,形成完整的链式调用
chain.invoke({"input": "你是什么模型?"})  # 调用chain,并传入具体的用户输入

3、实现RAG+Langchain

       若大模型对所问问题理解不到位,可基于外部知识,增强大模型回复。

#  结合相关知识的来生成更好地答案,分几步:
#  第一步: 寻找关于相应的一些文库,并抓取内容
#  第二步: 把文库切块(trunks)并存放到向量数据库中
#  第三步: 对于新的问题,我们首选从vector store中提取trunks, 并融合到llm的prompt里

from langchain_community.document_loaders import WebBaseLoader  # 一个用于加载网页内容的工具,通常用于从网页中提取文档或数据。

# 创建WebBaseLoader实例,传入网页链接
loader = WebBaseLoader("https://openai.com/research/video-generation-models-as-world-simulators")")
docs = loader.load()  # 调用load方法加载网页内容

#  使用openai embedding
from langchain_openai import OpenAIEmbeddings
# 创建 OpenAIEmbeddings 实例
embeddings = OpenAIEmbeddings()

       使用 langchain 库中的 RecursiveCharacterTextSplitterFAISS 向量数据库来处理文本数据,并将其存储到向量数据库中。

from langchain_community.vectorstores import FAISS  # 导入 FAISS 向量数据库
from langchain.text_splitter import RecursiveCharacterTextSplitter  # 导入 RecursiveCharacterTextSplitter

# 用于将长文本递归地分割为较小的片段
text_splitter = RecursiveCharacterTextSplitter()

# 把 docs 切分成 trunks,在这里只有一个 doc,因为我们只抓取了一个页面
documents = text_splitter.split_documents(docs)

# 存放在向量数据库中。把 trunk 转化成向量时候用的 embedding 工具为 OpenAIEmbeddings
vector = FAISS.from_documents(documents, embeddings)

       1. 给定input,从vector database搜索相似的documents(trunks)

       2. documents加入到prompt里面(prompt template, 变量比如{context})

       3. prompt call LLM, LLM返回response(答案)

       4. 通过output parser得到格式化完之后的结果

# 这个链式调用会将一个文档列表格式化为一个提示,然后将该提示传递给一个语言模型(LLM)。
from langchain.chains.combine_documents import create_stuff_documents_chain  # 用于创建一个链式调用,该链将多个文档组合成一个提示

# 定义一个 ChatPromptTemplate,用于将文档和问题格式化为一个提示
prompt = ChatPromptTemplate.from_template("""Answer the following question based only on the provided context:

<context>
{context}
</context>

Question: {input}""")

# 创建一个链式调用,将文档链和语言模型组合在一起
document_chain = create_stuff_documents_chain(llm, prompt)

from langchain.chains import create_retrieval_chain  # 用于从向量数据库中检索相关信息,并生成最终的回答。

# 将向量数据库转换为检索器
retriever = vector.as_retriever()

# 创建检索链,结合检索器和文档链
retrieval_chain = create_retrieval_chain(retriever, document_chain)

# 调用检索链,传入用户输入的查询
response = retrieval_chain.invoke({"input": "什么是deepseek?"})

# 从响应中提取并打印最终的回答
print(response["answer"])

4、Agent

       大模型Agent(AI Agent)是一种基于大型语言模型(LLM)构建的智能体,它能够感知环境、进行决策并执行任务以实现特定目标。Agent的核心在于其自主性和主动性,它不仅能够理解用户的需求,还能像人类一样主动完成一系列关联性任务。其基本架构可以总结为:Agent = LLM(大模型) + 记忆 + 规划 + 工具使用

  • 记忆:包括短期记忆(如会话上下文)和长期记忆(如用户偏好、历史任务等),帮助Agent记住信息以便更好地完成任务。

  • 规划:将复杂任务分解为多个可执行的子任务,并评估执行策略。

  • 工具使用:通过调用外部工具(如API、数据库等)来扩展自身能力。

# 导入一个工具创建函数,用于生成一个能够检索信息的工具。
from langchain.tools.retriever import create_retriever_tool

# 创建一个检索工具
retriever_tool = create_retriever_tool(
    retriever,  # 检索器对象,负责从数据源中检索信息
    "Sora",  # 工具的名称,标识这个工具的功能
    "Search for information about Sora. For any questions about Sora, you must use this tool!"  # 工具的描述,说明其用途和使用场景
)

# 将创建的检索工具放入一个列表中
tools = [retriever_tool]

# 导入LangChain OpenAI模块中的ChatOpenAI类
from langchain_openai import ChatOpenAI

# 导入提供了从 LangChain 社区中拉取预定义的 prompt 模板的功能。
from langchain import hub

# 用于创建一个基于 OpenAI 函数的代理(Agent)以及执行代理的任务,管理工具的调用和结果的处理。
from langchain.agents import create_openai_functions_agent, AgentExecutor

# 从LangChain的hub中拉取一个预定义的prompt模板
prompt = hub.pull("hwchase17/openai-functions-agent")

# 初始化一个OpenAI语言模型
llm = ChatOpenAI(model="gpt-4", temperature=0)  # 使用GPT-4模型,设置温度为0(表示输出更确定)

# 创建一个OpenAI函数代理(Agent)
agent = create_openai_functions_agent(llm, tools, prompt)  # 将语言模型、工具和prompt传递给代理

# 初始化AgentExecutor
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)  # 将代理和工具传递给执行器,并设置为详细模式

# 调用agent_executor的invoke方法,处理用户输入
agent_executor.invoke({"input": "What is the Sora model?"})

       补充:PromptTemplate和ChatPromptTemplate的区别。

  • PromptTemplate 适用于简单的文本生成任务,如生成描述、解释等。

  • ChatPromptTemplate 适用于对话场景,如聊天机器人、问答系统等。

from langchain.prompts import PromptTemplate

prompt_template = PromptTemplate.from_template(
    "编写一段关于{主题}的小红书宣传文案,需要采用{风格}语气"
)
prompt_template.format(主题="美国留学", 风格="幽默")


#  输出:'编写一段关于美国留学的小红书宣传文案,需要采用幽默语气'


from langchain_core.prompts import ChatPromptTemplate

chat_template = ChatPromptTemplate.from_messages(
    [
        ("system", "你是AI助教,你的名字是{name}."),
        ("human", "你好"),
        ("ai", "你好,有什么可以帮到您?"),
        ("human", "{user_input}"),
    ]
)

messages = chat_template.format_messages(name="张三", user_input="你的名字是什么?")

llm.invoke(messages)


#  输出:'你好,我的名字是张三,我是你的AI助教。有什么可以帮你的?'


chain = chat_template | llm
chain.invoke({"name":"张三", "user_input":"你的名字是什么?"})

#  输出:'你好,我是AI助教,我的名字是张三。'


#  流式进行输出
for chunk in llm.stream(messages):
    print(chunk.content, end="", flush=True)

对于给定的例子提供简短的prompt:

from langchain.prompts import (
    ChatPromptTemplate,
    FewShotChatMessagePromptTemplate,
)

# 示例数据:输入和输出的示例对
examples = [
    {"input": "2+2", "output": "4"},
    {"input": "2+3", "output": "5"},
]

# 定义单个示例的模板
example_prompt = ChatPromptTemplate.from_messages(
    [
        ("human", "{input}"),  # 用户输入
        ("ai", "{output}"),    # AI 输出
    ]
)

# 创建 FewShotChatMessagePromptTemplate,用于将示例数据格式化为提示
few_shot_prompt = FewShotChatMessagePromptTemplate(
    example_prompt=example_prompt,  # 单个示例的模板
    examples=examples,              # 示例数据
)

# 打印格式化后的 FewShot 示例提示
print(few_shot_prompt.format())


# 输出:Human: 2+2
#       AI: 4
#       Human: 2+3
#       AI: 5


# 定义最终的提示模板
final_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "You are a wondrous wizard of math."),  # 系统指令
        few_shot_prompt,  # 少样本示例
        ("human", "{input}"),  # 用户输入
    ]
)

# 将最终的提示模板与语言模型连接,形成一个链式调用
chain = final_prompt | llm

# 调用链,传入输入并获取响应
chain.invoke({"input": "4+6"})

# 输出:10

5、Cache

       对于之前问题的答案,直接从cache中返回,减少成本、提高效率。

%%time
from langchain.cache import InMemoryCache # 简单的内存缓存实现,用于存储语言模型的调用结果。
from langchain.globals import set_llm_cache # 用于设置全局的缓存机制。

set_llm_cache(InMemoryCache()) # 将全局的缓存设置为 InMemoryCache 的实例。这意味着后续的语言模型调用结果将被缓存到内存中。

# 第一次,需要直接调用,需要消耗时间
llm.invoke("讲一个冷笑话")

%%time
# 第二次调用,直接从cache中获取
llm.invoke("讲一个冷笑话")

6、追踪token的使用

from langchain.callbacks import get_openai_callback # 上下文管理器,用于捕获和记录语言模型调用的详细信息
from langchain_openai import ChatOpenAI

# 初始化语言模型
llm = ChatOpenAI(model_name="gpt-4")  # 使用 GPT-4 模型

# 进入上下文管理器
with get_openai_callback() as cb:
    result = llm.invoke("最近心情怎么样?")
    print(cb)

"""输出
Tokens Used: 58
	Prompt Tokens: 16
		Prompt Tokens Cached: 0
	Completion Tokens: 42
		Reasoning Tokens: 0
Successful Requests: 1
Total Cost (USD): $0.003
"""

with get_openai_callback() as cb:
    result = llm.invoke("Tell me three jokes")
    result2 = llm.invoke("Tell me a joke")
    print(cb)

"""输出
Tokens Used: 91
	Prompt Tokens: 22
		Prompt Tokens Cached: 0
	Completion Tokens: 69
		Reasoning Tokens: 0
Successful Requests: 2
Total Cost (USD): $0.0048000000000000004
"""

三、参考资料

       Langchain官方文档

Logo

一站式 AI 云服务平台

更多推荐