04_LangChain服务部署与链路监控

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)

限制

安装

对于客户端和服务器:

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 文档 了解更多信息。

  1. 使用 langchain cli 命令创建新应用

    bash 复制代码
    langchain app new my-app
  2. 在 add_routes 中定义可运行对象。转到 server.py 并编辑

  3. 使用 poetry 添加第三方包

    bash 复制代码
    cd my-app
    poetry add langchain-openai
  4. 设置相关环境变量。例如:

    bash 复制代码
    export OPENAI_API_KEY=your-api-key
  5. 启动您的应用

    bash 复制代码
    poetry 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年提出了第一个数学神经元模型,为现代深度学习奠定了理论基础。然而,由于当时计算能力的限制,这些早期理论直到几十年后才能在实践中充分应用。"
}
相关推荐
王国强20094 小时前
LangChain 设计原理分析⁷ | Agent 架构设计详解:决策循环与 ReAct
langchain
王国强20099 小时前
LangChain 设计原理分析⁶ | Memory 系统设计:如何构建上下文感知的链
langchain
都叫我大帅哥11 小时前
🌟 LangChain回调机制全解析:从入门到实战,打造你的AI智能小助手
python·langchain·ai编程
Chasing__Dreams13 小时前
langchain--1--prompt、output格式、LCEL示例
langchain
王国强20091 天前
LangChain 设计原理分析⁵ | PromptTemplate 模板系统与上下文注入机制
langchain
都叫我大帅哥1 天前
当AI遇上话痨:LangGraph的`trim_messages`裁剪艺术完全指南
python·langchain·ai编程
青衫客362 天前
LLM——使用 LangGraph 构建 ReAct 智能体:多轮对话 + 工具调用 + 可视化流程图
langchain·大模型·llm·agent·langgraph