1 用LCEL构建一个简单的LLM应用程序
1.1 简介
在这个快速入门中,我们将向您展示如何使用LangChain构建一个简单的LLM应用程序。
这个应用程序将文本从英语翻译成另一种语言。
这是一个相对简单的LLM应用程序——它只是一个LLM调用加上一些提示。
尽管如此,这仍然是开始使用LangChain的好方法——只需一些提示和一个LLM调用就可以构建许多功能!
提示
阅读本教程后您将了解,如何使用语言模型、如何解析它们的输出、如何创建提示模板、如何使用LCEL将它们链接起来、如何在使用LangSmith创建的链中获得良好的可观察性,以及如何使用LangServe部署它们
阅读本教程后,您将对以下内容有一个更深层次的理解:
- 使用语言模型
- 使用PromptTemplates和outputparser
- 使用LangChain表达式语言(LCEL)将组件链接在一起
- 使用LangSmith调试和跟踪应用程序
- 使用LangServe部署应用程序
让我们开始吧!
1.2 设置
1.2.1 Jupyter笔记本
本指南(以及文档中的大多数其他指南)使用Jupyter笔记本,并假设读者也是。
Jupyter笔记本非常适合学习如何使用LLM系统,因为经常会出现问题(意外输出,API故障等),而在交互式环境中阅读指南是更好地理解它们的好方法。
本教程和其他教程可能最方便地在Jupyter笔记本中运行。有关如何安装的说明请参阅此处。
1.2.2 安装LangChain
要运行本教程,您需要安装LangChain。要安装LangChain,运行:
pip install langchain
conda install langchain -c conda-forge
提示
有关安装LangChain的详细信息,请参阅我们的安装指南。
1.2.3 LangSmith
使用LangChain构建的许多应用程序将包含多个步骤,并调用多个LLM调用。
随着这些应用程序变得越来越复杂,能够检查链或代理内部究竟发生了什么变得至关重要。最好的方法就是使用LangSmith。
在上面的链接注册后,确保设置环境变量以开始记录跟踪:
export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY="..."
或者,如果在Jupyter笔记本中,您可以这样设置它们:
import getpass
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()
1.3 使用语言模型
首先,让我们学习如何单独使用语言模型。
LangChain支持许多不同的语言模型,您可以互换使用它们。
有关开始使用特定模型的详细信息,请参阅受支持的集成。
提示
不同的语言模型,都需要先安装其对应的包,并传入相应的参数,具体的安装和使用方法请参考集成。
pip install -qU langchain-openai
pip install -qU langchain-anthropic
pip install -qU langchain-openai
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass()
from langchain_openai import ChatOpenAI
model = ChatOpenAI(model="gpt-4")
import getpass
import os
os.environ["ANTHROPIC_API_KEY"] = getpass.getpass()
from langchain_anthropic import ChatAnthropic
model = ChatAnthropic(model="claude-3-5-sonnet-20240620")
import getpass
import os
os.environ["AZURE_OPENAI_API_KEY"] = getpass.getpass()
from langchain_openai import AzureChatOpenAI
model = AzureChatOpenAI(
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
azure_deployment=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"],
openai_api_version=os.environ["AZURE_OPENAI_API_VERSION"],
)
让我们首先直接使用这个模型。
chatmodel是LangChain“Runnables”的实例,这意味着它们公开了与它们交互的标准接口。
为了简单地调用模型,我们可以将消息列表传递给.invoke方法。
提示
HumanMessage是用户输入,它是LangChain的标准消息类型之一。 SystemMessage是系统提示。
from langchain_core.messages import HumanMessage, SystemMessage
messages = [
SystemMessage(content="Translate the following from English into Italian"), # 提示 content值的意思是“将英语翻译成意大利语”
HumanMessage(content="hi!"),
]
model.invoke(messages)
API 参考文档:HumanMessage | SystemMessage
提示
AIMessage也是LangChain的标准消息类型之一,它包含了模型的响应。 content是模型的响应。以及一些与响应相关的元数据。
AIMessage(content='ciao!', response_metadata={'token_usage': {'completion_tokens': 3, 'prompt_tokens': 20, 'total_tokens': 23}, 'model_name': 'gpt-4', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-fc5d7c88-9615-48ab-a3c7-425232b562c5-0')
如果我们启用了LangSmith,我们可以看到这个运行被记录到LangSmith,并且可以看到LangSmith的跟踪。
1.4 OutputParsers
注意,来自模型的响应是一个AIMessage。它包含一个字符串响应以及关于响应的其他元数据。通常我们可能只想处理字符串响应。
我们可以通过使用简单的输出解析器解析出这个响应。
我们首先导入简单的输出解析器。
from langchain_core.output_parsers import StrOutputParser
parser = StrOutputParser()
API 参考文档:StrOutputParser
使用它的一种方法是单独使用它。例如,我们可以保存语言模型调用的结果,然后将其传递给解析器。
# 使用result接收语言模型的结果
result = model.invoke(messages)
# 再将result传递给解析器
parser.invoke(result)
'Ciao!'
更常见的是,我们可以将模型与输出解析器“链接”起来。这意味着该输出解析器将在此链中的每次都被调用。
该链接受语言模型的输入类型(字符串或消息列表),并返回输出解析器的输出类型(字符串)。
可以使用|操作符轻松创建链。操作符在LangChain中用于将两个元素组合在一起。
chain = model | parser
chain.invoke(messages)
'Ciao!'
1.5 Prompt Templates
现在,我们将消息列表直接传递给语言模型。这些信息列表从何而来?
通常,它是由用户输入和应用程序逻辑组合而成的。
此应用程序逻辑通常接受原始用户输入,并将其转换为准备传递给语言模型的消息列表。
常见的转换包括添加系统消息或使用用户输入格式化模板。
PromptTemplates是LangChain中的一个概念,旨在帮助进行这种转换。它们接收原始用户输入并返回准备��递给语言模型的数据(提示符)。
让我们在这里创建一个PromptTemplate。它将接受两个用户变量:
language
:将文本翻译成的语言text
:要翻译的文本
from langchain_core.prompts import ChatPromptTemplate
API 参考文档:ChatPromptTemplate
首先,让我们创建一个字符串,我们将其格式化为系统消息:
system_template = "Translate the following into {language}:"
接下来,我们可以创建PromptTemplate。这将是system_template和一个更简单的模板的组合,用于放置要翻译的文本:
prompt_template = ChatPromptTemplate.from_messages(
[("system", system_template), ("user", "{text}")]
)
这个提示模板的输入是一个字典。
我们可以单独使用这个提示模板,看看它单独做什么。
result = prompt_template.invoke({"language": "italian", "text": "hi"})
result
ChatPromptValue(messages=[SystemMessage(content='Translate the following into italian:'), HumanMessage(content='hi')])
我们可以看到它返回一个由两条消息组成的ChatPromptValue。
如果我们想直接访问消息,我们可以这样做:
result.to_messages()
[SystemMessage(content='Translate the following into italian:'),
HumanMessage(content='hi')]
提示
就是通过输入变量的方式转换为消息列表。
1.6 用LCEL将组件链接在一起(LCEL)
现在我们可以使用pipe(|)操作符将它与上面的模型和输出解析器结合起来:
chain = prompt_template | model | parser
chain.invoke({"language": "italian", "text": "hi"})
'ciao'
提示
执行过程是通过invoke函数将变量先传给prompt_template,也就是使用PromptTemplate将变量转换为消息列表,再将消息列表传给model,最后再将model的输出通过parser解析为字符串。
这是一个使用LangChain表达式语言(LCEL)将LangChain模块链接在一起的简单示例。这种方法有几个好处,包括优化的流和跟踪支持。
1.7 使用LangServe服务
现在我们已经构建了一个应用程序,我们需要为它提供服务。
这就是LangServe的用武之地。LangServe帮助开发人员将LangChain链部署为REST API。
你不需要使用LangServe来使用LangChain,但在本指南中,我们将展示如何使用LangServe部署应用程序。
虽然本指南的第一部分旨在在Jupyter Notebook或脚本中运行,但我们现在将不再使用它。
我们将创建一个Python文件,然后从命令行与它交互。
pip install "langserve[all]"
1.7.1 Server
要为我们的应用程序创建一个服务器,我们将创建一个server.py
文件。这将包含为应用程序提供服务的逻辑。它由三部分组成:
- 我们刚刚构建的链的定义
- FastAPI应用
- 为链提供服务的路由的定义,使用langserve.add_routes完成
#!/usr/bin/env python
from fastapi import FastAPI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
from langserve import add_routes
# 1. 创建一个PromptTemplate
system_template = "Translate the following into {language}:"
prompt_template = ChatPromptTemplate.from_messages([
('system', system_template),
('user', '{text}')
])
# 2. 创建一个语言模型
model = ChatOpenAI()
# 3. 创建一个输出解析器
parser = StrOutputParser()
# 4. 创建链 LCEL
chain = prompt_template | model | parser
# 5. 创建FastAPI应用
app = FastAPI(
title="LangChain Server",
version="1.0",
description="A simple API server using LangChain's Runnable interfaces",
)
# 6. 添加路由
add_routes(
app,
chain,
path="/chain",
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="localhost", port=8000)
API 参考文档:ChatPromptTemplate | StrOutputParser | ChatOpenAI
就是这样!如果我们执行这个文件:
python serve.py
我们应该看到我们的链在http://localhost:8000被启动。
1.7.2 Playground
每个LangServe服务都有一个简单的内置UI,用于配置和调用具有流输出和中间步骤可见性的应用程序。
去http://localhost:8000/chain/playground/试试吧!
传入与之前相同的输入- {"language": "italian", "text": "hi"}
-它的响应应该与之前相同。
1.7.3 Client
现在让我们设置一个客户端,以便通过编程方式与我们的服务进行交互。
我们可以使用langserve.RemoteRunnable。
轻松地做到这一点。使用它,我们可以与服务链交互,就像它在客户端运行一样。
from langserve import RemoteRunnable
remote_chain = RemoteRunnable("http://localhost:8000/chain/")
remote_chain.invoke({"language": "italian", "text": "hi"})
1.8 结论
就是这样!在本教程中,您学习了如何创建第一个简单的LLM应用程序。
您已经学习了如何使用语言模型、如何解析它们的输出、如何创建提示模板、如何使用LCEL将它们链接起来、如何在使用LangSmith创建的链中获得良好的可观察性,以及如何使用LangServe部署它们。
这只是你想要学习成为一名熟练的人工智能工程师的表面。幸运的是,我们还有很多其他资源!
为了进一步了解LangChain的核心概念,我们有详细的概念指南。
如果您对这些概念有更具体的问题,请参阅指南的以下部分: