惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
PCI Perspectives
PCI Perspectives
T
Tailwind CSS Blog
月光博客
月光博客
Apple Machine Learning Research
Apple Machine Learning Research
大猫的无限游戏
大猫的无限游戏
V
V2EX
D
Docker
P
Proofpoint News Feed
阮一峰的网络日志
阮一峰的网络日志
博客园 - 司徒正美
酷 壳 – CoolShell
酷 壳 – CoolShell
云风的 BLOG
云风的 BLOG
H
Help Net Security
The Register - Security
The Register - Security
宝玉的分享
宝玉的分享
C
Check Point Blog
T
Threatpost
The GitHub Blog
The GitHub Blog
P
Privacy International News Feed
G
Google Developers Blog
博客园 - Franky
爱范儿
爱范儿
T
Tor Project blog
博客园 - 聂微东
Google DeepMind News
Google DeepMind News
G
GRAHAM CLULEY
雷峰网
雷峰网
Cyberwarzone
Cyberwarzone
人人都是产品经理
人人都是产品经理
C
Cybersecurity and Infrastructure Security Agency CISA
Vercel News
Vercel News
Scott Helme
Scott Helme
aimingoo的专栏
aimingoo的专栏
Martin Fowler
Martin Fowler
MyScale Blog
MyScale Blog
Last Week in AI
Last Week in AI
GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
腾讯CDC
K
Kaspersky official blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Project Zero
Project Zero
F
Fortinet All Blogs
AWS News Blog
AWS News Blog
The Cloudflare Blog
C
CERT Recently Published Vulnerability Notes
I
InfoQ
Spread Privacy
Spread Privacy
T
Tenable Blog

博客园 - 一名程序媛呀

Anki插件开发必知必会:钩子函数与右键菜单定制 httpx 传参总报错?这次把 GET、POST、文件上传到响应处理的坑给你一次填平 从卡顿到丝滑:FastAPI 调用外部 API 的正确姿势(httpx 实战) 还在 XHR、Fetch 和 Axios 之间纠结?我踩过的坑,希望你一个都不用碰到 你的REST接口还在“过度投喂”数据吗?——FastAPI + GraphQL实战避坑指南 Uvicorn、Gunicorn 傻傻分不清?FastAPI 生产部署避坑指南 Termux里的二进制和脚本,到底怎么运行才不踩坑?Termux-service 保活妙招! 刚部署的 LibreTranslate 频频翻车?我掏出了 20 年前的 StarDict 词典,用 FastAPI 搭了个本地词典翻译 API 别再用网页翻译看源码了!你的私人翻译神器LibreTranslate,部署避坑指南来了 掏出手机就能搭个 WebDAV 同步服务器?这操作有点香 别只盯着GitBook了!这个文档神器让你的笔记秒变网站 写爬虫时用了代理还被封?Python 代理的那些隐藏坑,我替你踩明白了 FastAPI 身份验证总踩坑?这份 FastAPI Users “避坑指南”请收好 旧手机别扔!用 Termux 搭个私人云盘,比网盘香多了 你的FastAPI又在服务器上“跑不起来”了?来,今天咱把打包这件事彻底聊透 写页面时别再把 Element Plus 整个搬进来啦!Vue3按需加载的坑我帮你踩平了 前端包管理咋选?我从npm叛逃到pnpm的血泪史(附避坑指南) 聊聊 fetch 使用中我踩过的那些坑和正确打开方式 FastApiAdmin 后端接口开发好了,前端管理界面怎么调用与显示? 给 FastApiAdmin 加个“会议纪要”模块,我把后端二次开发的坑踩了个遍 我用了FastApiAdmin后,连夜把踩过的坑都整理出来了 告别 Typora 后的新欢:我把所有笔记迁移到了 Obsidian 这个“第二大脑” 你的Agent API还在裸奔?从认证到沙箱,我用FastAPI搭了几道防线 让 FastAPI Agent 思考不阻塞:手把手教你实现异步任务与后台处理方案 让FastAPI Agent真正记住你:聊聊会话记忆与持久化存储的落地实践 FastAPI Agent 函数调用实战:我让 AI 学会了“自己动手查天气“ FastAPI 少有人提的实用技巧:把 Depends 依赖提到路由层,代码少写60% FastAPI 生产环境静态文件完全指南:从 /favicon.ico 404 到 HSTS 混合内容,一次全根治 用了loguru我才明白,Python日志还能这么写 FastAPI 后台任务:BackgroundTasks 的使用场景与注意事项 FastAPI配置管理避坑指南:从硬编码到 .env 与 pydantic_settings 类,连路由用法都给你捋清楚 FastAPI 文件上传避坑全指南:分块存盘、类型校验与安全兜底 FastAPI + Pydantic 模型终极实战手册:从能跑就行到固若金汤,这些技巧你一定用得上 FastAPI + SQLAlchemy 2.0 通用CRUD操作手册 —— 从同步到异步,一次讲透 FastAPI订单防超卖实战:从数据库锁到Saga分布式事务,这一篇给你理清了 FastAPI 生产环境避坑指南:用 Alembic 管理数据库迁移,别再手动改表结构了! FastAPI服务半夜又挂了?先别急着重启,查查你的数据库连接池“池子”是不是漏了 FastAPI数据库ORM怎么选?我肝了三个Demo后,终于不再纠结了 Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看 Vue 3 组合式 API 香是香,但从Vue2迁移时你可别像我当初一样踩进这 3 个深坑里 我用fastapi-scaff搭了个项目,两天工期缩到两小时,老板以为我开挂了 FastAPI+Vue:文件分片上传+秒传+断点续传,这坑我帮你踩平了! FastAPI自动生成的API文档太丑?我花了一晚上把它改成了客户愿意付费的样子 告别手写 API 胶水代码:FastAPI 与 Vue 的“契约自动机” OpenAPI 实战 FastAPI + Vue 前后端分离实战:我的项目结构“避坑指南” FastAPI + Celery 实战:异步任务里调用 Redis 和数据库的全解析,及生产级组织方案 FastAPI里玩转Redis和数据库的正确姿势,别让异步任务把你坑哭了! FastAPI + Celery 实战:异步任务的坑与解法,我帮你踩了一遍 FastAPI子应用挂载:别再让root_path坑你一夜 FastAPI项目半夜报警吵醒你?聊聊告警这事儿怎么搞! 别再数据线了!用FastAPI 5分钟搭个局域网文件+剪贴板神器 FastAPI单元测试实战:别等上线被喷才后悔,TestClient用对了真香! FastAPI状态共享秘籍:别再让中间件、依赖和路由“各自为政”了! FastAPI实战:WebSocket vs Socket.IO,这回真给我整明白了! 从0到1,FastAPI + PostgreSQL + Tortoise ORM 实战避坑指南 FastAPI + PostgreSQL 实战:给应用装上“缓存”和“日志”翅膀 FastAPI + PostgreSQL 实战:从入门到不踩坑,一次讲透
初探:用 FastAPI 搭建你的第一个 AI Agent 接口
一名程序媛呀 · 2026-05-09 · via 博客园 - 一名程序媛呀

看到有朋友留言说想了解下 FastAPI 开发 AI Agent 相关的话题,之前有玩过一段时间,奈何本机电脑配置一般,跑起来不流畅,便作罢了,但该走的路,该踩的坑也是一样没落下,最近整理了下,把代码也再跑了下,后续会逐渐分享给各位参考,今天先开个头。

你是不是也有过这种憋屈的时刻:兴致勃勃在本地跑了个大模型,问他“今天天气咋样”都能回得有模有样,可一旦想把它接进自己的 App、小程序,或者让同事调一下——整个人就卡住了?

这事儿其实可以特别简单:一个 FastAPI 服务 + 一个本地 Ollama,就能跑通一个完整的 AI Agent 接口,还能自动给你生成漂亮的 Swagger 文档。今天我就把这条捷径画出来,你跟着走一遍,差不多晚饭前就能跑起来。

🎯 本文能帮你解决的

把“本地大模型”变成“标准 HTTP API”,顺便搞清楚 Agent 最核心的骨架—— Agent = LLM + 工具 + 编排逻辑 ,而不是一上来就啃那些重框架。

你会得到一个带请求/响应校验、环境变量管理、自动生成接口文档的最小可行 Agent 后端。

🧭 内容速览

· 一个让本地 LLM“开口接客”的痛点场景

· 用餐厅点餐比喻,拆解 Agent 到底是个啥

· FastAPI + Ollama + Pydantic 的最小实战代码

· 请求生命周期:从你的问题到 Agent 那句回答

· 几个一偷懒就翻车的坑,帮你提前绕开

🔑 第一部分:那把“钥匙”到底在哪儿?

看个案例:小媛说他在本地把 Llama3 跑起来了,想给自己的客服系统加个自动回复接口。

需求不复杂:前端扔一段用户问题过来,后端问 Ollama,然后把答案送回去。她觉得这应该半小时搞定。

结果呢?她先是卡在“怎么把每次的提问包装成 API”,然后又纠结“返回的结果该用啥格式”,最后看着一堆手动拼的 JSON schema 叹了口气。

这就是典型的手里有发动机,却没给车架和轮胎。FastAPI 正好就是那套车架,帮我们把发动机(LLM)稳稳地装上去,还顺带送个仪表盘(Swagger)。

🍔 第二部分:Agent 这套“套餐”到底怎么理解

先别急着敲代码,咱们聊聊 Agent 的本质。我特别喜欢用 快餐店点餐 来打比方:

👩‍🍳 LLM —— 就是后厨那个万能大厨,你提啥要求他都能给整出个菜。

🧰 工具 —— 是大厨手边的锅铲、烤箱、菜刀。没有工具,他只能干聊;有了工具,他才能查天气、调数据库、执行函数。

📋 编排逻辑 —— 是前台那张点餐流程单:先确认需求,再选择合适的工具,最后让大厨出餐,错了还要打回重做。

所以一个最简化的 Agent 接口,不是直接把用户的话丢给 Ollama 完事,而是要在代码里体现这三层。今天我们先把基础路走通,让“大厨”先能出餐,后面再加“工具”就容易了。

⚡ 第三部分:动手!从零搭一个 /chat 端点

先晒一下我们的目标——一个跑在本地、用 Swagger 就能聊天的接口。你发一段话,它回一段话,背后调的是 Ollama。

咱们的项目目录就简简单单几个文件:

├── main.py # 主服务入口
├── models.py # 请求/响应模型
├── config.py # 环境变量配置
└── pyproject.toml

好,咱们先来搞定环境。 我默认你已经装好了 Ollama 并且拉取了模型,比如 llama3。然后一行命令把依赖装齐:

uv add fastapi[standard] httpx

对,你没看错,连 httpx 都得装,一会儿我们要用它去异步调 Ollama 的 API,这时候就别用 requests 同步请求了,一上量接口直接卡成 PPT

接下来重点来了,定义请求和响应模型。 打开 models.py,用 Pydantic 来管住进出。
我喜欢把这事儿交给 Pydantic,比手写字典强一万倍——自动校验,还能直接喂给 Swagger。

from pydantic import BaseModel

class ChatRequest(BaseModel):
    message: str

class ChatResponse(BaseModel):
    reply: str

这里再说个容易翻车的点:模型里字段如果写成 msg 这种简写,回头对接前端的人会恨你一辈子。老老实实把可读性拉满。

然后是 config.py,咱们用 pydantic-settings 管理环境变量。这样不用把地址硬编码在代码里,随时可以通过 .env 或环境变量覆盖。

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    ollama_base_url: str = "http://localhost:11434"
    model_name: str = "llama3"

    class Config:
        env_file = ".env"

settings = Settings()

官方文档虽然默认就支持 .env,但根据以往的经验,一定要在根目录放一个 .env 文件,并且记得加进 .gitignore。不然某天队友的 API Key 就被你公之于众了,那场面可太尴尬。

主角来了:main.py。我们先搭个骨架,再用依赖注入把 settings 传进去,给 /chat 端点用。

from fastapi import FastAPI, Depends
from models import ChatRequest, ChatResponse
from config import Settings, settings
import httpx

app = FastAPI(title="AI Agent 接口", version="0.1.0")

def get_settings():
    return settings

@app.post("/chat", response_model=ChatResponse)
async def chat(
    req: ChatRequest,
    config: Settings = Depends(get_settings)
):
    async with httpx.AsyncClient() as client:
        resp = await client.post(
            f"{config.ollama_base_url}/api/generate",
            json={
                "model": config.model_name,
                "prompt": req.message,
                "stream": False
            },
            timeout=30.0
        )
        resp.raise_for_status()
        data = resp.json()
        return ChatResponse(reply=data["response"])

你可能会问:“就这?Agent 的‘工具’和‘编排’呢?”
别急,今天咱们先把大厨请出来。后面几篇我会慢慢给这个骨架添上“菜单”——工具调用逻辑,让它可以查天气、搜文档。

现在先跑起来,体验一下从零到一的快感。

最后啰嗦一句,启动命令就一行: fastapi run main.py
然后打开 http://localhost:8000/docs ,你会看到一个自带交互界面的 Swagger。直接在里面 Try it out 测试,看到回复的那一瞬间,你心里一定会喊一声“舒坦”。

🔁 第四部分:一个请求的完整生命周期

为了让你心里更有谱,我把整个过程拆成五步:

前端(或 Swagger)把 用户的一句话 按 ChatRequest 格式发到 /chat

FastAPI 自动校验字段,不对就立刻返回 422 错误,省得垃圾数据钻进大模型

依赖注入 把 Settings 对象默默准备好,代码里直接用

用 httpx 异步调用 Ollama 的 /api/generate,把大厨喊醒

Ollama 返回的 response 字段塞进 ChatResponse,Swagger 自动渲染成漂亮的 JSON 文档

你瞧,整个链路清晰得就像一条笔直的大路,每个弯拐在哪里一目了然。以后想加缓存、加日志、加工具,只要顺着这条路插进去就行。

⚠️ 注意事项与进阶思考

· 千万别在公网暴露 Ollama 的 11434 端口,这家伙默认没鉴权!

· 生产环境一定要加请求频率限制,大模型慢,分分钟把你的 FastAPI 线程池打满。

· stream: False 用着爽,但做打字机效果时记得换成流式响应,那又是另一个好玩的话题。

· 接下来我会在这个例子上逐步加上工具调用(比如用搜索引擎的 API),让 Agent 真的“动手干活”。


好啦,今天就先聊到这儿。那种亲手把模型装进接口的踏实感,真的会让人上瘾。如果你也跟着跑通了,评论区炫耀一下;如果卡在哪一步,也可留言甩过来,我拿过键盘咱们一起解决它。

担心错过后续的“加工具”、“写编排”系列?点个关注,咱们下篇见🚀。顺手点赞 + 收藏,别让这篇实战笔记沉底,说不定你的同事今晚就用上了。