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 决策循环,帮助你把"原理级理解"变成"可落地工程"。

相关推荐
王国强200934 分钟前
LangChain 设计原理分析¹⁴ | 模拟实现一个精简版 LangChain
langchain
前端双越老师9 小时前
【干货】使用 langChian.js 实现掘金“智能总结” 考虑大文档和 token 限制
人工智能·langchain·node.js
Dajiaonew9 小时前
Spring AI RAG 检索增强 应用
java·人工智能·spring·ai·langchain
xuanwuziyou1 天前
LangChain 多任务应用开发
人工智能·langchain
大志说编程1 天前
LangChain框架入门16:智能客服系统RAG应用实战
后端·langchain·aigc
AI大模型1 天前
从零开始,亲手开发你的第一个AI大模型(一)基础知识
程序员·langchain·agent
掘我的金2 天前
15_LangChain自定义Callback组件
langchain
东方不败之鸭梨的测试笔记3 天前
智能测试用例生成工具设计
人工智能·ai·langchain
堆栈future3 天前
LangGraph实践-构建AI工作流:创建一本大模型应用开发书籍
langchain·llm·aigc