30天从零开始学AI应用开发(Day 20):用 FastAPI 给你的 RAG 穿上接口,别人也能访问了
这是系列的第 20 篇。整个系列写给零基础、想入行 AI 的朋友每天一篇30 天后你会做出 3 个能写进简历的项目。这篇解决什么问题昨天的 RAG 系统跑通了但它有个限制只能在你自己的电脑上用命令行交互。想给别人用怎么办总不能让人家坐到你电脑前敲命令吧。今天给它穿上接口变成一个服务。做完这一步你的系统就从“本地脚本”升级成“能被程序调用的服务”这是所有产品的必经之路。顺便说FastAPI 是现在 Python 后端的主流选择AI 应用开发岗位的招聘要求里出现频率很高。今天学的东西以后你工作中大概率天天用。一、接口是什么给程序用的门你已经在用接口了只是没意识到。Day 6 你调大模型 API那个/chat/completions就是接口。你发一个请求过去它返回一个结果。现在我们要做的是把自己的 RAG 系统也做成这样一个门别人发个问题过来你返回答案。打个比方你的 RAG 系统是后厨昨天只有你自己能进去端菜。今天在墙上开个窗口窗口上有张菜单写好怎么点单、能点哪些菜。这个窗口加菜单就是接口学名叫 API。而 FastAPI 是帮你造这个窗口的工具它会自动生成菜单文档还免费送一个测试页面。二、从最小示例开始先装包pipinstallfastapi uvicorn写一个能跑的最小服务新建 api.pyfromfastapiimportFastAPI appFastAPI()# 创建应用app.get(/)# 声明访问根路径时执行下面这个函数defhello():return{message:服务已启动}跑起来uvicorn api:api--reload注意命令的格式uvicorn 文件名:应用名。这里文件是 api.py应用变量叫 app所以是api:app。加 --reload 是改代码后自动重启开发时很省事。跑起来后浏览器打开http://127.0.0.1:8000会看到那行 JSON。再打开http://127.0.0.1:8000/docs你会看到一个漂亮的交互页面FastAPI 自动生成了接口文档还能直接在页面上点“试一下”。这个自动文档是 FastAPI 的招牌功能面试提到它是加分项。三、把 RAG 封成接口现在干正事。接口接收一个问题调用昨天的 answer 函数返回答案和来源。先定义请求的数据格式。FastAPI 用 Pydantic 来做数据校验你只需要声明字段和类型fromfastapiimportFastAPIfrompydanticimportBaseModelfromragimportanswer# 复用昨天写的核心逻辑appFastAPI(titleRAG 知识库问答接口)classAskRequest(BaseModel):请求体只接收一个 question 字段question:strtop_k:int3# 可选参数默认检索 3 条classAskResponse(BaseModel):响应体答案加来源answer:strsources:list[str]然后是接口本体app.post(/ask)# post 表示提交数据不是单纯获取defask(req:AskRequest):text,hitsanswer(req.question)returnAskResponse(answertext,sources[h[source]forhinhits])为什么用 post 而不是 get因为提问是“提交内容并得到结果”不是“读取某个页面”。这是接口设计的基本礼仪也很容易被问到。顺带一个接口设计的经验参数要给默认值。top_k 默认 3调用方不传也能用这就是好设计的细节。四、测试你的接口跑起来之后有两种测法。方法一在 /docs 页面上直接点。找到 /ask点“Try it out”填一段 JSON 进去{question:出差住宿怎么报销}点 Execute下面会显示返回结果。这是最省事的测法不用写任何测试代码。方法二用 curl 命令能验证真实调用链路curl-XPOST http://127.0.0.1:8000/ask\-HContent-Type: application/json\-d{\question\:\出差住宿怎么报销\}看到返回的 JSON 里有 answer 和 sources接口就通了。五、让接口更像个正经服务三个小改进让你的接口显得专业。改进一加健康检查。部署之后判断服务有没有活着就靠它app.get(/health)defhealth():return{status:ok}改进二加异常处理。别让一个报错把整个服务搞崩fromfastapiimportHTTPExceptionapp.post(/ask)defask(req:AskRequest):try:text,hitsanswer(req.question)returnAskResponse(answertext,sources[h[source]forhinhits])exceptExceptionase:raiseHTTPException(status_code500,detailf处理失败{e})改进三处理跨域。以后你用网页前端调这个接口浏览器会因为跨域把请求拦掉加上中间件一次解决fromfastapi.middleware.corsimportCORSMiddleware app.add_middleware(CORSMiddleware,allow_origins[*],# 教学方便先全放开正式项目要指定域名allow_methods[*],allow_headers[*],)这三样加上你的接口就从“能跑”变成“能交付”。六、这个能力为什么重要到这一步你手上其实已经有了一个完整的 AI 应用后端数据在向量库里逻辑在 rag.py 里对外有标准接口。这意味着可以让网页前端调它Day 27 会用 Streamlit 做界面可以让别的程序调它比如你的微信机器人可以挂到服务器上让所有人用Day 28 部署从“自己玩”到“给别人用”这一步跨过去你的项目性质就变了。常见报错排查报错一uvicorn 命令找不到。说明包没装到这个环境里。用python -m uvicorn api:app --reload试试这样一定能找到。报错二启动报错说找不到 app。检查命令里的文件名:变量名是否和代码一致。文件叫 api.py变量叫 app就写api:app写错一个字母都不行。报错三访问 8000 端口打不开。端口可能被占用。换一个uvicorn api:app --reload --port 8001。报错四请求返回 422 错误。这是参数校验没通过通常是你发的 JSON 字段名和 class 里定义的不一致。比如定义的是 question你发了 “q”。看 /docs 页面上的请求示例照着抄。报错五调接口时卡很久。正常因为大模型生成要几秒。想改善体验就用 Day 12 学的东西不过流式输出在接口里要用流式响应稍微复杂一点属于进阶内容。今天的作业把接口跑通用 /docs 页面测三个问题一个资料里有答案的、一个需要综合的、一个资料里没有的。把 /docs 页面的截图发到评论区那个自动生成的文档页面挺好看的值得晒。明天预告Day 21《周复盘 项目二简历写法》。第三周结束我们把这周的成果整理一下重点是把项目二写进简历。RAG 项目的简历描述有讲究写好了能让面试官主动追问明天给你完整模板和追问应对思路。————————————————*系列目录30天从零开始学AI应用 开发