Files

1 line
16 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"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"}}}}