从零上线一个 AI 小工具:FastAPI、Docker 到服务器部署全流程源码实战
AI工具 部署完整教程|附源码
随着大模型技术的快速发展,越来越多企业和个人开发者开始尝试将 AI 能力接入自己的业务系统中。例如:智能客服、知识库问答、文案生成、代码助手、简历优化、合同分析、数据报表解读等场景,都可以通过 AI 工具实现自动化和智能化。
本文将从零开始,带你完成一个 AI 工具 Web 应用 的完整部署流程。该工具支持用户在网页中输入问题,后端调用大模型接口生成回答,并返回给前端展示。文章包含项目结构、源码示例、本地运行、Docker 部署、服务器上线、环境变量配置以及常见问题排查。
本文适合以下读者:
- 想学习 AI 应用开发的初学者;
- 想快速搭建 AI 问答工具的开发者;
- 想将大模型能力集成进业务系统的团队;
- 想了解 FastAPI + 前端 + Docker 部署流程的人。
一、项目效果说明
我们要实现的 AI 工具主要包含以下功能:
- 用户在网页输入问题;
- 前端将问题发送给后端 API;
- 后端读取环境变量中的 API Key;
- 后端调用大模型接口;
- 返回 AI 生成的结果;
- 前端展示回答内容;
- 支持 Docker 一键部署;
- 支持服务器生产环境运行。
最终效果类似一个简单版 ChatGPT:
用户:请帮我写一段产品介绍文案
AI:当然可以,以下是一段适合电商平台使用的产品介绍文案……
为了让教程更容易理解,我们使用以下技术栈:
| 模块 | 技术 |
|---|---|
| 后端框架 | FastAPI |
| 服务运行 | Uvicorn |
| 前端页面 | HTML + CSS + JavaScript |
| 接口调用 | OpenAI 兼容 API |
| 环境变量 | python-dotenv |
| 部署方式 | Docker / Docker Compose |
| 服务器环境 | Ubuntu 22.04 |
说明:本文示例采用 OpenAI 兼容格式接口。如果你使用的是其他大模型服务,例如通义千问、DeepSeek、智谱、月之暗面、硅基流动等,只要服务商提供 OpenAI 兼容接口,通常只需要替换
BASE_URL、API_KEY和MODEL_NAME即可。
二、项目目录结构
首先创建项目目录:
mkdir ai-tool-demo
cd ai-tool-demo
推荐的项目结构如下:
ai-tool-demo
├── app
│ ├── main.py
│ ├── ai_client.py
│ └── schemas.py
├── static
│ ├── index.html
│ ├── style.css
│ └── app.js
├── .env.example
├── requirements.txt
├── Dockerfile
├── docker-compose.yml
└── README.md
各文件作用说明:
| 文件 | 作用 |
|---|---|
main.py |
FastAPI 主程序入口 |
ai_client.py |
封装 AI 接口调用逻辑 |
schemas.py |
请求和响应数据模型 |
index.html |
前端页面 |
style.css |
页面样式 |
app.js |
前端交互逻辑 |
.env.example |
环境变量示例 |
requirements.txt |
Python 依赖 |
Dockerfile |
Docker 镜像构建文件 |
docker-compose.yml |
Docker Compose 部署配置 |
三、后端源码编写
1. 安装依赖文件
创建 requirements.txt:
fastapi==0.115.0
uvicorn[standard]==0.30.6
python-dotenv==1.0.1
openai==1.45.0
pydantic==2.8.2
这里使用 openai 官方 SDK,因为很多模型服务都兼容 OpenAI 格式。
2. 编写数据模型
创建 app/schemas.py:
from pydantic import BaseModel, Field
class ChatRequest(BaseModel):
message: str = Field(..., min_length=1, description="用户输入的问题")
class ChatResponse(BaseModel):
answer: str = Field(..., description="AI 返回的回答")
该文件用于定义 API 请求和响应结构。
ChatRequest 表示用户请求,必须包含 message 字段。
ChatResponse 表示 AI 返回结果,包含 answer 字段。
使用 Pydantic 可以让 FastAPI 自动完成参数校验和接口文档生成。
3. 封装 AI 调用逻辑
创建 app/ai_client.py:
import os
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.getenv("AI_API_KEY")
BASE_URL = os.getenv("AI_BASE_URL")
MODEL_NAME = os.getenv("AI_MODEL_NAME", "gpt-4o-mini")
if not API_KEY:
raise RuntimeError("缺少环境变量 AI_API_KEY,请检查 .env 配置")
if not BASE_URL:
raise RuntimeError("缺少环境变量 AI_BASE_URL,请检查 .env 配置")
client = OpenAI(
api_key=API_KEY,
base_url=BASE_URL
)
def ask_ai(message: str) -> str:
"""
调用大模型接口并返回文本结果
"""
system_prompt = """
你是一个专业、耐心、表达清晰的 AI 助手。
请使用中文回答用户问题。
如果用户要求写作,请尽量给出结构清晰、可直接使用的内容。
如果用户要求技术方案,请给出步骤、代码或示例。
"""
try:
response = client.chat.completions.create(
model=MODEL_NAME,
messages=[
{
"role": "system",
"content": system_prompt
},
{
"role": "user",
"content": message
}
],
temperature=0.7,
max_tokens=1200
)
answer = response.choices[0].message.content
return answer or "AI 未返回有效内容"
except Exception as e:
return f"调用 AI 服务失败:{str(e)}"
该文件主要做三件事:
- 从环境变量中读取 API 配置;
- 初始化 OpenAI 客户端;
- 封装
ask_ai方法供接口调用。
需要注意的是,不建议将 API Key 直接写死在代码里。生产环境中应通过环境变量或密钥管理服务注入。
4. 编写 FastAPI 主程序
创建 app/main.py:
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
from app.schemas import ChatRequest, ChatResponse
from app.ai_client import ask_ai
app = FastAPI(
title="AI Tool Demo",
description="一个简单的 AI 工具部署示例",
version="1.0.0"
)
@app.get("/health")
def health_check():
return {
"status": "ok",
"message": "AI Tool service is running"
}
@app.post("/api/chat", response_model=ChatResponse)
def chat(request: ChatRequest):
answer = ask_ai(request.message)
return ChatResponse(answer=answer)
app.mount("/static", StaticFiles(directory="static"), name="static")
@app.get("/")
def index():
return FileResponse("static/index.html")
这里提供了三个入口:
| 路径 | 方法 | 说明 |
|---|---|---|
/ |
GET | 访问前端页面 |
/api/chat |
POST | AI 问答接口 |
/health |
GET | 健康检查接口 |
FastAPI 启动后,还会自动生成接口文档:
http://localhost:8000/docs
四、前端源码编写
1. HTML 页面
创建 static/index.html:
AI 工具 Demo
AI 智能助手
输入你的问题,AI 将为你生成回答
2. CSS 样式
创建 static/style.css:
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
background: #f4f6fb;
color: #222;
}
.container {
max-width: 900px;
margin: 0 auto;
padding: 24px;
}
header {
text-align: center;
margin-bottom: 24px;
}
header h1 {
margin-bottom: 8px;
font-size: 32px;
}
header p {
color: #666;
}
main {
background: #fff;
border-radius: 16px;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
overflow: hidden;
}
.chat-box {
height: 520px;
padding: 20px;
overflow-y: auto;
border-bottom: 1px solid #eee;
}
.message {
max-width: 80%;
margin-bottom: 16px;
padding: 12px 14px;
line-height: 1.7;
border-radius: 12px;
white-space: pre-wrap;
}
.message.user {
margin-left: auto;
background: #1677ff;
color: #fff;
}
.message.ai {
margin-right: auto;
background: #f0f2f5;
color: #222;
}
.input-area {
display: flex;
gap: 12px;
padding: 16px;
}
textarea {
flex: 1;
height: 80px;
resize: none;
border: 1px solid #ddd;
border-radius: 10px;
padding: 12px;
font-size: 15px;
outline: none;
}
textarea:focus {
border-color: #1677ff;
}
button {
width: 100px;
border: none;
border-radius: 10px;
background: #1677ff;
color: #fff;
font-size: 16px;
cursor: pointer;
}
button:hover {
background: #0958d9;
}
button:disabled {
background: #aaa;
cursor: not-allowed;
}
3. JavaScript 交互逻辑
创建 static/app.js:
const chatBox = document.getElementById("chatBox");
const messageInput = document.getElementById("messageInput");
const sendBtn = document.getElementById("sendBtn");
function appendMessage(content, role) {
const div = document.createElement("div");
div.className = `message ${role}`;
div.textContent = content;
chatBox.appendChild(div);
chatBox.scrollTop = chatBox.scrollHeight;
}
async function sendMessage() {
const message = messageInput.value.trim();
if (!message) {
alert("请输入问题");
return;
}
appendMessage(message, "user");
messageInput.value = "";
sendBtn.disabled = true;
sendBtn.textContent = "生成中";
appendMessage("AI 正在思考中,请稍候……", "ai");
const loadingNode = chatBox.lastChild;
try {
const response = await fetch("/api/chat", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
message: message
})
});
const data = await response.json();
if (!response.ok) {
loadingNode.textContent = "请求失败,请稍后重试";
return;
}
loadingNode.textContent = data.answer;
} catch (error) {
loadingNode.textContent = "网络异常,请检查服务是否正常运行";
} finally {
sendBtn.disabled = false;
sendBtn.textContent = "发送";
}
}
sendBtn.addEventListener("click", sendMessage);
messageInput.addEventListener("keydown", function (event) {
if (event.key === "Enter" && !event.shiftKey) {
event.preventDefault();
sendMessage();
}
});
到这里,一个最基础的 AI 工具前后端代码已经完成。
五、配置环境变量
创建 .env.example:
AI_API_KEY=你的API_KEY
AI_BASE_URL=https://api.openai.com/v1
AI_MODEL_NAME=gpt-4o-mini
本地运行时复制一份:
cp .env.example .env
然后编辑 .env:
AI_API_KEY=sk-xxxxxxxxxxxxxxxx
AI_BASE_URL=https://api.openai.com/v1
AI_MODEL_NAME=gpt-4o-mini
如果你使用其他兼容 OpenAI 的模型服务,配置可能类似:
AI_API_KEY=你的服务商密钥
AI_BASE_URL=https://api.deepseek.com
AI_MODEL_NAME=deepseek-chat
或者:
AI_API_KEY=你的密钥
AI_BASE_URL=https://api.siliconflow.cn/v1
AI_MODEL_NAME=Qwen/Qwen2.5-72B-Instruct
注意:不同平台的 BASE_URL 格式可能略有区别,有的需要 /v1,有的不需要,应以服务商文档为准。
六、本地运行项目
1. 创建虚拟环境
python3 -m venv venv
激活虚拟环境:
macOS / Linux:
source venv/bin/activate
Windows:
venv\Scripts\activate
2. 安装依赖
pip install -r requirements.txt
3. 启动服务
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
看到类似输出表示启动成功:
Uvicorn running on http://0.0.0.0:8000
访问:
http://localhost:8000
接口文档:
http://localhost:8000/docs
测试健康检查:
curl http://localhost:8000/health
返回:
{
"status": "ok",
"message": "AI Tool service is running"
}
七、使用 Docker 部署
本地运行虽然方便,但生产环境通常推荐使用 Docker。Docker 可以把代码、依赖和运行环境打包,减少“我电脑能跑,服务器不能跑”的问题。
1. 编写 Dockerfile
创建 Dockerfile:
FROM python:3.11-slim
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
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"]
说明:
python:3.11-slim:使用轻量 Python 镜像;WORKDIR /app:设置容器工作目录;COPY requirements.txt .:先复制依赖文件;pip install:安装依赖;COPY . .:复制项目源码;EXPOSE 8000:声明服务端口;CMD:容器启动命令。
2. 编写 docker-compose.yml
创建 docker-compose.yml:
version: "3.9"
services:
ai-tool:
build: .
container_name: ai-tool-demo
ports:
- "8000:8000"
env_file:
- .env
restart: always
3. 构建并启动
docker compose up -d --build
查看容器状态:
docker ps
查看日志:
docker logs -f ai-tool-demo
访问:
http://服务器IP:8000
如果是本机 Docker,则访问:
http://localhost:8000
停止服务:
docker compose down
重启服务:
docker compose restart
八、服务器部署完整流程
下面以 Ubuntu 22.04 服务器为例。
1. 登录服务器
ssh root@你的服务器IP
2. 更新系统
apt update && apt upgrade -y
3. 安装 Docker
curl -fsSL https://get.docker.com | bash
启动 Docker:
systemctl enable docker
systemctl start docker
检查版本:
docker --version
4. 安装 Docker Compose
新版 Docker 通常已经集成 compose 插件,可以执行:
docker compose version
如果没有,可以参考官方文档安装。
5. 上传项目代码
方式一:使用 Git 拉取:
git clone https://你的仓库地址/ai-tool-demo.git
cd ai-tool-demo
方式二:使用 scp 上传:
scp -r ai-tool-demo root@服务器IP:/opt/
然后进入目录:
cd /opt/ai-tool-demo
6. 配置环境变量
cp .env.example .env
vim .env
填写真实配置:
AI_API_KEY=你的真实API_KEY
AI_BASE_URL=https://api.openai.com/v1
AI_MODEL_NAME=gpt-4o-mini
7. 启动服务
docker compose up -d --build
检查服务:
docker ps
curl http://127.0.0.1:8000/health
如果返回 status: ok,说明部署成功。
九、配置 Nginx 反向代理
如果你希望通过域名访问,例如:
https://ai.example.com
建议使用 Nginx 反向代理。
1. 安装 Nginx
apt install nginx -y
2. 创建站点配置
vim /etc/nginx/sites-available/ai-tool
写入:
server {
listen 80;
server_name ai.example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
启用配置:
ln -s /etc/nginx/sites-available/ai-tool /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
3. 配置 HTTPS
安装 Certbot:
apt install certbot python3-certbot-nginx -y
申请证书:
certbot --nginx -d ai.example.com
按提示完成后,即可通过 HTTPS 访问。
十、生产环境优化建议
基础版本部署完成后,如果要用于正式业务,还需要考虑以下优化。
1. 增加接口鉴权
当前 /api/chat 是公开接口,任何人都可以调用。如果部署到公网,可能导致 API Key 被间接滥用,产生高额费用。
可以增加简单 Token 鉴权:
from fastapi import Header, HTTPException
import os
ACCESS_TOKEN = os.getenv("ACCESS_TOKEN")
def verify_token(authorization: str = Header(None)):
if not ACCESS_TOKEN:
return
if authorization != f"Bearer {ACCESS_TOKEN}":
raise HTTPException(status_code=401, detail="Unauthorized")
然后在接口中加入依赖:
from fastapi import Depends
@app.post("/api/chat", response_model=ChatResponse)
def chat(request: ChatRequest, auth=Depends(verify_token)):
answer = ask_ai(request.message)
return ChatResponse(answer=answer)
2. 增加请求频率限制
为了防止恶意刷接口,可以使用 Nginx 限流,也可以在应用层使用 Redis 记录用户请求次数。
Nginx 示例:
limit_req_zone $binary_remote_addr zone=ai_limit:10m rate=10r/m;
server {
listen 80;
server_name ai.example.com;
location /api/chat {
limit_req zone=ai_limit burst=5 nodelay;
proxy_pass http://127.0.0.1:8000;
}
}
3. 记录日志
建议记录每次请求的时间、用户 IP、模型名称、消耗 token、错误信息等,便于后续分析成本和排查问题。
4. 支持流式输出
当前示例是一次性返回完整答案。如果答案较长,用户需要等待较久。生产环境中可以使用 SSE 或 WebSocket 实现流式输出,让 AI 边生成边显示,体验更接近 ChatGPT。
5. 接入数据库
如果需要保存聊天记录,可以接入 PostgreSQL、MySQL 或 MongoDB。基本表结构可以包含:
| 字段 | 含义 |
|---|---|
| id | 主键 |
| user_id | 用户 ID |
| question | 用户问题 |
| answer | AI 回答 |
| model | 模型名称 |
| created_at | 创建时间 |
6. 增加知识库能力
如果你想让 AI 根据企业文档回答问题,可以进一步接入 RAG 架构:
- 上传 PDF、Word、Markdown 等文档;
- 将文档切分成多个片段;
- 使用 Embedding 模型生成向量;
- 存入向量数据库;
- 用户提问时先检索相关内容;
- 将检索结果和问题一起发送给大模型;
- 大模型基于知识库生成回答。
常见向量数据库包括:
- Milvus;
- Qdrant;
- Weaviate;
- pgvector;
- Chroma。
十一、常见问题排查
1. 启动时报错:缺少 AI_API_KEY
原因是没有配置 .env 文件,或者 Docker 没有正确加载环境变量。
解决方法:
cat .env
docker compose down
docker compose up -d --build
确认 docker-compose.yml 中包含:
env_file:
- .env
2. 接口返回调用 AI 服务失败
可能原因包括:
- API Key 错误;
- Base URL 错误;
- 模型名称不存在;
- 服务商余额不足;
- 网络无法访问服务商接口;
- 请求参数不兼容。
可以先用 curl 测试服务商接口,确认 Key 和地址是否可用。
3. 页面可以打开,但发送无响应
检查浏览器控制台和后端日志:
docker logs -f ai-tool-demo
也可以直接测试接口:
curl -X POST http://127.0.0.1:8000/api/chat \
-H "Content-Type: application/json" \
-d '{"message":"你好,请介绍一下你自己"}'
4. 服务器 IP 无法访问
检查安全组和防火墙:
ufw status
如果需要开放 8000 端口:
ufw allow 8000
如果使用云服务器,还需要在云厂商控制台放行端口。
5. Nginx 配置后访问 502
502 通常表示 Nginx 无法连接后端服务。
检查后端是否运行:
docker ps
curl http://127.0.0.1:8000/health
检查 Nginx 配置:
nginx -t
systemctl status nginx
十二、README 示例
可以创建一个简单的 README.md,方便团队成员使用:
# AI Tool Demo
一个基于 FastAPI 的 AI 工具部署示例。
## 功能
- AI 问答
- Web 页面访问
- Docker 部署
- OpenAI 兼容接口
## 本地运行
```bash
cp .env.example .env
pip install -r requirements.txt
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
Docker 部署
docker compose up -d --build
环境变量
AI_API_KEY=你的API_KEY
AI_BASE_URL=https://api.openai.com/v1
AI_MODEL_NAME=gpt-4o-mini
---
## 十三、完整源码汇总
为了方便复制,这里再次列出关键源码。
### `app/main.py`
```python
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
from app.schemas import ChatRequest, ChatResponse
from app.ai_client import ask_ai
app = FastAPI(title="AI Tool Demo")
@app.get("/health")
def health_check():
return {"status": "ok"}
@app.post("/api/chat", response_model=ChatResponse)
def chat(request: ChatRequest):
answer = ask_ai(request.message)
return ChatResponse(answer=answer)
app.mount("/static", StaticFiles(directory="static"), name="static")
@app.get("/")
def index():
return FileResponse("static/index.html")
app/ai_client.py
import os
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
client = OpenAI(
api_key=os.getenv("AI_API_KEY"),
base_url=os.getenv("AI_BASE_URL")
)
MODEL_NAME = os.getenv("AI_MODEL_NAME", "gpt-4o-mini")
def ask_ai(message: str) -> str:
response = client.chat.completions.create(
model=MODEL_NAME,
messages=[
{"role": "system", "content": "你是一个专业的中文 AI 助手。"},
{"role": "user", "content": message}
],
temperature=0.7
)
return response.choices[0].message.content
app/schemas.py
from pydantic import BaseModel
class ChatRequest(BaseModel):
message: str
class ChatResponse(BaseModel):
answer: str
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"]
docker-compose.yml
version: "3.9"
services:
ai-tool:
build: .
container_name: ai-tool-demo
ports:
- "8000:8000"
env_file:
- .env
restart: always
十四、总结
本文从零开始完成了一个 AI 工具的开发与部署,涵盖了后端接口、前端页面、环境变量、本地运行、Docker 打包、服务器部署、Nginx 反向代理、HTTPS 配置以及生产环境优化建议。
这个项目虽然简单,但已经具备一个 AI 应用的基本雏形。你可以基于它继续扩展更多能力,例如:
- 增加登录注册;
- 增加聊天历史;
- 增加流式输出;
- 增加知识库问答;
- 增加图片生成;
- 增加文件上传分析;
- 增加多模型切换;
- 增加后台管理系统。
如果你只是想快速上线一个 AI 工具,那么本文的源码已经足够作为最小可用版本。如果你希望做成商业化产品,则需要进一步完善权限控制、计费系统、日志监控、数据安全和模型成本管理。
AI 应用开发的核心不只是“调用一个模型接口”,更重要的是围绕真实业务场景设计稳定、可用、可扩展的系统。希望这篇教程能帮助你快速完成第一个 AI 工具的部署。