本文来自《AI 应用开发课程》月份 1 课程文档,已整理为网站文章版本。
学习目标
学完本节后,你应当能够:
- 理解为什么月份 1 必须学 FastAPI。
- 启动一个最小 FastAPI 服务。
- 理解路由、请求处理和自动文档的基本关系。
前置知识
- 已完成 Python 工程化模块
- 已完成普通 LLM API 调用
1. 为什么月份 1 就学 FastAPI
因为 AI 应用最终很少只是脚本。你迟早会面对这些需求:
- 对外提供接口
- 与前端或其他服务对接
- 做健康检查
- 做流式响应
- 上传文件或接收结构化请求
FastAPI 是这条路线中的默认后端框架,原因不是“它最流行”,而是它在月份 1 阶段刚好覆盖:
- 类型友好
- Pydantic 集成强
- 文档自动生成
- 异步支持自然
2. 安装依赖
在项目中执行:
uv add fastapi uvicorn
3. 最小服务
创建 app/main.py:
from fastapi import FastAPI
app = FastAPI(title="Month1 AI Service")
@app.get("/health")
async def health() -> dict[str, str]:
return {"status": "ok"}
启动:
uv run uvicorn app.main:app --reload
访问:
http://127.0.0.1:8000/healthhttp://127.0.0.1:8000/docs
4. 代码讲解
app = FastAPI(...)
创建应用实例。
@app.get("/health")
声明一个 GET 路由。
async def health()
使用异步函数定义接口,便于后续接入异步模型调用。
5. FastAPI 请求处理图
flowchart LR
A["客户端请求"] --> B["FastAPI 路由匹配"]
B --> C["请求参数解析"]
C --> D["调用 service 层"]
D --> E["返回响应模型"]
月份 1 最关键的是理解:
- 路由层不是业务层
- FastAPI 只是协议入口,不应该承载所有逻辑
6. 推荐目录结构
app/
├── api/
│ └── routes.py
├── services/
│ └── chat_service.py
├── models.py
└── main.py
为什么要拆 api/ 和 services/
因为后面 CLI 和 API 都要复用 services/ 中的核心逻辑。
7. 实操任务
- 起一个最小 FastAPI 服务
- 添加
/health - 打开
/docs - 将服务目录拆成
api和services
8. 自测题
- 为什么月份 1 不推荐把所有逻辑都写在
main.py? - 为什么 FastAPI 特别适合和 Pydantic 配合?
/docs为什么对学习阶段很有价值?
9. 作业与验收
验收标准:
- 服务可以启动
/health可访问/docs可访问- 目录中已有服务层位置
10. 常见错误
- 路由文件和业务逻辑混在一起
- 启动命令模块路径写错
- 只关注接口能返回,不关注结构是否清晰
11. 本章与前文关系
前面的 LLM API 和 Tool Calling 模块,仍然主要停留在“脚本能力”层面。现在要解决的,是月份 1 的一个关键跨越:
如何把模型能力变成服务能力?
FastAPI 的作用不是让你多学一个 Web 框架,而是让你开始从“我自己能跑通”升级到“其他系统也能调用”。
12. 本章在研发助手项目中的位置
研发助手项目到第 4 周时必须同时支持:
- CLI 使用
- API 使用
CLI 更适合本地研发工作流,API 更适合:
- 调试
- 对外展示
- 后续前端接入
- 服务化思维训练
所以 FastAPI 在月份 1 的地位不是可选项,而是服务化底盘。
13. 为什么月份 1 选 FastAPI,而不是泛讲所有后端框架
这里的取舍非常明确:
- 月份 1 不做“后端框架横向对比课”
- 月份 1 只学习对 AI 应用最直接有用的一套服务化能力
FastAPI 适合当前阶段,主要因为它天然贴合:
- Pydantic 模型
- 异步调用
- 自动文档
- 轻量服务化
14. 错误示例 vs 正确示例
错误示例:把路由、模型调用和业务逻辑全塞进 main.py
这样做短期能跑,长期会让项目快速失控:
- 路由层和业务层混在一起
- 逻辑无法复用给 CLI
- 测试边界不清晰
正确示例:入口层极薄,服务层承载核心逻辑
月份 1 后续所有 FastAPI 代码都应围绕这个原则组织。
15. 完整文件级示例:main.py + routes.py
app/main.py
"""FastAPI 应用入口。"""
from fastapi import FastAPI
from app.api.routes import router
app = FastAPI(
title="Month1 AI Service",
description="月份 1 的最小 AI 服务示例",
)
app.include_router(router)
app/api/routes.py
"""定义月份 1 的最小 API 路由。"""
from fastapi import APIRouter
router = APIRouter()
@router.get("/health")
async def health() -> dict[str, str]:
"""健康检查接口。
它的存在并不是为了技术炫耀,而是为了让你和调用方都能快速判断服务是否启动成功。
"""
return {"status": "ok"}
16. 逐段解释这组完整示例
为什么 app = FastAPI(...) 不直接写全部逻辑
因为 FastAPI 实例应该更像应用的装配点,而不是逻辑仓库。
为什么先单独引入 router
这是在提前建立一种非常重要的工程习惯:
main.py负责组装routes.py负责路由定义- service 层负责业务
为什么第一个接口一定是 /health
因为这是最基础的可观测性入口。它能快速回答:
- 服务起没起来
- 路由有没有挂上
- 基础运行环境是否正常
17. 从最小服务到月份 1 服务化项目的递进
第一步:只有 /health
验证:
- 服务能启动
- 路由能工作
- 自动文档可访问
第二步:增加 /chat
把已有模型调用能力接成服务。
第三步:增加 /tools/run
把工具执行能力接成服务。
第四步:增加流式响应
提升体验并理解更真实的数据流。
18. 自动文档为什么在学习阶段特别有价值
FastAPI 自动生成的 /docs,对月份 1 有两个特别重要的价值:
- 它让你可以快速验证请求和响应结构
- 它让你看到 Pydantic 模型如何自动转成接口文档
这会帮助你建立一个很重要的直觉:
模型结构、服务结构和文档结构,其实是联动的。
19. 调试与排错:本章最常见问题
问题一:启动命令模块路径写错
例如 uvicorn app.main:app --reload 里的 app.main:app 对不上实际目录。
问题二:服务启动了,但 /docs 打不开
说明你要检查:
- 端口是否正确
- 路由是否注册
- 应用是否真的启动成功
问题三:把 FastAPI 学成“接口函数大杂烩”
月份 1 必须时刻记住:FastAPI 只是入口,不是业务堆放处。
20. 本章完成后你应该具备的能力
完成本章后,你应当做到:
- 能启动最小 FastAPI 服务。
- 能解释
/health和/docs的意义。 - 能理解入口层与路由层的最小拆分。
- 能为后续
/chat和/tools/run做准备。
21. 如果你卡在这里,先回看哪几章
- 项目结构仍然混乱:回看 工程模板说明.md
- 异步不稳:回看 05-asyncio基础.md
22. 从本章过渡到下一章的桥接说明
接下来进入 02-请求响应模型设计.md。
本章解决的是“服务壳子怎么起”,下一章将解决“这个壳子里装什么结构”。也就是:你的 API 到底接收什么、返回什么、错误如何表达。这一步会把 FastAPI 和前面学过的 Pydantic 真正连接起来。