从需求到上线:用 FastAPI 做一个智能工单助手实战教程
AI编程 实战案例分享|附配置文件
当“AI 编程”从概念走向落地,真正能提升效率的不是简单让大模型写几段代码,而是把 AI 融入需求分析、架构设计、编码实现、测试验证、代码审查、文档生成与部署发布的完整工程流程中。本文将通过一个真实可复用的实战案例,分享如何使用 AI 辅助开发一个“智能工单分类与自动回复系统”,并附上关键配置文件,方便读者参考实践。
一、为什么要做 AI 编程实战?
过去我们谈到 AI 编程,更多停留在“让 AI 写函数”“让 AI 生成 SQL”“让 AI 修 Bug”这些局部场景。但在真实项目中,软件开发并不是孤立地写代码,而是一整套工程化流程:
- 需求是否清晰?
- 模块边界是否合理?
- 数据结构是否可扩展?
- 接口是否具备稳定性?
- 异常情况是否考虑完整?
- 单元测试和集成测试是否覆盖核心路径?
- 配置是否支持多环境?
- 日志、监控、限流、降级是否具备?
- 后续维护者是否能看懂?
AI 的价值,不只是提高“敲代码速度”,而是帮助我们降低思考成本、补齐工程细节、快速生成初稿、发现潜在风险,并把开发人员从大量重复劳动中释放出来。
本文的案例选择了一个比较典型的企业级场景:智能工单分类与自动回复系统。它既有后端接口,也有 AI 调用;既需要工程配置,也需要提示词设计;既能体现 AI 编程效率,也能落到真实业务中。
二、案例背景:智能工单分类与自动回复系统
假设某 SaaS 平台每天会收到大量用户反馈工单,例如:
- “登录时一直提示验证码错误”
- “订单支付成功了但后台没显示”
- “能不能开发批量导出功能”
- “系统好像变慢了,页面加载很久”
- “我想咨询企业版价格”
客服人员需要对这些工单进行分类、判断优先级,并给出初步回复。传统做法通常依赖人工判断,效率低且容易出现不一致。
因此我们希望开发一个后端服务,实现以下能力:
- 接收用户提交的工单内容;
- 调用大模型分析工单类别;
- 判断工单优先级;
- 生成一段客服初步回复;
- 保存分析结果;
- 提供查询接口;
- 支持多环境配置;
- 具备基础日志、异常处理与测试能力。
三、技术选型
本案例采用较常见且易落地的技术栈:
| 类型 | 技术 |
|---|---|
| 后端语言 | Python 3.11 |
| Web 框架 | FastAPI |
| 数据库 | PostgreSQL |
| ORM | SQLAlchemy |
| 配置管理 | Pydantic Settings |
| AI 接口 | OpenAI / 兼容 OpenAI 协议的大模型服务 |
| 测试 | Pytest |
| 部署 | Docker + Docker Compose |
| 日志 | Loguru |
为什么选择 FastAPI?因为它开发效率高、类型提示友好、自动生成 API 文档,非常适合 AI 辅助编程。AI 在生成 FastAPI 项目结构、接口定义、Pydantic Schema、单元测试时表现较好。
四、项目目录结构
在正式编码前,可以先让 AI 生成一个工程目录结构,然后我们人工审查和微调。最终目录如下:
ai-ticket-assistant/
├── app/
│ ├── api/
│ │ └── ticket_api.py
│ ├── core/
│ │ ├── config.py
│ │ └── logger.py
│ ├── db/
│ │ ├── database.py
│ │ └── models.py
│ ├── schemas/
│ │ └── ticket_schema.py
│ ├── services/
│ │ ├── ai_service.py
│ │ └── ticket_service.py
│ └── main.py
├── tests/
│ └── test_ticket_api.py
├── .env.example
├── requirements.txt
├── Dockerfile
├── docker-compose.yml
└── README.md
这个结构比较清晰:
api:负责接口层;core:放置全局配置和日志;db:数据库连接与模型;schemas:请求和响应数据结构;services:业务逻辑;main.py:应用入口;tests:测试代码;- 配置文件放在项目根目录。
五、AI 编程实践流程
1. 先让 AI 帮助拆解需求
我们可以给 AI 输入这样的提示词:
你是一名资深后端架构师。
我要开发一个智能工单分类与自动回复系统,技术栈为 Python + FastAPI + PostgreSQL。
请帮我拆解功能模块、设计接口、设计数据表,并指出需要注意的工程风险。
AI 通常会给出如下建议:
- 工单提交接口;
- 工单查询接口;
- AI 分类服务;
- 数据库存储;
- 配置管理;
- 日志记录;
- 错误处理;
- 接口鉴权;
- 限流机制;
- AI 调用失败兜底;
- Prompt 版本管理。
这里要注意:AI 给出的方案不一定完全正确,但它可以作为第一版草稿。开发者真正的价值在于审查、筛选、调整和补充,而不是无脑复制。
2. 设计数据模型
本案例中,核心实体是 Ticket,需要保存:
- 工单 ID;
- 用户 ID;
- 工单内容;
- 分类结果;
- 优先级;
- AI 回复内容;
- 处理状态;
- 创建时间;
- 更新时间。
示例模型如下:
from sqlalchemy import Column, Integer, String, Text, DateTime
from sqlalchemy.sql import func
from app.db.database import Base
class Ticket(Base):
__tablename__ = "tickets"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(String(64), nullable=False, index=True)
content = Column(Text, nullable=False)
category = Column(String(64), nullable=True)
priority = Column(String(32), nullable=True)
ai_reply = Column(Text, nullable=True)
status = Column(String(32), default="created")
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
这个模型并不复杂,但已经能够支撑最小可用版本。真实业务中还可以继续增加:
- 租户 ID;
- 客服处理人;
- 人工修改后的分类;
- AI 置信度;
- Prompt 版本;
- 模型名称;
- Token 消耗;
- 处理耗时。
这些字段对于后续质量评估和成本分析非常有价值。
六、核心业务逻辑设计
业务流程如下:
用户提交工单
↓
后端接收内容
↓
调用 AI 分析类别、优先级、回复建议
↓
结构化解析 AI 返回结果
↓
保存数据库
↓
返回工单分析结果
接口设计:
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/tickets |
提交工单并分析 |
| GET | /api/tickets/{ticket_id} |
查询工单详情 |
| GET | /api/tickets |
查询工单列表 |
请求示例:
{
"user_id": "u10001",
"content": "我昨天已经支付成功了,但是后台订单状态还是未支付,请帮我看一下。"
}
响应示例:
{
"id": 1,
"user_id": "u10001",
"content": "我昨天已经支付成功了,但是后台订单状态还是未支付,请帮我看一下。",
"category": "支付问题",
"priority": "高",
"ai_reply": "您好,我们已经收到您的反馈。订单支付状态异常可能与支付回调延迟或订单同步有关,我们会尽快为您核查,请您提供订单号以便进一步处理。",
"status": "created"
}
七、Prompt 设计:让 AI 输出稳定结构
AI 编程项目中,Prompt 的质量直接影响系统稳定性。如果只是让模型“帮我分类”,返回结果可能是自然语言,不方便程序解析。
更好的做法是要求 AI 返回严格 JSON。
示例 Prompt:
你是一名专业客服工单分析助手。
请根据用户提交的工单内容,完成以下任务:
1. 判断工单类别,只能从以下类别中选择:
- 登录问题
- 支付问题
- 订单问题
- 功能建议
- 性能问题
- 价格咨询
- 其他问题
2. 判断优先级,只能从以下级别中选择:
- 低
- 中
- 高
- 紧急
3. 生成一段礼貌、简洁、专业的客服初步回复。
请严格按照如下 JSON 格式返回,不要输出任何额外解释:
{
"category": "支付问题",
"priority": "高",
"reply": "您好,我们已经收到您的问题,会尽快为您处理。"
}
用户工单内容如下:
{{ticket_content}}
这里的关键点是:
- 明确角色;
- 限定分类范围;
- 限定优先级范围;
- 要求严格 JSON;
- 不允许输出额外解释;
- 使用变量占位符。
即便如此,生产环境中也不能完全相信模型输出,仍然需要做 JSON 解析异常处理和字段校验。
八、关键代码示例
1. 配置管理
app/core/config.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
app_name: str = "AI Ticket Assistant"
app_env: str = "dev"
debug: bool = True
database_url: str
ai_api_key: str
ai_base_url: str
ai_model: str = "gpt-4o-mini"
ai_timeout: int = 30
class Config:
env_file = ".env"
settings = Settings()
配置文件不应该写死在代码里,尤其是数据库密码、API Key 等敏感信息。使用 .env 和环境变量是更合适的方式。
2. AI 服务封装
app/services/ai_service.py
import json
from openai import OpenAI
from app.core.config import settings
client = OpenAI(
api_key=settings.ai_api_key,
base_url=settings.ai_base_url
)
class AIService:
@staticmethod
def analyze_ticket(content: str) -> dict:
prompt = f"""
你是一名专业客服工单分析助手。
请根据用户提交的工单内容,完成以下任务:
1. 判断工单类别,只能从以下类别中选择:
- 登录问题
- 支付问题
- 订单问题
- 功能建议
- 性能问题
- 价格咨询
- 其他问题
2. 判断优先级,只能从以下级别中选择:
- 低
- 中
- 高
- 紧急
3. 生成一段礼貌、简洁、专业的客服初步回复。
请严格按照如下 JSON 格式返回,不要输出任何额外解释:
{{
"category": "支付问题",
"priority": "高",
"reply": "您好,我们已经收到您的问题,会尽快为您处理。"
}}
用户工单内容如下:
{content}
"""
response = client.chat.completions.create(
model=settings.ai_model,
messages=[
{"role": "system", "content": "你是一个只返回 JSON 的客服工单分析助手。"},
{"role": "user", "content": prompt}
],
temperature=0.2,
timeout=settings.ai_timeout
)
result_text = response.choices[0].message.content
try:
return json.loads(result_text)
except Exception:
return {
"category": "其他问题",
"priority": "中",
"reply": "您好,我们已经收到您的反馈,客服人员会尽快为您处理。"
}
这里设置 temperature=0.2,目的是降低输出随机性。对于分类、抽取、结构化分析这类任务,通常不需要太高的创造性。
3. 业务服务
app/services/ticket_service.py
from sqlalchemy.orm import Session
from app.db.models import Ticket
from app.services.ai_service import AIService
class TicketService:
@staticmethod
def create_ticket(db: Session, user_id: str, content: str) -> Ticket:
ai_result = AIService.analyze_ticket(content)
ticket = Ticket(
user_id=user_id,
content=content,
category=ai_result.get("category"),
priority=ai_result.get("priority"),
ai_reply=ai_result.get("reply"),
status="created"
)
db.add(ticket)
db.commit()
db.refresh(ticket)
return ticket
@staticmethod
def get_ticket(db: Session, ticket_id: int) -> Ticket | None:
return db.query(Ticket).filter(Ticket.id == ticket_id).first()
@staticmethod
def list_tickets(db: Session, limit: int = 20):
return db.query(Ticket).order_by(Ticket.id.desc()).limit(limit).all()
这个服务层负责整合 AI 能力和数据库操作,让接口层保持简洁。
九、附:配置文件
下面是本项目中较关键的配置文件,读者可以根据自己的环境调整。
1. .env.example
APP_NAME=AI Ticket Assistant
APP_ENV=dev
DEBUG=true
DATABASE_URL=postgresql://postgres:postgres@db:5432/ticket_db
AI_API_KEY=your_api_key_here
AI_BASE_URL=https://api.openai.com/v1
AI_MODEL=gpt-4o-mini
AI_TIMEOUT=30
如果你使用的是兼容 OpenAI 协议的国内大模型服务,只需要修改:
AI_BASE_URL=https://your-model-provider.com/v1
AI_API_KEY=your_provider_api_key
AI_MODEL=your_model_name
2. requirements.txt
fastapi==0.115.0
uvicorn==0.30.6
sqlalchemy==2.0.34
psycopg2-binary==2.9.9
pydantic==2.8.2
pydantic-settings==2.4.0
openai==1.43.0
python-dotenv==1.0.1
loguru==0.7.2
pytest==8.3.2
httpx==0.27.2
3. Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
4. docker-compose.yml
version: "3.9"
services:
api:
build: .
container_name: ai-ticket-api
ports:
- "8000:8000"
env_file:
- .env
depends_on:
- db
restart: always
db:
image: postgres:15
container_name: ai-ticket-db
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: ticket_db
ports:
- "5432:5432"
volumes:
- ticket_pg_data:/var/lib/postgresql/data
restart: always
volumes:
ticket_pg_data:
5. app/main.py
from fastapi import FastAPI
from app.api.ticket_api import router as ticket_router
from app.db.database import Base, engine
from app.core.config import settings
Base.metadata.create_all(bind=engine)
app = FastAPI(title=settings.app_name)
app.include_router(ticket_router, prefix="/api")
@app.get("/health")
def health_check():
return {
"status": "ok",
"env": settings.app_env
}
6. app/db/database.py
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base
from app.core.config import settings
engine = create_engine(settings.database_url)
SessionLocal = sessionmaker(
autocommit=False,
autoflush=False,
bind=engine
)
Base = declarative_base()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
十、AI 编程中的常见问题与解决方案
1. AI 生成的代码能不能直接用?
不建议直接用于生产环境。AI 生成代码通常有以下问题:
- 依赖版本可能不匹配;
- 异常处理不完整;
- 安全边界不足;
- 数据库事务处理粗糙;
- 缺少测试;
- 对业务规则理解不准确;
- 可能使用已经过时的 API。
正确方式是:让 AI 生成初稿,开发者进行审查、重构、测试和验证。
2. AI 返回内容不是 JSON 怎么办?
这是 AI 应用开发中非常常见的问题。解决方式包括:
- 在 Prompt 中强调“只返回 JSON”;
- 使用更低的 temperature;
- 在系统消息中约束模型行为;
- 对返回内容做清洗;
- 增加 JSON Schema 校验;
- 解析失败时使用兜底逻辑;
- 对关键场景增加人工审核。
在生产环境中,不能假设 AI 永远会按格式返回。
3. 如何控制 AI 调用成本?
AI 调用成本来自多个方面:
- 请求次数;
- 输入 Token;
- 输出 Token;
- 模型单价;
- 重试次数;
- 并发流量。
优化方式包括:
- 精简 Prompt;
- 对相似问题做缓存;
- 对低价值请求不调用大模型;
- 使用较小模型完成简单分类;
- 仅对复杂问题调用高级模型;
- 设置最大输出长度;
- 记录每次调用成本。
例如,对于非常明确的关键词,可以先用规则判断:
如果内容包含“支付成功”“订单未支付”“扣款”等词,可优先归类为支付问题;
如果内容包含“登录”“验证码”“密码”等词,可优先归类为登录问题。
规则能解决的,不一定都要交给大模型。
4. 如何提升分类准确率?
可以从三个方向优化:
第一,优化 Prompt。
把分类标准写得更明确,并给出少量示例。
第二,引入历史数据。
用历史工单和人工标注结果构建评估集,定期测试模型表现。
第三,加入人工反馈闭环。
客服人员可以修改 AI 分类结果,系统记录修改前后的差异,用于后续优化。
AI 系统上线之后,不是“一次开发永久稳定”,而是要持续观察、评估和迭代。
十一、测试建议
AI 编程项目尤其需要测试,因为模型输出有不确定性。测试可以分为两类:
1. 普通接口测试
验证接口是否能正常接收请求、返回响应、写入数据库。
def test_create_ticket(client):
response = client.post("/api/tickets", json={
"user_id": "u10001",
"content": "我已经付款了,但订单状态还是未支付"
})
assert response.status_code == 200
data = response.json()
assert data["user_id"] == "u10001"
assert data["content"] is not None
2. AI 服务测试
AI 服务测试不建议每次都真实调用大模型,因为这样会带来成本、速度和不稳定性问题。更好的方式是使用 Mock。
def test_ai_result_mock(monkeypatch):
def mock_analyze_ticket(content):
return {
"category": "支付问题",
"priority": "高",
"reply": "您好,我们已收到您的支付问题反馈。"
}
monkeypatch.setattr(
"app.services.ai_service.AIService.analyze_ticket",
mock_analyze_ticket
)
result = mock_analyze_ticket("支付成功但订单未更新")
assert result["category"] == "支付问题"
十二、部署与运行
复制环境变量文件:
cp .env.example .env
修改 .env 中的 AI Key 和模型配置。
启动服务:
docker compose up -d
访问健康检查接口:
curl http://localhost:8000/health
提交工单:
curl -X POST http://localhost:8000/api/tickets \
-H "Content-Type: application/json" \
-d '{
"user_id": "u10001",
"content": "我支付成功了,但是订单状态一直没有变化"
}'
如果运行正常,将返回 AI 分析后的分类、优先级和回复建议。
十三、这个案例带来的启发
通过这个案例可以看到,AI 编程的核心不是“让 AI 取代程序员”,而是让 AI 成为开发过程中的高效协作者。
它可以帮助我们:
- 快速生成项目骨架;
- 快速编写样板代码;
- 辅助设计接口和数据表;
- 生成 Prompt 初稿;
- 生成单元测试;
- 编写 README;
- 排查错误日志;
- 优化 SQL 或接口性能;
- 总结代码审查意见。
但同时,开发者仍然必须负责:
- 判断业务规则;
- 设计系统边界;
- 审查代码质量;
- 控制安全风险;
- 处理异常场景;
- 评估模型效果;
- 维护系统长期稳定性。
换句话说,AI 编程提升的是“工程生产力”,而不是取消“工程判断力”。
十四、总结
本文通过“智能工单分类与自动回复系统”这个案例,完整展示了 AI 编程在真实项目中的应用方式。从需求拆解、目录设计、Prompt 编写、接口开发、AI 服务封装,到配置文件、Docker 部署和测试策略,基本覆盖了一个 AI 应用后端项目的核心环节。
如果你正在尝试 AI 编程,建议不要只停留在“让 AI 写一段代码”,而是尝试把 AI 放进完整研发流程中:
- 用 AI 辅助需求分析;
- 用 AI 生成项目结构;
- 用 AI 编写代码初稿;
- 用 AI 补充测试用例;
- 用 AI 解释报错和日志;
- 用 AI 生成文档;
- 最后由开发者进行审查、运行和优化。
真正高效的 AI 编程模式,是“人负责方向与判断,AI 负责辅助与加速”。当我们掌握这种协作方式,开发效率会有明显提升,项目交付质量也会更加稳定。