LangServe服务部署
概述
LangServe 🦜️🏓 帮助开发者将 LangChain 可运行和链部署为 REST API。
该库集成了 FastAPI 并使用 pydantic 进行数据验证。
Pydantic 是一个在 Python中用于数据验证和解析的第三方库,现在是Python中使用广泛的数据验证库。
- 它利用声明式的方式定义数据模型和Python 类型提示的强大功能来执行数据验证和序列化,使您的代码更可靠、更可读、更简洁且更易于调试。
- 它还可以从模型生成 JSON 架构,提供了自动生成文档等功能,从而轻松与其他工具集成
此外,它提供了一个客户端,可用于调用部署在服务器上的可运行对象。JavaScript 客户端可在 LangChain.js 中找到。
特性
- 从 LangChain 对象自动推断输入和输出模式,并在每次 API 调用中执行,提供丰富的错误信息
- 带有 JSONSchema 和 Swagger 的 API 文档页面
- 高效的 /invoke、/batch 和 /stream 端点,支持单个服务器上的多个并发请求
- /stream_log 端点,用于流式传输链/代理的所有(或部分)中间步骤
- 新功能:自 0.0.40 版本起,支持 /stream_events,使流式传输更加简便,无需解析 /stream_log 的输出
- 使用经过严格测试的开源 Python 库构建,如 FastAPI、Pydantic、uvloop 和 asyncio
- 使用客户端 SDK 调用 LangServe 服务器,就像本地运行可运行对象一样(或直接调用 HTTP API)
限制
- 目前不支持服务器发起的事件的客户端回调
- 当使用 Pydantic V2 时,将不会生成 OpenAPI 文档。FastAPI 支持混合使用 pydantic v1 和 v2 命名空间。
安装
对于客户端和服务器:
bash
pip install langserve
或者分别安装:
bash
# 客户端代码
pip install "langserve[client]"
# 服务器代码
pip install "langserve[server]"
LangChain CLI 🛠️
使用 LangChain CLI 快速启动 LangServe 项目。
要使用 langchain CLI,请确保已安装最新版本的 langchain-cli:
bash
pip install -U langchain-cli
设置
注意:我们使用 poetry 进行依赖管理。请参阅 poetry 文档 了解更多信息。
-
使用 langchain cli 命令创建新应用
bashlangchain app new my-app
-
在 add_routes 中定义可运行对象。转到 server.py 并编辑
-
使用 poetry 添加第三方包
bashcd my-app poetry add langchain-openai
-
设置相关环境变量。例如:
bashexport OPENAI_API_KEY=your-api-key
-
启动您的应用
bashpoetry run uvicorn my_app.server:app --reload
示例应用
服务器
以下是一个部署 OpenAI 聊天模型,讲述有关特定主题笑话的链的服务器:
python
#!/usr/bin/env python
from fastapi import FastAPI
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langserve import add_routes
app = FastAPI(
title="LangChain Server",
version="1.0",
description="A simple API server using LangChain's Runnable interfaces",
)
# 创建一个链
model = ChatOpenAI(temperature=0.8)
prompt = ChatPromptTemplate.from_template("讲一个关于{topic}的笑话")
chain = prompt | model
# 添加链路由
add_routes(
app,
chain,
path="/joke",
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="localhost", port=8000)
如果您打算从浏览器调用您的端点,您还需要设置 CORS 头。您可以使用 FastAPI 的内置中间件来实现:
python
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# 配置 CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 允许所有源访问,生产环境中应该限制
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
文档
如果您已部署上述服务器,可以使用以下命令查看生成的 OpenAPI 文档:
文档地址:http://localhost:8000/docs
请确保添加 /docs
后缀。
⚠️ 首页 /
没有被设计定义,因此 curl localhost:8000
或访问该 URL 将返回 404。如果您想在 /
上有内容,请定义一个端点 @app.get("/")
。
客户端
Python SDK
python
from langserve.client import RemoteRunnable
# 连接到远程可运行项
remote_chain = RemoteRunnable("http://localhost:8000/joke/")
# 同步调用
response = remote_chain.invoke({"topic": "人工智能"})
print(response)
# 流式调用
for chunk in remote_chain.stream({"topic": "人工智能"}):
print(chunk, end="", flush=True)
# 异步调用
import asyncio
async def main():
async for chunk in remote_chain.astream({"topic": "人工智能"}):
print(chunk, end="", flush=True)
asyncio.run(main())
在 TypeScript 中(需要 LangChain.js 版本 0.0.166 或更高):
typescript
import { RemoteRunnable } from "langchain/runnables/remote";
const chain = new RemoteRunnable({
url: "http://localhost:8000/joke/",
});
const response = await chain.invoke({
topic: "人工智能",
});
console.log(response);
使用 requests 的 Python 代码:
python
import requests
response = requests.post(
"http://localhost:8000/joke/invoke",
json={"input": {"topic": "人工智能"}}
)
print(response.json())
您也可以使用 curl:
bash
curl -X 'POST' \
'http://localhost:8000/joke/invoke' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{"input": {"topic": "人工智能"}}'
端点
以下代码:
python
add_routes(
app,
chain,
path="/my_runnable",
)
将以下端点添加到服务器:
- POST
/my_runnable/invoke
- 对单个输入调用可运行项 - POST
/my_runnable/batch
- 对一批输入调用可运行项 - POST
/my_runnable/stream
- 对单个输入调用并流式传输输出 - POST
/my_runnable/stream_log
- 对单个输入调用并流式传输输出,包括生成的中间步骤的输出 - POST
/my_runnable/astream_events
- 对单个输入调用并在生成时流式传输事件,包括来自中间步骤的事件 - GET
/my_runnable/input_schema
- 可运行项的输入的 JSON 模式 - GET
/my_runnable/output_schema
- 可运行项的输出的 JSON 模式 - GET
/my_runnable/config_schema
- 可运行项的配置的 JSON 模式
这些端点与 LangChain 表达式语言接口 相匹配。
LangChain 服务监控
与构建任何类型的软件一样,使用LLM构建时,总会有调试的需求。模型调用可能会失败,模型输出可能格式错误,或者可能存在一些嵌套的模型调用,不清楚在哪一步出现了错误的输出。有三种主要的调试方法:
- 详细模式(Verbose):为你的链中的"重要"事件添加打印语句
- 调试模式(Debug):为你的链中的所有事件添加日志记录语句
- LangSmith跟踪 :将事件记录到 LangSmith,以便在那里进行可视化
详细模式(Verbose Mode) | 调试模式(Debug Mode) | LangSmith跟踪 | |
---|---|---|---|
免费 | ✅ | ✅ | ✅ |
用户界面 | ❌ | ❌ | ✅ |
持久化 | ❌ | ❌ | ✅ |
查看所有事件 | ❌ | ✅ | ✅ |
查看"重要"事件 | ✅ | ❌ | ✅ |
本地运行 | ✅ | ✅ | ❌ |
LangSmith Tracing(跟踪)
使用LangChain构建的许多应用程序将包含多个步骤,其中包含多次LLM调用。随着这些应用程序变得越来越复杂,能够检查链或代理内部发生了什么变得至关重要。
这样做的最佳方式是使用 LangSmith。在上面的链接上注册后,请确保设置你的环境变量以开始记录跟踪:
python
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "your-api-key" # 从LangSmith获取
# 对于特定项目
os.environ["LANGCHAIN_PROJECT"] = "My Project Name" # 可选
LangSmith官网:smith.langchain.com/
tavily官网:tavily.com/
假设我们有一个代理,并且希望可视化它所采取的操作和接收到的工具输出。在没有任何调试的情况下,这是我们看到的:
python
from langchain.agents import initialize_agent, AgentType
from langchain.tools import Tool
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(temperature=0)
# 定义工具
tools = [
Tool(
name="Search",
func=lambda x: "搜索结果: " + x,
description="用于在网络上搜索信息的工具"
)
]
# 初始化代理
agent = initialize_agent(
tools,
llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True
)
# 运行代理
agent.run("谁是当前中国的国家主席?")
我们没有得到太多输出,但由于我们设置了LangSmith,我们可以轻松地看到发生了什么:smith.langchain.com/public/a89f...
Verbose(详细日志打印)
如果你在Jupyter笔记本中进行原型设计或运行Python脚本,打印出链运行的中间步骤可能会有所帮助。有许多方法可以以不同程度的详细程度启用打印。
注意:即使启用了LangSmith,这些仍然有效,因此你可以同时打开并运行它们。
set_verbose(True)
设置 verbose 标志将以稍微更易读的格式打印出输入和输出,并将跳过记录某些原始输出(例如 LLM 调用的令牌使用统计信息),以便您可以专注于应用程序逻辑。
python
import langchain
langchain.set_verbose(True)
# 也可以在创建时设置verbose参数
from langchain.chains import LLMChain
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
llm = ChatOpenAI(temperature=0)
prompt = PromptTemplate.from_template("告诉我关于{topic}的一个事实")
chain = LLMChain(llm=llm, prompt=prompt, verbose=True)
# 运行链
chain.run(topic="人工智能")
输出示例:
erlang
> Entering new LLMChain chain...
Prompt after formatting:
告诉我关于人工智能的一个事实
> Finished chain.
'人工智能(AI)领域的一个有趣事实是:图灵测试是由英国数学家和计算机科学家艾伦·图灵于1950年提出的,用于测试机器是否具有与人类相当的智能。这个测试要求评判者与隐藏的人类和计算机进行文本对话,如果评判者无法可靠地区分出谁是人类谁是计算机,那么这台计算机就被认为通过了测试。直到今天,没有AI系统能够完全通过严格的图灵测试。'
Debug(调试日志打印)
set_debug(True)
设置全局的 debug 标志将导致所有具有回调支持的 LangChain 组件(链、模型、代理、工具、检索器)打印它们接收的输入和生成的输出。这是最详细的设置,将完全记录原始输入和输出。
python
import langchain
langchain.set_debug(True)
# 运行相同的链
chain.run(topic="深度学习")
输出示例(将比verbose模式更详细):
css
[chain/start] [1:chain:LLMChain] Entering Chain run with input:
{
"topic": "深度学习"
}
[chain/start] [1:chain:LLMChain > 2:llm:ChatOpenAI] Entering LLM run with input:
{
"prompts": [
"Human: 告诉我关于深度学习的一个事实"
]
}
[chain/end] [1:chain:LLMChain < 2:llm:ChatOpenAI] [3.52s] Exiting LLM run with output:
{
"generations": [
[
{
"text": "深度学习的一个有趣事实是,尽管这个领域在2010年代才真正兴起,但其核心概念------人工神经网络的基础理论------实际上可以追溯到20世纪40年代。沃伦·麦卡洛克和沃尔特·皮茨在1943年提出了第一个数学神经元模型,为现代深度学习奠定了理论基础。然而,由于当时计算能力的限制,这些早期理论直到几十年后才能在实践中充分应用。",
"generation_info": {
"finish_reason": "stop"
},
"message": {
"content": "深度学习的一个有趣事实是,尽管这个领域在2010年代才真正兴起,但其核心概念------人工神经网络的基础理论------实际上可以追溯到20世纪40年代。沃伦·麦卡洛克和沃尔特·皮茨在1943年提出了第一个数学神经元模型,为现代深度学习奠定了理论基础。然而,由于当时计算能力的限制,这些早期理论直到几十年后才能在实践中充分应用。",
"additional_kwargs": {},
"type": "ai",
"example": false
}
}
]
],
"llm_output": {
"token_usage": {
"completion_tokens": 187,
"prompt_tokens": 13,
"total_tokens": 200
},
"model_name": "gpt-3.5-turbo"
}
}
[chain/end] [1:chain:LLMChain] [3.52s] Exiting Chain run with output:
{
"text": "深度学习的一个有趣事实是,尽管这个领域在2010年代才真正兴起,但其核心概念------人工神经网络的基础理论------实际上可以追溯到20世纪40年代。沃伦·麦卡洛克和沃尔特·皮茨在1943年提出了第一个数学神经元模型,为现代深度学习奠定了理论基础。然而,由于当时计算能力的限制,这些早期理论直到几十年后才能在实践中充分应用。"
}