项目概述
云帆Ai 是一个基于 Flask 后端 + 原生 HTML/CSS/JS 前端构建的多模型 AI 对话平台,对接硅基流动(SiliconFlow)API,聚合 Qwen、DeepSeek、Llama、FLUX 等主流模型。
核心能力:SSE 流式对话、AI 生图、会话管理、积分计费(双模式)、用户体系、公告系统、管理后台。
团队:策划 李子卓 · 代码 戴宇航 · UI 吴炎烽
设计理念
- 零前端框架:纯原生 JS,不依赖 Vue/React,降低维护成本
- JSON 持久化:会话数据存 JSON 文件,用户数据存 SQLite,双轨并行
- SSE 流式:对话使用 Server-Sent Events 实现打字机效果
- 配置驱动:所有行为参数均可后台热更新,无需改代码
技术栈
| 层 | 技术 | 说明 |
|---|---|---|
| 后端框架 | Flask 3.x | 轻量 Web 框架,路由 + 模板渲染 |
| 实时通信 | Flask-SocketIO | 后台实时推送(在线数、日志、统计) |
| 跨域 | Flask-CORS | API 跨域支持 |
| 数据库 | SQLite | 用户、日志、积分流水等结构化数据 |
| 会话存储 | JSON 文件 | 对话消息持久化到 data/chat/ |
| AI 接口 | SiliconFlow API | 兼容 OpenAI 格式的多模型聚合 API |
| 前端 | 原生 HTML/CSS/JS | 无构建工具,无打包步骤 |
| 图标库 | Lucide Icons | 轻量 SVG 图标 |
依赖清单
# requirements.txt
flask>=3.0.0
flask-cors>=4.0.0
flask-socketio>=5.3.0
simple-websocket>=1.0.0
requests>=2.31.0目录结构
环境搭建
1. 安装 Python 依赖
pip install -r requirements.txt2. 配置 API 密钥
首次启动前,编辑 config.json 填入 SiliconFlow API Key:
{
"api_key": "sk-xxxxxxxxxxxxxxxx",
"base_url": "https://api.siliconflow.cn/v1",
"default_model": "deepseek-ai/DeepSeek-V4-Flash"
}3. 启动服务
python app.py默认监听 http://localhost:5000。首次启动自动初始化 SQLite 数据库并创建超级管理员账号。
admin,密码 admin123。请登录后立即在后台修改密码。
配置系统
配置分两层:core/config.py 中的 DEFAULT_CONFIG 为默认值,config.json 为运行时覆盖值。后台保存时合并写入 config.json。
配置结构概览
| 配置段 | 说明 | 关键字段 |
|---|---|---|
(根级) | API 与模型 | api_key, base_url, default_model, system_prompt, max_tokens, temperature |
auth | 认证 | captcha_enabled, password_min_length |
guest | 游客控制 | allow_chat, conversation_limit, credits_per_ip |
credits | 积分计费 | charge_mode, cost_per_message, input_token_price_per_1k, output_token_price_per_1k |
notify | 通知 | mode(dev/sms/email), sms.*, email.* |
diagnostic | AI 自检 | enabled, auto_backup, max_upload_chars |
terms | 服务条款 | login_required, content |
modules | 功能模块 | script.enabled, manga.enabled, image.* |
配置更新白名单
后台 API POST /api/config 只接受白名单内的字段。白名单定义在 app.py 的 nested_allowed 字典中。新增配置字段时需同步更新白名单,否则保存会被忽略。
# app.py 中的白名单示例
nested_allowed = {
"credits": {"enabled", "name", "cost_per_message",
"charge_mode", "input_token_price_per_1k", ...},
"auth": {"captcha_enabled", "password_min_length"},
...
}数据库设计
使用 SQLite,数据库文件 data/aichat.db。建表逻辑在 core/db.py 的 init_db() 中,幂等执行。
表结构
| 表名 | 用途 | 关键字段 |
|---|---|---|
roles | 角色 | code(super_admin/admin/user), level |
users | 用户 | uid, username, password_hash, role_id, credits, status |
verification_codes | 验证码 | target, code, purpose, expires_at |
login_tokens | 登录令牌 | user_id, token, expires_at, revoked |
operation_logs | 操作日志 | user_id, action, target, detail, ip |
access_logs | 访问日志 | path, method, status, duration_ms |
credit_transactions | 积分流水 | user_id, delta, balance_after, reason |
anonymous_quotas | 游客配额 | fingerprint, conversation_count, message_count |
guest_credits | 游客积分 | fingerprint, credits, total_granted |
diagnostic_reports | 自检报告 | health_score, summary, issues_json |
会话存储(JSON)
对话消息不存数据库,而是以 JSON 文件存于 data/chat/{user_uid}/{session_id}.json。每个文件包含完整会话元数据和消息列表。
{
"id": "abc123",
"title": "新建对话",
"category": "chat",
"model": "deepseek-ai/DeepSeek-V4-Flash",
"created_at": "2026-08-09T10:00:00",
"messages": [
{"role": "user", "content": "你好", "created_at": "..."},
{"role": "assistant", "content": "你好!",
"token_usage": {"prompt_tokens": 10, "completion_tokens": 5}}
]
}API 接口
所有 API 返回 JSON,格式:{"ok": true/false, ...data}。需登录的接口通过 Cookie 鉴权,管理员接口需 admin 及以上角色。
对话接口
| 方法 | 路径 | 功能 |
|---|---|---|
| POST | /api/sessions/<id>/messages | 发送消息(SSE 流式返回) |
| GET | /api/sessions | 获取会话列表 |
| POST | /api/sessions | 创建新会话 |
| GET | /api/sessions/<id> | 获取会话详情(含消息) |
| DEL | /api/sessions/<id> | 删除会话 |
| PATCH | /api/sessions/<id> | 更新会话(标题/分类等) |
| POST | /api/upload | 上传文件/图片 |
| GET | /api/uploads/<filename> | 访问上传的文件 |
SSE 事件格式
# 发送消息后,SSE 流式返回以下事件:
event: delta
data: {"text": "你"} # 增量文本
event: done
data: {"text": "你好!", "credits_cost": 1, "prompt_tokens": 10,
"completion_tokens": 5, "charge_mode": "token", "credits": 99}生图接口
| 方法 | 路径 | 功能 |
|---|---|---|
| POST | /api/image/generate | 生成图片(支持 FLUX/SD 等模型) |
用户与积分
| 方法 | 路径 | 功能 |
|---|---|---|
| GET | /api/user/profile | 获取个人信息 |
| PUT | /api/user/profile | 修改个人信息 |
| GET | /api/credits/info | 获取积分余额 + 计费配置 |
| GET | /api/user/credits/transactions | 积分流水明细 |
| POST | /api/user/password | 修改密码 |
公告接口
| 方法 | 路径 | 功能 |
|---|---|---|
| GET | /api/announcements | 获取已启用公告列表 |
| GET | /api/announcements/latest | 获取最新公告 |
| GET | /api/admin/announcements | 管理员:全部公告 |
| POST | /api/admin/announcements | 管理员:创建公告 |
| PUT | /api/admin/announcements/<id> | 管理员:更新公告 |
| DEL | /api/admin/announcements/<id> | 管理员:删除公告 |
管理后台
| 方法 | 路径 | 功能 |
|---|---|---|
| GET | /api/config | 获取系统配置 |
| POST | /api/config | 更新系统配置(按白名单) |
| POST | /api/config/test | 测试 API 连通性 |
| GET | /api/models | 获取可用模型列表 |
| GET | /api/modules | 获取功能模块配置 |
| GET | /api/health | 健康检查 |
用户管理、角色变更等接口在 routes/user_api.py 蓝图中注册。
核心模块
core/config.py — 配置中心
DEFAULT_CONFIG:默认配置字典,包含所有可配置项load_config():加载配置,合并默认值与config.jsonsave_config(cfg):保存配置到config.json- 路径常量:
CHAT_DIR、ANNOUNCEMENTS_PATH等
core/db.py — 数据库
init_db():建表 + 角色种子 + 创建超级管理员(幂等)get_db():获取数据库连接(上下文管理器,自动关闭)- 支持列迁移(
ALTER TABLE ADD COLUMN兼容旧库)
core/dao.py — 数据访问层
- 用户 CRUD:
create_user、get_user_by_*、update_user - 积分操作:
add_credits、deduct_credits、get_credit_transactions - 日志:
log_operation、log_access - 游客:
get_guest_credits、deduct_guest_credits
core/auth.py — 鉴权
login_user(user):创建令牌,写入 Cookielogout_user():吊销令牌current_user():从请求中解析当前用户- 装饰器:
@login_required、@admin_required、@super_admin_required
core/realtime.py — 实时推送
- 基于 Flask-SocketIO,向后台推送实时数据
- 事件:
stats_update(统计)、log_new(新日志)、online_update(在线数)
core/notify.py — 通知服务
- 三种模式:
dev(写日志)、sms(阿里云/腾讯云短信)、email(SMTP 邮件) - 用于注册/登录验证码发送
core/diagnostic.py — AI 自检
- 收集系统状态,调用大模型分析健康度
- 支持自动备份与修复建议
- 安全门控:
diagnostic.enabled = False时严禁上传任何系统信息
计费系统
支持两种扣费模式,后台可随时切换,互不干扰。
模式一:固定积分(fixed)
每次对话扣固定积分:cost_per_message(文本)或 cost_per_image(带图)。简单直观,与消息长度无关。
模式二:Token 换算(token)
按实际输入/输出 Token 数计算积分,更精细:
# 计算公式
cost = ceil( prompt_tokens / 1000 × input_token_price_per_1k
+ completion_tokens / 1000 × output_token_price_per_1k )
# 示例:输入 500 token × 0.3 + 输出 200 token × 1.0
# = 0.15 + 0.2 = 0.35 → 向上取整 = 1 积分关键配置项
| 字段 | 默认值 | 说明 |
|---|---|---|
charge_mode | fixed | 计费模式:fixed / token |
input_token_price_per_1k | 0.3 | 每 1K 输入 Token 的积分数 |
output_token_price_per_1k | 1.0 | 每 1K 输出 Token 的积分数 |
tokens_per_credit | 1000 | 兜底汇率(单价为 0 时使用) |
round_mode | ceil | 取整:ceil / round / floor |
min_credit_cost | 0 | 最低消费兜底 |
image_charge_mode | fixed | 生图独立计费模式 |
image_tokens_per_image | 8000 | 生图 token 模式下每张折算 Token |
核心函数(app.py)
_estimate_tokens_from_text(text):本地估算 Token(中英文混合)_estimate_prompt_tokens(messages):估算 prompt Token(含图片 +1024)calc_chat_credits(cfg, usage, has_image, msgs):对话积分计算calc_image_credits(cfg, count):生图积分计算
usage > 本地估算。SSE 请求会带
stream_options: {include_usage: true} 以获取真实 Token 数。
公告系统
全局公告,用户每天首次打开聊天页自动弹窗。公告数据存于 data/announcements.json。
数据结构
{
"id": "a1b2c3d4e5f6",
"title": "系统升级公告",
"content": "<h3>...</h3>", # 支持 HTML
"created_at": "2026-08-09T10:00:00",
"updated_at": "2026-08-09T10:00:00",
"active": true, # 是否启用
"pinned": false # 是否置顶
}前端去重逻辑
aichat-ann-auto-date:localStorage 记录当天弹窗日期,每天只自动弹一次aichat-ann-read-ids:localStorage 记录已读公告 ID,控制红点显示
<script>、<iframe>、on* 事件属性,防止 XSS。
前端架构
纯原生 JS,无框架无构建。所有页面通过 Jinja2 模板渲染,JS 文件通过 <script> 标签引入。
JS 文件职责
| 文件 | 职责 |
|---|---|
utils.js | 公共工具:$() 选择器、api() 请求封装、toast() 提示、escapeHtml()、refreshIcons() |
chat.js | 对话页全部逻辑:消息收发、SSE 解析、会话管理、生图、公告、积分展示 |
admin.js | 后台管理:用户管理、配置编辑、公告 CRUD、自检、日志 |
auth.js | 登录/注册页逻辑 |
profile.js | 个人中心:信息修改、积分明细 |
theme.js | 深浅色主题切换(localStorage 持久化) |
home-orbit.js | 首页轨道动画 |
CSS 架构
全站样式集中在 static/css/style.css,通过 CSS 变量实现深浅色双主题。关键变量:
/* 深色(默认)*/
--bg: #0d1117; /* 页面背景 */
--bg-elevated: #161b22; /* 卡片背景 */
--text: #e6edf3; /* 主文字 */
--accent: #6366f1; /* 主题色 */
--border: #30363d; /* 边框 */
/* 浅色 */
[data-theme="light"] { --bg: #ffffff; --text: #1f2328; ... }?v=日期 控制缓存。修改 JS/CSS 后需同步更新 HTML 中的版本号,否则浏览器加载旧文件。
鉴权机制
登录流程
- 用户提交用户名+密码 → 后端校验
password_hash(Werkzeug 生成/验证) - 验证通过 → 生成随机
token存入login_tokens表,设置 Cookie(7天有效) - 后续请求通过 Cookie 中的 token 解析当前用户
角色体系
| 角色 code | 名称 | 权限 |
|---|---|---|
super_admin | 超级管理员 | 全部权限 + 用户删除 + 角色变更 |
admin | 管理员 | 后台管理 + 用户状态管理 + 积分调整 |
user | 普通用户 | 对话、生图、个人信息 |
游客模式
未登录用户可有限使用对话功能,受 guest 配置控制:
guest.allow_chat:是否允许游客对话guest.conversation_limit:最大会话数guest.message_limit_per_session:单会话消息上限guest.credits_per_ip:每 IP 游客积分配额
生产部署
推荐方式
# 1. 安装依赖
pip install -r requirements.txt
# 2. 初始化配置(首次)
# 编辑 config.json 填入 api_key、修改 admin_password
# 3. 启动(开发)
python app.py
# 4. 生产环境建议用 gunicorn + eventlet
pip install gunicorn eventlet
gunicorn -w 1 -k eventlet -b 0.0.0.0:5000 app:app- SocketIO 需要
eventlet或geventworker,-w 1单进程 - 生产环境务必修改
admin_password - 定期备份
data/目录(含 SQLite + 会话 JSON) - 反代时需配置 WebSocket 支持(Nginx:
proxy_set_header Upgrade $http_upgrade)
Nginx 反代参考
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /socket.io/ {
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}