
上篇给 build_request_id 写了测试,项目算「能跑、能验证」了。但启动还是一句:
uv run uvicorn app.main:app --reload --port 8000这等于还停留在「在我电脑上能跑」。换台机器、换个同事,环境对不上就跑不起来。今天就把这个 Demo 往「可运行、可演示、能分享」推一步。
今天做了五件事:Docker 化、简单前端、CORS、样例库、README。
Docker 解决的核心问题是:把 Python 版本、依赖、启动命令,打包成一个标准箱,到哪台机器都能原样开起来。类比集装箱——里面装什么只有你自己知道,但外面尺寸统一,吊上船就能走。
今天建了 Dockerfile、.dockerignore,然后两条命令:
docker build -t resume-analyzer-api .
docker run --env-file .env -p 8000:8000 resume-analyzer-api有个坑必须记牢,写在 Dockerfile 的 CMD 里:
CMD ["uv", "run", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]--host 0.0.0.0 不能省。容器有自己独立的网络命名空间,不绑这个地址,容器外面根本访问不到 FastAPI。
.env 绝不能打进镜像.env 里有:
DEEPSEEK_API_KEY=...一旦 COPY .env 进镜像,这镜像只要分享出去,密钥就跟着泄露了。
正确做法是镜像只装代码和环境,密钥运行时注入:
docker run --env-file .env -p 8000:8000 resume-analyzer-api一句话:镜像保存代码和环境,密钥在运行时注入。
之前调接口只能用 curl 或 FastAPI 自带的 /docs。今天加了个最小页面:
app/static/index.html页面上有目标岗位输入框、简历文本框、开始分析按钮、结果展示区,靠:
fetch("/analyze_resume")调后端。
意义很直接:结构化 API 终于有了一个不用看文档也能操作的入口。
不用额外起一个 Web 服务器,FastAPI 直接把页面顶上来:
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
app.mount("/static", StaticFiles(directory="app/static"), name="static")
@app.get("/")
def index() -> FileResponse:
return FileResponse("app/static/index.html")这样浏览器开 http://127.0.0.1:8000/ 就能看到页面。前后端同一个服务,部署省事。
如果页面和 API 都来自 http://127.0.0.1:8000,同源,没跨域问题。但前端若跑在 http://127.0.0.1:5500,后端在 8000,虽然都在本机,端口不同,浏览器就判定为不同源,会拦请求。
规则很简单:协议、域名、端口,任意一个不同都算跨域。
后端要显式放行:
from fastapi.middleware.cors import CORSMiddleware
origins = [
"http://127.0.0.1:5500",
"http://localhost:5500",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=False,
allow_methods=["*"],
allow_headers=["*"],
expose_headers=["X-Request-ID"],
)注意 expose_headers=["X-Request-ID"] —— 前面几篇辛辛苦苦加的 request_id,如果这里不暴露,前端 fetch 的响应头里读不到它,追踪闭环就断在最后一公里。
给前端加了几个一键填充按钮:
不用每次手敲文本。尤其「触发 422 样例」,一点就能验证之前写的 VALIDATION_ERROR + request_id + 错误结构是不是真的工作。Demo 从「能用」变成「容易演示」。
最后写 README。它的作用是让未来的你或别人知道:项目是什么、怎么启动、怎么测试、怎么部署。
建议至少覆盖:
项目简介
项目结构
环境变量
本地启动
Docker 启动
前端页面
API 示例
错误响应示例
运行测试
当前限制
学习总结这一步的本质是把一堆代码,变成一个别人能理解和复用的项目。
AI 应用不只是后端能调模型,还要能运行、能访问、能演示、能交付。
前面几篇攒的是内功:
Agent 能力 / API 封装 / 错误响应 / 日志 / 测试今天补的是外功:
容器化 / 前端入口 / 跨域 / 样例演示 / 项目说明能验证还不够,能交付才算完成。
到现在,这个 PydanticAI 简历分析 Demo 已经具备:
结构化输出 Pydantic output_type
字段校验 field_validator
工具调用 Tool
Schema/Evidence 分层结构 + 原文溯源
API 封装 FastAPI
统一错误响应 HTTPException + error_detail
request_id 追踪 全局异常处理器
日志 logging
pytest 测试 test_utils
Docker 化 Dockerfile
简单前端 static/index.html
CORS 配置 CORSMiddleware
样例库 Demo 预设
README 交付说明这已经是一个完整的小型 AI 工程闭环了。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。