资讯动态

AI辅助搭建FastAPI服务:从零写一个文章摘要接口

发布时间:2026/10/30 0:54:25 来源:尧图企业网站定制
一直想给自己的小工具加一个能被外部调用的接口手机端要用另一个脚本也要用装个网页又不想绑死在同一个前端上。想来想去最合适的还是后端 API 服务。以前光是想到路由、鉴权、部署这一套流程就头大这次我试着让 AI 全程参与搭一个 API 服务从环境初始化到写完一个能跑的接口再到接上大模型能力整个过程出乎意料地顺。这篇文章记录的就是这个“小项目实战”的第一期用 AI 从零搭一个 API 服务。文章会讲清楚为什么选 FastAPI 而不是 Flask 或 Node.js怎么设计一个可用的接口怎么用 AI 生成和修改代码以及我在调试、部署阶段踩到的一堆坑。适合两类人看一是还没完整写过真正的后端服务但想快速拥有一个属于自己的 API 的开发者二是已经在写业务代码想用 AI 把脚手架、造轮子这类重复劳动压缩到最短的工程师。我尽量把每一步都拆到可以直接照做也会把“为什么这样做”讲明白毕竟抄代码容易抄完能改才是真会。1. 项目整体设计与思路拆解1.1 一个“小工具”为什么会需要 API 服务先说场景。我想做一个“一句话摘要助手”输入一篇长文章返回一段干净的核心摘要可以放到笔记软件里也可以接到自己写的微信机器人上。这个需求听起来很简单但细想就会发现必须要有一个独立的服务来承接因为调用方不止一个。手机上的快捷指令需要通过 HTTP 请求拿到结果。另一个运行在电脑上的定时脚本也要复用同一个能力不能各自重复实现摘要逻辑。后续如果要做成网页前端可以直接调用同一个后端接口不用给每端写一套逻辑。所以这个项目拆到最后核心就是提供一个能接收文本、返回摘要的 API 服务。这个服务在哪个机房、用什么语言写的都不重要重要的是它有稳定的 URL、有清晰的入参出参、有合理的错误处理。API 服务的本质就是“把能力变成一个可以被程序调用的入口”就像餐厅的前台服务员你不需要知道后厨怎么做菜只要下单就能拿到菜。这也是这次项目最关键的认知不要一开始就想做平台、做微服务先做一个小而全的 API能跑、能调试、能对方联网环境负责就已经解决绝大多数个人工具的痛点了。1.2 为什么选 AI 来辅助搭建而不是自己硬写我写后端的能力不算差但“写一个能用的 API”和“快速写一个能用的 API”之间差距非常大。以前搭 FastAPI 服务至少要花时间回忆依赖版本、路由装饰器写法、参数校验库的用法。这些不是难而是繁琐而且一边写一边查文档很容易打断思路。这次我把节奏改成我负责设计和验证AI 负责代码生成和解释。具体分工是这样我先想清楚接口要接收什么、返回什么、鉴权怎么处理。AI 根据我的描述生成第一版代码包括路由、模型、异常处理。遇到报错直接把报错信息丢给 AI让它解释原因并给修复方案。接口写完后让 AI 补一组测试用例验证边界情况。实际跑下来AI 给我最大的帮助不是能写多复杂的代码而是把“从零到跑起来”的时间压缩到了十几分钟。如果我自己写光环境依赖就能折腾一晚上。当然AI 生成的代码不能闭眼用它经常把能跑和能用混为一谈所以后面我会专门讲拿到代码后的审阅清单。1.3 技术选型为什么是 FastAPI Python 大模型 API选型这件事我纠结过一轮。候选方案有 Python 的 Flask、FastAPI还有 Node.js 的 Express。最后选了 FastAPI理由可以列成表格维度FastAPIFlaskNode.js/Express上手成本低装饰器风格直观更低中等异步写法要考虑自动文档自带 OpenAPI Swagger 文档需要额外配置需要额外配置参数校验基于 Pydantic 自动完成基本靠手写需要工具库性能异步支持性能不错同步为主够用性能不错生态和 AI 生态契合类型提示友好老牌生态前端友好适合场景快速构建 API、AI 后端传统 Web 页面全栈前端团队AI 相关项目普遍用 Python很多大模型 SDK 也对 Python 支持最好所以“Python FastAPI”是当下搭 AI API 服务最省事的组合。FastAPI 的类型提示天然适合描述请求和响应结构Pydantic 自动做数据校验省掉很多 if else 判断。大模型 API 的选型我选了支持 OpenAI 兼容协议的服务商比如 DeepSeek、智谱、讯飞星火这类都可以。理由很简单协议统一之后代码里只需要配置 base_url、api_key、model 这三个值后续想换服务商改环境变量就行不用重写调用逻辑。这也是做 API 服务时很重要的思路——“面向协议编程而不是面向具体厂商编程”。2. 核心细节解析与实操要点2.1 API 服务的基本构成与运行机制在让 AI 写代码之前先要知道一个最小 API 服务里有哪几样东西。FastAPI 应用的核心构成其实非常少路由Route定义 URL 路径和对应的方法比如GET /health。请求处理函数Handler收到请求后执行逻辑返回响应。数据模型Model定义请求体和响应体的结构FastAPI 会基于它做自动校验。异常处理Exception Handler把错误转换成统一的 HTTP 状态码和提示信息。一个最简单的 FastAPI 服务用代码表示就是from fastapi import FastAPI app FastAPI() app.get(/health) def health(): return {status: ok}跑起来之后访问http://127.0.0.1:8000/health就会得到 JSON 响应。这里不要小看这个/health接口它就像是服务的“体检入口”任何服务上线前都应该有用来确认进程活着、依赖是否初始化成功。实际部署时负载均衡和监控系统都会定期请求这个接口来判断服务健康状态。再往底层说一层FastAPI 本身并不直接监听端口它是 ASGI 框架需要配合 Uvicorn 这样的 ASGI 服务器运行。Uvicorn 负责接收 HTTP 请求解析之后交给 FastAPI 处理FastAPI 再把返回值交给 Uvicorn 发回给客户端。理解这一点对排查启动问题很有用比如端口被占用、uvicorn 参数写错都是这个环节常见的坑。2.2 接口设计的关键决策入参、出参与鉴权很多初学者搭 API喜欢“拿到啥返回啥”但真正可用的接口一定要在设计阶段确定三件事入参结构、出参结构、鉴权方式。入参结构要明确哪些是路径参数哪些是查询参数哪些是请求体。以摘要 API 为例长文本放请求体里更合适因为文本可能很长放在 URL 里既不方便也不安全{ content: 这是一段很长的文章内容..., max_length: 100 }出参结构长期来看统一格式比怎么方便怎么返回更好用。我常用的统一结构是{ code: 0, message: success, data: { summary: 这是摘要结果 } }这个结构的好处是不管接口返回什么业务数据调用方都能先解析code和message再根据情况处理data。如果每个接口返回结构都不一样前端和脚本就要为每个接口单独写一套解析逻辑维护成本会指数级上升。鉴权方式个人项目不必要上 OAuth 那套复杂流程用一个简单的 API Key 就够了调用方在请求头带上X-API-Key服务端校验通过才继续处理否则返回 401。这个方案简单、直接、够用等以后真有用户体系了再升级也不迟。2.3 提示词技巧怎么让 AI 产出能直接跑的代码AI 生成的代码质量八分靠提示词。我踩过不少次“代码看起来对一跑就报错”的坑后来总结出一个比较稳定的提示词结构分四层角色你是一个熟悉 FastAPI 和 Python 的资深后端工程师。 任务帮我创建一个文章摘要 API 服务。 约束 - 使用 FastAPI 框架 - 请求体包含 content 和 max_length 字段 - 响应统一为 code/message/data 结构 - API Key 从请求头 X-API-Key 读取校验失败返回 401 - 代码要可以直接保存为 main.py 运行 上下文我会用 Uvicorn 启动服务Python 版本 3.11。这个结构的关键在于“约束”和“上下文”两层。没有约束AI 会自由发挥给你写个 Flask 版本或者连数据库都给你装上没有上下文它不会知道你项目的运行条件可能生成用到新版语法但你的 Python 版本跑不了。把这两块写清楚AI 返回的代码基本就是“能用”级别了。拿到代码之后我会按这个清单快速审一遍确认没有明显隐患是否用了if __name__ __main__避免直接运行时重复创建实例。敏感配置API Key是否从环境变量读取而不是硬编码在代码里。参数校验是否齐全比如max_length是否为非负整数。异常处理是否有兜底比如模型调用失败时返回 500 而不是整个服务崩溃。3. 实操过程与核心环节实现3.1 从零初始化项目环境先准备运行环境。我的电脑上装的是 Python 3.11直接用系统自带的venv做虚拟环境没必要装 Anaconda 这种大块头。命令如下mkdir ai-api-demo cd ai-api-demo python3 -m venv venv source venv/bin/activate激活虚拟环境之后安装需要的依赖pip install fastapi uvicorn python-dotenv openai这里解释一下为什么装openai这个包虽然我用的不一定是 OpenAI 官方服务但市面上主流大模型 API 都兼容 OpenAI 的客户端协议所以直接用openai库把base_url指向任意兼容服务商即可。python-dotenv用于读取.env文件里的敏感配置比如 API Key。装完依赖之后验证一下版本避免后面出现莫名其妙的兼容性问题python -c import fastapi; print(fastapi.__version__)这一步看起来很基础但非常重要。很多 AI 生成代码默认依赖最新版本如果你本地装的是旧版本等跑到报错再去排查会浪费不少时间。装完立刻确认版本属于“三分钟预防一小时”的典型习惯。3.2 让 AI 生成第一个业务接口并跑起来环境准备好之后我开始和 AI 对话。第一轮只让它生成一个健康检查接口和一个简单的“文件接收”接口先走通链路再说大模型的事。我给的提示词大致是请帮我写一个 FastAPI 应用保存为 main.py。 要求 1. 有一个 GET /health 接口返回 {status: ok} 2. 有一个 POST /echo 接口接收 JSON 请求体 {content: 字符串}返回 {code: 0, message: success, data: {content: 原始内容}} 3. 使用统一响应格式 code/message/data 4. Python 3.11FastAPI 最新稳定版AI 生成的代码大致如下我做了少量整理删掉了多余的注释from fastapi import FastAPI from pydantic import BaseModel app FastAPI() class EchoRequest(BaseModel): content: str def ok_response(dataNone): return {code: 0, message: success, data: data} app.get(/health) def health(): return {status: ok} app.post(/echo) def echo(req: EchoRequest): return ok_response({content: req.content})启动服务uvicorn main:app --host 0.0.0.0 --port 8000看到Uvicorn running on http://0.0.0.0:8000这样的日志服务就已经跑起来了。我习惯加上参数--reload调试改代码会自动重启不用手动断开重来。不过--reload只是开发环境用的生产环境千万别开否则会带来不必要的资源开销和频繁重启风险。用 curl 测试一下curl -X POST http://127.0.0.1:8000/echo \ -H Content-Type: application/json \ -d {content:hello}返回结果{code:0,message:success,data:{content:hello}}到这一步一个最小 API 服务已经通了。整个过程约五分钟大部分时间花在等 AI 输出和检查代码上比自己从零写要快太多。3.3 接入大模型做一个真正的“文章摘要”API第一个接口只是热身这个项目的核心功能是“文章摘要”。我继续让 AI 基于已有代码扩展。为了让生成的代码更贴合我的调用场景我在提示词里补充了具体需求细节在上一个 FastAPI 项目基础上增加一个 POST /summarize 接口。 请求模型字段content必填字符串max_length可选int默认100。 实现逻辑 1. 从请求头 X-API-Key 读取 API Key与服务器配置的 API_KEY 环境变量比对不一致则返回 401。 2. 调用 OpenAI 兼容的大模型接口模型名从环境变量 MODEL_NAME 读取。 3. 把 content 截断到足够长的长度后发给模型提示词要求返回不超过 max_length 字的核心摘要。 4. 统一返回 code/message/data 结构data 中包含 summary 字段。 使用 python-dotenv 加载 .env 文件。AI 生成的核心代码逻辑如下这里展示关键片段完整项目代码我会统一整理import os from fastapi import FastAPI, Header, HTTPException from pydantic import BaseModel from openai import OpenAI from dotenv import load_dotenv load_dotenv() app FastAPI() client OpenAI( base_urlos.getenv(API_BASE_URL), api_keyos.getenv(OPENAI_API_KEY), ) MODEL_NAME os.getenv(MODEL_NAME, deepseek-chat) EXPECTED_API_KEY os.getenv(API_KEY, ) class SummarizeRequest(BaseModel): content: str max_length: int 100 class SummarizeResponse(BaseModel): code: int message: str data: dict app.post(/summarize) def summarize(req: SummarizeRequest, x_api_key: str Header(...)): if x_api_key ! EXPECTED_API_KEY: raise HTTPException(status_code401, detailinvalid api key) truncated req.content[:4000] prompt f请用不超过{req.max_length}字概括以下内容的核心信息\n{truncated} resp client.chat.completions.create( modelMODEL_NAME, messages[{role: user, content: prompt}], max_tokens200, ) summary resp.choices[0].message.content.strip() return {code: 0, message: success, data: {summary: summary}}这一段逻辑里有两个关键设计点。第一个是Header(...)的写法...表示这个请求头字段是必选的如果调用方没带X-API-KeyFastAPI 会直接返回 422 参数错误比自己在函数内部判断要省很多代码。第二个是req.content[:4000]截断这个是为后面防止 token 超限准备的先在这里埋一个兜底。在项目根目录创建.env文件OPENAI_API_KEY你的密钥 API_BASE_URLhttps://api服务商地址 MODEL_NAMEdeepseek-chat API_KEY自己设置的接口访问密钥然后重启服务再用带请求头的请求测试curl -X POST http://127.0.0.1:8000/summarize \ -H Content-Type: application/json \ -H X-API-Key: my-secret-key \ -d {content:这里放一段几百字的文章,max_length:50}如果一切正常会返回类似这样的结果{code:0,message:success,data:{summary:文章主要讨论了...}}接上大模型的 API一个能实际使用的“文章摘要”服务就完成了。从项目初始化到这一步总耗时不到半小时其中有一半时间是在和 AI 来回确认接口设计细节。3.4 本地测试与简单部署上线本地跑通只是第一步想让自己的脚本在任意地方都能调这个 API还需要部署到云服务器上。这个项目的部署我选了最省事的方式把项目代码放到一台云服务器上用 systemd 托管 uvicorn 进程再通过 Nginx 做反向代理和 HTTPS 证书管理。如果你还没有服务器也可以先用简单的进程管理工具核心思路都一样。先后把本地代码传到服务器在服务器上创建虚拟环境并装依赖python3 -m venv venv source venv/bin/activate pip install -r requirements.txt用 systemd 创建一个服务单元文件ai-api.service内容大致如下[Unit] DescriptionAI API Service Afternetwork.target [Service] Userwww-data WorkingDirectory/opt/ai-api EnvironmentFile/opt/ai-api/.env ExecStart/opt/ai-api/venv/bin/uvicorn main:app --host 127.0.0.1 --port 8000 Restartalways [Install] WantedBymulti-user.target这里有一个值得注意的细节systemd 里通过EnvironmentFile加载.env文件这样就不需要代码里再显式调用load_dotenv()进程启动时环境变量自动注入逻辑更干净也不会在重启时出现环境变量读取不到的问题。然后启动并设置开机自启sudo systemctl daemon-reload sudo systemctl enable --now ai-apiNginx 配置反向代理把域名流量转发到本机 8000 端口server { listen 80; server_name api.example.com; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }配置好之后重载 Nginx再把域名解析指向服务器浏览器访问http://api.example.com/health就能看到服务状态了。这是最简单、最常用的小项目部署方案。很多教程上来就让你用 Docker但我不建议小项目一上来就套容器编排先把 systemd 这套跑明白积累的排查经验到了用 Docker 的时候都能用上。4. 常见问题与排查技巧实录4.1 Docker 权限报错permission denied while trying to connect to the docker api这个报错是我在尝试用 Docker 方式跑服务时遇到的完整信息是permission denied while trying to connect to the docker api at unix:///var/run/docker.sock。原因是当前用户没有加入docker用户组没有权限访问 Docker 守护进程的套接字。排查思路很简单先确认 Docker 是否在运行再确认当前用户是否在 docker 组里。systemctl status docker id $USER如果用户不在 docker 组执行sudo usermod -aG docker $USER然后重新登录一次让组权限生效。需要注意不要图省事直接sudo docker跑这样虽然能用但会让后续自动化脚本的权限管理变得混乱。不过说实话我最后没有用 Docker 跑这个项目因为单文件应用用 systemd 托管更直接少了一层容器封装排查问题也更省事。Docker 更适合需要复现环境、多服务编排的场景。4.2 API Key 未配置no api key for provider route接入大模型的第一个报错是no api key for provider route xxx。这个报错的意思是你选择的模型服务商路由找不到对应的 API Key。最常见的两个原因一是.env文件里没有配置OPENAI_API_KEY二是代码中client初始化时没按服务商要求取到值。排查顺序如下确认.env文件存在并且和main.py在同一个目录。确认.env里的变量名和代码里os.getenv(OPENAI_API_KEY)完全一致大小写、下划线都不能差。在client OpenAI(...)这行前后加一行print(os.getenv(OPENAI_API_KEY))看是否输出真实值排查load_dotenv()是否生效。确认.env文件没有被加入.gitignore之外的地方比如某些编辑器会忽略隐藏文件。这里我要提一个很坑的细节如果你在 systemd 里用EnvironmentFile加载.env而代码里又调用了load_dotenv()那么后者的作用是“不覆盖已存在的环境变量”。如果.env里的值有误可能生效的是错误值。排查时候我会用systemctl cat ai-api看一下环境文件路径是否写错或在服务里追加一个临时ExecStartPre命令打印环境变量值。4.3 上下文超长API error: 400 this models maximum context length is 1048576 tokens这个报错很典型很多第一次接大模型的开发者都会遇到。完整信息类似API error: 400 this models maximum context length is 1048576 tokens. However, you requested X tokens。意思是你发给模型的输入加上请求的max_tokens超过了该模型的最大上下文限制。1048576 tokens 看起来很多但如果你把一整个网页文本不加处理直接塞进去很容易触发超限。解决思路分三层截断输入在代码里对content做长度限制比如content[:4000]这是我的第一道防线。可以根据模型能力调整比如取 3000 到 6000 个字符。分片处理如果原始文本确实特别长先把文本按段落或固定长度切分成多个 chunk分别生成摘要再汇总成总摘要。这一步逻辑稍复杂但对真正处理长文档很有用。控制输出生成摘要时max_tokens不要设置过大比如要求 100 字摘要设置max_tokens200是安全的设置太大反而容易让总和超限还浪费成本。需要提醒的是错误信息里带的 token 数是模型内部的计数方式和用户肉眼看到的“字数”不完全一样。中文字符差不多 1 到 2 个 token英文单词约 1 到 2 个 token。不要用“5000 字”去直接等于“5000 token”不然容易估算错误。4.4 免费额度与调用量监控接入大模型 API 后还有一个很容易被忽略的问题免费额度用完了怎么办。各家服务商通常都会提供一定量的免费额度但超出后就按 tokens 计费。个人项目没有预算压力还好一旦接入定时任务一个死循环可能一晚上跑掉几十万 tokens第二天一看账单吓一跳。建议做两件事在代码里限制请求频率最简单粗暴的就是在/summarize接口增加一个全局计数器限制每分钟最多调用 N 次。真正的生产服务可以用慢速键值存储实现分布式限流但个人项目进程内计数就够了。在服务商控制台开启额度告警设置每日消费上限超过后自动停止调用。这是最后一道保险比代码层面的限制更可靠。我自己实际也踩过这个坑当时写了一个批量摘要脚本一次性跑几千条文本刚开始还挺美等调完一看调用统计免费额度基本见底。之后我就学乖了所有调用前先统计剩余额度批量任务用tqdm打印进度把调用量控制在预期范围内。最后分享一个小技巧这个实战项目做完之后我发现最值得保留的习惯是“让 AI 顺手写测试”。接口跑通之后我会把生成的 FastAPI 代码和需求丢给 AI让它配套生成一份test_main.py用pytest和httpx写几个基础用例覆盖正常请求、鉴权失败、参数缺失这三种情况。有了测试之后后面每次改动代码跑一遍测试就能快速确认有没有把接口改坏省下的时间远不止写测试那几分钟。这个项目的下一步我想把摘要接口加上缓存同一篇文本的摘要结果在 24 小时内直接复用缓存避免重复调用大模型既省钱又提速。再往后可以进一步把接口组合成一个简单的 AI Agent让一个接口能根据用户意图自动选择调用摘要、翻译或关键词提取能力。任何一次从零搭建只要走通了第一个接口后面所有扩展都只是在这个地基上添砖加瓦而已。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑