上一篇 下一篇 分享链接 返回 返回顶部

从零上线一个 AI 小工具:FastAPI、Docker 到服务器部署全流程源码实战

发布人:慈云数据-客服中心 发布时间:23小时前 阅读量:6

AI工具 部署完整教程|附源码

随着大模型技术的快速发展,越来越多企业和个人开发者开始尝试将 AI 能力接入自己的业务系统中。例如:智能客服、知识库问答、文案生成、代码助手、简历优化、合同分析、数据报表解读等场景,都可以通过 AI 工具实现自动化和智能化。

本文将从零开始,带你完成一个 AI 工具 Web 应用 的完整部署流程。该工具支持用户在网页中输入问题,后端调用大模型接口生成回答,并返回给前端展示。文章包含项目结构、源码示例、本地运行、Docker 部署、服务器上线、环境变量配置以及常见问题排查。

本文适合以下读者:

  • 想学习 AI 应用开发的初学者;
  • 想快速搭建 AI 问答工具的开发者;
  • 想将大模型能力集成进业务系统的团队;
  • 想了解 FastAPI + 前端 + Docker 部署流程的人。

一、项目效果说明

我们要实现的 AI 工具主要包含以下功能:

  1. 用户在网页输入问题;
  2. 前端将问题发送给后端 API;
  3. 后端读取环境变量中的 API Key;
  4. 后端调用大模型接口;
  5. 返回 AI 生成的结果;
  6. 前端展示回答内容;
  7. 支持 Docker 一键部署;
  8. 支持服务器生产环境运行。

最终效果类似一个简单版 ChatGPT:

用户:请帮我写一段产品介绍文案
AI:当然可以,以下是一段适合电商平台使用的产品介绍文案……

为了让教程更容易理解,我们使用以下技术栈:

模块 技术
后端框架 FastAPI
服务运行 Uvicorn
前端页面 HTML + CSS + JavaScript
接口调用 OpenAI 兼容 API
环境变量 python-dotenv
部署方式 Docker / Docker Compose
服务器环境 Ubuntu 22.04

说明:本文示例采用 OpenAI 兼容格式接口。如果你使用的是其他大模型服务,例如通义千问、DeepSeek、智谱、月之暗面、硅基流动等,只要服务商提供 OpenAI 兼容接口,通常只需要替换 BASE_URLAPI_KEYMODEL_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)}"

该文件主要做三件事:

  1. 从环境变量中读取 API 配置;
  2. 初始化 OpenAI 客户端;
  3. 封装 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 将为你生成回答

你好,我是 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 架构:

  1. 上传 PDF、Word、Markdown 等文档;
  2. 将文档切分成多个片段;
  3. 使用 Embedding 模型生成向量;
  4. 存入向量数据库;
  5. 用户提问时先检索相关内容;
  6. 将检索结果和问题一起发送给大模型;
  7. 大模型基于知识库生成回答。

常见向量数据库包括:

  • 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 工具的部署。

目录结构
全文