LangChain 设计原理分析¹³ | LangChain Serve 快速部署

主题:LangServe、FastAPI、流式返回

目标:学会把任意 Runnable(链 / Agent / 检索链)一键发布为可调用的 HTTP API,并掌握同步、流式、批量等调用方式。


一、为什么用 LangServe?

  • 零胶水 :任何 RunnablePromptTemplate | LLM | Parser | ...)都能一行路由发布。
  • 统一协议invoke / stream / batch 等语义在客户端完全一致。
  • 兼容生态:FastAPI / Uvicorn / Docker / Kubernetes 生产级部署。
  • 端到端链路 :本地调试 → 远程部署 → RemoteRunnable 远程调用,代码无缝迁移。

二、环境准备

bash 复制代码
# 基础依赖(按需)
pip install -U "langchain>=0.2" "langchain-openai>=0.1" "langserve>=0.2" fastapi uvicorn

# 如果要做检索或解析,可按需安装
# pip install -U faiss-cpu chromadb unstructured

若使用 OpenAI 等云端模型,请在运行前设置环境变量:

  • Windows PowerShell: setx OPENAI_API_KEY "your-key"
  • Linux/macOS: export OPENAI_API_KEY=your-key

三、把链发布为 REST API

1)定义一条最简单的链(Runnable)

python 复制代码
# file: chain_def.py

import os

from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser


def build_chain():
    prompt = ChatPromptTemplate.from_messages([
        ("system", "你是简洁、有逻辑的中文助理。"),
        ("human", "请简要回答:{question}")
    ])
    llm = ChatOpenAI(
        temperature=0,
        model="glm-4.5",
        openai_api_key=os.getenv("ZAI_API_KEY"),
        openai_api_base="https://open.bigmodel.cn/api/paas/v4/"
    )
    return prompt | llm | StrOutputParser()

2)用 LangServe + FastAPI 暴露这条链

python 复制代码
# file: server.py

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from langserve import add_routes
from chain_def import build_chain

app = FastAPI(title="LangServe Demo", version="1.0")

# 可按需开放跨域(本地前端调试很有用)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # 生产环境请按需收紧
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 将 Runnable 发布到 /qa 路径
qa_chain = build_chain()
add_routes(app, qa_chain, path="/qa")

# 也可以挂多个链:
# add_routes(app, another_chain, path="/summarize")

# 启动:uvicorn server:app --reload --port 8000

启动服务:

bash 复制代码
uvicorn server:app --reload --port 8000

3)快速测试

  • 同步调用(invoke)
bash 复制代码
curl -X POST http://localhost:8000/qa/invoke \
     -H "Content-Type: application/json;charset=utf-8" \
     -d '{"input": {"question": "什么是LangServe?"}}'
  • 流式返回(Server-Sent Events)
bash 复制代码
curl -N -X POST http://localhost:8000/qa/stream \
     -H "Content-Type: application/json" \
     -d '{"input": {"question": "用一句话科普黑洞"}}'
  • 批量调用(batch)
bash 复制代码
curl -X POST http://localhost:8000/qa/batch \
     -H "Content-Type: application/json" \
     -d '{"inputs": [{"question":"A是什么?"}, {"question":"B是什么?"}]}'

返回结果会是结构化 JSON(invoke/batch)或一系列 SSE 数据块(stream)。

四、远程客户端:像本地一样使用远程链

RemoteRunnable 让你像使用本地链一样调用远端服务,无需手写 HTTP。

python 复制代码
# file: client.py

from langserve import RemoteRunnable

remote = RemoteRunnable("http://localhost:8000/qa")

# 1) 同步调用
out = remote.invoke({"question": "给我一句激励语"})
print("INVOKE:", out)

# 2) 流式返回
print("STREAM:", end=" ")
for chunk in remote.stream({"question": "简述量子纠缠"}):
    print(chunk, end="")
print()

# 3) 批量调用
res = remote.batch([
    {"question": "牛顿第一定律是什么?"},
    {"question": "相对论的核心观点?"},
])
print("BATCH:", res)

五、给链定义输入/输出 Schema(更稳、更可维护)

如果你的链需要严格的字段校验(例如对外开放 API),可以加 Pydantic Schema。

python 复制代码
# file: chain_def_schema.py

import os

from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableLambda


class QAInput(BaseModel):
    question: str = Field(..., description="用户问题")


class QAOutput(BaseModel):
    answer: str


def build_typed_chain():
    prompt = ChatPromptTemplate.from_template("用三句话回答:{question}")
    llm = ChatOpenAI(
        temperature=0,
        model="glm-4.5",
        openai_api_key=os.getenv("ZAI_API_KEY"),
        openai_api_base="https://open.bigmodel.cn/api/paas/v4/"
    )

    # 将 llm 输出封装到结构化输出
    def wrap(d: dict) -> QAOutput:
        return QAOutput(answer=d["answer"])

    # 把字符串输出映射成 {"answer": text}
    chain = prompt | llm | (lambda msg: {"answer": msg.content})
    return RunnableLambda(lambda x: QAInput(**x)) | chain | RunnableLambda(wrap)

server.py 中挂载:

python 复制代码
# ...
from chain_def_schema import build_typed_chain

typed_chain = build_typed_chain()
add_routes(app, typed_chain, path="/typed_qa")

此时 /typed_qa 的输入输出将遵循你定义的 Pydantic 模型,OpenAPI 文档也会更清晰。

六、把 Agent / 检索链 也一把梭:任何 Runnable 都能 Serve

Agent / RAG 只要最终是 Runnable,一律可 add_routes

python 复制代码
# file: my_rag_module.py

import os

from langchain.chains.retrieval import create_retrieval_chain
from langchain_community.embeddings import XinferenceEmbeddings
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableLambda
from langchain_openai import ChatOpenAI
from langchain_community.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_core.documents import Document
from langchain.prompts import ChatPromptTemplate


def build_rag_chain():
    docs = [Document(
        page_content="孔子是儒家学派的创始人,《论语》是记述他思想言论的著作。"
                     "曾子是孔子的弟子,儒家四书之一《大学》是他所作。"
                     "子思是孔子的孙子,曾子是他的老师,《中庸》是其所作。"
                     "孟子是子思门人的学生,深受《中庸》影响,《孟子》是其思想的凝聚。"
                     "王阳明在孔孟学说的基础之上吸收了道家和禅宗的思想精华,开辟了儒学新境界,是近五百年内儒家第一人。"
    )]
    splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=20)
    chunks = splitter.split_documents(docs)

    embedding = XinferenceEmbeddings(
        server_url="http://127.0.0.1:9997",
        model_uid="bge-large-zh-v1.5"
    )

    vs = FAISS.from_documents(chunks, embedding)
    retriever = vs.as_retriever(search_kwargs={"k": 1})

    prompt = ChatPromptTemplate.from_messages([
        ("system", "你是检索增强问答助手。基于上下文回答:\n{context}"),
        ("human", "{question}")
    ])
    llm = ChatOpenAI(
        temperature=0,
        model="glm-4.5",
        openai_api_key=os.getenv("ZAI_API_KEY"),
        openai_api_base="https://open.bigmodel.cn/api/paas/v4/"
    )
    rag_chain = (
        RunnableLambda(lambda x: {
            "question": x["question"],
            "context": retriever.invoke(x["question"])
        })
        | prompt
        | llm
        | StrOutputParser()
    )

    return rag_chain

server.py 中:

python 复制代码
# ...
from my_rag_module import build_rag_chain

rag_chain = build_rag_chain()
add_routes(app, rag_chain, path="/rag")

现在你已经把 RAG 对外暴露成 API(支持 invoke/stream/batch 三种调用)。

七、流式返回的实现要点与坑位

  • 客户端 :SSE(Server-Sent Events)逐 token/片段接收。RemoteRunnable.stream() 已封装好。
  • 服务端add_routes 自动提供 /stream 端点,不用你手写生成器。
  • 观察到空字符串:部分模型或中间解析会抛空段,属于正常分包;只要最终能正确拼接即可。
  • 生产中建议 :对流式输出做超时控制输出清洗(去除重复空白、异常分隔)。

八、生产部署清单

1)Gunicorn + Uvicorn Workers(多进程/多协程)

bash 复制代码
pip install "uvicorn[standard]" gunicorn

# Linux/macOS 示例
gunicorn -k uvicorn.workers.UvicornWorker \
         -w 2 \
         -b 0.0.0.0:8000 \
         server:app
  • -w 工作者数量:按 CPU/内存调优
  • I/O 密集型链路可考虑 --threads 或更多协程

2)Dockerfile(简洁版)

dockerfile 复制代码
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -U pip && pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8000"]

requirements.txt 示例:

shell 复制代码
langchain>=0.2
langchain-openai>=0.1
langserve>=0.2
fastapi
uvicorn

3)安全与限流

  • 密钥管理:用环境变量 + KMS/Secrets Manager,避免写死在代码里。
  • CORS 与鉴权 :生产环境务必收紧 allow_origins,并在网关或路由层加签名校验或 JWT。
  • 速率限制:建议配合 API 网关或反向代理(如 Nginx/Envoy/Cloudflare)。

九、进阶技巧

  • 多路由多链 :一个服务挂多个 Runnable,分不同路径管理(如 /qa/rag/agent)。
  • 版本化 :为重要链做 /v1/qa/v2/qa 路径,灰度升级。
  • 请求透传 :LangServe 会把 config 透传到底层,可用于打标签、LangSmith 追踪、超参数设置。
  • 客户端复用RemoteRunnable 与本地 Runnable API 一致,迁移成本几乎为零。

🔚 小结

  • add_routes(app, runnable, path="/...") 是发布 API 的核心一招。
  • RemoteRunnable 让你"像本地链一样"使用远端链。
  • LangServe 原生提供 invoke / stream / batch 三态调用,配合 FastAPI / Uvicorn,既能本地开发又能生产部署。
  • 通过 Pydantic 模型约束输入输出、CORS/鉴权/限流保障安全性,轻松做到工程级上线。

接下来我们将从零搭建一个迷你框架:定义 Runnable 协议、实现链式组合与配置流转,再做一个最小可用的 Agent 决策循环,帮助你把"原理级理解"变成"可落地工程"。

相关推荐
Dontla26 分钟前
黑马大模型RAG与Agent智能体实战教程LangChain提示词——6、提示词工程(提示词优化、few-shot、金融文本信息抽取案例、金融文本匹配案例)
redis·金融·langchain
JaydenAI1 小时前
[LangChain之链]LangChain的Chain——由Runnable构建的管道
python·langchain
草帽lufei1 小时前
LangChain 框架核心向量存储
langchain
猫头虎1 小时前
如何使用Docker部署OpenClaw汉化中文版?
运维·人工智能·docker·容器·langchain·开源·aigc
qq_5470261792 小时前
LangChain 1.0 核心概念
运维·服务器·langchain
uXrvbWJGleS2 小时前
三相两电平整流器Simulink仿真探究
langchain
猫头虎2 小时前
手动部署开源OpenClaw汉化中文版过程中常见问题排查手册
人工智能·langchain·开源·github·aigc·agi·openclaw
程序员ken3 小时前
深入理解大语言模型(8) 使用 LangChain 开发应用程序之上下文记忆
人工智能·python·语言模型·langchain
一切尽在,你来14 小时前
第二章 预告内容
人工智能·langchain·ai编程
一切尽在,你来18 小时前
1.1 AI大模型应用开发和Langchain的关系
人工智能·langchain