大模型工程师学习日记(五):基于LangServe的AI服务架构深度解析
1.概述
LangServe 🦜️🏓 帮助开发者将 LangChain
可运行和链部署为 REST API。
该库集成了 FastAPI 并使用 pydantic 进行数据验证。
Pydantic 是一个在 Python中用于数据验证和解析的第三方库,现在是Python中使用广泛的数据验证库。
- 它利用声明式的方式定义数据模型和Python 类型提示的强大功能来执行数据验证和序列化,使您的代码更可靠、更可读、更简洁且更易于调试。。
- 它还可以从模型生成 JSON 架构,提供了自动生成文档等功能,从而轻松与其他工具集成
此外,它提供了一个客户端,可用于调用部署在服务器上的可运行对象。JavaScript 客户端可在 LangChain.js 中找到。
2.特性
- 从 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)
3.限制
- 目前不支持服务器发起的事件的客户端回调
- 当使用 Pydantic V2 时,将不会生成 OpenAPI 文档。FastAPI 支持混合使用 pydantic v1 和 v2 命名空间。更多细节请参见下面的章节。
4.安装
对于客户端和服务器:
pip install --upgrade "langserve[all]"
或者对于客户端代码,pip install "langserve[client]"
,对于服务器代码,pip install "langserve[server]"
。
5.LangChain CLI 🛠️
使用 LangChain
CLI 快速启动 LangServe
项目。
要使用 langchain CLI,请确保已安装最新版本的 langchain-cli
。您可以使用 pip install -U langchain-cli
进行安装。
5.1设置
注意:我们使用 poetry
进行依赖管理。请参阅 poetry 文档 了解更多信息。
5.1.2 使用 langchain cli 命令创建新应用
langchain app new my-app
5.1.3. 在 add_routes 中定义可运行对象。转到 server.py 并编辑
add_routes(app. NotImplemented)
5.1.4. 使用 poetry
添加第三方包(例如 langchain-openai、langchain-anthropic、langchain-mistral 等)
#安装pipx,参考:https://pipx.pypa.io/stable/installation/
pip install pipx
#加入到环境变量,需要重启PyCharm
pipx ensurepath
# 安装poetry,参考:https://python-poetry.org/docs/
pipx install poetry
#安装 langchain-openai 库,例如:poetry add [package-name]
poetry add langchain
poetry add langchain-openai
5.1.5. 设置相关环境变量。例如,
export OPENAI_API_KEY="sk-..."
5.1.6. 启动您的应用
poetry run langchain serve --port=8000
6.示例应用
6.1服务器
以下是一个部署 OpenAI 聊天模型,讲述有关特定主题笑话的链的服务器。
#!/usr/bin/env python
from fastapi import FastAPI
from langchain_openai import ChatOpenAI
from langserve import add_routes
app = FastAPI(
title="LangChain 服务器",
version="1.0",
description="使用 Langchain 的 Runnable 接口的简单 API 服务器",
)
add_routes(
app,
ChatOpenAI(model="gpt-4"),
path="/openai",
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="localhost", port=8000)
如果您打算从浏览器调用您的端点,您还需要设置 CORS 头。
您可以使用 FastAPI 的内置中间件来实现:
from fastapi.middleware.cors import CORSMiddleware
# 设置所有启用 CORS 的来源
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
expose_headers=["*"],
)
7.文档
如果您已部署上述服务器,可以使用以下命令查看生成的 OpenAPI 文档:
文档地址:http://localhost:8000/docs
curl localhost:8000/docs
请确保添加 /docs
后缀。
⚠️ 首页 /
没有被设计定义,因此 curl localhost:8000
或访问该 URL
将返回 404。如果您想在 /
上有内容,请定义一个端点 @app.get("/")
。
8.客户端
Python SDK
from langchain.schema.runnable import RunnableMap
from langchain_core.prompts import ChatPromptTemplate
from langserve import RemoteRunnable
openai = RemoteRunnable("http://localhost:8000/openai/")
prompt = ChatPromptTemplate.from_messages(
[("system", "你是一个喜欢写故事的助手"), ("system", "写一个故事,主题是: {topic}")]
)
# 可以定义自定义链
chain = prompt | RunnableMap({
"openai": openai
})
response = chain.batch([{"topic": "猫"}])
print(response)
#[{'openai': AIMessage(content='从前,有一个叫做肖恩的男孩,他在一个宁静的乡村里生活。一天,他在家的后院发现了一个小小的,萌萌的猫咪。这只猫咪有一双大大的蓝色眼睛,毛色如同朝霞般的粉色,看起来非常可爱。\n\n肖恩把这只猫咪带回了家,他给她取名为“樱花”,因为她的毛色让他联想到春天盛开的樱花。肖恩非常喜欢樱花,他用心照顾她,每天都会为她准备新鲜的食物和清水,还会陪她玩耍,带她去散步。\n\n樱花也非常喜欢肖恩,她会在肖恩读书的时候躺在他的脚边,会在他伤心的时候安慰他,每当肖恩回家的时候,她总是第一个跑出来迎接他。可是,樱花有一个秘密,她其实是一只会说人话的猫。\n\n这个秘密是在一个月圆的夜晚被肖恩发现的。那天晚上,肖恩做了一个噩梦,他从梦中惊醒,发现樱花正坐在他的床边,用人的语言安慰他。肖恩一开始以为自己在做梦,但是当他清醒过来,樱花还在继续讲话,他才知道这是真的。\n\n樱花向肖恩解释,她是一只来自神秘的猫咪国度的使者,她的任务是保护和帮助那些善良和爱护动物的人。肖恩因为对她的善良和照顾,使她决定向他展现真实的自我。\n\n肖恩虽然感到惊讶,但他并没有因此而害怕或者排斥樱花。他觉得这只使得他更加喜欢樱花,觉得这是他们之间的特殊纽带。\n\n从那天开始,肖恩和樱花的关系变得更加亲密,他们像最好的朋友一样,分享彼此的秘密,一起度过快乐的时光。樱花也用她的智慧和力量,帮助肖恩解决了许多困扰他的问题。\n\n许多年过去了,肖恩长大了,他离开了乡村,去了城市上大学。但是,无论他走到哪里,都会带着樱花。他们的友情和互相的陪伴,让他们无论在哪里,都能感到家的温暖。\n\n最后,肖恩成为了一名作家,他写下了自己和樱花的故事,这个故事被人们广为传播,让更多的人知道了这个关于善良、友情和勇气的故事。而樱花,也永远陪伴在肖恩的身边,成为他生活中不可或缺的一部分。\n\n这就是肖恩和樱花的故事,一个关于男孩和他的猫的故事,充满了奇迹、温暖和爱。', response_metadata={'token_usage': {'completion_tokens': 1050, 'prompt_tokens': 33, 'total_tokens': 1083}, 'model_name': 'gpt-4-0613', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-c44f1624-ea75-424b-ba3d-e741baf44bda-0', usage_metadata={'input_tokens': 33, 'output_tokens': 1050, 'total_tokens': 1083})}]
在 TypeScript 中(需要 LangChain.js 版本 0.0.166 或更高):
import { RemoteRunnable } from "@langchain/core/runnables/remote";
const chain = new RemoteRunnable({
url: `http://localhost:8000/openai/`,
});
const result = await chain.invoke({
topic: "cats",
});
使用 requests
的 Python 代码:
import requests
response = requests.post(
"http://localhost:8000/openai",
json={'input': {'topic': 'cats'}}
)
response.json()
您也可以使用 curl
:
curl --location --request POST 'http://localhost:8000/openai/stream' \
--header 'Content-Type: application/json' \
--data-raw '{
"input": {
"topic": "狗"
}
}'
9.端点
以下代码:
...
add_routes(
app,
runnable,
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 表达式语言接口相匹配 --