14 · FastAPI 服务化:把 RAG 机器人变成 HTTP API
本片目标:让前端网页/其他系统能调用你的 RAG 机器人。用 FastAPI 暴露 REST API:问答接口 + 流式接口 + 会话接口。 新增规定性:13(服务契约:HTTP 路由、请求/响应模型、同步 vs 异步路由) 数据字典:FastAPI 路由声明、Pydantic 请求/响应模型、uvicorn 启动。 进程线程模型:本片核心——同步def路由丢进线程池 vs 异步async def路由在事件循环。 网络模型:HTTP/1.1 REST;流式接口走 SSE(EventSource 协议)。
1. 上集回顾
第 13 篇把 langchain_core 整个地基翻了一遍——你知道了哪些模块是你的日常武器。但地基再清楚,机器人还跑在你的本地进程里,外部世界够不着。 还差最后一步:怎么让外部世界调用你的机器人?- 前端网页怎么问?——浏览器不能
import你的 Python 函数; - 其他微服务怎么问?——它们发 HTTP 请求。
POST /chat 发问题,你返回答案。这是生产系统的标准接口形态。
2. 数据字典:FastAPI 三件套
2.1 路由(route)
2.2 请求/响应模型(Pydantic)
/docs 白送)。
2.3 启动(uvicorn)
3. 关键方法/装饰器
4. 进程线程模型(本片最重要)
FastAPI 有两种路由写法,性能差异巨大:4.1 同步路由:def chat(...)(错误示范)
4.2 异步路由:async def chat(...)(生产正解)
ainvoke 走 httpx.AsyncClient,等待响应时释放线程(第 12 篇网络模型)。异步路由可以支撑几百上千并发,同步路由几十就满了。
4.3 桥接:同步链 + 异步路由
如果链是同步的(比如第 09 篇的rag_chain.invoke),异步路由里要桥接:
run_in_executor(第 12 篇的桥)把同步调用丢进线程池,事件循环等 Future——LangChain 内部自己也用这个机制。
5. 网络模型
5.1 普通问答接口
5.2 流式接口(SSE,打字机)
astream → 你的服务再转成 SSE 给前端。两层流式叠加,中间是你的服务做桥。
6. 验证:跑起来
配套代码code/14_api.py:一个完整的问答服务(3 个接口):
POST /chat:普通问答(异步路由 + 记忆会话)POST /chat/stream:流式问答(SSE)GET /health:健康检查
http://localhost:8000/docs 能看到自动生成的 API 文档。
7. 边界
- 同步
def路由别用于模型调用——除非并发极低。生产一律async def+ainvoke。 - SSE 是单向推送——适合流式文本;双向交互要 WebSocket(超出本系列范围)。
--reload只用于开发——生产用uvicorn --workers N多进程(但内存里记忆/Chroma 每进程一份,注意第 15 篇的持久化)。- CORS:前端跨域要配
CORSMiddleware(第 15 篇)。
推荐资料(延伸阅读)
- FastAPI 官方文档 —— 路由 / 依赖 / 生命周期权威参考
- FastAPI 官方文档 · 流式响应 —— StreamingResponse 与 SSE
- LangChain 官方文档 · 流式 —— 服务端 astream 的官方姿势
8. 未完待续
API 有了,但离”生产级”还差最后一公里:- 配置散在代码里(模型名、k 值、路径)——要配置化;
- 向量库索引怎么自动更新(文档改了要重新入库)——要索引管线;
- 出错怎么办、怎么溯源(答案来自哪块)——要错误处理 + 引用溯源;
- 会话记忆持久化(重启不丢)——要存储层。