0%

初识 FastAPI

是什么

  FastAPI 是一个基于 Python 的现代 Web 后端框架,用于快速构建 API 服务,让我们快速写出类似这样的接口:

1
2
3
4
5
6
7
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def hello():
return {"message": "Hello FastAPI"}

  运行后,别人访问

1
http://服务器地址/

  就能得到

1
{"message": "Hello FastAPI"}

前后端分离与前后端不分离

  前后端不分离时,用户访问 127.0.0.1:8000/index.html,经过后端 urls 路由转发到后端函数,再读取数据库,后端直接返回 login.html 页面给用户。也就是:页面 HTML 是后端生成并返回的。

  

图 1 前后端不分离
  

  前后端分离时,前端只负责页面显示和用户交互,后端只负责提供数据接口。例如前端 vue 调用接口

1
2
3
4
axios.post("/api/update", {
name: "zhangsan",
age: 123
})

  后端 FastAPI 收到请求:

1
2
3
4
@app.post("/api/update")
def update_user(data: User):
# 修改数据库
return {"msg": "更新成功"}

  这里的后端不返回完整的 HTML 页面,只返回数据,例如

1
2
3
{
"msg": "更新成功"
}

  

图 2 前后端分离
  

RESTful 风格的 API

  普通的 API 接口可能这样写,将所有的动作直接写在 URL 里。

1
2
3
4
/getUser?id=1
/addUser
/deleteUser?id=1
/updateUser

  RESTful API 更推荐这样写

1
2
3
4
/users
/users/1
/articles
/articles/10

  URL 主要表示资源,动作由 HTTP 方法表示,例如

操作 HTTP 方法 RESTful 接口
获取所有用户 GET /users
获取某个用户 GET /users/1
新增用户 POST /users
修改用户 PUT / PATCH /users/1
删除用户 DELETE /users/1

  FastAPI 就很适合写 RESTful API,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from fastapi import FastAPI

app = FastAPI()

@app.get("/users")
def get_users():
return [{"id": 1, "name": "zhangsan"}]

@app.get("/users/{user_id}")
def get_user(user_id: int):
return {"id": user_id, "name": "zhangsan"}

@app.post("/users")
def create_user():
return {"message": "user created"}

@app.delete("/users/{user_id}")
def delete_user(user_id: int):
return {"message": f"user {user_id} deleted"}

FastAPI 的最小实现

  创建 conda 新环境,通过 pip 安装 fastapi。新建 main.py 文件,写入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
from fastapi import FastAPI

import uvicorn

app = FastAPI()

@app.get("/")
def root():
return {"message": "Hello World"}

if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8080)

  这段代码创建一个 FastAPI 后端应用,定义了一个 GET / 接口,用 uvicorn 在本机 8080 端口启动服务。

  async 将函数声明为异步函数,使其可以在执行 I/O 操作(如数据库请求、HTTP调用)时使用 await 挂起当前任务,从而不阻塞事件循环,提高并发能力。例如:

1
2
3
4
@app.get("/users")
async def get_users():
data = await db.fetch_all()
return data

  运行上面的代码,访问 http://127.0.0.1:8080/ 就可以看到 Hello World 了。

  

图 3 返回 hello world
  

FastAPI 接口文档

  我们将刚刚的代码添加几个步骤,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from fastapi import FastAPI

import uvicorn

app = FastAPI()

@app.get("/get")
async def get():
return {"message": "This is a GET request"}

@app.post("/post")
async def post():
return {"message": "This is a POST request"}

@app.put("/put")
async def put():
return {"message": "This is a PUT request"}

@app.delete("/delete")
async def delete():
return {"message": "This is a DELETE request"}

if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8080)

  运行代码,访问 http://127.0.0.1:8080/docs,即可看到一份完整的 API 文档:

  

图 4 API文档
  

  我们可以在这个页面查看后端的接口信息。

路由分发

  路由分发是指:用户访问某个 URL 时,后端根据“路径 + 请求方法”,把请求交给对应的函数处理。,可以理解为:网址和函数之间的对应关系。

  新建 api 文件夹,在该文件夹中新建 book.py 文件,写入如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from fastapi import APIRouter

api_book = APIRouter()

@api_book.get("/get")
async def book_get():
return {"message": "This is a GET request"}

@api_book.post("/post")
async def book_post():
return {"message": "This is a POST request"}

@api_book.put("/put")
async def book_put():
return {"message": "This is a PUT request"}

@api_book.delete("/delete")
async def book_delete():
return {"message": "This is a DELETE request"}

  这就表示创建了一个路由,并定义了路由内部的功能。接下来,我们在 main.py 中写入如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
from fastapi import FastAPI

import uvicorn

from api.book import api_book

app = FastAPI()

app.include_router(api_book, prefix="/book",tags=["book"])

if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8080)

  在 app 对象中添加子路由,并将其前缀设置为 “/book”,这样,刚刚 book.py 中定义的请求就可以通过 “/book/***” 来访问。

request 对象

  request 对象指的是客户端发给服务器的这一次请求的完整信息,比如用户访问接口时,浏览器或前端会向 FastAPI 后端发送 HTTP 请求:

GET /book/get

  这个请求里面可能包含很多信息,例如请求方法、请求路径、请求参数等等,FastAPI 里的 Request 对象就是用来拿这些信息的。我们修改部分代码,如下

1
2
3
4
5
6
7
8
9
10
11
from fastapi import FastAPI, Request

app = FastAPI()

@app.get("/info")
async def info(request: Request):
return {
"method": request.method,
"url": str(request.url),
"client": request.client.host
}

  request 中包含请求方法,可以通过 request.method 获取,还可以通过 request.url 获取完整的 URL,通过 request.query_params 获取查询参数等等。

Pydantic

  Pydantic 是一个基于 Python 类型注解的数据解析与校验库,用于在运行时对数据进行验证、转换和结构化。我可以通过以下代码创建一个类

1
2
3
4
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int

  它可以帮我检查数据对不对,自动把 JSON 转成 Python 对象,自动生成 API 文档。其真实用例如下:

1
2
3
4
5
6
7
8
9
10
11
12
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class User(BaseModel):
name: str
age: int

@app.post("/user")
async def create_user(user: User):
return user

  在前端发送如下数据后,

1
2
3
4
{
"name": "zhangsan",
"age": 18
}

  FastAPI + Pydantic 自动解析 JSON,并将其变为 Py 对象,如果前端错传,也会直接报错。

FastAPI 在 AGENT 中的作用

  FastAPI 通常作为 Agent 系统的 HTTP 服务层,负责接收用户请求并将其转发给 Agent 核心逻辑,同时返回处理结果。一个典型的 Agent 系统如下:

1
2
3
4
5
6
7
用户

FastAPI(API层)

Agent Orchestrator(调度层)

LLM / Tools / Memory / Vector DB

  所以 FastAPI 在 Agent 中具体作为入口接口、统一 API 层、连接前端,并且还可以作为多 Agent 的路由与调度入口。最关键的是可以作为工具调用中转站,FastAPI 将工具能力封装为 API,使 Agent 可以通过 HTTP 或函数调用方式使用这些能力,例如

1
2
3
@app.post("/search")
async def search(query: str):
return search_engine.run(query)

  Agent 就可以再调用这个接口。

总结

  FastAPI 在 Agent 中的作用,就是把“智能体能力”变成一个可以被前端调用的 HTTP 服务入口,同时负责路由、参数、并发和部署。FastAPI 是 Agent 项目中不可或缺的一环,值得更加深入的学习。