LangChain:LangServe 从自动路由到自定义端点的全面指南

LangServe 的核心:add_routes 函数

LangServe 的使用非常简单,其核心功能由 add_routes 函数提供。这个函数负责将一个 LangChain 的可运行对象(Runnable)“挂载”到一个 FastAPI 应用实例上,并自动为其创建一套标准化的 REST API 端点。

下面是一个最基础的示例:

import uvicorn
from fastapi import FastAPI
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langserve import add_routes

# 1. 创建 FastAPI 应用实例
app = FastAPI(
    title="LangServe 示例",
    version="1.0",
    description="一个简单的 LangServe API 服务器",
)

# 2. 创建一个 LangChain 可运行对象 (Runnable)
model = ChatOpenAI()
prompt = ChatPromptTemplate.from_template("给我讲一个关于 {topic} 的笑话")
chain = prompt | model

# 3. 使用 add_routes 将 chain 部署在 /joke 路径
add_routes(
    app,
    chain,
    path="/joke",
)

if __name__ == "__main__":
    uvicorn.run(app, host="localhost", port=8000)

仅仅通过调用 add_routes,我们就为这个“笑话生成器”链创建了一整套功能完备的 API 接口,无需手动编写任何路由处理逻辑。

add_routes 自动生成的端点

当您调用 add_routes(app, chain, path="/joke") 后,LangServe 会在指定的路径下自动生成一系列 API 端点。这些端点遵循 LangChain 表达式语言(LCEL)的接口标准,提供了丰富的功能,包括调用、批量处理、流式传输和模式检查 。

下表详细列出了所有自动生成的端点及其功能:

HTTP 方法

路径

功能描述

POST

/joke/invoke

在单个输入上调用链(Chain)。

POST

/joke/batch

在一批输入上批量调用链,提高效率。

POST

/joke/stream

在单个输入上调用链,并以流式方式返回最终的输出。

POST

/joke/stream_log

在单个输入上调用链,并流式返回所有中间步骤的输出和最终结果。

POST

/joke/astream_events

(v0.0.40+ 新增) 在单个输入上调用链,并以事件流的形式返回,更容易处理中间步骤。

GET

/joke/input_schema

获取链的输入数据模型的 JSON Schema,用于客户端验证。

GET

/joke/output_schema

获取链的输出数据模型的 JSON Schema。

GET

/joke/config_schema

获取链的配置参数的 JSON Schema。

GET

/joke/playground/

提供一个交互式的 Web UI 界面,用于测试和调试您的链。

通过 add_routes ,LangServe 极大地简化了 API 的创建过程,让开发者可以专注于业务逻辑的实现,而不是繁琐的路由配置。

终极灵活性:集成自定义 FastAPI 路由

LangServe 的强大之处不仅在于其自动化能力,更在于它与 FastAPI 的无缝集成。这意味着您可以在使用 add_routes 的同时,利用 FastAPI 提供的所有原生功能来定义任意数量的自定义路由。这为您提供了无与伦比的灵活性,可以构建完全符合您需求的复杂 API。

正如您在问题中提到的,您可以非常轻松地添加一个标准的 FastAPI 路径操作(Path Operation),例如 @app.get("/test")。

添加自定义端点

让我们在之前的示例代码基础上,增加一个自定义的 GET 端点和一个 POST 端点:

import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langserve import add_routes

# 创建 FastAPI 应用实例
app = FastAPI(
    title="LangServe 示例与自定义路由",
    version="1.0",
    description="一个结合了 LangServe 和自定义 FastAPI 端点的 API 服务器",
)

# --- LangServe 部分 ---
model = ChatOpenAI()
prompt = ChatPromptTemplate.from_template("给我讲一个关于 {topic} 的笑话")
add_routes(app, prompt | model, path="/joke")

# --- 自定义 FastAPI 路由部分 ---

# 1. 添加一个简单的 GET 端点
@app.get("/test")
async def test_get():
    """这是一个自定义的 GET 测试端点"""
    return {
        "message": "这是一个来自自定义 FastAPI 端点的 GET 响应",
        "method": "GET"
    }

# 2. 添加一个接收数据的 POST 端点
class CustomData(BaseModel):
    name: str
    value: int

@app.post("/custom-data")
async def create_custom_data(data: CustomData):
    """这是一个接收自定义数据的 POST 端点"""
    return {
        "message": "成功接收到数据",
        "received_data": data
    }

if __name__ == "__main__":
    uvicorn.run(app, host="localhost", port=8000)

FastAPI 支持的所有 HTTP 方法装饰器

通过这种方式 ,您可以利用 FastAPI 支持的所有 HTTP 方法装饰器来定义您的 API 行为。这为您处理各种客户端请求(如网页表单、其他后端服务、物联网设备等)提供了完整的工具集。

下表总结了 FastAPI 中所有可用的路径操作装饰器 3:

装饰器

HTTP 方法

典型用途

@app.get()

GET

读取或检索数据。

@app.post()

POST

创建新数据。

@app.put()

PUT

完全更新现有数据。

@app.delete()

DELETE

删除数据。

1. GET 请求

GET 方法通常用于检索数据。

无参数

您甚至可以使用 @app.api_route() 装饰器,为一个路径同时指定多种 HTTP 方法,进一步简化代码 。

@app.get("/items")
async def get_all_items():
    """获取所有项目"""
    return {"items": [{"id": 1, "name": "A"}, {"id": 2, "name": "B"}]}
路径参数 (Path Parameters)

路径参数用于从 URL 路径中捕获值,通常用于标识特定资源。

@app.get("/items/{item_id}")
async def get_item_by_id(item_id: int):
    """根据 ID 获取单个项目"""
    return {"item_id": item_id, "name": f"Item {item_id}"}
查询参数 (Query Parameters)

查询参数是 URL 中 ? 之后的部分,用于过滤或分页。

from typing import Optional

@app.get("/items/search")
async def search_items(keyword: str, limit: int = 10, skip: Optional[int] = 0):
    """根据关键字搜索项目,支持分页"""
    return {"keyword": keyword, "limit": limit, "skip": skip}
2. POST 请求

POST 方法通常用于创建新资源。

无参数

无参数的 POS

@app.post("/actions/reset")
async def reset_system():
    """触发系统重置动作"""
    return {"message": "System has been reset"}
请求体 (Request Body)

这是 POST 最常见的用法,客户端通过请求体发送数据(通常是 JSON)。

from pydantic import BaseModel

class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float

@app.post("/items")
async def create_item(item: Item):
    """创建一个新项目"""
    return {"message": "Item created successfully", "item_data": item}
3. PUT 请求

PUT 方法通常用于完整地更新一个现有资源。

路径参数 + 请求体

PUT 请求几乎总是同时需要路径参数(指定要更新哪个资源)和请求体(提供新的完整数据)。

@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    """完整更新一个项目"""
    return {"item_id": item_id, "message": "Item updated successfully", "new_data": item}
4. DELETE 请求

DELETE 方法用于删除资源。

无参数

例如,用于删除所有资源。

@app.delete("/items")
async def delete_all_items():
    """删除所有项目"""
    return {"message": "All items have been deleted"}
路径参数

这是 DELETE 最常见的用法,通过路径参数指定要删除的资源。

from fastapi import status, Response

@app.delete("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_item(item_id: int):
    """根据 ID 删除单个项目"""
    # 在实际应用中,这里会执行数据库删除操作
    # 成功删除后,返回 204 状态码,无需响应体
    return Response(status_code=status.HTTP_204_NO_CONTENT)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值