这次我们直接看 FastAPI。如果你写 Python,迟早要写接口、做后端、把模型封装成服务,FastAPI 是目前上手成本最低、文档最省心、性能也够用的那一档。跟 Flask 比,它自带请求参数校验、自动生成接口文档、异步支持,省掉大量手写校验和文档维护的功夫;跟 Django 比,它轻量,没有繁琐的项目脚手架,一个文件就能跑起一个服务。今天这篇就从零开始,把一个 FastAPI 项目从环境准备到部署上线完整过一遍,重点包括路由、路径参数、Pydantic 请求体、响应模型、统一返回格式、Union 类型、依赖注入、权限管理、中间件、自动 API 文档,以及最常见的“把本地模型封装成 HTTP 接口”场景。看完之后,你应该能自己搭一个能跑、能调、能上线的接口服务。
这篇文章是给零基础读者写的,不要求你有 Flask 或 Django 经验,只需要会最基本的 Python 语法,比如函数、类、列表和字典。如果你之前只用 Jupyter Notebook 写过数据处理脚本,也可以照着做,代码量不大,每一步都有可复制的命令和示例。重点不是把 FastAPI 的每个特性背下来,而是先跑通一个最小服务,再逐步加参数校验、加权限控制、加统一返回格式,最后接到你的业务里。
1. FastAPI 核心能力速览
| 能力项 | 说明 |
|---|---|
| 项目类型 | Python Web 框架,用于构建 HTTP 接口服务 |
| 开发语言 | Python,官方要求 3.8+,建议使用 3.10 或更高版本 |
| 安装方式 | pip 安装 fastapi + uvicorn,无需额外编译 |
| 路由功能 | 支持 GET、POST、PUT、DELETE、PATCH 等常用 HTTP 方法 |
| 参数处理 | 路径参数、查询参数、请求体、请求头、Cookie、表单 |
| 数据校验 | 基于 Pydantic,自动校验请求字段类型与范围 |
| 返回格式 | 支持 response_model 统一输出,可自定义 ApiResponse 模型 |
| 权限控制 | 依赖注入 + Header 校验 + APIRouter 路由级拦截 |
| 自动文档 | 内置 Swagger UI(/docs)和 ReDoc(/redoc) |
| 异步支持 | 原生 async/await,也支持普通 def 同步函数 |
| 批量任务 | 可借助 BackgroundTasks 或外部队列实现,本教程会给出基础用法 |
| 适合场景 | 后端 API、模型封装、微服务、前后端分离项目、本地工具服务 |
这套能力对零基础用户最友好的地方在于:不需要写一堆装饰器之外的框架代码,你定义函数,FastAPI 负责把 HTTP 请求转换成 Python 参数,再帮你把返回值转成 JSON。如果你之前被 Flask 的手动请求解析和参数校验折磨过,FastAPI 的体验会明显轻松很多。
2. 适用场景与使用边界
FastAPI 适合三类场景。
第一类是纯后端 API。前端 Vue、React,或者小程序、App,通过 HTTP 请求访问你的接口,FastAPI 返回 JSON 数据。第二类是算法和模型封装。你把一个图像分类模型、OCR 模型、文本生成模型、语音识别模型或者 RAG 知识库问答流程包成一个服务,输入文本或者文件,输出结构化结果。第三类是内部工具和自动化平台,比如给团队做一个数据查询接口、定时任务管理后台、批量处理任务网关。
使用边界也要说清楚。FastAPI 本身不提供数据库 ORM,需要配合 SQLAlchemy、SQLModel 或 Tortoise-ORM 使用;也不像 Django 自带 Admin 后台,需要自己写管理页面;对于页面渲染,虽然可以用 Jinja2 做服务端渲染,但那不是 FastAPI 的主场,它更适合做纯 API 服务。
在模型封装和数据服务场景里,还要注意合规使用。如果你把图片、文档、人脸、声音、文本等数据传给模型接口处理,必须确认数据和素材来源合法,涉及个人肖像、声音、版权文本时需要获得明确授权,尤其是把服务部署到公网时,要先加权限控制,再开放访问。本地测试时建议仅监听 127.0.0.1,避免接口暴露到局域网或公网。
3. 环境准备与前置条件
开始之前,先准备三样东西:Python、虚拟环境和一个编辑器。
3.1 Python 版本确认
FastAPI 官方要求 Python 3.8 及以上。不过考虑到类型注解的便利性,我建议使用 Python 3.10 或更高版本,这样可以直接用str | None这种简化写法,而不是写Union[str, None]。确认版本:
python --version如果你的系统里同时装了多个 Python,可以用python3命令确认。Windows 用户如果提示找不到命令,可以检查是否勾选了“Add Python to PATH”,或者使用安装的完整路径。
3.2 创建虚拟环境
每个项目单独建虚拟环境,避免依赖版本互相污染。这是零基础最容易忽略的一步,也是后面“为什么我这跑不起来”最常见的根因。
Windows 下执行:
python -m venv venv venv\Scripts\activatemacOS 或 Linux 下执行:
python3 -m venv venv source venv/bin/activate激活后,命令行提示符前面会多出一个(venv),说明当前已经进入虚拟环境。
3.3 编辑器选择
推荐使用 VS Code,装好 Python 扩展后,代码补全和类型提示体验很好。如果你习惯 PyCharm,也完全可以,新建项目时选择已有的虚拟环境路径就行。对于零基础来说,VS Code 轻量一些,启动快,不用等索引。
4. 安装 FastAPI 与启动第一个服务
4.1 安装依赖
FastAPI 真正干活需要两个库:fastapi提供框架能力,uvicorn负责启动一个 ASGI 服务器。安装命令:
pip install fastapi pip install "uvicorn[standard]"uvicorn[standard]会额外安装一些性能相关的依赖,比如uvloop、websockets,如果你用默认的uvicorn也可以跑,但推荐直接装带标准扩展的版本。
4.2 编写最小服务
新建一个main.py,写入下面的代码:
from fastapi import FastAPI app = FastAPI() @app.get("/") def read_root(): return {"message": "Hello FastAPI"}这里做了一件事:创建 FastAPI 实例app,然后定义了一个处理GET /请求的函数。函数返回值是一个字典,FastAPI 会自动把它转成 JSON 响应。
4.3 启动服务
在终端执行:
uvicorn main:app --reloadmain:app表示从main.py文件中导入名为app的对象,--reload表示代码文件修改后自动重启服务,开发时非常方便。
启动后终端会显示Uvicorn running on http://127.0.0.1:8000。浏览器打开http://127.0.0.1:8000,你应该能看到:
{"message": "Hello FastAPI"}到这里,你的第一个 FastAPI 服务已经跑起来了。这个流程适合所有后续接口开发,后面的所有代码都写在main.py里,保存后刷新页面,--reload会自动加载新代码。
5. 路由与路径参数:从 GET 到动态路径
5.1 常见 HTTP 方法与路由注册
FastAPI 用装饰器注册路由。基础写法是:
from fastapi import FastAPI app = FastAPI() @app.get("/items") def get_items(): return {"method": "GET"} @app.post("/items") def create_item(): return {"method": "POST"} @app.put("/items") def update_item(): return {"method": "PUT"} @app.delete("/items") def delete_item(): return {"method": "DELETE"}每个装饰器对应一个 HTTP 方法,函数名可以随便取,真正决定访问路径的是装饰器里的字符串参数。
5.2 路径参数
路径参数是 URL 地址中动态变化的那一部分。比如获取某个用户的信息,路径可以设计成/users/1、/users/2,这里的1、2就是路径参数。
@app.get("/users/{user_id}") def get_user(user_id: int): return {"user_id": user_id, "name": f"user_{user_id}"}注意user_id: int这个类型注解。FastAPI 会根据它做两件事:第一,把 URL 里的字符串自动转成 int 类型;第二,如果访问/users/abc,自动返回 422 参数校验错误,而不是等到函数内部报异常。
这就是 FastAPI 和 Flask 最大的区别之一:参数校验是声明式的,你写类型,它帮你做校验,不需要手动写isinstance()判断。
5.3 查询参数
查询参数是 URL 问号后面的部分。比如分页接口/items?skip=0&limit=10,这里的skip和limit就是查询参数。
@app.get("/items") def list_items(skip: int = 0, limit: int = 10): return {"skip": skip, "limit": limit}带默认值的参数表示调用方可以不传,不带默认值的参数必须传,否则会返回 422 错误。
@app.get("/search") def search(q: str): return {"query": q}访问/search?q=fastapi返回{"query": "fastapi"},访问/search会返回校验失败。
6. 请求体与 Pydantic 模型
POST、PUT 请求通常需要携带请求体。FastAPI 的处理方式是定义一个 Pydantic 模型,然后用它作为函数参数的类型注解。
from pydantic import BaseModel class Item(BaseModel): name: str price: float is_offer: bool = False @app.post("/items") def create_item(item: Item): return {"name": item.name, "price": item.price, "is_offer": item.is_offer}6.1 请求体验证
当你向/items发送 POST 请求时,FastAPI 会读取请求体内的 JSON 数据,按照Item模型做类型校验。下面这个请求是合法的:
{ "name": "键盘", "price": 199.0 }is_offer有默认值False,所以不传也可以。如果传入price: "abc",FastAPI 会返回 422 错误,告诉你price字段期望一个 float 类型。
这种校验能力在真实项目中非常关键。没有框架帮你做校验时,每个接口都要自己判断字段是否存在、类型对不对、范围合理不合理,代码写起来又长又容易漏。Pydantic 模型让这部分变成声明式配置。
6.2 字段约束
Pydantic 不只校验类型,还可以通过Field控制长度和范围:
from pydantic import BaseModel, Field class Item(BaseModel): name: str = Field(..., min_length=1, max_length=50) price: float = Field(..., gt=0, le=100000)...表示这个字段必填。min_length、max_length控制字符串长度,gt表示大于 0,le表示小于等于 100000。这些约束同样会在请求进入函数前自动校验。
7. 统一返回格式与 response_model
实际项目中,如果一个接口返回{"code": 0, "message": "success", "data": ...},另一个接口直接返回原始数据,前端代码会非常痛苦。统一返回格式是 FastAPI 工程化里很基础也很重要的一步。
7.1 定义统一返回模型
先定义一个通用的响应模型:
from typing import Any from pydantic import BaseModel class ApiResponse(BaseModel): code: int = 0 message: str = "success" data: Any = Nonedata使用Any类型,表示可以放任意数据,这样无论是字典、列表还是字符串都能放进这个模型。
7.2 接口里返回统一结构
@app.post("/items", response_model=ApiResponse) def create_item(item: Item): saved = {"name": item.name, "price": item.price} return ApiResponse(data=saved)这样接口返回的 JSON 结构就固定为:
{ "code": 0, "message": "success", "data": { "name": "键盘", "price": 199.0 } }7.3 失败时返回统一错误
还需要一个失败分支。比如参数校验通过了,但业务逻辑判断数据不合法,这时候可以抛HTTPException或者返回自定义的错误码:
from fastapi import HTTPException @app.get("/items/{item_id}", response_model=ApiResponse) def get_item(item_id: int): if item_id <= 0: raise HTTPException(status_code=400, detail="item_id must be positive") return ApiResponse(data={"item_id": item_id})HTTPException适合处理需要自动生成错误状态码的场景。如果你希望前端误码逻辑简单,也可以自己定义一个错误响应函数,统一返回code非 0 的结构,比如:
def error_response(message: str, code: int = 1): return ApiResponse(code=code, message=message, data=None)统一返回格式的核心价值是让前后端对接的契约稳定下来,特别是当后端接口由多个同事维护时,所有接口遵循同一个结构,前端可以封装一个统一的请求器,省掉大量重复判断逻辑。
8. Union 与 Optional:接口参数类型怎么写
FastAPI 相关教程里经常出现Union和Optional,搜索引擎里也经常有人搜“fastapi union作用”。这里单独说明。
8.1 允许参数为 None
最常见的场景是:某个查询参数可以不传,也可以传。比如搜索接口,用户可能没输入关键词。
from typing import Union @app.get("/search") def search(q: Union[str, None] = None): return {"query": q}Union[str, None]表示这个参数的类型可以是str,也可以是None。不传时,FastAPI 会把它当成None。
Python 3.10 及以上版本可以简写成:
@app.get("/search") def search(q: str | None = None): return {"query": q}两种写法效果一样。
8.2 Optional 与 Union 的关系
早期 FastAPI 教程里经常写Optional[str],它的本质就是Union[str, None]。但更准确的表达是:Optional只表示“允许为空”,不表示“有默认值”。真正让参数可以不传的是后面的= None。所以推荐直接用str | None = None,语义更直白。
8.3 Union 的另一个用途:多类型参数
Union也可以用在请求体模型字段上:
class Config(BaseModel): timeout: Union[int, float] = 1.0 retries: Union[int, None] = None这个能力在对接第三方接口、模型参数配置里很常见,因为外部传进来的配置经常存在多种合法类型。
9. 依赖注入与权限管理
FastAPI 的权限管理,核心机制是依赖注入(Depends)。简单说,你定义一个函数负责校验权限,然后在接口函数中声明依赖,FastAPI 会在执行接口函数前先执行校验函数。
9.1 一个最简单的 Token 校验
from fastapi import Depends, Header, HTTPException def verify_token(authorization: str = Header(...)): if authorization != "secret-token": raise HTTPException(status_code=401, detail="unauthorized") return authorization @app.get("/secure") def secure_endpoint(token: str = Depends(verify_token)): return {"status": "ok"}请求/secure时,如果不带Authorization请求头,会返回 422;如果带了Authorization: secret-token,就会正常返回{"status": "ok"}。
9.2 使用 APIRouter 做路由级权限控制
项目变大后,不可能给每个接口都手动加Depends。更好的做法是按模块拆分路由,然后用APIRouter统一加权限依赖。
先创建一个routers包,目录结构如下:
project/ ├── main.py └── routers/ ├── __init__.py └── admin.pyadmin.py:
from fastapi import APIRouter, Depends router = APIRouter(prefix="/admin", dependencies=[Depends(verify_token)]) @router.get("/stats") def get_stats(): return {"users": 100}main.py注册路由:
from fastapi import FastAPI from routers.admin import router as admin_router app = FastAPI() app.include_router(admin_router)这样/admin/stats会自动执行verify_token校验,不需要在接口函数里重复编写。
9.3 更细的权限拆分
真实项目里,可以用依赖叠加实现不同权限等级。比如先校验是否登录,再校验是否有管理员权限:
def verify_admin(token: str = Depends(verify_token)): if token != "admin-token": raise HTTPException(status_code=403, detail="forbidden") return token @router.get("/admin-only", dependencies=[Depends(verify_admin)]) def admin_only(): return {"secret": "admin data"}这种依赖注入的设计比在接口函数内部手写权限判断清晰得多,权限逻辑可以复用,测试也更好写。
10. 中间件与 CORS 配置
10.1 自定义 HTTP 中间件
中间件的作用是在请求进入路由函数之前、响应返回给客户端之前,插入一些统一处理逻辑,比如日志记录、耗时统计、请求 ID 注入。
import time from fastapi import Request @app.middleware("http") async def add_process_time_header(request: Request, call_next): start = time.time() response = await call_next(request) process_time = time.time() - start response.headers["X-Process-Time"] = str(round(process_time, 4)) return response这里call_next(request)会继续往下执行实际的接口函数,拿到响应后,给响应头添加了一个X-Process-Time字段,记录请求耗时。这样前端和排查日志时都能看到每个接口的响应时间。
10.2 CORS 配置
如果你的前端页面运行在http://localhost:3000,后端接口运行在http://localhost:8000,浏览器默认会拦截跨域请求,导致前端无法调接口。FastAPI 通过CORSMiddleware解决:
from fastapi.middleware.cors import CORSMiddleware app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:3000"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], )开发阶段可以直接用allow_origins=["*"],表示允许所有来源访问。但部署到公网时,建议把allow_origins限制为你自己的前端域名,避免接口被其他站点任意调用。
10.3 中间件执行顺序
FastAPI 的中间件是嵌套执行的,先注册的先处理请求。多个中间件之间的顺序会影响逻辑,比如 CORS 中间件应该尽量早注册,确保预检请求能正常通过。
11. 自动 API 文档与接口调试
FastAPI 内置了 Swagger UI 和 ReDoc,启动服务后直接访问/docs和/redoc就能看到。
11.1 Swagger UI
启动uvicorn main:app --reload后,浏览器访问:
http://127.0.0.1:8000/docs页面上会列出所有已注册的路由、HTTP 方法、请求参数、请求体模型和响应模型。点击某个接口,可以直接填入参数并点击 Execute 发起真实请求,FastAPI 会展示完整的请求 URL、请求体和响应结果。
这个能力在零基础入门阶段尤其有用。你不需要提前准备 Postman 或 curl,只要服务跑起来,就能在/docs页面对每个接口做测试。
11.2 OpenAPI 导出
FastAPI 的自动文档基于 OpenAPI 规范,接口结构会生成一份标准的 JSON 描述文件,默认路径:
http://127.0.0.1:8000/openapi.json这份文件可以被 Postman、Apifox 等工具导入,也可以用于生成客户端 SDK。如果团队要求接口文档统一管理,FastAPI 服务本身就是文档源,不需要额外维护。
11.3 给接口加描述信息
给接口函数写 docstring 和参数描述,文档会更清晰:
@app.get("/items/{item_id}") def get_item(item_id: int): """ 根据 ID 获取商品信息。 - item_id: 商品 ID,必须为正整数 """ return {"item_id": item_id}docstring 会显示在/docs页面的接口说明里。零基础阶段不要求写得多规范,但建议从第一天开始养成注释习惯,后面接口多了会省很多沟通成本。
12. 实战:用 FastAPI 封装本地模型服务
FastAPI 在 AI 场景里最常见的用法之一,就是把视觉模型、文本模型、RAG 知识库问答等封装成 HTTP 接口。这里给出一个通用思路,你用同样的套路可以套到自己的模型上。
12.1 同步推理接口
假设你有一个 OCR 函数,输入是一张图片的 base64 字符串,输出是识别文本。可以这样封装:
import base64 from pydantic import BaseModel from fastapi import FastAPI app = FastAPI() class OCRInput(BaseModel): image_base64: str def run_ocr(image_base64: str) -> str: # 这里调用你自己的 OCR 模型 # 示例:解码图片 -> 模型推理 -> 返回文本 return "识别结果" @app.post("/ocr", response_model=ApiResponse) def ocr_api(req: OCRInput): try: result = run_ocr(req.image_base64) return ApiResponse(data={"text": result}) except Exception as e: return ApiResponse(code=1, message=str(e), data=None)关键点有三个:第一,请求体用 Pydantic 模型约束输入;第二,模型推理逻辑单独抽成run_ocr函数,方便测试;第三,异常捕获后在统一返回格式里返回错误信息,而不是让服务直接崩溃。
12.2 长耗时任务的 BackgroundTasks
如果模型推理需要十几秒甚至几分钟,HTTP 请求会长时间阻塞。这时候可以用BackgroundTasks先把任务接收下来,再异步处理,前端通过任务 ID 轮询结果。
from fastapi import BackgroundTasks from pydantic import BaseModel class TaskRequest(BaseModel): input_text: str task_store = {} def process_task(task_id: str, input_text: str): # 模拟耗时推理 result = input_text.upper() task_store[task_id] = result @app.post("/task") def create_task(req: TaskRequest, background_tasks: BackgroundTasks): import uuid task_id = str(uuid.uuid4()) background_tasks.add_task(process_task, task_id, req.input_text) return {"task_id": task_id, "status": "pending"} @app.get("/task/{task_id}") def get_task(task_id: str): if task_id in task_store: return {"task_id": task_id, "status": "done", "result": task_store[task_id]} return {"task_id": task_id, "status": "pending"}这种“提交任务 + 轮询结果”的模式,在视觉模型封装、RAG 知识库问答、批量文本生成里非常常用。BackgroundTasks适合单机轻量场景,如果任务量很大,需要换成 Celery 或 Redis 队列,但接口设计思路是一样的。
12.3 配置参数通过查询参数传递
模型推理的 batch size、温度、最大长度等参数可以通过查询参数或请求体传入:
class GenerateInput(BaseModel): prompt: str temperature: float = 0.7 max_tokens: int = 512这样同一个接口可以适配多种推理配置,调用方按需调整。
13. 生产部署:uvicorn 多进程与 Docker
开发时用--reload,生产环境不能这样跑。生产部署需要关掉自动重载、绑定对外地址、启动多个 worker。
13.1 多进程启动
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4--workers 4表示启动 4 个 worker 进程,能利用多核 CPU 提高并发能力。需要注意的是,--reload和--workers不能同时使用,开发用--reload,生产用--workers。
13.2 Docker 部署
写一个 Dockerfile:
FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8000 CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]requirements.txt内容:
fastapi uvicorn[standard]构建和运行:
docker build -t fastapi-demo . docker run -d -p 8000:8000 fastapi-demo启动后访问http://localhost:8000和http://localhost:8000/docs,效果跟本地运行一致。
13.3 部署时要注意的点
生产部署前要检查 CORS 白名单、接口鉴权是否生效、是否开启了文档站点、日志输出是否完整。如果接口涉及隐私数据,建议在反向代理层启用 HTTPS,并把 Swagger 文档限制在内网访问,避免接口定义和数据结构直接暴露到公网。
14. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
启动报错ModuleNotFoundError: No module named 'fastapi' | 虚拟环境未激活或未安装依赖 | 执行pip list检查 fastapi 是否存在 | 激活虚拟环境后执行pip install fastapi |
| 启动报端口被占用 | 8000 端口已被其他进程占用 | 查看日志“address already in use” | 换端口启动:uvicorn main:app --reload --port 8001 |
| 修改代码后服务不生效 | 启动时没加--reload | 确认启动命令参数 | 开发时加上--reload,或手动重启服务 |
| 访问接口返回 422 | 请求参数缺失或类型不匹配 | 在/docs页面使用 Execute 测试 | 检查字段名、类型是否与 Pydantic 模型一致 |
| 前端跨域请求失败 | 后端未配置 CORS | 查看浏览器控制台错误信息 | 配置CORSMiddleware,限制允许的来源 |
| 请求体字段是合法的,但仍校验失败 | 字段名不一致,或使用了下划线/驼峰混用 | 查看/docs中请求体示例 | 保持前后端字段命名一致 |
/docs页面打不开 | 服务未启动或端口不对 | curl 访问/openapi.json | 确认 uvicorn 正常启动、端口未冲突 |
| 部署后只有容器内能访问 | 容器端口未映射 | 检查docker ps端口映射 | 运行容器时加-p 8000:8000 |
| 同步接口阻塞,请求特别慢 | 模型推理耗时较长,未使用异步或后台任务 | 观察接口响应时间 | 按需改用async def或BackgroundTasks |
Union类型接口直接报错 | Python 版本较低,无法解析新语法 | 执行python --version | 升级 Python 3.10+,或用typing.Union写法 |
最重要的一条排查思路:FastAPI 的报错信息通常比较明确,先看终端日志,再看/docs页面有没有正确显示接口,最后看请求响应体里的具体错误字段。大部分 422 错误都能从响应体的detail字段直接定位到哪个参数不对。
15. 最佳实践与学习建议
最后给零基础读者几条实践建议。
第一,先跑通最小示例,再逐步加功能。不要一开始就打算写一个完整系统,先跑Hello FastAPI,再加路径参数,再加请求体,最后引入权限和数据库。每加一个功能,都在/docs页面验证一次。
第二,从第一天起使用统一返回格式。哪怕只是一个 demo,也建议定义ApiResponse模型。后期接口变多后,统一返回格式能省掉大改前端的麻烦。
第三,路径、参数、模型命名保持与业务语义一致。接口路径建议使用名词复数形式,比如/users、/items;请求体和响应体字段使用小写字母加下划线,前后端约定一致,避免在接口层做大量字段映射。
第四,权限控制要早加。即使只是本地开发,也可以通过 Header 写一个简单的 token 校验,习惯后进入真实项目时会少踩很多坑。注意 token 不要硬编码在代码里,建议通过环境变量或配置文件读取。
第五,日志和异常处理要有。接口函数内部不要把所有异常都吞掉,至少要打印 traceback,或者返回统一错误结构。部署时把--reload关掉,使用--workers多进程启动。
接下来你可以准备两件事:第一,把这篇教程里的代码全部手敲一遍,再自己加一个/health健康检查接口和/version版本号接口,试试路径参数和查询参数的综合用法;第二,如果有正在训练的模型,试着用POST /predict把它封装成 HTTP 接口,前端调用一下,体会一下模型到服务的完整链路。学完这些基础,下一步就是接 SQLAlchemy 操作数据库、用 Pydantic Settings 管理配置、写单元测试,这些都可以一步一个坑慢慢来。