基于 Flask 的全栈 Web 应用,集成 AI 图像生成、360° 全景浏览、校园地图探索、多轮对话设计 Agent(含语音输入)与创意设计社区。
| 模块 | 说明 |
|---|---|
主应用 (sigs.html) |
地图选点 → 全景漫游 / 设计模式 → AI Agent 引导 → 后台生图 → 分享社区 |
| AI 设计 Agent | 多模态 LLM 分析全景图,三轮对话收集设计意图,支持语音输入(Web Speech API) |
| 社区 | 登录发帖、点赞、分页浏览;作品图片持久保存在 static/converted/ |
| 我的作品 | 后台任务轮询,状态:generating / done / failed |
| 研究者入口 | 研究者账号可发布对比作品(原图 + 生成图) |
| 独立工具页 | GPT-Image-2 生图、NanoBanana2 超分、格式转换、单图全景、地图页 |
image_test/
├── app.py # Flask 主程序(路由 + 业务逻辑)
├── config.py # 全局配置(API、目录、LLM)
├── database.py # SQLite 数据层(用户、帖子、项目、问卷)
├── rate_limit.py # 跨进程/跨平台限流(Windows 用线程锁,Linux 用 fcntl)
├── async_tasks.py # 后台线程池(LLM 异步调用、任务状态文件)
├── migrate_data.py # 一次性迁移:data/*.json → SQLite
├── wsgi.py # Gunicorn 入口
├── gunicorn_config.py # 生产环境配置
├── test_changes.py # 本地模块自检脚本
├── requirements.txt
├── .env / .env.example
├── data/ # 运行时数据(git 忽略)
│ ├── app.db # SQLite 主库
│ ├── .secret_key # Session 密钥(未配置 FLASK_SECRET_KEY 时自动生成)
│ ├── agent_sessions/ # Agent 对话会话 JSON
│ ├── async_tasks/ # 异步任务状态 JSON
│ └── rate_limits/ # 限流计数文件
├── static/ # 用户生成与上传的图片(不自动删除)
│ ├── uploads/
│ ├── converted/ # 生图结果 JPG(社区 image_url 多指向此处)
│ ├── panorama/
│ └── results/
├── panorama_images/ # 校园实景 166 张全景 + coordinates.csv
├── assets/ # Leaflet 等静态资源
└── templates/
├── sigs.html # 主 SPA(默认首页 /)
├── index.html # /generate — GPT-Image-2
├── nano.html # /nano — NanoBanana2
├── convert.html # /convert
├── panorama.html # /panorama
└── map.html # /map
- Python 3.10+
- 推荐浏览器:Chrome / Edge(Agent 语音输入、Web Speech API)
- 速创 API 密钥:api.wuyinkeji.com
- 可选:兼容 OpenAI Chat Completions 的多模态 LLM(Agent 对话)
# 1. 安装依赖
pip install -r requirements.txt
# 2. 配置环境变量
cp .env.example .env编辑 .env:
# 必填:速创图像 API
SUCHUANG_API_KEY=你的密钥
# 必填:Agent 多模态对话(OpenAI 兼容接口)
LLM_API_KEY=你的_LLM_密钥
LLM_BASE_URL=https://你的服务地址/v1
LLM_MODEL=模型名称
# 可选:固定 Session 密钥(多机部署时建议设置)
# FLASK_SECRET_KEY=随机长字符串# 3. 若从旧版 JSON 数据升级,执行一次迁移
python migrate_data.py
# 4. 启动开发服务器
python app.py
# 访问 http://127.0.0.1:5000gunicorn -c gunicorn_config.py wsgi:app默认绑定 127.0.0.1:5003(见 gunicorn_config.py),可按需修改。
| 路由 | 页面 | 说明 |
|---|---|---|
/ |
sigs.html |
主应用(欢迎 / 地图 / 社区 / 研究者) |
/generate |
index.html |
GPT-Image-2 图生图 |
/nano |
nano.html |
NanoBanana2 超分 |
/convert |
convert.html |
URL 图片转 JPG |
/panorama |
panorama.html |
单图 360° 查看 |
/map |
map.html |
校园地图 + 全景 |
/sigs |
sigs.html |
同主应用 |
| 模型 | 提交 | 查询 |
|---|---|---|
| GPT-Image-2 | POST /api/generate |
GET /api/result/<task_id> |
| NanoBanana2 | POST /api/nano/generate |
GET /api/nano/result/<task_id> |
任务状态:2 = 完成,3 = 失败。结果 PNG 会自动转为 JPG 存于 static/converted/。
| 路由 | 方法 | 说明 |
|---|---|---|
/api/auth/register |
POST | 注册 |
/api/auth/login |
POST | 登录(Session Cookie) |
/api/auth/logout |
POST | 登出 |
/api/auth/me |
GET | 当前用户(含 admin、researcher、survey_completed) |
旧版 users.json 中的 SHA256 密码在首次登录时会自动升级为 bcrypt。
| 路由 | 方法 | 说明 |
|---|---|---|
/api/agent/chat |
POST | action: start / reply / revise / confirm / poll |
start/reply/revise:提交后返回async_task_id,前端轮询poll直至completed- 需配置
LLM_API_KEY、LLM_BASE_URL、LLM_MODEL - 限流:
agent10 次/分钟;agent_poll60 次/分钟(按 IP)
| 路由 | 方法 | 说明 |
|---|---|---|
/api/carbon/compare |
POST | 提交改造前/后图片 URL,返回 async_task_id |
/api/carbon/compare/<task_id> |
GET | 轮询评估结果 |
请求体示例:
{
"before_image_url": "/panorama_images/panorama_images_XXX/1.jpg",
"after_image_url": "/static/converted/abc.jpg",
"design_prompt": "生态花园改造…",
"lang": "cn"
}返回 result 含:is_more_eco_friendly、eco_improvement_score、estimated_carbon_reduction_percent、estimated_annual_co2_reduction_kg、dimensions、key_changes 等(LLM 估算,非实测 LCA)。
测试页:浏览器打开 http://127.0.0.1:5000/carbon-test — 登录后可填前后图 URL、一键分析并查看结果。
| 路由 | 方法 | 认证 | 说明 |
|---|---|---|---|
/api/community/posts |
GET | 可选 | 分页列表,登录用户含 liked_by_me |
/api/community/posts |
POST | 是 | 发帖 |
/api/community/posts/<id> |
PUT | 作者 | 更新 image_url |
/api/community/posts/<id> |
DELETE | 管理员 | 删帖(不删除磁盘图片) |
/api/community/posts/<id>/like |
POST | 是 | 点赞 |
/api/community/posts/<id>/unlike |
POST | 是 | 取消点赞 |
/api/community/my-posts |
GET | 是 | 我的帖子 |
/api/community/posts/by-panorama |
GET | 否 | 按全景 URL 查作品 |
| 路由 | 方法 | 说明 |
|---|---|---|
/api/projects |
POST | 提交生图任务(FormData: prompt, panorama_file_url 等) |
/api/projects |
GET | 分页列表 |
/api/projects/<id>/status |
GET | 轮询状态,服务端会查询速创 API 并更新 DB |
/api/projects/<id> |
DELETE | 删除项目记录 |
| 路由 | 方法 | 说明 |
|---|---|---|
/api/researcher/posts |
GET | 研究者作品列表(原图 + 生成图对比) |
/api/admin/users |
GET | 用户列表(管理员) |
/api/admin/users/<username>/researcher |
PUT | 设置研究者身份 |
| 路由 | 说明 |
|---|---|
/api/map/points |
166 个校园点 [{id, lat, lon, image_url}] |
/api/upload |
上传参考图 |
/api/panorama/upload |
上传用户全景 |
/api/convert |
JSON {"url":"..."} 下载并转 JPG |
/thumb/<path> |
缩略图 WebP 缓存 |
/panorama_images/<path> |
校园实景原图 |
GET /api/community/posts/by-panorama?panorama_url=/panorama_images/panorama_images_ZWCZZTYBJ9/12.jpg{
"panorama_url": "/panorama_images/panorama_images_ZWCZZTYBJ9/12.jpg",
"posts": [{ "id", "author", "prompt", "image_url", "likes", ... }],
"count": 1
}无需登录。image_url 通常为 /static/converted/<uuid>.jpg。
- 社区作品图片不会自动删除。历史定时清理
static/uploads|panorama|converted的逻辑已禁用(_cleanup_temp_files()为空操作)。 - 管理员删帖仅删除数据库记录,磁盘文件保留。
- 生图结果持久化在
static/converted/,社区缩略图通过/thumb/...访问。
速创 API 的 urls 参数需要公网 HTTP URL。本地参考图上传顺序:
- 主图床:
litterbox.catbox.moe(约 1 小时有效,国内可访问) - 备用:
tmpfiles.org
若出现 image upload failed, please check the image,多为图床 URL 无法被速创服务器拉取,可重试或检查网络。
- 用户 / 帖子 / 点赞 / 项目 / 问卷:SQLite
data/app.db(WAL 模式,支持多 worker) - Agent 会话:
data/agent_sessions/*.json - LLM 异步任务:
data/async_tasks/*.json+ 线程池
- Agent「小清」通过 OpenAI 兼容接口分析全景图并多轮引导设计。
- 前端
callAgentAsync在收到session_id后立即用于轮询,避免空 session 导致 400。 - 输入框旁 🎤 按钮:基于浏览器 Web Speech API,语言随界面中/英切换(
zh-CN/en-US),Chrome/Edge 可用。
#welcome → 登录/注册 → 地图选点 → 设计模式 → Agent 对话(可语音)
→ 确认生成 → POST /api/projects → 轮询 status
→ 完成:全景展示生成图 → 分享到社区
#community → 浏览 / 点赞 / 全景查看
#researcher → 研究者专属发布与浏览(需 researcher 权限)
- 目录:
panorama_images/ - 约 166 张等距柱状投影图,坐标见
coordinates.csv - 路径规则:
/panorama_images/panorama_images_{SET_ID}/{NUM}.jpg
python test_changes.py若 data/ 下仍有 users.json、community_posts.json 等:
python migrate_data.py迁移时:bcrypt 密码原样保留;64 位十六进制视为旧版 SHA256,登录时自动升级;明文密码会立即 bcrypt 哈希。
rate_limit.py在 Windows 上使用threading.Lock(开发单进程可用);Linux 生产环境使用fcntl跨 worker 锁。- 避免同时启动多个
python app.py占用 5000 端口,否则请求可能打到旧进程。
| 问题 | 说明 |
|---|---|
| Agent 显示「LLM 未配置」 | 检查 .env 中 LLM_* 三项 |
| Agent 429 轮询过于频繁 | 前端轮询间隔 2s;勿短时间内重复触发 |
| 作品一直「生成中」 | 可能已 failed 但页面未刷新;刷新或查 data/app.db 中 projects.status |
生图失败 image upload failed |
图床 URL 不可达,已切换 catbox,仍失败可重试 |
| Module 脚本作用域 | sigs.html 中 Three.js 模块需通过 window.state 与普通脚本通信 |
| 全景 BackSide 镜像 | 纹理需 texture.repeat.x = -1 |
在 sigs.html 的 I18N 对象中增加语言包,并更新 setLang() 与设置项。
config.py添加接口常量app.py添加_submit_xxx()与路由- 复用
_upload_to_hosting()、_convert_to_jpg()、_query_result()
- 图片放入
panorama_images/panorama_images_{SET}/ - 在
coordinates.csv增加一行
flask>=3.0
requests>=2.31
python-dotenv>=1.0
urllib3<2
gunicorn>=21.2
bcrypt>=4.0
Pillow>=10.0
内部项目,使用前请确认 API 密钥与校园影像数据的使用授权。