1 line
16 KiB
JSON
1 line
16 KiB
JSON
{"repo": "akemyakemy/xengineer-04-01", "files": {"README.md": {"b889cf700f0b0c87dd3bd8746544c0b98277a651": {"t": 1785595278.354583, "n": 9380, "h": "7de764376b960a70", "c": "# 🤖 AI 视觉对话助手 (AI Vision Assistant)\n\n七牛云 × XEngineer 暑期实训营「第四批次议题」选题一\n\n以摄像头画面为输入,通过自然语言与 AI 对话——让 AI 帮你\"看\"身边的东西,问它任何问题。\n\n---\n\n## 📺 演示视频\n\n> [**点击观看完整演示视频**](https://www.bilibili.com/video/BV1wqJP6PEsC/?spm_id_from=333.1387.homepage.video_card.click&vd_source=1f416b3c046eee13f733ba90b1ced172)\n\n## 🚀 快速启动\n\n### 🌐 在线体验(无需部署)\n\n作者已部署可用的线上版本,直接用 Chrome 浏览器访问即可:\n\n**[https://ava.542000.xyz](https://ava.542000.xyz)**\n\n> 授权摄像头后即可立刻开始视觉对话,无需任何配置。\n\n---\n\n### 💻 本地运行\n\n> **环境要求:Go ≥ 1.23 · Chrome 浏览器**\n\n**1. 配置环境变量**\n\n```bash\ncp .env.example .env\n# 编辑 .env,填入你的 Mimo API Key\n```\n\n| 变量名 | 说明 | 示例值 |\n|---|---|---|\n| `MIMO_URL` | Mimo API 地址 | `https://token-plan-cn.xiaomimimo.com/v1` |\n| `MIMO_KEY` | 你的 API Key | `sk-xxxxxx` |\n| `MODEL_OK` | 模型名称(支持逗号分隔多个,优先选 omni/vision/vl) | `mimo-v2-omni` |\n\n**2. 启动服务**\n\n```bash\ncd backend && go run ./cmd/server\n```\n\n**3. 打开浏览器**\n\n访问 `http://127.0.0.1:5173`,授权摄像头后即可开始视觉对话。\n\n---\n\n### ☁️ 生产部署\n\n项目采用前后端分离部署方案,详见 [DEPLOYMENT.md](./DEPLOYMENT.md)。\n\n| 部分 | 平台 | 说明 |\n|---|---|---|\n| 后端 | [Railway](https://railway.app/) | 根目录 `Dockerfile` 自动构建,配置 `MIMO_URL` / `MIMO_KEY` / `MODEL_OK` 环境变量 |\n| 前端 | [Cloudflare Pages](https://pages.cloudflare.com/) | 发布目录 `frontend/public`,无需构建步骤,修改 `config.js` 中的后端地址 |\n\n---\n\n## 📋 开发流程\n\n本项目完整经历了从 0 到 1 的产品开发周期,共五个阶段:\n\n```\n产品设计 ──► MVP 实现 ──► 产品上线 ──► 测试维护 ──► 文档编写\n 📐 💻 ☁️ 🔧 📝\n```\n\n### 📐 阶段一:产品设计\n\n梳理核心需求与技术可行性,产出以下设计文档(见 `设计文档/` 目录):\n\n- **需求文档**:明确用户场景、功能边界与非功能性约束\n- **产品流程图**:端到端交互流程,覆盖摄像头授权 → 事件相机抽帧 → Mimo 问答 → 空间画像更新全链路\n- **可行性分析**:浏览器端帧差事件相机方案论证,避免持续视频流上传\n- **空间画像格式设计**:`Profile`(scene + objects + confidence)数据结构定义\n\n### 💻 阶段二:MVP 实现\n\n按前后端分离架构逐步实现:\n\n| 模块 | 实现内容 |\n|---|---|\n| Go 后端 | HTTP 服务、Mimo 代理、帧缓存、对话历史、空间画像存储与生成 |\n| 浏览器前端 | 摄像头采集、帧差事件相机、事件驱动采样、空间画像渲染 |\n| 语音交互 | Web Speech API 中文识别、TTS 播报、音频频谱可视化 |\n| 空间画像 | 12 帧触发生成、8 帧节流更新、双端维护(前端即时展示 + 后端持久化) |\n\n### ☁️ 阶段三:产品上线\n\n采用前后端分离部署:\n\n- **后端** → Railway 平台,基于根目录 `Dockerfile` 自动构建 Go 服务\n- **前端** → Cloudflare Pages,发布 `frontend/public` 静态目录,零构建\n- **线上地址** → [https://ava.542000.xyz](https://ava.542000.xyz)\n\n### 🔧 阶段四:测试与维护\n\n- **单元测试**:覆盖 Mimo 客户端、API Handler、空间画像服务(`go test ./...`)\n- **端到端验证**:`frontend/scripts/verify-browser.mjs` 无头 Chrome 自动化脚本,验证摄像头启动与完整对话流程\n- **问题修复**:定位并修复后期出现的帧缓存上传错误提示(静默处理非关键后台失败)\n\n### 📝 阶段五:README 文档编写\n\n按照规范化文档结构完整撰写本 README,涵盖项目简介、快速启动、功能特性、技术架构、项目结构、空间画像机制与开发流程,方便后续贡献者快速上手。\n\n---\n\n## ✨ 功能特性\n\n| 功能 | 说明 |\n|---|---|\n| 📷 **实时视觉问答** | 摄像头画面直接提问,AI 实时理解并回答 |\n| 🎙️ **语音输入/播报** | Web Speech API 中文语音识别 + TTS 语音播报回答 |\n| 🧠 **空间画像记忆** | AI 自动记住画面中的物体及位置,跨轮对话共享上下文 |\n| 📸 **事件相机抽帧** | 浏览器端帧差算法,按画面变化程度智能选取关键帧 |\n| 🔥 **运动热力图** | Canvas 实时渲染帧差热力图与运动区域边框 |\n| 💬 **多对话管理** | 支持新建、切换、置顶多个独立对话,历史消息持久保存 |\n| ☁️ **端云协同** | 浏览器端完成抽帧,云端 Mimo 大模型完成多模态理解 |\n\n## 🏗️ 技术架构\n\n```\n┌──────────────────────────────────────────────────────────┐\n│ 浏览器端 (原生 HTML/CSS/JS) │\n│ │\n│ ┌────────────┐ ┌─────────────────┐ ┌───────────────┐ │\n│ │ 摄像头采集 │ │ 事件相机 (帧差) │ │ 语音识别/合成 │ │\n│ │ VideoCapture│ │ EventCamera │ │ SpeechController│ │\n│ └─────┬──────┘ └───────┬─────────┘ └───────────────┘ │\n│ │ │ │\n│ └────────┬────────┘ │\n│ ▼ │\n│ ┌──────────────────────────────────────────────────────┐ │\n│ │ 事件驱动采样器 (EventDrivenSampler) │ │\n│ │ 高事件 420ms │ 低事件 900ms │ 静态 2200ms │ │\n│ └──────────────────────┬───────────────────────────────┘ │\n└─────────────────────────┼──────────────────────────────────┘\n │ POST /api/frames (关键帧 + 事件元数据)\n │ POST /api/vision (查询 + 事件数据)\n┌─────────────────────────┼──────────────────────────────────┐\n│ 后端 (Go 1.23 · 标准库 net/http) │\n│ ▼ │\n│ ┌──────────────────────────────────────────────────────┐ │\n│ │ API Handler │ │\n│ │ /api/vision │ /api/frames │ /api/spatial │ /api/conversations │\n│ └──────┬───────────────┬─────────────────┬─────────────┘ │\n│ │ │ │ │\n│ ▼ ▼ ▼ │\n│ ┌─────────────┐ ┌────────────┐ ┌──────────────────────┐ │\n│ │ framecache │ │conversation│ │ spatialprofile │ │\n│ │ (帧环形缓存) │ │ Store │ │ LocalClient + Store │ │\n│ │ 最多12帧 │ │ (对话历史) │ │ (JSON 文件持久化) │ │\n│ └─────────────┘ └────────────┘ └──────────┬───────────┘ │\n│ │ │\n└──────────────────────────────────────────────┼───────────────┘\n │ OpenAI 兼容 API\n┌──────────────────────────────────────────────┼───────────────┐\n│ Mimo 云端大模型 │ │\n│ ▼ │\n│ mimo-v2-omni (多模态视觉理解 + 空间画像生成) │\n└───────────────────────────────────────────────────────────────┘\n```\n\n| 层级 | 技术 | 说明 |\n|---|---|---|\n| 摄像头采集 | 浏览器 `getUserMedia` | 720p 视频流,Canvas 截帧为 320×240 JPEG |\n| 事件相机 | 原生 JS 帧差算法 | 16×12 网格亮度差分,阈值 24,避免持续上传视频流 |\n| 语音交互 | 浏览器 Web Speech API | 中文语音识别 + TTS 播报 + 音频频谱可视化 |\n| 前端框架 | 原生 HTML/CSS/ES Module | 零构建工具依赖,模块化组织 |\n| 后端框架 | Go 1.23 + 标准库 `net/http` | 零外部依赖,静态文件 + REST API 一体服务 |\n| 帧缓存 | 内存环形缓冲(最多 12 帧)| 按事件分数动态选取 1/2/4 帧发送给模型 |\n| 空间画像 | 内存 + JSON 文件持久化 | 每 12 帧首次生成,之后每 8 帧增量更新 |\n| 多模态模型 | Mimo (OpenAI 兼容接口) | `mimo-v2-omni`,同时处理图像理解与空间画像生成 |\n| 部署 | Railway (后端) + Cloudflare Pages (前端) | Docker 镜像部署,前端静态托管 |\n\n## 📁 项目结构\n\n```\nXEngineer-04-01/\n├── backend/\n│ ├── cmd/\n│ │ ├── server/main.go # 主服务入口,装配所有依赖并启动 HTTP 服务\n│ │ └── spatial-profile/main.go # 空间画像独立服务入口(可选独立部署)\n│ ├── internal/\n│ │ ├── api/\n│ │ │ ├── handler.go # HTTP 路由、请求校验、静态文件服务\n│ │ │ └── handler_test.go # API 集成测试\n│ │ ├── config/\n│ │ │ └── config.go # .env 配置加载,自动选择视觉模型\n│ │ ├── conversation/\n│ │ │ └── store.go # 对话历史内存存储(增删查、置顶排序)\n│ │ ├── eventmeta/\n│ │ │ └── event.go # 事件相机元数据归一化(分数裁剪、运动框过滤)\n│ │ ├── framecache/\n│ │ │ └── store.go # 帧环形缓冲(最多 12 帧,按事件分数选帧)\n│ │ ├── mimo/\n│ │ │ ├── client.go # Mimo OpenAI 兼容多模态请求封装 + Prompt 构造\n│ │ │ └── client_test.go # Mimo 客户端单元测试\n│ │ ├── spatial/\n│ │ │ └── graph.go # 空间画像知识图谱(实体 upsert、属性合并)\n│ │ └── spatialprofile/\n│ │ ├── client.go # 空间画像客户端(LocalClient / HTTPClient)\n│ │ ├── model.go # Mimo 空间画像生成模型(12帧→场景+物体)\n│ │ ├── server.go # 空间画像独立 HTTP 服务路由\n│ │ ├── server_test.go # 空间画像服务测试\n│ │ ├── store.go # 空间画像持久化存储(内存缓存 + JSON 文件)\n│ │ └── types.go # Profile 数据结构、Normalize/ToContext 转换\n│ └── go.mod\n├── frontend/\n│ ├── public/\n│ │ ├── js/\n│ │ │ ├── app.js # 主应用逻辑,组装各模块、管理对话与帧处理循环\n│ │ │ ├── api-client.js # 后端 REST API 调用封装\n│ │ │ ├── config.js # API 基地址配置(本地开发 / 生产部署切换)\n│ │ │ ├── event-camera.js # 浏览器端帧差事件相机(16×12 网格、运动框检测)\n│ │ │ ├── sampler.js # 事件驱动采样器(动态采样间隔)\n│ │ │ ├── spatial-graph.js # 前端空间画像管理(Map 存储、upsert 合并)\n│ │ │ ├── speech.js # Web Speech API 语音识别/合成 + 音频可视化\n│ │ │ ├── ui.js # UI 渲染工具(消息气泡、热力图、实体卡片)\n│ │ │ └── video-capture.js # 摄像头管理(getUserMedia、Canvas 截帧)\n│ │ ├── index.html # 单页应用入口\n│ │ └── styles.css # 全局样式(响应式三栏布局)\n│ ├── scripts/\n│ │ └── verify-browser.mjs # 无头 Chrome 端到端验证脚本\n│ └── package.json\n├── 设计文档/ # 需求、流程与可行性设计文档\n├── .env.example # 环境变量模板\n├── Dockerfile # Railway 后端 Docker 镜像构建\n├── railway.json # Railway 部署配置\n├── wrangler.toml # Cloudflare Pages 前端部署配置\n└── package.json # 根目录开发编排命令(npm run dev)\n```\n\n\n\n## 🧠 空间画像机制\n\n空间画像是本项目的核心记忆系统,让 AI 能在多轮对话中持续\"记住\"它看到过的场景和物体。\n\n### 数据结构\n\n```json\n{\n \"scene\": \"桌面上摆放着电脑、水杯和书本\",\n \"objects\": [\n { \"name\": \"水杯\", \"description\": \"位于画面右侧,白色马克杯\", \"confidence\": 0.92 },\n { \"name\": \"笔记本电脑\", \"description\": \"位于画面中央,屏幕亮起\", \"confidence\": 0.98 }\n ],\n \"updatedAt\": \"2026-06-14T10:30:00Z\"\n}\n```\n\n### 生成与更新流程\n\n```\n摄像头帧缓存 (最多 12 帧)\n │\n │ 累计到 12 帧时首次触发\n │ 之后每新增 8 帧触发一次\n ▼\n spatialprofile.MimoModel.Generate()\n │ 将 12 帧关键帧 + 已有画像发给 Mimo\n │ Mimo 返回新的 scene + objects JSON\n ▼\n spatialprofile.Store.Set() ← 内存缓存 + JSON 文件持久化\n │\n ▼\n 下次视觉问答时注入 SpatialContext ← 作为历史记忆上下文传给 Mimo\n```\n\n### 关键设计原则\n\n| 设计 | 说明 |\n|---|---|\n| **异步后台更新** | 空间画像更新在 goroutine 中执行,不阻塞视觉问答响应 |\n| **当前帧优先** | Mimo 被明确告知:当前图片永远优先于历史空间画像,二者冲突以图片为准 |\n| **增量合并** | 有历史画像时执行更新模式,当前帧不可见的旧物体会被删除或改写 |\n| **双端维护** | 前端 `SpatialGraph` 即时展示,后端 `Store` 按 session 持久化,多轮共享 |\n| **置信度过滤** | 每个物体携带 `confidence` 字段(0-1),低置信度物体可被后续帧覆盖 |\n| **触发节流** | 首次 12 帧触发,之后每 8 帧才再次触发,避免频繁调用 Mimo API |\n"}}}} |