commit 126167715e31e1d90a459075f2c97cb9cb1bbe0d Author: mula.liu Date: Mon Jan 19 17:52:53 2026 +0800 v 1.0.2 diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..59d0302 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,72 @@ +# Git相关 +.git +.gitignore +.gitattributes + +# 文档 +*.md +README.md +LICENSE +CHANGELOG.md + +# 编辑器和IDE +.vscode +.idea +*.swp +*.swo +*~ +.DS_Store + +# 依赖目录 +**/node_modules +**/__pycache__ +**/*.pyc +**/.pytest_cache +**/.coverage +**/htmlcov + +# 构建产物(这些会在Dockerfile中单独处理) +**/dist +**/build +**/.next +**/.nuxt + +# 环境变量文件 +.env +.env.* +!.env.example + +# 日志文件 +**/*.log +**/logs +**/npm-debug.log* +**/yarn-debug.log* +**/yarn-error.log* + +# 测试相关 +**/coverage +**/.nyc_output +**/test +**/tests + +# 临时文件 +**/tmp +**/temp +**/.cache + +# Docker相关 +docker-compose*.yml +!docker-compose.yml +Dockerfile* +!Dockerfile + +# 备份文件 +backups/ +*.backup +*.bak + +# 上传文件(会通过volume挂载) +uploads/ + +# 项目备份 +project_backup_*/ diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..f408896 --- /dev/null +++ b/.env.example @@ -0,0 +1,30 @@ +# ==================== 数据库配置 ==================== +# MySQL数据库配置 +MYSQL_ROOT_PASSWORD=Unis@123 +MYSQL_DATABASE=imeeting +MYSQL_USER=imeeting +MYSQL_PASSWORD=Unis@123 +MYSQL_PORT=3306 + +# ==================== 缓存配置 ==================== +# Redis配置 +REDIS_PORT=6379 +REDIS_PASSWORD=Unis@123 +REDIS_DB=0 + +# ==================== 应用端口配置 ==================== +# iMeeting服务HTTP端口(默认80) +HTTP_PORT=80 + +# ==================== 应用配置 ==================== +# 应用访问地址(用于生成外部链接、二维码等) +# - 直接访问: http://服务器IP +# - 域名访问: https://your-domain.com (需配置接入服务器Nginx) +BASE_URL=https://imeeting.unisspace.com + +# 前端API地址(通过Nginx代理访问后端) +VITE_API_BASE_URL=/api + +# ==================== LLM配置 ==================== +# 通义千问API密钥(请替换为实际密钥) +QWEN_API_KEY=sk-c2bf06ea56b4491ea3d1e37fdb472b8f diff --git a/.gemini-clipboard/clipboard-1768468287858.png b/.gemini-clipboard/clipboard-1768468287858.png new file mode 100644 index 0000000..bcd8f1a Binary files /dev/null and b/.gemini-clipboard/clipboard-1768468287858.png differ diff --git a/.gemini-clipboard/clipboard-1768470582901.png b/.gemini-clipboard/clipboard-1768470582901.png new file mode 100644 index 0000000..7b998d4 Binary files /dev/null and b/.gemini-clipboard/clipboard-1768470582901.png differ diff --git a/.gemini-clipboard/clipboard-1768470643790.png b/.gemini-clipboard/clipboard-1768470643790.png new file mode 100644 index 0000000..cb6ed0c Binary files /dev/null and b/.gemini-clipboard/clipboard-1768470643790.png differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..716d1dd --- /dev/null +++ b/.gitignore @@ -0,0 +1,65 @@ +# OS files +.DS_Store +Thumbs.db + +# Environment variables +.env +backend/.env +frontend/.env +frontend/.env.local +frontend/.env.production.local + +# Docker / Data +data/ +backups/ +logs_export/ + +# Node.js +node_modules/ +frontend/node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +frontend/dist/ +frontend/logs/ + +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +env/ +venv/ +.env/ +.venv/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +backend/venv/ +backend/__pycache__/ +backend/logs/ + +# Project specific +backend/uploads/ +backend/config/ +backend/app.zip +资料/*.zip + +# IDEs +.vscode/ +.idea/ +*.swp +*.swo diff --git a/AI.md b/AI.md new file mode 100644 index 0000000..81979c8 --- /dev/null +++ b/AI.md @@ -0,0 +1,682 @@ +# imeeting 录音AI解析功能技术方案 + +## 需求分析 + +用户上传完整的会议录音文件,系统需要完成以下处理: + +1. **人声分离**:识别和分离不同的说话人 +2. **语音转文字**:将音频内容转换为文字转录 +3. **时间戳标记**:为每段对话标记时间戳 +4. **智能摘要**:生成会议摘要和关键信息提取 + +## 技术选择对比 + +### 1. 语音转文字 (ASR) 技术 + +#### 选项A:OpenAI Whisper +**优势:** +- 开源免费,支持本地部署 +- 多语言支持(包括中文) +- 准确率高,特别是对中文识别效果好 +- 支持不同模型大小(tiny, base, small, medium, large) +- 可以输出时间戳信息 +- 社区活跃,文档完善 + +**劣势:** +- 需要GPU加速才能获得最佳性能 +- 大模型文件较大(large模型约3GB) +- 处理速度相对较慢 + +**部署方式:** +```python +import whisper +model = whisper.load_model("medium") +result = model.transcribe("audio.mp3", language="zh") +``` + +#### 选项B:Azure Speech Services +**优势:** +- 微软云服务,稳定可靠 +- 支持实时转录和批量转录 +- 中文识别准确率高 +- 支持说话人识别 +- 自动标点和格式化 + +**劣势:** +- 需要付费使用 +- 依赖网络连接 +- 数据隐私考虑 + +#### 选项C:百度语音识别API +**优势:** +- 针对中文优化 +- 识别准确率高 +- 提供免费额度 +- 国内服务稳定 + +**劣势:** +- 需要付费(超出免费额度) +- API调用限制 +- 数据需上传到百度服务器 + +### 2. 说话人分离 (Speaker Diarization) 技术 + +#### 选项A:pyannote-audio +**优势:** +- 开源免费 +- 专业的说话人分离库 +- 支持实时和批量处理 +- 可以与Whisper很好集成 +- 输出详细的说话人时间段信息 + +**劣势:** +- 需要预训练模型 +- 对音频质量要求较高 +- 处理复杂场景(多人同时说话)效果有限 + +**使用示例:** +```python +from pyannote.audio import Pipeline +pipeline = Pipeline.from_pretrained("pyannote/speaker-diarization") +diarization = pipeline("audio.wav") +``` + +#### 选项B:Azure Speaker Recognition +**优势:** +- 集成在Azure Speech Services中 +- 可以识别特定说话人身份 +- 云端处理,无需本地资源 + +**劣势:** +- 付费服务 +- 需要预先注册说话人声纹 + +### 3. 智能摘要生成技术 + +#### 选项A:OpenAI GPT API +**优势:** +- 强大的文本理解和总结能力 +- 支持中文 +- 可以生成结构化摘要 +- API调用简单 + +**劣势:** +- 付费服务 +- 需要网络连接 +- Token限制 + +#### 选项B:本地LLM(如Llama2/ChatGLM) +**优势:** +- 可本地部署 +- 数据隐私安全 +- 一次部署长期使用 + +**劣势:** +- 需要大量GPU内存 +- 部署复杂度高 +- 中文效果可能不如专业API + +## 推荐技术方案 + +### 方案一:完全开源方案(推荐) +``` +音频文件 → Whisper (语音转文字) → pyannote-audio (说话人分离) → 本地LLM (摘要生成) +``` + +**技术栈:** +- **ASR**: OpenAI Whisper (medium模型) +- **说话人分离**: pyannote-audio +- **摘要生成**: ChatGLM-6B 或 Llama2-7B-Chat +- **音频处理**: librosa, pydub +- **后端**: Python FastAPI +- **任务队列**: Celery + Redis + +**优势:** +- 完全开源,无API费用 +- 数据隐私安全 +- 可控性强,可定制化 + +**挑战:** +- 需要GPU服务器资源 +- 部署复杂度较高 +- 需要模型优化调参 + +### 方案二:混合方案 +``` +音频文件 → Whisper (语音转文字) → pyannote-audio (说话人分离) → Qwen3 (摘要生成) +``` + +**优势:** +- ASR和说话人分离本地处理,保护音频隐私 +- 摘要生成使用成熟API,效果好 +- 平衡了成本和效果 + +## 实施架构 + +### 处理流程 +1. **文件上传**: 用户上传音频文件到服务器 +2. **预处理**: 音频格式转换、降噪处理 +3. **说话人分离**: 使用pyannote-audio识别说话人片段 +4. **语音识别**: 使用Whisper对每个说话人片段进行转录 +5. **后处理**: 合并转录结果,添加时间戳和说话人标签 +6. **摘要生成**: 基于转录文本生成会议摘要 +7. **结果存储**: 将处理结果存储到数据库 + +### 技术要求 +- **硬件**: 推荐NVIDIA GPU (4GB+ VRAM) +- **内存**: 16GB+ RAM +- **存储**: SSD存储,用于模型文件和临时音频文件 +- **网络**: 如使用云API需要稳定网络连接 + +### 性能估算 +对于1小时的会议录音: +- **Whisper转录**: 约5-15分钟(取决于GPU性能) +- **说话人分离**: 约2-5分钟 +- **摘要生成**: 约30秒-2分钟 +- **总处理时间**: 8-22分钟 + +## 后续优化方向 + +1. **实时处理**: 支持流式音频处理 +2. **多语言支持**: 扩展到英文等其他语言 +3. **说话人识别**: 建立说话人声纹库,实现身份识别 +4. **关键词提取**: 自动提取会议关键词和主题 +5. **情感分析**: 分析说话人情感倾向 +6. **会议洞察**: 生成会议参与度、发言时长等统计信息 + +## 环境部署指南 + +### 系统要求 + +**推荐配置(16GB内存 + T4 GPU + Ubuntu):** +- **操作系统**: Ubuntu 20.04 LTS 或更高版本 +- **GPU**: NVIDIA T4 (16GB VRAM) 或同等性能显卡 +- **内存**: 16GB RAM 最低,32GB 推荐 +- **存储**: 100GB+ SSD存储空间 +- **CPU**: 8核心以上处理器 +- **Python**: 3.8-3.11 + +### 1. Whisper 语音转文字环境部署 + +#### 1.1 安装CUDA和cuDNN +```bash +# 安装NVIDIA驱动 +sudo apt update +sudo apt install nvidia-driver-470 + +# 安装CUDA 11.8 +wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda_11.8.0_520.61.05_linux.run +sudo chmod +x cuda_11.8.0_520.61.05_linux.run +sudo ./cuda_11.8.0_520.61.05_linux.run + +# 配置环境变量 +echo 'export PATH=/usr/local/cuda-11.8/bin:$PATH' >> ~/.bashrc +echo 'export LD_LIBRARY_PATH=/usr/local/cuda-11.8/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc +source ~/.bashrc +``` + +#### 1.2 创建Python虚拟环境 +```bash +# 安装conda +wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh +bash Miniconda3-latest-Linux-x86_64.sh + +# 创建虚拟环境 +conda create -n imeeting python=3.10 +conda activate imeeting +``` + +#### 1.3 安装Whisper和依赖 +```bash +# 安装PyTorch (CUDA版本) +pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 + +# 安装Whisper +pip install openai-whisper + +# 安装音频处理库 +pip install librosa pydub soundfile + +# 验证安装 +python -c "import whisper; print('Whisper installed successfully')" +``` + +#### 1.4 下载并测试Whisper模型 +```bash +# 在Python中预下载模型 +python -c " +import whisper +# 下载medium模型 (适合中文,约1.5GB) +model = whisper.load_model('medium') +print('Medium model downloaded successfully') +" +``` + +#### 1.5 Whisper使用示例 +```python +import whisper +import time + +# 加载模型 +model = whisper.load_model("medium") + +# 转录音频 +def transcribe_audio(audio_path): + start_time = time.time() + result = model.transcribe( + audio_path, + language="zh", # 中文 + task="transcribe", + verbose=True, + word_timestamps=True # 获取词级别时间戳 + ) + + processing_time = time.time() - start_time + print(f"处理时间: {processing_time:.2f}秒") + + return result + +# 使用示例 +# result = transcribe_audio("meeting.wav") +# print(result["text"]) +``` + +### 2. pyannote-audio 说话人分离环境部署 + +#### 2.1 安装pyannote.audio +```bash +# 激活虚拟环境 +conda activate imeeting + +# 安装pyannote.audio +pip install pyannote.audio + +# 安装额外依赖 +pip install pytorch-lightning +``` + +#### 2.2 获取Hugging Face访问权限 +```bash +# 安装huggingface-hub +pip install huggingface-hub + +# 登录Hugging Face (需要先在https://huggingface.co注册账号) +huggingface-cli login +``` + +**注意**: 需要在Hugging Face上申请访问pyannote模型的权限: +1. 访问 https://huggingface.co/pyannote/speaker-diarization +2. 点击"Request access"申请访问权限 +3. 等待审批通过(通常1-2天) + +#### 2.3 pyannote.audio使用示例 +```python +from pyannote.audio import Pipeline +import torch + +# 检查GPU是否可用 +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") +print(f"使用设备: {device}") + +# 加载说话人分离模型 +pipeline = Pipeline.from_pretrained( + "pyannote/speaker-diarization-3.1", + use_auth_token=True # 使用HF token +) + +# 将模型移动到GPU +pipeline = pipeline.to(device) + +def speaker_diarization(audio_path): + """说话人分离""" + diarization = pipeline(audio_path) + + # 输出结果 + speakers_info = [] + for turn, _, speaker in diarization.itertracks(yield_label=True): + speakers_info.append({ + "speaker": speaker, + "start": turn.start, + "end": turn.end, + "duration": turn.end - turn.start + }) + + return speakers_info + +# 使用示例 +# speakers = speaker_diarization("meeting.wav") +# for info in speakers: +# print(f"说话人 {info['speaker']}: {info['start']:.2f}s - {info['end']:.2f}s") +``` + +### 3. Ollama + 本地LLM 摘要生成环境部署 + +#### 3.1 安装Ollama +```bash +# 下载并安装Ollama +curl -fsSL https://ollama.ai/install.sh | sh + +# 启动Ollama服务 +sudo systemctl start ollama +sudo systemctl enable ollama + +# 验证安装 +ollama --version +``` + +#### 3.2 下载和配置中文LLM模型 +```bash +# 下载Qwen2.5模型 (推荐用于中文摘要) +ollama pull qwen2.5:7b + +# 或者下载ChatGLM3模型 +ollama pull chatglm3:6b + +# 或者下载Llama3.1中文版 +ollama pull llama3.1:8b + +# 查看已下载的模型 +ollama list +``` + +#### 3.3 配置Ollama服务 +```bash +# 创建Ollama配置目录 +sudo mkdir -p /etc/systemd/system/ollama.service.d + +# 创建配置文件 +sudo tee /etc/systemd/system/ollama.service.d/override.conf > /dev/null < setup_imeeting_ai.sh << 'EOF' +#!/bin/bash + +set -e + +echo "开始部署imeeting AI环境..." + +# 更新系统 +sudo apt update && sudo apt upgrade -y + +# 安装必要的系统依赖 +sudo apt install -y wget curl git build-essential + +# 安装NVIDIA驱动(如果还没安装) +if ! command -v nvidia-smi &> /dev/null; then + echo "安装NVIDIA驱动..." + sudo apt install -y nvidia-driver-470 + echo "请重启系统后重新运行此脚本" + exit 1 +fi + +# 安装Miniconda +if [ ! -d "$HOME/miniconda3" ]; then + echo "安装Miniconda..." + wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh + bash Miniconda3-latest-Linux-x86_64.sh -b + rm Miniconda3-latest-Linux-x86_64.sh +fi + +# 初始化conda +source ~/miniconda3/bin/activate + +# 创建虚拟环境 +echo "创建Python虚拟环境..." +conda create -n imeeting python=3.10 -y +conda activate imeeting + +# 安装PyTorch和相关库 +echo "安装PyTorch..." +pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 + +# 安装AI相关库 +echo "安装AI相关库..." +pip install openai-whisper pyannote.audio ollama +pip install librosa pydub soundfile huggingface-hub + +# 安装Ollama +echo "安装Ollama..." +curl -fsSL https://ollama.ai/install.sh | sh + +# 启动Ollama服务 +sudo systemctl start ollama +sudo systemctl enable ollama + +# 下载模型 +echo "下载模型..." +ollama pull qwen2.5:7b + +echo "环境部署完成!" +echo "请使用以下命令激活环境:" +echo "conda activate imeeting" + +EOF + +chmod +x setup_imeeting_ai.sh +``` + +#### 4.2 运行部署脚本 +```bash +./setup_imeeting_ai.sh +``` + +### 5. 性能优化建议 + +#### 5.1 GPU内存优化 +```python +import torch + +# 清理GPU缓存 +def clear_gpu_cache(): + if torch.cuda.is_available(): + torch.cuda.empty_cache() + +# 使用混合精度 +from torch.cuda.amp import autocast + +# 在推理时使用autocast +with autocast(): + result = model.transcribe(audio_path) +``` + +#### 5.2 批处理优化 +```python +# 批量处理音频文件 +def batch_process_audio(audio_files, batch_size=2): + results = [] + for i in range(0, len(audio_files), batch_size): + batch = audio_files[i:i+batch_size] + # 处理批次 + for audio_file in batch: + result = process_single_audio(audio_file) + results.append(result) + # 清理缓存 + clear_gpu_cache() + return results +``` + +### 6. 监控和日志 + +#### 6.1 系统监控 +```bash +# 安装监控工具 +pip install nvidia-ml-py3 psutil + +# GPU监控脚本 +python -c " +import nvidia_ml_py3 as nvml +import psutil +import time + +nvml.nvmlInit() +handle = nvml.nvmlDeviceGetHandleByIndex(0) + +while True: + # GPU使用率 + util = nvml.nvmlDeviceGetUtilizationRates(handle) + print(f'GPU使用率: {util.gpu}%') + + # 内存使用 + mem_info = nvml.nvmlDeviceGetMemoryInfo(handle) + print(f'GPU内存: {mem_info.used/1024**3:.1f}GB / {mem_info.total/1024**3:.1f}GB') + + # CPU和RAM + print(f'CPU使用率: {psutil.cpu_percent()}%') + print(f'RAM使用率: {psutil.virtual_memory().percent}%') + print('-' * 40) + + time.sleep(5) +" +``` + +### 7. 故障排除 + +#### 7.1 常见问题 +1. **CUDA版本不匹配**: 确保PyTorch版本与CUDA版本匹配 +2. **GPU内存不足**: 减小模型尺寸或使用CPU模式 +3. **Hugging Face访问权限**: 确保已获得pyannote模型访问权限 +4. **Ollama服务未启动**: 检查服务状态 `sudo systemctl status ollama` + +#### 7.2 测试脚本 +```python +# 创建测试脚本 +def test_environment(): + """测试环境是否正确配置""" + + # 测试CUDA + import torch + print(f"CUDA可用: {torch.cuda.is_available()}") + if torch.cuda.is_available(): + print(f"GPU设备: {torch.cuda.get_device_name(0)}") + print(f"GPU内存: {torch.cuda.get_device_properties(0).total_memory / 1024**3:.1f}GB") + + # 测试Whisper + try: + import whisper + print("✓ Whisper安装成功") + except ImportError: + print("✗ Whisper安装失败") + + # 测试pyannote + try: + from pyannote.audio import Pipeline + print("✓ pyannote.audio安装成功") + except ImportError: + print("✗ pyannote.audio安装失败") + + # 测试Ollama + try: + import ollama + client = ollama.Client() + models = client.list() + print(f"✓ Ollama连接成功,可用模型: {len(models['models'])}") + except Exception as e: + print(f"✗ Ollama连接失败: {e}") + +if __name__ == "__main__": + test_environment() +``` + +## 开发阶段规划 + +### 阶段一:基础转录功能 +- 集成Whisper进行基础语音转文字 +- 实现音频文件上传和处理队列 +- 基础的转录结果展示 + +### 阶段二:说话人分离 +- 集成pyannote-audio +- 实现多说话人识别和标记 +- 优化音频预处理流程 + +### 阶段三:智能摘要 +- 集成大语言模型或API +- 实现会议摘要自动生成 +- 添加关键信息提取功能 + +### 阶段四:系统优化 +- 性能优化和错误处理 +- 用户界面完善 +- 部署和运维自动化 \ No newline at end of file diff --git a/DOCKER_README.md b/DOCKER_README.md new file mode 100644 index 0000000..944b9ae --- /dev/null +++ b/DOCKER_README.md @@ -0,0 +1,431 @@ +# Docker部署快速开始 + +本目录包含完整的Docker Compose部署配置,支持一键部署iMeeting应用。 + +## 📋 文件说明 + +| 文件 | 说明 | +|------|------| +| `docker-compose.yml` | Docker Compose配置文件 | +| `.env.example` | 环境变量模板 | +| `.dockerignore` | Docker构建忽略文件 | +| `start.sh` ⭐ | 一键启动脚本(推荐) | +| `stop.sh` | 停止服务脚本 | +| `manage.sh` | 服务管理脚本 | +| `generate-ssl-cert.sh` | SSL证书生成脚本 | +| `DOCKER_DEPLOYMENT.md` | 详细部署文档 | +| `DOCKER_README.md` | 本文档 | + +## 🏗️ 系统架构 + +``` +方式一:直接访问 + 用户 → http://服务器IP → iMeeting Nginx (80) → Frontend/Backend + +方式二:域名访问(HTTPS) + 用户 → https://domain → 接入服务器Nginx (SSL) → iMeeting服务器 (80) → Frontend/Backend +``` + +**5个服务容器**: +- **Nginx**: HTTP入口(仅HTTP,SSL由接入服务器处理) +- **Frontend**: React前端应用 +- **Backend**: FastAPI后端服务 +- **MySQL**: 数据库 +- **Redis**: 缓存 + +**数据持久化**: +- `./data/` - 所有数据存储在此目录 + +## 🚀 快速开始 + +### 方式一:使用启动脚本(推荐) + +```bash +# 1. 复制并配置环境变量 +cp .env.example .env +vim .env # 配置七牛云、LLM密钥等 + +# 2. 一键启动 +./start.sh +``` + +脚本会自动完成: +- ✅ 检查Docker依赖 +- ✅ 创建必要目录 +- ✅ 生成SSL证书 +- ✅ 配置后端环境变量 +- ✅ 构建前端 +- ✅ 启动所有服务 +- ✅ 等待健康检查 + +### 方式二:手动启动 + +```bash +# 1. 配置环境变量 +cp .env.example .env +cp backend/.env.example backend/.env +vim .env # 配置主环境变量 +vim backend/.env # 配置后端环境变量 + +# 2. 生成SSL证书 +./generate-ssl-cert.sh + +# 3. 构建前端 +cd frontend +npm install +npm run build +cd .. + +# 4. 启动所有服务 +docker-compose up -d + +# 5. 查看服务状态 +docker-compose ps +``` + +## 🌐 访问地址 + +启动成功后: + +**直接访问(HTTP)**: +- **HTTP访问**: http://localhost 或 http://服务器IP +- **API文档**: http://localhost/docs 或 http://服务器IP/docs +- **API路径**: http://localhost/api/ 或 http://服务器IP/api/ + +**域名访问(HTTPS)**: +- 需要在接入服务器配置Nginx反向代理 +- 参考文档:[GATEWAY_NGINX_CONFIG.md](GATEWAY_NGINX_CONFIG.md) +- 访问示例:https://imeeting.yourdomain.com + +## ⚙️ 环境变量配置 + +### 必须配置项 + +编辑 `.env` 文件,修改以下配置: + +```bash +# 七牛云存储(必填,否则无法上传文件) +QINIU_ACCESS_KEY=your_actual_access_key +QINIU_SECRET_KEY=your_actual_secret_key +QINIU_BUCKET=your_bucket_name +QINIU_DOMAIN=your_domain.clouddn.com + +# LLM API(必填,否则无法使用AI功能) +QWEN_API_KEY=your_actual_qwen_api_key + +# 生产环境必改密码 +MYSQL_ROOT_PASSWORD=change_this_password +MYSQL_PASSWORD=change_this_password +REDIS_PASSWORD=change_this_password +``` + +### 可选配置项 + +```bash +# 应用访问地址(用于生成二维码等) +BASE_URL=http://localhost # 生产环境改为: https://your-domain.com + +# Nginx端口(默认80/443) +HTTP_PORT=80 +HTTPS_PORT=443 + +# 如需直接访问后端/前端(开发调试用) +# BACKEND_PORT=8001 +# FRONTEND_PORT=3001 +``` + +## 📦 数据目录 + +所有数据存储在 `./data/` 目录: + +``` +data/ +├── mysql/ # MySQL数据库文件 +├── redis/ # Redis持久化文件 +├── uploads/ # 用户上传的文件(音频、图片等) +└── logs/ # 日志文件 + ├── backend/ + ├── frontend/ + └── nginx/ +``` + +**重要提示**: +- 定期备份 `data/` 目录 +- 生产环境建议挂载独立数据盘到 `./data/` + +## 🔧 日常管理 + +### 使用管理脚本(推荐) + +```bash +./manage.sh +``` + +交互式菜单提供以下功能: +1. 查看服务状态 +2. 查看实时日志 +3. 重启所有服务 +4. 重启单个服务 +5. 进入容器终端 +6. **备份数据库** +7. 恢复数据库 +8. 清理Redis缓存 +9. 更新服务 +10. 查看资源使用 +11. 导出日志 + +### 常用命令 + +```bash +# 查看服务状态 +docker-compose ps + +# 查看日志 +docker-compose logs -f # 所有服务 +docker-compose logs -f nginx # Nginx日志 +docker-compose logs -f backend # 后端日志 +tail -f data/logs/nginx/imeeting_access.log # 访问日志 + +# 重启服务 +docker-compose restart # 重启所有 +docker-compose restart nginx # 重启Nginx + +# 停止服务 +./stop.sh # 交互式停止 +docker-compose down # 停止并删除容器 +``` + +## 🔐 域名和HTTPS配置 + +iMeeting服务器本身仅提供HTTP服务。如需通过域名访问(HTTPS),需要在接入服务器配置Nginx反向代理。 + +### 配置接入服务器 + +完整配置步骤请参考:[GATEWAY_NGINX_CONFIG.md](GATEWAY_NGINX_CONFIG.md) + +**简要步骤**: +1. 在接入服务器安装Nginx +2. 使用Let's Encrypt获取SSL证书 +3. 配置Nginx反向代理到iMeeting服务器IP +4. 配置DNS A记录指向接入服务器 + +**配置示例**: +```nginx +server { + listen 443 ssl http2; + server_name imeeting.yourdomain.com; + + ssl_certificate /etc/letsencrypt/live/imeeting.yourdomain.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/imeeting.yourdomain.com/privkey.pem; + + location / { + proxy_pass http://iMeeting服务器IP:80; + # ... 其他配置 + } +} +``` + +详见:[GATEWAY_NGINX_CONFIG.md](GATEWAY_NGINX_CONFIG.md) + +## 🔍 故障排查 + +### 查看日志 + +```bash +# 服务日志 +docker-compose logs -f + +# 文件日志 +tail -f data/logs/nginx/imeeting_error.log +tail -f data/logs/backend/*.log +``` + +### 检查服务状态 + +```bash +docker-compose ps +``` + +所有服务应显示 `healthy` 状态。 + +### 测试连接 + +```bash +# 测试Nginx +curl http://localhost/health + +# 测试HTTPS +curl -k https://localhost/health + +# 测试API文档 +curl http://localhost/docs +``` + +### 常见问题 + +| 问题 | 解决方法 | +|------|----------| +| 端口被占用 | 修改.env中的HTTP_PORT | +| 502错误 | 检查backend和frontend是否健康 | +| 数据库连接失败 | 检查backend/.env配置 | +| 前端无法访问API | 检查VITE_API_BASE_URL配置 | +| 如何配置HTTPS | 参考GATEWAY_NGINX_CONFIG.md配置接入服务器 | + +详见:`DOCKER_DEPLOYMENT.md` 故障排查章节 + +## 📊 服务组件 + +| 服务 | 容器名 | 内部端口 | 外部端口 | 健康检查 | +|------|--------|----------|----------|----------| +| Nginx | imeeting-nginx | 80 | 80 | ✅ | +| Frontend | imeeting-frontend | 3001 | - | ✅ | +| Backend | imeeting-backend | 8001 | - | ✅ | +| MySQL | imeeting-mysql | 3306 | - | ✅ | +| Redis | imeeting-redis | 6379 | - | ✅ | + +外部仅暴露Nginx的80端口(HTTP),其他服务通过内部网络通信。 +如需HTTPS,请在接入服务器配置SSL。 + +## 🔄 更新部署 + +### 更新代码 + +```bash +# 拉取最新代码 +git pull + +# 重新构建 +docker-compose build + +# 重启服务 +docker-compose up -d +``` + +### 仅更新前端 + +```bash +cd frontend +npm run build +cd .. +docker-compose build frontend +docker-compose up -d frontend +docker-compose restart nginx +``` + +### 仅更新后端 + +```bash +docker-compose build backend +docker-compose up -d backend +``` + +## 💾 备份与恢复 + +### 备份数据库 + +```bash +# 使用管理脚本 +./manage.sh # 选择"6) 备份数据库" + +# 或手动执行 +docker-compose exec mysql mysqldump -uroot -p imeeting > backup.sql +``` + +### 备份所有数据 + +```bash +# 备份data目录 +tar czf imeeting_backup_$(date +%Y%m%d).tar.gz data/ + +# 备份配置 +tar czf imeeting_config_$(date +%Y%m%d).tar.gz .env backend/.env nginx/ +``` + +### 恢复数据 + +```bash +# 恢复数据库 +docker-compose exec -T mysql mysql -uroot -p imeeting < backup.sql + +# 恢复data目录 +tar xzf imeeting_backup_20240101.tar.gz +``` + +## 🛡️ 安全提示 + +生产环境部署前,请务必: + +1. ✅ **修改所有默认密码** + - MYSQL_ROOT_PASSWORD + - MYSQL_PASSWORD + - REDIS_PASSWORD + +2. ✅ **配置真实SSL证书** + - 使用Let's Encrypt或商业证书 + - 不要使用自签名证书 + +3. ✅ **设置文件权限** + ```bash + chmod 600 .env backend/.env + chmod 600 nginx/ssl/server.key + ``` + +4. ✅ **启用防火墙** + ```bash + ufw allow 80/tcp + ufw allow 443/tcp + ufw enable + ``` + +5. ✅ **定期备份数据** + - 设置自动备份脚本 + - 异地备份 + +6. ✅ **监控日志** + - 定期检查错误日志 + - 设置日志轮转 + +## 📚 更多信息 + +详细的部署说明、配置选项、性能优化等,请查看: + +- **详细部署文档**: [DOCKER_DEPLOYMENT.md](DOCKER_DEPLOYMENT.md) +- **Nginx配置说明**: [nginx/README.md](nginx/README.md) + +## 🆘 获取帮助 + +如遇问题: + +1. 查看日志:`docker-compose logs -f` +2. 查看健康状态:`docker-compose ps` +3. 查看详细文档:`DOCKER_DEPLOYMENT.md` +4. 提交Issue到项目仓库 + +## 📞 快速命令参考 + +```bash +# 启动 +./start.sh # 一键启动(推荐) +docker-compose up -d # 启动所有服务 + +# 管理 +./manage.sh # 管理菜单(推荐) +docker-compose ps # 查看状态 +docker-compose logs -f # 查看日志 +docker-compose restart # 重启服务 + +# 停止 +./stop.sh # 停止服务(推荐) +docker-compose down # 停止并删除容器 + +# 备份 +./manage.sh # 选择备份功能 +tar czf backup.tar.gz data/ # 备份所有数据 + +# 更新 +git pull && docker-compose build && docker-compose up -d +``` + +--- + +**祝您使用愉快!** 🎉 diff --git a/README.md b/README.md new file mode 100644 index 0000000..fc2eef4 --- /dev/null +++ b/README.md @@ -0,0 +1,167 @@ +# iMeeting - 智慧会议平台 + +## 项目简介 + +iMeeting 是一个基于 AI 技术的智能会议记录与内容管理平台,通过自动化的语音转录、说话人识别和 AI 摘要功能,帮助专业人士高效管理会议内容,从繁琐的记录工作中解放出来。 + +## 核心价值 + +- **解放生产力** - 自动化的会议转录和摘要,让用户从繁琐的记录工作中解放出来 +- **信息不丢失** - 精准记录每一次会议的细节,确保关键信息和决策得到妥善保存 +- **高效回顾** - 通过时间轴、发言人和关键词,快速定位会议内容 +- **便捷分享** - 轻松分享会议纪要、材料和关键节点给相关人员 + +## 技术栈 + +### 平台端 (Backend) +- **框架**: Python 3.9+ / FastAPI +- **数据库**: MySQL 5.7+ +- **缓存**: Redis 5.0+ +- **AI服务**: 阿里云通义千问 (Dashscope) + - 语音识别: Paraformer-v2 + - 说话人分离 + - 大语言模型摘要 +- **存储**: 本地对象存储 +- **身份认证**: JWT / Python-JOSE +- **部署**: Docker / Nginx + +### 客户端 (Frontend) +- **框架**: React 19.1 + Vite 7.0 +- **UI组件**: Ant Design 5.27 +- **路由**: React Router DOM 7.7 +- **Markdown**: @uiw/react-md-editor 4.0 +- **可视化**: Markmap (思维导图) +- **其他工具**: + - Axios (HTTP 客户端) + - html2canvas + jsPDF (导出功能) + - QRCode.react (二维码生成) + - Lucide React (图标库) + +## 功能模块 + +### 平台功能 + +| 功能模块 | 功能描述 | 状态 | +|---------|---------|------| +| **用户管理** | 用户创建、编辑、删除、密码重置、角色权限管理 | ✅ 已完成 | +| **会议管理** | 会议创建、编辑、删除、参会人员管理 | ✅ 已完成 | +| **音频处理** | 音频文件上传、存储、格式验证 | ✅ 已完成 | +| **异步转录服务** | 基于Paraformer的异步语音识别 | ✅ 已完成 | +| **说话人分离** | 基于CAM++ ,支持自定义标签 | ✅ 已完成 | +| **AI 摘要生成** | 异步生成会议纪要,支持自定义 Prompt | ✅ 已完成 | +| **任务状态管理** | 转录任务和 LLM 任务的状态追踪 | ✅ 已完成 | +| **声纹采集** | 用户声纹数据采集和管理 | ✅ 已完成 | +| **身份认证** | JWT Token 认证、登录登出、Token 刷新 | ✅ 已完成 | +| **图片上传** | 会议相关图片上传,支持 Markdown 引用 | ✅ 已完成 | +| **多会议知识模块** | 基于多会议摘要的知识总结 | ✅ 已完成 | +| **完整的对外接口** | 提供基于PC客户端、手机客户端、专用设备的服务接口 | ✅ 已完成 | +| | | | +| *待扩展功能* | *以下功能将在后续版本中添加* | | +| **对话模式的M-Agent** | 对话模式的会议Agent| | +| **平台多租户**| 云平台支持多租户| | + +### PC客户端功能 + +| 功能模块 | 功能描述 | 状态 | +|---------|---------|------| +| **用户登录** | 登录界面、Token 存储、自动登录 | ✅ 已完成 | +| **会议列表** | 会议展示、筛选、搜索 | ✅ 已完成 | +| **会议采集** | 支持快速会议和自定义会议 | ✅ 已完成 | +| **导出功能** | 会议纪要预览 | ✅ 已完成 | +| **响应式设计** | 适配不同屏幕尺寸 | ✅ 已完成 | +| | | | +| *待扩展功能* | *以下功能将在后续版本中添加* | | +| **声纹采集界面** | 声纹录制、上传、状态管理 | | +| **会议总结概览** | 获取按会议ID的总结一览| | + +### 手机客户端功能 +| 功能模块 | 功能描述 | 状态 | +|---------|---------|------| + +## 快速开始 + +### 环境要求 + +- Node.js 16+ +- Python 3.9+ +- MySQL 5.7+ +- Redis 5.0+ +- Docker (可选) + +### 安装与运行 + +#### 后端启动 + +```bash +cd backend +pip install -r requirements.txt +python main.py +``` + +默认运行在 `http://localhost:8000` + +#### 前端启动 + +```bash +cd frontend +npm install +npm run dev +``` + +默认运行在 `http://localhost:5173` + +### 配置说明 + +详细的配置文档请参考: +- 数据库设计: [database.md](./database.md) +- 项目详细设计: [project.md](./project.md) +- AI 集成文档: [AI.md](./AI.md) + +## 核心特性 + +### 异步任务处理 + +系统采用异步任务架构,支持大文件和长时间处理: + +- **语音转录任务**: 基于阿里云 Dashscope 的异步 API,支持任务状态追踪 +- **AI 摘要任务**: 使用 FastAPI BackgroundTasks,支持进度更新和轮询 + +### 数据安全 + +- JWT Token 认证机制 +- 基于角色的权限控制 (RBAC) +- 密码 bcrypt 加密 +- Token 黑名单机制 + +### 高性能 + +- Redis 缓存任务状态 +- 异步处理避免阻塞 +- 分页查询优化 +- 音频流式传输 + +## API 文档 + +启动后端服务后,访问以下地址查看 API 文档: + +- Swagger UI: `http://localhost:8000/docs` +- ReDoc: `http://localhost:8000/redoc` + +## 未来规划 + +- [ ] 实时转录 - 支持对正在进行的会议进行实时语音转文字 +- [ ] 日历集成 - 与 Google Calendar、Outlook Calendar 集成 +- [ ] 行动项提取 - AI 自动识别会议中的待办事项 +- [ ] 跨会议搜索 - 对所有会议内容进行全文语义搜索 +- [ ] 移动端应用 - 开发 iOS 和 Android 原生应用 +- [ ] 多语言支持 - 支持中英文等多语言界面 +- [ ] 会议协作 - 支持多人实时协作编辑会议纪要 +- [ ] 数据分析 - 会议统计分析和可视化报表 + +## 许可证 + +[请添加许可证信息] + +## 联系方式 + +[请添加联系方式] diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..1bd1800 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,908 @@ +# iMeeting 产品路线图 + +## 项目概述 + +iMeeting 是一个智能会议管理和知识库系统,旨在通过 AI 技术提升会议效率,自动生成会议纪要,并从多次会议中提炼知识。 + +--- + +## Phase 1: 基础会议管理与知识库系统(已完成) + +### 核心功能 + +#### 1. 会议管理 +- **会议创建与录音**:支持创建会议并关联音频文件 +- **音频转录**:基于阿里云 DashScope 的语音识别,支持异步转录 +- **AI 总结生成**:使用大语言模型(通义千问)自动生成会议纪要 +- **提示词模版**:支持预定义和自定义提示词模版,适配不同会议场景 +- **标签系统**:支持为会议添加标签,方便分类和检索 + +#### 2. 知识库系统 +- **基于会议的知识提炼**:从多个会议纪要中提炼知识库内容 +- **自定义提示词**:用户可以指定特定的分析角度和总结需求 +- **Markdown 输出**:知识库内容以 Markdown 格式存储和展示 +- **标签关联**:支持知识库的标签分类 +- **共享机制**:支持知识库的个人/共享模式 + +#### 3. 用户权限管理 +- **用户认证**:基于 JWT 的用户登录与会话管理 +- **角色权限**:区分普通用户和管理员 +- **菜单权限**:动态菜单权限控制系统 + +#### 4. 管理后台 +- **用户管理**:用户创建、编辑、删除、权限配置 +- **系统监控**:在线用户、任务监控、系统资源监控 +- **提示词仓库**:集中管理所有提示词模版 + +### 技术架构 + +#### 后端技术栈 +- **框架**:FastAPI(Python) +- **数据库**:MySQL 8.0 +- **缓存**:Redis 5.0+ +- **AI 服务**:阿里云 DashScope(通义千问) +- **对象存储**:七牛云 OSS +- **异步任务**:FastAPI BackgroundTasks + +#### 前端技术栈 +- **框架**:React 18 +- **路由**:React Router +- **UI 组件**:Ant Design + 自定义组件 +- **Markdown 渲染**:react-markdown + +#### 数据模型(核心表) +- `users`:用户表 +- `meetings`:会议表 +- `knowledge_bases`:知识库表 +- `prompts`:提示词模版表 +- `transcription_tasks`:转录任务表 +- `summary_tasks`:总结任务表 +- `knowledge_base_tasks`:知识库生成任务表 +- `tags`:标签表 + +--- + +## Phase 2: 知识库系统大升级(规划中) + +### 升级目标 + +将知识库系统从单一的"会议纪要汇总"升级为功能完整的"AI 知识助手",参考 NotebookLM 的交互模式,提供多维度的知识管理和音频播客生成能力。 + +--- + +### 1. 输入来源扩展 + +#### 1.1 功能需求 +- ✅ **会议来源**(已支持):从多个会议纪要中提炼 +- 🆕 **外部文件上传**: + - 支持 PDF、Word、TXT、Markdown 文件 + - 支持音频文件(MP3、WAV、M4A) + - 支持视频文件(MP4、AVI、MOV)提取音频 + - 单个知识库可混合多种来源 + +#### 1.2 技术方案 + +##### 文档解析 +```python +# 依赖库选型 +- PDF: PyPDF2 / pdfplumber(文本提取) +- Word: python-docx(DOCX 文件) +- Markdown: 直接读取 +- TXT: 直接读取,支持多种编码(UTF-8、GBK) +``` + +**技术评估**: +- ✅ **可行性**:高,Python 生态成熟 +- ⚠️ **挑战**: + - PDF 中的表格、图片识别(可选用 OCR) + - 大文件处理(需要分块上传和处理) +- 💰 **成本**:无额外费用,依赖开源库 + +##### 音频/视频处理 +```python +# 依赖库选型 +- 音频提取: ffmpeg-python(视频转音频) +- 音频格式转换: pydub +``` + +**技术评估**: +- ✅ **可行性**:高,现有转录流程可复用 +- ⚠️ **挑战**: + - 视频文件较大,需要优化存储和处理 + - 需要增加进度反馈 +- 💰 **成本**: + - 视频存储成本增加(七牛云存储费用) + - 转录费用与现有一致(按时长计费) + +##### 数据库设计 +```sql +-- 新增表:知识库来源文件表 +CREATE TABLE kb_source_files ( + file_id INT AUTO_INCREMENT PRIMARY KEY, + kb_id INT NOT NULL COMMENT '关联的知识库ID', + file_type ENUM('pdf', 'docx', 'txt', 'markdown', 'audio', 'video') NOT NULL, + file_name VARCHAR(255) NOT NULL, + file_url VARCHAR(512) NOT NULL COMMENT '文件存储URL', + file_size BIGINT COMMENT '文件大小(字节)', + extracted_text TEXT COMMENT '提取的文本内容', + upload_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (kb_id) REFERENCES knowledge_bases(kb_id) ON DELETE CASCADE +); + +-- 修改知识库表 +ALTER TABLE knowledge_bases +ADD COLUMN source_type ENUM('meetings', 'files', 'mixed') DEFAULT 'meetings' COMMENT '内容来源类型'; +``` + +--- + +### 2. 提示词模版升级 + +#### 2.1 功能需求 +- ✅ **选择模版**(已支持):从提示词仓库选择预设模版 +- 🆕 **附加提示词**:在模版基础上追加自定义需求 +- 🆕 **结构化输出**:生成标题 + 多级内容(章节、小节) +- 🆕 **输出格式控制**:支持指定输出结构(JSON Schema) + +#### 2.2 技术方案 + +##### 提示词组合 +```python +def build_knowledge_prompt( + template_prompt: str, # 基础模版 + additional_prompt: str, # 附加提示词 + output_format: dict # 输出格式控制 +) -> str: + """ + 组合提示词策略: + 1. 基础模版(定义分析维度和风格) + 2. 附加提示词(用户自定义需求) + 3. 输出格式要求(结构化 JSON 或 Markdown) + """ + return f""" +{template_prompt} + +## 用户补充要求 +{additional_prompt} + +## 输出格式要求 +请按照以下结构输出(Markdown 格式): +# 标题 +## 章节1 +### 小节1.1 +内容... +### 小节1.2 +内容... +## 章节2 +... +""" +``` + +**技术评估**: +- ✅ **可行性**:高,现有提示词系统可直接扩展 +- 📊 **优化方向**: + - 使用通义千问的 `response_format` 参数实现结构化输出 + - 提供可视化的输出结构编辑器 +- 💰 **成本**:无额外成本 + +##### 结构化输出(通义千问支持) +```python +# 通义千问支持 JSON Schema 格式控制 +response_format = { + "type": "json_schema", + "json_schema": { + "name": "knowledge_base_output", + "schema": { + "type": "object", + "properties": { + "title": {"type": "string"}, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "section_title": {"type": "string"}, + "subsections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "subsection_title": {"type": "string"}, + "content": {"type": "string"} + } + } + } + } + } + } + } + } + } +} +``` + +--- + +### 3. 音频概览生成(TTS 播客) + +#### 3.1 功能需求 +- 🆕 **文字转语音**:将知识库内容转换为音频 +- 🆕 **播客式对话**(类似 NotebookLM): + - 双人对话形式(主持人 + 嘉宾) + - 自然的问答式讲解 + - 语气生动,易于理解 + +#### 3.2 技术方案 + +##### 方案一:基础 TTS(快速实现) + +**服务选型**: +```python +# 1. 阿里云语音合成(推荐) +- 优势:已集成 DashScope,音质自然,支持多音色 +- 成本:约 0.002 元/次(100字符) +- 特性:支持 SSML 标签控制语速、停顿 + +# 2. 微软 Azure TTS +- 优势:音质最佳,支持神经网络语音 +- 成本:约 $4/百万字符 +- 特性:支持情感控制、多语言 + +# 3. OpenAI TTS +- 优势:音质优秀,与 GPT 集成度高 +- 成本:约 $15/百万字符 +- 特性:6 种不同音色可选 +``` + +**实现流程**: +```python +async def generate_basic_audio(kb_content: str) -> str: + """ + 基础 TTS 实现 + 1. 文本预处理(分段、去除特殊字符) + 2. 调用 TTS API + 3. 音频文件合并 + 4. 上传到七牛云 + """ + # 分段处理(避免单次请求过长) + segments = split_text_by_paragraphs(kb_content, max_length=500) + + audio_files = [] + for segment in segments: + audio = await tts_service.synthesize( + text=segment, + voice="zhichu", # 阿里云音色 + rate=1.0, # 语速 + pitch=0 # 音调 + ) + audio_files.append(audio) + + # 合并音频 + final_audio = merge_audio_files(audio_files) + audio_url = upload_to_qiniu(final_audio, "kb_audio") + + return audio_url +``` + +**技术评估**: +- ✅ **可行性**:高,实现简单 +- ⚠️ **局限性**: + - 单调朗读,无对话感 + - 缺乏停顿和情感 +- 💰 **成本**: + - 阿里云 TTS:约 0.02 元/千字 + - 10 万字知识库:约 2 元/次 + +--- + +##### 方案二:播客式对话(NotebookLM 风格) + +**技术架构**: + +``` +输入: 知识库内容 (Markdown) + ↓ +1. 内容理解与脚本生成 + - 使用 LLM 将内容改写为对话脚本 + - 双人角色:主持人(引导)+ 专家(讲解) + ↓ +2. 对话脚本优化 + - 添加开场白和结束语 + - 插入自然的停顿和过渡 + - 添加情感标记(SSML) + ↓ +3. 多音色 TTS 合成 + - 主持人音色:女声,温和亲切 + - 专家音色:男声,稳重专业 + ↓ +4. 音频后处理 + - 添加背景音乐(轻音乐) + - 音量均衡化 + - 添加片头片尾 + ↓ +输出: 播客式音频文件 (MP3) +``` + +**LLM 脚本生成示例**: +```python +PODCAST_SCRIPT_PROMPT = """ +你是一个播客制作专家。请将以下知识库内容改写为一段双人对话脚本: +- 主持人(Host):提出问题,引导话题,语气轻松友好 +- 专家(Expert):讲解内容,回答问题,语气专业自信 + +要求: +1. 开场白介绍今天的主题 +2. 通过问答形式逐步展开知识点 +3. 加入自然的过渡语("那么..."、"接下来...") +4. 结束时做简短总结 + +知识库内容: +{kb_content} + +请输出 JSON 格式: +{{ + "title": "播客标题", + "intro": {{ + "host": "开场白...", + "expert": "回应..." + }}, + "dialogues": [ + {{"speaker": "host", "text": "问题1..."}}, + {{"speaker": "expert", "text": "解答1..."}}, + ... + ], + "outro": {{ + "host": "总结...", + "expert": "结束语..." + }} +}} +""" + +async def generate_podcast_script(kb_content: str) -> dict: + """使用 LLM 生成播客脚本""" + response = await llm_service.call( + prompt=PODCAST_SCRIPT_PROMPT.format(kb_content=kb_content), + response_format={"type": "json_object"} + ) + return json.loads(response) + +async def synthesize_podcast(script: dict) -> str: + """合成播客音频""" + audio_segments = [] + + # 片头音乐 + audio_segments.append(load_intro_music()) + + # 开场白 + for speaker, text in script["intro"].items(): + voice = VOICES[speaker] # {"host": "xiaoyun", "expert": "zhichu"} + audio = await tts_service.synthesize(text, voice=voice) + audio_segments.append(audio) + audio_segments.append(silence(duration=0.5)) # 停顿 0.5 秒 + + # 主体对话 + for dialogue in script["dialogues"]: + speaker = dialogue["speaker"] + text = dialogue["text"] + voice = VOICES[speaker] + audio = await tts_service.synthesize(text, voice=voice) + audio_segments.append(audio) + audio_segments.append(silence(duration=0.3)) + + # 结束语 + for speaker, text in script["outro"].items(): + voice = VOICES[speaker] + audio = await tts_service.synthesize(text, voice=voice) + audio_segments.append(audio) + + # 片尾音乐 + audio_segments.append(load_outro_music()) + + # 合并所有音频 + final_audio = merge_with_background_music(audio_segments) + + # 上传到七牛云 + audio_url = upload_to_qiniu(final_audio, "kb_podcast") + return audio_url +``` + +**技术评估**: +- ✅ **可行性**:中等 + - LLM 脚本生成:成熟方案 + - 多音色 TTS:阿里云、Azure 均支持 + - 音频后处理:需要 ffmpeg 或 pydub +- ⚠️ **挑战**: + - 脚本质量依赖 LLM prompt 优化 + - 音频合成时长较长(需要异步处理) + - 音频文件较大,存储成本增加 +- 💰 **成本**(以 5000 字知识库为例): + - LLM 脚本生成(输入 5000 字 + 输出 3000 字):约 0.05 元 + - TTS 合成(约 3000 字对话):约 0.06 元 + - **总成本:约 0.11 元/次** + +**音频处理库**: +```python +# 新增依赖 +ffmpeg-python==0.2.0 # 音频处理 +pydub==0.25.1 # 音频编辑 +``` + +--- + +##### 方案对比 + +| 特性 | 方案一:基础 TTS | 方案二:播客对话 | +|------|------------------|------------------| +| **实现难度** | 低(1-2 天) | 中(3-5 天) | +| **音频质量** | 单调朗读 | 自然对话 | +| **用户体验** | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | +| **成本** | 0.02 元/千字 | 0.11 元/5000 字 | +| **适用场景** | 快速阅读 | 深度学习 | + +**推荐方案**: +- 🚀 **Phase 2.1**:先实现方案一(基础 TTS),快速上线 +- 🎯 **Phase 2.2**:再实现方案二(播客对话),提升体验 + +--- + +### 4. NotebookLM 式交互 + +#### 4.1 功能需求 +- 🆕 **知识库问答**:基于知识库内容的智能问答 +- 🆕 **引用溯源**:回答时显示来源(段落、页码) +- 🆕 **相关内容推荐**:基于用户提问推荐相关知识点 +- 🆕 **多轮对话**:支持上下文记忆的连续对话 + +#### 4.2 技术方案 + +##### 方案一:基于向量数据库的 RAG(推荐) + +**技术架构**: +``` +知识库内容 + ↓ +1. 文本分块 (Chunking) + - 按段落或语义分块(500-1000 字/块) + - 保留元数据(来源、章节、页码) + ↓ +2. 向量化 (Embedding) + - 使用阿里云通义千问 Embedding API + - 或使用 OpenAI text-embedding-3-small + ↓ +3. 存储到向量数据库 + - Milvus(开源,功能强大) + - 或 Qdrant(轻量,易部署) + - 或 PostgreSQL + pgvector(复用现有数据库) + ↓ +4. 用户提问 + ↓ +5. 向量检索 + - 将问题向量化 + - 检索 Top-K 相似内容块 + ↓ +6. LLM 生成回答 + - 将检索结果作为上下文 + - 生成准确回答 + 来源引用 +``` + +**实现示例**: +```python +from dashscope import TextEmbedding +from qdrant_client import QdrantClient +from qdrant_client.models import Distance, VectorParams, PointStruct + +# 1. 向量化服务 +class EmbeddingService: + def embed_text(self, text: str) -> List[float]: + """将文本转换为向量""" + response = TextEmbedding.call( + model='text-embedding-v3', + input=text + ) + return response.output['embeddings'][0]['embedding'] + +# 2. 向量数据库 +class VectorStore: + def __init__(self): + self.client = QdrantClient(host="localhost", port=6333) + + def create_collection(self, kb_id: int): + """为知识库创建向量集合""" + self.client.create_collection( + collection_name=f"kb_{kb_id}", + vectors_config=VectorParams(size=1536, distance=Distance.COSINE) + ) + + def add_chunks(self, kb_id: int, chunks: List[dict]): + """添加文本块到向量库""" + points = [] + for i, chunk in enumerate(chunks): + embedding = embedding_service.embed_text(chunk['text']) + points.append(PointStruct( + id=i, + vector=embedding, + payload={ + "text": chunk['text'], + "source": chunk['source'], + "section": chunk['section'] + } + )) + self.client.upsert(collection_name=f"kb_{kb_id}", points=points) + + def search(self, kb_id: int, query: str, top_k: int = 3): + """搜索相似内容""" + query_vector = embedding_service.embed_text(query) + results = self.client.search( + collection_name=f"kb_{kb_id}", + query_vector=query_vector, + limit=top_k + ) + return results + +# 3. RAG 问答 +async def answer_question(kb_id: int, question: str, chat_history: List[dict] = None): + """基于知识库回答问题""" + # 检索相关内容 + results = vector_store.search(kb_id, question, top_k=3) + + # 构建上下文 + context = "\n\n".join([ + f"[来源: {r.payload['section']}]\n{r.payload['text']}" + for r in results + ]) + + # 构建 prompt + prompt = f""" +基于以下知识库内容回答用户问题。如果无法从内容中找到答案,请明确告知。 + +知识库内容: +{context} + +用户问题:{question} + +请提供准确的回答,并在回答中标注来源章节。 +""" + + # 调用 LLM + response = await llm_service.call(prompt, chat_history=chat_history) + + # 返回回答 + 来源 + return { + "answer": response, + "sources": [ + {"section": r.payload['section'], "text": r.payload['text'][:200]} + for r in results + ] + } +``` + +**技术评估**: +- ✅ **可行性**:高 + - 向量数据库:Qdrant(轻量级)或 pgvector(复用 MySQL) + - Embedding:阿里云通义千问 Embedding API(0.0007 元/千 tokens) +- 📊 **优势**: + - 回答准确性高(基于实际内容) + - 支持引用溯源 + - 检索速度快(毫秒级) +- 💰 **成本**(以 10 万字知识库为例): + - 向量化:约 0.07 元(一次性) + - 每次问答检索:免费(本地向量库) + - LLM 生成:约 0.01 元/次 + +--- + +##### 方案二:基于 LLM 长上下文(备选) + +**技术方案**: +```python +async def answer_with_full_context(kb_content: str, question: str): + """直接将整个知识库作为上下文""" + prompt = f""" +你是一个知识库助手。请基于以下知识库内容回答用户问题。 + +知识库内容: +{kb_content} + +用户问题:{question} + +请提供准确的回答,并标注引用的段落。 +""" + response = await llm_service.call(prompt) + return response +``` + +**技术评估**: +- ✅ **可行性**:中等 + - 通义千问支持 128K tokens 上下文 + - 约 10 万字中文 +- ⚠️ **局限性**: + - 大文本上下文成本高 + - 无法精确定位来源 + - 不支持多知识库联合查询 +- 💰 **成本**: + - 每次问答(10 万字上下文):约 0.15 元 + - **比 RAG 方案贵 10 倍以上** + +**推荐方案**:**方案一(RAG)** 为主,方案二作为小规模知识库的快速方案。 + +--- + +##### 数据库设计 + +```sql +-- 知识库对话历史表 +CREATE TABLE kb_chat_history ( + chat_id INT AUTO_INCREMENT PRIMARY KEY, + kb_id INT NOT NULL COMMENT '关联知识库ID', + user_id INT NOT NULL COMMENT '用户ID', + question TEXT NOT NULL COMMENT '用户提问', + answer TEXT NOT NULL COMMENT 'AI回答', + sources JSON COMMENT '回答来源(JSON数组)', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (kb_id) REFERENCES knowledge_bases(kb_id) ON DELETE CASCADE, + FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE, + INDEX idx_kb_user (kb_id, user_id), + INDEX idx_created_at (created_at) +); + +-- 知识库向量块表 +CREATE TABLE kb_text_chunks ( + chunk_id INT AUTO_INCREMENT PRIMARY KEY, + kb_id INT NOT NULL COMMENT '关联知识库ID', + chunk_text TEXT NOT NULL COMMENT '文本块内容', + chunk_metadata JSON COMMENT '元数据(章节、页码等)', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (kb_id) REFERENCES knowledge_bases(kb_id) ON DELETE CASCADE, + INDEX idx_kb_id (kb_id) +); +``` + +--- + +### 5. 前端交互升级 + +#### 5.1 新增页面/组件 + +``` +知识库详情页 +├── 📄 内容展示区 +│ ├── Markdown 渲染(已有) +│ └── 音频播放器(新增) +│ ├── 播放/暂停 +│ ├── 进度条 +│ ├── 倍速调节 +│ └── 下载音频 +│ +├── 💬 智能问答区(新增) +│ ├── 对话输入框 +│ ├── 对话历史列表 +│ ├── 来源引用卡片 +│ └── 相关问题推荐 +│ +└── 📊 知识库信息 + ├── 来源文件列表(新增) + └── 标签、创建时间等(已有) +``` + +#### 5.2 技术实现 + +```jsx +// 音频播放器组件 +import ReactAudioPlayer from 'react-audio-player'; + +const KnowledgeAudioPlayer = ({ audioUrl }) => { + return ( +
+

🎧 音频概览

+ +
+ ); +}; + +// 智能问答组件 +const KnowledgeChatbot = ({ kbId }) => { + const [messages, setMessages] = useState([]); + const [input, setInput] = useState(''); + const [loading, setLoading] = useState(false); + + const handleAsk = async () => { + setLoading(true); + const response = await apiClient.post(`/knowledge-bases/${kbId}/ask`, { + question: input, + chat_history: messages + }); + + setMessages([ + ...messages, + { role: 'user', content: input }, + { + role: 'assistant', + content: response.data.answer, + sources: response.data.sources + } + ]); + setInput(''); + setLoading(false); + }; + + return ( +
+
+ {messages.map((msg, idx) => ( +
+
{msg.content}
+ {msg.sources && ( +
+

📚 来源

+ {msg.sources.map((src, i) => ( +
+ {src.section} +

{src.text}...

+
+ ))} +
+ )} +
+ ))} +
+
+ setInput(e.target.value)} + placeholder="向知识库提问..." + onKeyPress={(e) => e.key === 'Enter' && handleAsk()} + /> + +
+
+ ); +}; +``` + +--- + +## Phase 2 技术依赖汇总 + +### 新增 Python 依赖 +```txt +# 文档解析 +PyPDF2==3.0.1 +pdfplumber==0.10.3 +python-docx==1.1.0 + +# 音频处理 +ffmpeg-python==0.2.0 +pydub==0.25.1 + +# 向量数据库(二选一) +qdrant-client==1.7.0 # 推荐:轻量级向量库 +# 或 +pgvector==0.2.3 # 备选:PostgreSQL 扩展 + +# 阿里云 Embedding(可选,通义千问已集成) +# 无需新增依赖,使用现有 dashscope +``` + +### 新增前端依赖 +```json +{ + "react-audio-player": "^0.17.0", + "react-markdown": "^9.0.0" // 已有 +} +``` + +### 基础设施 +- **向量数据库**:Qdrant(Docker 部署) + ```bash + docker run -p 6333:6333 qdrant/qdrant + ``` +- **音频处理**:FFmpeg(系统依赖) + ```bash + apt-get install ffmpeg # Ubuntu + brew install ffmpeg # macOS + ``` + +--- + +## 成本预估(Phase 2) + +### 开发成本 +| 模块 | 工作量(人天) | 说明 | +|------|---------------|------| +| 文件上传与解析 | 3-5 天 | PDF、Word、音频解析 | +| 提示词升级 | 2-3 天 | 附加提示词、结构化输出 | +| 基础 TTS | 2-3 天 | 文字转语音 | +| 播客对话(可选) | 5-7 天 | LLM 脚本生成 + 多音色合成 | +| RAG 问答系统 | 5-7 天 | 向量化、检索、对话 | +| 前端交互升级 | 3-5 天 | 音频播放器、聊天界面 | +| **总计** | **20-30 天** | 约 1-1.5 个月 | + +### 运营成本(月) +| 项目 | 预估用量 | 单价 | 月成本 | +|------|---------|------|--------| +| **阿里云 TTS** | 100 万字 | 0.02 元/千字 | 20 元 | +| **LLM 脚本生成** | 50 次(5000 字/次) | 0.05 元/次 | 2.5 元 | +| **Embedding 向量化** | 100 万字 | 0.0007 元/千 tokens | 0.7 元 | +| **LLM 问答** | 1000 次 | 0.01 元/次 | 10 元 | +| **七牛云存储(音频)** | 10 GB | 0.148 元/GB/天 | 44 元 | +| **Qdrant 服务器** | 1 核 2G | - | 0 元(自建) | +| **总计** | - | - | **约 77 元/月** | + +*注:基于中小规模使用场景(月活 100-500 用户)* + +--- + +## 技术风险与缓解措施 + +### 风险 1:向量数据库性能 +- **风险**:大规模知识库检索延迟 +- **缓解**: + - 使用 Qdrant 的分片和副本 + - 限制单次检索 Top-K 数量 + - 增加缓存层(Redis) + +### 风险 2:播客生成质量 +- **风险**:LLM 生成的对话脚本不自然 +- **缓解**: + - 提供多个脚本模版供用户选择 + - 支持用户编辑脚本后再合成 + - 引入少样本学习(Few-shot)优化 prompt + +### 风险 3:文件解析准确性 +- **风险**:PDF、Word 解析失败或乱码 +- **缓解**: + - 提供预览功能,让用户确认提取结果 + - 支持手动文本粘贴作为备选 + - 增加 OCR 处理扫描件 PDF + +### 风险 4:成本控制 +- **风险**:TTS 和 LLM 调用费用超预算 +- **缓解**: + - 设置单用户每日调用限额 + - 音频生成采用队列异步处理 + - 提供缓存机制避免重复生成 + +--- + +## 实施建议 + +### Phase 2.1(基础版,2-3 周) +✅ **优先级高** +1. 文件上传与解析(PDF、Word、TXT) +2. 基础 TTS 音频生成 +3. 提示词附加功能 + +### Phase 2.2(进阶版,3-4 周) +🎯 **优先级中** +1. RAG 问答系统(向量检索) +2. 播客式对话生成 +3. 前端聊天界面 + +### Phase 2.3(优化版,2-3 周) +🔧 **优先级低** +1. 音频后处理(背景音乐、片头片尾) +2. 多轮对话记忆 +3. 相关问题推荐 + +--- + +## 总结 + +Phase 2 升级将把 iMeeting 知识库系统从"被动阅读"升级为"主动交互",核心亮点包括: +1. ✅ **多源输入**:会议 + 文件 + 音视频 +2. 🎙️ **音频播客**:类 NotebookLM 的对话式音频 +3. 💬 **智能问答**:基于 RAG 的精准问答 +4. 📊 **结构化输出**:自动生成多级章节 + +**技术可行性**:高(基于成熟技术栈) +**成本可控性**:高(月运营成本 < 100 元) +**开发周期**:1-1.5 个月(20-30 人天) + +建议采用**分阶段迭代**方式,先上线基础版(文件上传 + 基础 TTS),快速验证用户需求,再逐步完善高级功能(播客对话 + RAG 问答)。 diff --git a/backend b/backend new file mode 160000 index 0000000..6195285 --- /dev/null +++ b/backend @@ -0,0 +1 @@ +Subproject commit 61952852d72b8803072fa792eb61553c5986a01c diff --git a/database.md b/database.md new file mode 100644 index 0000000..738b913 --- /dev/null +++ b/database.md @@ -0,0 +1,412 @@ +# 数据库设计文档 + +本数据库采用 `MySQL 5.7+`。 + +## 1. 表结构概览 + +- **users**: 用户信息表 +- **roles**: 角色信息表 +- **meetings**: 会议主表 +- **attendees**: 参会人员关联表 +- **tags**: 标签表 +- **audio_files**: 会议音频文件表 +- **attachments**: 会议附件表 (未来扩展) +- **transcript_tasks**: 语音转录任务表 +- **transcript_segments**: 语音转录内容分段表 +- **meeting_summaries**: AI 生成的会议纪要表(由llm_tasks替代) +- **llm_tasks**: AI总结任务表 +- **prompts**: 提示词仓库表 +- **knowledge_bases**: 知识库主表 +- **knowledge_bases_task**: 知识库生成任务表 +- **dict_data**: 字典/码表数据表 +- **client_downloads**: 客户端下载管理表 + +--- + +## 2. 表结构详情 + +### 2.1. `users` - 用户表 + +存储用户信息和登录凭证。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `user_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 用户唯一ID | +| `role_id` | INT | NOT NULL, FK | 角色ID (关联 `roles` 表) | +| `username` | VARCHAR(50) | UNIQUE, NOT NULL | 登录用户名 | +| `caption` | VARCHAR(50) | NOT NULL | 用户显示昵称 | +| `email` | VARCHAR(100) | UNIQUE, NOT NULL | 用户邮箱 | +| `password_hash` | VARCHAR(255) | NOT NULL | 哈希后的密码 | +| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 账户创建时间 | + +### 2.1.1 'user_voiceprint' - 用户声纹表 + +| 字段名 | 类型 | 说明 | +|--------|------|------| +| vp_id | INT | 主键,自增ID | +| user_id | INT | 用户ID,唯一索引 | +| file_path | VARCHAR(255) | 音频文件相对路径 | +| file_size | INT | 文件大小(字节) | +| duration_seconds | DECIMAL(5,2) | 音频时长(秒),如 10.25 | +| vector_data | TEXT | 声纹向量JSON数组,如 [0.123, 0.456, ...] | +| collected_at | TIMESTAMP | 采集时间 | +| updated_at | TIMESTAMP | 更新时间 | + +### 2.2. `roles` - 角色表 + +存储用户角色信息。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `role_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 角色唯一ID | +| `role_name` | VARCHAR(50) | UNIQUE, NOT NULL | 角色名称 (e.g., "admin", "user") | + +### 2.3. `meetings` - 会议表 + +存储会议的核心元数据。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `meeting_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 会议唯一ID | +| `user_id` | INT | FK | 会议创建者ID (关联 `users` 表) | +| `title` | VARCHAR(255) | NOT NULL | 会议标题 | +| `meeting_time` | TIMESTAMP | NULL | 会议召开时间 | +| `user_prompt` | TEXT | NULL | 用户输入的提示词 (重复)| +| `summary` | TEXT | NULL | 会议摘要 (Markdown格式) | +| `tags` | VARCHAR(1024) | NULL | 以逗号分隔的标签字符串 | +| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 记录创建时间 | + +### 2.4. `attendees` - 参会人表 + +会议与用户的多对多关联表。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `attendee_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 唯一ID | +| `meeting_id` | INT | FK | 会议ID (关联 `meetings` 表) | +| `user_id` | INT | FK | 用户ID (关联 `users` 表) | +| | | UNIQUE (`meeting_id`, `user_id`) | | + +### 2.5. `tags` - 标签表 + +存储所有唯一的标签及其颜色,用于快速检索和维护。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `id` | INT | PRIMARY KEY, AUTO_INCREMENT | 标签唯一ID | +| `name` | VARCHAR(255) | UNIQUE, NOT NULL | 标签名称 | +| `color` | VARCHAR(7) | DEFAULT '#409EFF' | 标签颜色 (HEX) | +| `creator_id` INT NOT NULL, COMMENT '创建者用户ID (关联 `users` 表) ' | +| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | +### 2.6. `audio_files` - 音频文件表 + +存储上传的会议音频文件信息。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `audio_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 音频文件唯一ID | +| `meeting_id` | INT | FK | 关联的会议ID | +| `file_name` | VARCHAR(255) | | 原始文件名 | +| `file_path` | VARCHAR(512) | NOT NULL | 文件存储相对路径 | +| `file_size` | BIGINT | NULL | 文件大小 (bytes) | +| `upload_time` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 上传时间 | + +### 2.7. `attachments` - 会议附件表 + +存储会议相关的其他附件,如PPT、PDF等。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `attachment_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 附件唯一ID | +| `meeting_id` | INT | FK | 关联的会议ID | +| `file_name` | VARCHAR(255) | NOT NULL | 原始文件名 | +| `file_path` | VARCHAR(512) | NOT NULL | 文件存储路径或URL | +| `file_type` | VARCHAR(100) | | 文件MIME类型 | +| `uploaded_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 上传时间 | + +### 2.8. `transcript_tasks` - 转录任务表 + +记录语音转录任务的状态和元数据。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `task_id` | VARCHAR(100) | PRIMARY KEY | 业务任务唯一ID (UUID) | +| `paraformer_task_id`| VARCHAR(100) | NULL | 外部服务 (Dashscope) 的任务ID | +| `meeting_id` | INT | NOT NULL, FK | 关联的会议ID | +| `status` | ENUM(...) | DEFAULT 'pending' | 任务状态: 'pending', 'processing', 'completed', 'failed' | +| `progress` | INT | DEFAULT 0 | 任务进度百分比 (0-100) | +| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 任务创建时间 | +| `completed_at` | TIMESTAMP | NULL | 任务完成时间 | +| `error_message` | TEXT | NULL | 错误信息记录 | + +### 2.9. `transcript_segments` - 转录内容分段表 + +存储转录后的文字内容,按句子和发言人分段。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `segment_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 分段唯一ID | +| `meeting_id` | INT | FK | 关联的会议ID | +| `speaker_id` | INT | | AI识别的原始发言人ID (e.g., 0, 1, 2) | +| `speaker_tag` | VARCHAR(50) | NOT NULL | 用户可编辑的发言人标签 (e.g., "张三") | +| `start_time_ms` | INT | NOT NULL | 在音频中的开始时间 (毫秒) | +| `end_time_ms` | INT | NOT NULL | 在音频中的结束时间 (毫秒) | +| `text_content` | TEXT | NOT NULL | 转录的文本内容 | + +### 2.10. `meeting_summaries` - 会议纪要表(作废) + +存储由LLM生成的会议纪要。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `id` | INT | PRIMARY KEY, AUTO_INCREMENT | 纪要唯一ID | +| `meeting_id` | INT | FK | 关联的会议ID | +| `summary_content` | TEXT | NULL | 生成的纪要内容 | +| `user_prompt` | TEXT | NULL | 用户输入的额外提示 | +| `prompt_id` | INT | FK | 关联的提示词模版ID | +| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 生成时间 | + +### 2.11. `llm_tasks` - AI总结任务表 + +记录异步生成AI总结的任务状态。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `task_id` | VARCHAR(100) | PRIMARY KEY | 业务任务唯一ID (UUID) | +| `meeting_id` | INT | NOT NULL, FK | 关联的会议ID | +| `prompt_id` | INT | NOT NULL, FK | 关联的提示词模版ID | +| `user_prompt` | TEXT | NULL | 用户输入的额外提示 | +| `status` | ENUM(...) | DEFAULT 'pending' | 任务状态: 'pending', 'processing', 'completed', 'failed' | +| `progress` | INT | DEFAULT 0 | 任务进度百分比 (0-100) | +| `result` | TEXT | NULL | 成功时存储生成的纪要内容 | +| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 任务创建时间 | +| `completed_at` | TIMESTAMP | NULL | 任务完成时间 | +| `error_message` | TEXT | NULL | 错误信息记录 | + +### 2.13. `knowledge_bases` - 知识库表 + +存储用户生成和管理的知识库条目。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `kb_id` | INT | PRIMARY KEY, AUTO_INCREMENT | 知识库条目唯一ID | +| `title` | VARCHAR(255) | NOT NULL | 标题 | +| `user_prompt` | TEXT | NULL | 用户输入的提示词(重复) | +| `content` | TEXT | NULL | 生成的知识库内容 (Markdown格式) | +| `creator_id` | INT | NOT NULL, FK | 创建者用户ID (关联 `users` 表) | +| `is_shared` | BOOLEAN | NOT NULL, DEFAULT FALSE | 是否为共享知识库 (TRUE: 共享, FALSE: 个人) | +| `source_meeting_ids` | TEXT | NULL | 内容来源的会议ID列表 (逗号分隔) | +| `tags` | VARCHAR(255) | NULL | 逗号分隔的标签 | +| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| `updated_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 最后更新时间 | + +### 2.14. `knowledge_base_tasks` - 知识库生成任务表 + +记录异步生成知识库内容的AI任务状态。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `task_id` | VARCHAR(100) | PRIMARY KEY | 业务任务唯一ID (UUID) | +| `user_id` | INT | NOT NULL, FK | 发起任务的用户ID (关联 `users` 表) | +| `kb_id` | INT | NOT NULL, FK | 关联的知识库条目ID (关联 `knowledge_bases` 表) | +| `prompt_id` | INT | NOT NULL, FK | 关联的提示词模版ID | +| `user_prompt` | TEXT | NULL | 用户输入的提示词 | +| `status` | ENUM('pending', 'processing', 'completed', 'failed') | NOT NULL, DEFAULT 'pending' | 任务状态 | +| `progress` | INT | DEFAULT 0 | 任务进度百分比 (0-100) | +| `error_message` | TEXT | NULL | 任务失败时的错误信息 | +| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 任务创建时间 | +| `updated_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 任务状态更新时间 | +| `completed_at` | TIMESTAMP | NULL | 任务完成时间 | + +### 2.12. `prompts` - 提示词仓库表 + +存储系统中各种任务使用的大模型提示词模板。每个任务类型(会议任务、知识库任务)可以有多个提示词,但只能有一个默认且启用的提示词。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `id` | INT | AUTO_INCREMENT, PRIMARY KEY | 提示词唯一ID | +| `name` | VARCHAR(255) | NOT NULL | 提示词名称 | +| `task_type` | ENUM('MEETING_TASK', 'KNOWLEDGE_TASK') | NOT NULL | 任务类型:MEETING_TASK-会议任务, KNOWLEDGE_TASK-知识库任务 | +| `content` | TEXT | NOT NULL | 完整的提示词内容 | +| `is_default` | BOOLEAN | NOT NULL, DEFAULT FALSE | 是否为该任务类型的默认模板 | +| `is_active` | BOOLEAN | NOT NULL, DEFAULT TRUE | 是否启用(只有启用的提示词才能被使用) | +| `creator_id` | INT | NOT NULL, FK | 创建者用户ID (关联 `users` 表) | +| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | + +**约束说明:** +- 每个 `task_type` 同一时间只能有一个 `is_default=TRUE` 的提示词 +- 业务逻辑需确保:设置新默认提示词时,自动取消同类型其他提示词的默认状态 + +### 2.15. `prompt_config` - 提示词配置表(已废弃) + +**该表已废弃,功能整合到 `prompts` 表的 `task_type` 和 `is_default` 字段。** + +### 2.16. `dict_data` - 字典/码表数据表 + +存储系统中的码表数据,支持树形结构和扩展属性,用于管理客户端平台类型等配置数据。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `id` | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 主键ID | +| `dict_type` | VARCHAR(64) | NOT NULL, DEFAULT 'client_platform' | 字典类型(如 client_platform) | +| `dict_code` | VARCHAR(64) | NOT NULL | 业务编码(唯一Key,如 WIN、IOS、ANDROID) | +| `parent_code` | VARCHAR(64) | NOT NULL, DEFAULT 'ROOT' | 父级编码(ROOT为顶级,支持树形结构) | +| `tree_path` | VARCHAR(255) | NULL | 层级路径(辅助字段,如 0,1,10) | +| `label_cn` | VARCHAR(128) | NOT NULL | 中文名称 | +| `label_en` | VARCHAR(128) | NULL | 英文名称 | +| `sort_order` | INT | DEFAULT 0 | 排序权重 | +| `extension_attr` | JSON | NULL | 扩展属性(JSON格式,存储平台特有属性) | +| `is_default` | TINYINT | DEFAULT 0 | 是否默认选中(0: 否, 1: 是) | +| `status` | TINYINT | DEFAULT 1 | 状态(1: 正常, 0: 停用) | +| `create_time` | DATETIME | DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| | | UNIQUE KEY (`dict_type`, `dict_code`) | 确保编码在同类型下唯一 | + +**扩展属性示例(extension_attr):** +```json +{ + "suffix": ".exe", + "arch_support": ["x86", "x64"], + "icon": "monitor" +} +``` + +**树形结构示例:** +- ROOT + - DESKTOP (桌面端) + - WIN (Windows) + - MAC (macOS) + - LINUX (Linux) + - MOBILE (移动端) + - IOS (苹果iOS) + - ANDROID (安卓) + - TERMINAL (专用终端) + - TERM_STD (通用终端) + - TERM_S100 (中兴终端) + +### 2.17. `client_downloads` - 客户端下载管理表 + +存储各平台客户端版本信息,用于管理客户端下载和版本更新。 + +| 字段名 | 类型 | 约束 | 描述 | +| :--- | :--- | :--- | :--- | +| `id` | INT | PRIMARY KEY, AUTO_INCREMENT | 主键ID | +| `platform_code` | VARCHAR(64) | NOT NULL | 平台编码(关联 `dict_data.dict_code`) | +| `version` | VARCHAR(50) | NOT NULL | 版本号(如 1.0.0) | +| `version_code` | INT | NOT NULL | 版本号数值(用于版本比较) | +| `download_url` | VARCHAR(512) | NOT NULL | 下载链接 | +| `file_size` | BIGINT | NULL | 文件大小(bytes) | +| `release_notes` | TEXT | NULL | 更新说明 | +| `is_active` | BOOLEAN | NOT NULL, DEFAULT TRUE | 是否启用 | +| `is_latest` | BOOLEAN | NOT NULL, DEFAULT FALSE | 是否为最新版本 | +| `min_system_version` | VARCHAR(50) | NULL | 最低系统版本要求 | +| `created_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| `updated_at` | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | +| `created_by` | INT | NULL, FK | 创建者用户ID(关联 `users` 表) | +| | | INDEX (`platform_code`) | 平台编码索引 | + +**约束说明:** +- 同一 `platform_code` 同一时间只应有一个 `is_latest=TRUE` 的版本 +- `platform_code` 关联 `dict_data` 表的 `dict_code` 字段(client_platform类型) +- 业务逻辑需确保:设置新最新版本时,自动取消同平台其他版本的最新状态 + +**相关API接口:** +- `GET /api/clients/latest/by-platform` - 获取最新版本客户端 + - 支持两种调用方式(兼容新旧版本,返回数据结构一致): + 1. 旧版:传 `platform_type` 和 `platform_name` 参数 + 2. 新版:传 `platform_code` 参数(推荐) +- `POST /api/clients/upload` - 上传客户端安装包(管理员) + - 自动解析APK文件的版本信息 + - 自动读取文件大小并生成下载URL + +--- + +## 3. 关系图 (ERD) + +```mermaid +erDiagram + users { + int user_id PK + varchar(50) username + varchar(50) caption + varchar(100) email + varchar(255) password_hash + int role_id FK + timestamp created_at + } + + roles { + int role_id PK + varchar(50) role_name + } + + meetings { + int meeting_id PK + int user_id FK + varchar(255) title + timestamp meeting_time + text summary + varchar(1024) tags + timestamp created_at + } + + tags { + int id PK + varchar(255) name + varchar(7) color + } + + attendees { + int attendee_id PK + int meeting_id FK + int user_id FK + } + + audio_files { + int audio_id PK + int meeting_id FK + varchar(512) file_path + varchar(100) task_id + } + + transcript_tasks { + varchar(100) task_id PK + int meeting_id FK + varchar(100) paraformer_task_id + enum status + int progress + } + + transcript_segments { + int segment_id PK + int meeting_id FK + int speaker_id + varchar(50) speaker_tag + int start_time_ms + int end_time_ms + text text_content + } + + meeting_summaries { + int id PK + int meeting_id FK + text summary_content + } + + llm_tasks { + varchar(100) task_id PK + int meeting_id FK + enum status + int progress + } + + users ||--o{ meetings : "creates" + users ||--o{ attendees : "attends" + users }|..|| roles : "has role" + meetings ||--|{ attendees : "has" + meetings ||--|{ audio_files : "has" + meetings ||--|{ transcript_tasks : "has" + meetings ||--|{ transcript_segments : "has" + meetings ||--|{ meeting_summaries : "has" + meetings ||--|{ llm_tasks : "has" + +``` diff --git a/deploy.md b/deploy.md new file mode 100644 index 0000000..aa63ea9 --- /dev/null +++ b/deploy.md @@ -0,0 +1,5 @@ +# 环境 + +# 组件 ++ 数据库 mysql 5.7+ 10.100.51.51:3306 root | Unis@123 ++ 缓存 redis 6.2 10.100.51.51:6379 Unis@123 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..9a946f2 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,130 @@ +version: '3.8' + +services: + # MySQL数据库 + mysql: + image: mysql:8.0 + container_name: imeeting-mysql + restart: unless-stopped + environment: + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-Unis@123} + MYSQL_DATABASE: ${MYSQL_DATABASE:-imeeting} + MYSQL_USER: ${MYSQL_USER:-imeeting} + MYSQL_PASSWORD: ${MYSQL_PASSWORD:-Unis@123} + TZ: Asia/Shanghai + # 仅在需要外部访问数据库时暴露端口 + ports: + - "${MYSQL_PORT:-3306}:3306" + volumes: + - ./data/mysql:/var/lib/mysql + - ./backend/sql:/docker-entrypoint-initdb.d:ro + command: + - --character-set-server=utf8mb4 + - --collation-server=utf8mb4_unicode_ci + - --default-authentication-plugin=mysql_native_password + - --max_connections=1000 + - --max_allowed_packet=256M + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-Unis@123}"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + networks: + - imeeting-network + + # Redis缓存 + redis: + image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/redis:7-alpineredis:7-alpine + container_name: imeeting-redis + restart: unless-stopped + environment: + TZ: Asia/Shanghai + # 仅在需要外部访问Redis时暴露端口 + ports: + - "${REDIS_PORT:-6379}:6379" + volumes: + - ./data/redis:/data + command: > + redis-server + --appendonly yes + --requirepass ${REDIS_PASSWORD:-Unis@123} + --maxmemory 2gb + --maxmemory-policy allkeys-lru + healthcheck: + test: ["CMD", "redis-cli", "--raw", "incr", "ping"] + interval: 10s + timeout: 3s + retries: 5 + start_period: 10s + networks: + - imeeting-network + + # 后端服务 + backend: + build: + context: ./backend + dockerfile: Dockerfile + container_name: imeeting-backend + restart: unless-stopped + depends_on: + mysql: + condition: service_healthy + redis: + condition: service_healthy + env_file: + - ./backend/.env + environment: + # Python环境 + TZ: Asia/Shanghai + PYTHONPATH: /app + PYTHONUNBUFFERED: 1 + # 强制使用容器内部服务名,覆盖本地.env配置 + DB_HOST: mysql + REDIS_HOST: redis + API_PORT: 8000 + # 后端不直接暴露端口,通过nginx代理访问 + # ports: + # - "${BACKEND_PORT:-8000}:8000" + volumes: + - ./data/uploads:/app/uploads + - ./data/logs/backend:/app/logs + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + networks: + - imeeting-network + + # 前端服务 + frontend: + build: + context: ./frontend + dockerfile: Dockerfile + container_name: imeeting-frontend + restart: unless-stopped + depends_on: + backend: + condition: service_healthy + environment: + TZ: Asia/Shanghai + # 前端不直接暴露端口,通过nginx代理访问 + # ports: + # - "${FRONTEND_PORT:-3001}:80" + volumes: + - ./data/logs/frontend:/var/log/nginx + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:80/"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + networks: + - imeeting-network + +# 网络配置 +networks: + imeeting-network: + driver: bridge diff --git a/docs/CLIENT_DOWNLOADS_MODULE.md b/docs/CLIENT_DOWNLOADS_MODULE.md new file mode 100644 index 0000000..a449f2e --- /dev/null +++ b/docs/CLIENT_DOWNLOADS_MODULE.md @@ -0,0 +1,292 @@ +# 客户端下载管理模块 + +## 概述 + +本模块实现了一个完整的客户端下载管理系统,支持移动端(iOS/Android)和桌面端(Windows/Mac/Linux)的版本管理和下载。 + +## 功能特性 + +### 1. 管理员功能 +- ✅ 创建/编辑/删除客户端版本 +- ✅ 管理版本号和版本代码 +- ✅ 设置最新版本标记 +- ✅ 启用/禁用特定版本 +- ✅ 添加更新说明和系统要求 +- ✅ 平台分类管理(移动端/桌面端) +- ✅ 搜索和过滤功能 + +### 2. 用户功能 +- ✅ 查看所有平台的最新客户端 +- ✅ 按平台分类展示 +- ✅ 显示版本信息和文件大小 +- ✅ 一键下载 + +### 3. API功能 +- ✅ 获取所有客户端列表(支持分页和过滤) +- ✅ 获取最新版本客户端 +- ✅ 按平台获取最新版本(用于客户端版本检查) +- ✅ CRUD操作(仅管理员) + +## 数据库设计 + +### 表结构: `client_downloads` + +```sql +CREATE TABLE client_downloads ( + id INT AUTO_INCREMENT PRIMARY KEY, + platform_type ENUM('mobile', 'desktop') NOT NULL, + platform_name VARCHAR(50) NOT NULL, + version VARCHAR(50) NOT NULL, + version_code INT NOT NULL DEFAULT 1, + download_url TEXT NOT NULL, + file_size BIGINT, + release_notes TEXT, + is_active BOOLEAN DEFAULT TRUE, + is_latest BOOLEAN DEFAULT FALSE, + min_system_version VARCHAR(50), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + created_by INT, + FOREIGN KEY (created_by) REFERENCES users(user_id) ON DELETE SET NULL, + INDEX idx_platform (platform_type, platform_name), + INDEX idx_version (version_code), + INDEX idx_active (is_active, is_latest) +); +``` + +### 字段说明 + +- `platform_type`: 平台类型(mobile/desktop) +- `platform_name`: 具体平台(ios/android/windows/mac_intel/mac_m/linux) +- `version`: 版本号字符串(如: 1.0.0) +- `version_code`: 版本代码数字(用于版本比较,如: 1000) +- `download_url`: 下载链接 +- `file_size`: 文件大小(字节) +- `release_notes`: 更新说明 +- `is_active`: 是否启用 +- `is_latest`: 是否为最新版本 +- `min_system_version`: 最低系统版本要求 + +## API接口 + +### 公开接口(无需认证) + +#### 1. 获取客户端列表 +``` +GET /api/clients/downloads +Query参数: + - platform_type: mobile|desktop (可选) + - platform_name: ios|android|windows|mac_intel|mac_m|linux (可选) + - is_active: true|false (可选) + - page: 页码 (默认1) + - size: 每页数量 (默认50) +``` + +#### 2. 获取所有最新版本 +``` +GET /api/clients/downloads/latest +返回: { mobile: [...], desktop: [...] } +``` + +#### 3. 获取指定平台最新版本 +``` +GET /api/clients/downloads/{platform_name}/latest +示例: GET /api/clients/downloads/ios/latest +``` + +#### 4. 获取指定ID的客户端 +``` +GET /api/clients/downloads/{id} +``` + +### 管理员接口(需要管理员权限) + +#### 5. 创建客户端版本 +``` +POST /api/clients/downloads +Body: { + "platform_type": "mobile", + "platform_name": "ios", + "version": "1.0.0", + "version_code": 1000, + "download_url": "https://...", + "file_size": 52428800, + "release_notes": "初始版本...", + "is_active": true, + "is_latest": false, + "min_system_version": "iOS 13.0" +} +``` + +#### 6. 更新客户端版本 +``` +PUT /api/clients/downloads/{id} +Body: { + "version": "1.0.1", + "version_code": 1001, + "is_latest": true, + ... +} +``` + +#### 7. 删除客户端版本 +``` +DELETE /api/clients/downloads/{id} +``` + +## 前端组件 + +### 1. ClientManagement (管理员页面) +位置: `frontend/src/pages/ClientManagement.jsx` + +功能: +- 客户端版本CRUD操作 +- 平台筛选和搜索 +- 版本状态管理 +- 响应式卡片布局 + +### 2. ClientDownloads (用户下载组件) +位置: `frontend/src/components/ClientDownloads.jsx` + +功能: +- 展示最新客户端版本 +- 按平台分类 +- 一键下载 +- 可嵌入任何页面 + +## 安装和部署 + +### 1. 数据库初始化 + +```bash +# 执行SQL文件 +mysql -u your_user -p your_database < backend/sql/client_downloads.sql +``` + +### 2. 后端启动 + +后端会自动加载新的路由,无需额外配置。 + +### 3. 前端使用 + +#### 在管理员页面添加客户端管理: + +```jsx +import ClientManagement from './pages/ClientManagement'; + +// 在管理员路由中添加 +} /> +``` + +#### 在首页添加下载组件: + +```jsx +import ClientDownloads from './components/ClientDownloads'; + +// 在Dashboard或任何页面中添加 + +``` + +## 使用示例 + +### 管理员创建新版本 + +1. 访问管理后台的"客户端管理"页面 +2. 点击"新增客户端"按钮 +3. 填写版本信息: + - 选择平台类型和具体平台 + - 输入版本号和版本代码 + - 填写下载链接 + - 添加更新说明 + - 勾选"设为最新版本"(如果是最新) +4. 点击"创建"保存 + +### 用户下载客户端 + +1. 在首页查看"下载客户端"区域 +2. 选择对应平台 +3. 点击卡片即可下载 + +### 客户端版本检查 + +客户端可以调用API检查是否有新版本: + +```javascript +// 检查iOS最新版本 +const response = await fetch('/api/clients/downloads/ios/latest'); +const latest = await response.json(); + +if (latest.data.version_code > currentVersionCode) { + // 提示用户更新 + showUpdateDialog(latest.data); +} +``` + +## 版本号规范 + +- **版本号**: 采用语义化版本(Semantic Versioning),格式: `主版本.次版本.修订号` + - 例如: 1.0.0, 1.2.3, 2.0.0 + +- **版本代码**: 纯数字,用于程序化比较 + - 推荐格式: 主版本(2位) + 次版本(2位) + 修订号(2位) + - 例如: 1.0.0 -> 10000, 1.2.3 -> 10203, 2.0.0 -> 20000 + +## 平台支持 + +### 移动端 +- **iOS**: App Store链接或企业分发链接 +- **Android**: Google Play链接或APK直接下载 + +### 桌面端 +- **Windows**: .exe安装包 +- **Mac (Intel)**: Intel架构的.dmg安装包 +- **Mac (M系列)**: Apple Silicon原生支持的.dmg安装包 +- **Linux**: .AppImage或.deb/.rpm包 + +## 注意事项 + +1. **下载链接**: 确保下载链接长期有效,建议使用CDN或对象存储 +2. **文件大小**: 建议填写准确的文件大小,方便用户了解下载时间 +3. **版本管理**: + - 同一平台只能有一个"最新版本" + - 设置新版本为最新时,会自动将旧版本的最新标记��除 +4. **权限控制**: CRUD操作仅管理员可执行,查询接口公开访问 + +## 扩展建议 + +1. **统计功能**: 添加下载次数统计 +2. **发布计划**: 支持定时发布新版本 +3. **灰度发布**: 按百分比或用户组逐步推送新版本 +4. **更新检查**: 提供SDK方便客户端集成版本检查 +5. **更新强制**: 支持强制更新标记 + +## 文件清单 + +### 后端 +- `backend/sql/client_downloads.sql` - 数据库表结构和初始数据 +- `backend/app/models/models.py` - Pydantic数据模型 +- `backend/app/api/endpoints/client_downloads.py` - API路由和业务逻辑 +- `backend/main.py` - 路由注册 + +### 前端 +- `frontend/src/pages/ClientManagement.jsx` - 管理员管理页面 +- `frontend/src/pages/ClientManagement.css` - 管理页面样式 +- `frontend/src/components/ClientDownloads.jsx` - 用户下载组件 +- `frontend/src/components/ClientDownloads.css` - 下载组件样式 +- `frontend/src/config/api.js` - API配置 + +## 技术栈 + +### 后端 +- FastAPI +- MySQL +- Pydantic + +### 前端 +- React +- Lucide React Icons +- CSS3 + +## 作者 + +Generated with Claude Code diff --git a/frontend b/frontend new file mode 160000 index 0000000..6cbe02f --- /dev/null +++ b/frontend @@ -0,0 +1 @@ +Subproject commit 6cbe02fbf637e8cd3004c7947be5706a8cb814d7 diff --git a/manage.sh b/manage.sh new file mode 100755 index 0000000..1fe6dbf --- /dev/null +++ b/manage.sh @@ -0,0 +1,303 @@ +#!/bin/bash + +# iMeeting Docker 管理脚本 +# 用于日常管理和维护 + +set -e + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +print_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# 确定使用的命令 +if docker compose version &> /dev/null; then + COMPOSE_CMD="docker compose" +else + COMPOSE_CMD="docker-compose" +fi + +# 显示菜单 +show_menu() { + echo "" + echo -e "${BLUE}==================================${NC}" + echo -e "${BLUE} iMeeting 管理菜单${NC}" + echo -e "${BLUE}==================================${NC}" + echo "" + echo "1) 查看服务状态" + echo "2) 查看实时日志" + echo "3) 重启所有服务" + echo "4) 重启单个服务" + echo "5) 进入容器终端" + echo "6) 备份数据库" + echo "7) 恢复数据库" + echo "8) 清理Redis缓存" + echo "9) 更新服务" + echo "10) 查看资源使用" + echo "11) 导出日志" + echo "0) 退出" + echo "" + read -p "请选择操作 (0-11): " choice +} + +# 查看服务状态 +view_status() { + print_info "服务状态:" + $COMPOSE_CMD ps + echo "" + read -p "按任意键返回菜单..." -n 1 +} + +# 查看实时日志 +view_logs() { + echo "选择要查看的服务:" + echo "1) 所有服务" + echo "2) Nginx" + echo "3) 前端" + echo "4) 后端" + echo "5) MySQL" + echo "6) Redis" + read -p "请选择: " log_choice + + case $log_choice in + 1) $COMPOSE_CMD logs -f ;; + 2) $COMPOSE_CMD logs -f nginx ;; + 3) $COMPOSE_CMD logs -f frontend ;; + 4) $COMPOSE_CMD logs -f backend ;; + 5) $COMPOSE_CMD logs -f mysql ;; + 6) $COMPOSE_CMD logs -f redis ;; + *) print_error "无效选择" ;; + esac +} + +# 重启服务 +restart_services() { + print_info "重启所有服务..." + $COMPOSE_CMD restart + print_success "服务已重启" + read -p "按任意键返回菜单..." -n 1 +} + +# 重启单个服务 +restart_single_service() { + echo "选择要重启的服务:" + echo "1) Nginx" + echo "2) 前端" + echo "3) 后端" + echo "4) MySQL" + echo "5) Redis" + read -p "请选择: " service_choice + + case $service_choice in + 1) $COMPOSE_CMD restart nginx ;; + 2) $COMPOSE_CMD restart frontend ;; + 3) $COMPOSE_CMD restart backend ;; + 4) $COMPOSE_CMD restart mysql ;; + 5) $COMPOSE_CMD restart redis ;; + *) print_error "无效选择"; return ;; + esac + + print_success "服务已重启" + read -p "按任意键返回菜单..." -n 1 +} + +# 进入容器 +enter_container() { + echo "选择要进入的容器:" + echo "1) Nginx" + echo "2) 前端" + echo "3) 后端" + echo "4) MySQL" + echo "5) Redis" + read -p "请选择: " container_choice + + case $container_choice in + 1) $COMPOSE_CMD exec nginx sh ;; + 2) $COMPOSE_CMD exec frontend sh ;; + 3) $COMPOSE_CMD exec backend bash ;; + 4) $COMPOSE_CMD exec mysql bash ;; + 5) $COMPOSE_CMD exec redis sh ;; + *) print_error "无效选择" ;; + esac +} + +# 备份数据库 +backup_database() { + print_info "开始备份数据库..." + + mkdir -p backups + backup_file="backups/imeeting_$(date +%Y%m%d_%H%M%S).sql" + + source .env 2>/dev/null || true + MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-Unis@123} + + $COMPOSE_CMD exec mysql mysqldump -uroot -p"${MYSQL_ROOT_PASSWORD}" \ + --single-transaction \ + --routines \ + --triggers \ + imeeting > "$backup_file" + + print_success "数据库已备份到: $backup_file" + read -p "按任意键返回菜单..." -n 1 +} + +# 恢复数据库 +restore_database() { + print_warning "警告: 这将覆盖当前数据库!" + + if [ ! -d "backups" ] || [ -z "$(ls -A backups/*.sql 2>/dev/null)" ]; then + print_error "未找到备份文件" + read -p "按任意键返回菜单..." -n 1 + return + fi + + echo "" + echo "可用的备份文件:" + ls -lh backups/*.sql + echo "" + read -p "请输入备份文件名: " backup_file + + if [ ! -f "$backup_file" ]; then + print_error "文件不存在: $backup_file" + read -p "按任意键返回菜单..." -n 1 + return + fi + + read -p "确认恢复? (yes/no): " confirm + if [ "$confirm" = "yes" ]; then + print_info "开始恢复数据库..." + + source .env 2>/dev/null || true + MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-Unis@123} + + $COMPOSE_CMD exec -T mysql mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" imeeting < "$backup_file" + + print_success "数据库已恢复" + else + print_info "操作已取消" + fi + + read -p "按任意键返回菜单..." -n 1 +} + +# 清理Redis缓存 +clear_redis() { + print_warning "这将清空所有Redis缓存" + read -p "确认清空? (yes/no): " confirm + + if [ "$confirm" = "yes" ]; then + source .env 2>/dev/null || true + REDIS_PASSWORD=${REDIS_PASSWORD:-Unis@123} + + $COMPOSE_CMD exec redis redis-cli -a "${REDIS_PASSWORD}" FLUSHALL + print_success "Redis缓存已清空" + else + print_info "操作已取消" + fi + + read -p "按任意键返回菜单..." -n 1 +} + +# 更新服务 +update_services() { + echo "选择更新方式:" + echo "1) 更新所有服务" + echo "2) 仅更新前端" + echo "3) 仅更新后端" + read -p "请选择: " update_choice + + case $update_choice in + 1) + print_info "更新所有服务..." + $COMPOSE_CMD build + $COMPOSE_CMD up -d + ;; + 2) + print_info "更新前端..." + $COMPOSE_CMD build frontend + $COMPOSE_CMD up -d frontend + ;; + 3) + print_info "更新后端..." + $COMPOSE_CMD build backend + $COMPOSE_CMD up -d backend + ;; + *) + print_error "无效选择" + ;; + esac + + print_success "更新完成" + read -p "按任意键返回菜单..." -n 1 +} + +# 查看资源使用 +view_resources() { + print_info "容器资源使用情况:" + docker stats --no-stream $(docker ps --format "{{.Names}}" | grep imeeting) + echo "" + read -p "按任意键返回菜单..." -n 1 +} + +# 导出日志 +export_logs() { + print_info "导出日志..." + + mkdir -p logs_export + timestamp=$(date +%Y%m%d_%H%M%S) + + $COMPOSE_CMD logs --no-color > "logs_export/all_services_${timestamp}.log" + $COMPOSE_CMD logs --no-color nginx > "logs_export/nginx_${timestamp}.log" + $COMPOSE_CMD logs --no-color frontend > "logs_export/frontend_${timestamp}.log" + $COMPOSE_CMD logs --no-color backend > "logs_export/backend_${timestamp}.log" + $COMPOSE_CMD logs --no-color mysql > "logs_export/mysql_${timestamp}.log" + $COMPOSE_CMD logs --no-color redis > "logs_export/redis_${timestamp}.log" + + print_success "日志已导出到: logs_export/" + read -p "按任意键返回菜单..." -n 1 +} + +# 主循环 +main() { + while true; do + clear + show_menu + + case $choice in + 1) view_status ;; + 2) view_logs ;; + 3) restart_services ;; + 4) restart_single_service ;; + 5) enter_container ;; + 6) backup_database ;; + 7) restore_database ;; + 8) clear_redis ;; + 9) update_services ;; + 10) view_resources ;; + 11) export_logs ;; + 0) print_info "退出管理脚本"; exit 0 ;; + *) print_error "无效选择"; sleep 1 ;; + esac + done +} + +# 运行主程序 +main diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..00ff604 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "imeeting", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/package.json @@ -0,0 +1 @@ +{} diff --git a/project.md b/project.md new file mode 100644 index 0000000..e4fe554 --- /dev/null +++ b/project.md @@ -0,0 +1,218 @@ +# 项目设计文档:iMeeting (智慧会议) + +## 1. 项目概述 + +**项目名称**: iMeeting (智慧会议) + +**目标**: 为需要参加大量会议的专业人士、团队管理者和企业员工,提供一个高效、智能的会议记录与内容管理平台。通过AI技术,将非结构化的会议音视频内容,转化为易于检索、回顾和分发的结构化信息,从而节省用户整理会议纪要的时间,提升信息流转效率。 + +**核心价值**: +- **解放生产力**: 自动化的会议转录和摘要,让用户从繁琐的记录工作中解放出来。 +- **信息不丢失**: 精准记录每一次会议的细节,确保关键信息和决策得到妥善保存。 +- **高效回顾**: 通过时间轴、发言人和关键词,快速定位会议内容。 +- **便捷分享**: 轻松分享会议纪要、材料和关键节点给相关人员。 + +## 2. 核心功能 + +- **会议管理**: 创建、编辑、删除会议,管理参会人员。 +- **音频上传与处理**: 上传会议音频,触发后台异步任务进行语音转文字和说话人分离。 +- **智能转录内容**: 提供带时间轴、可编辑、可播放的会议文稿。 +- **发言人管理**: 自动识别发言人并支持用户自定义标签。 +- **AI会议纪要**: 异步生成会议摘要,支持用户自定义提示词,并可多次生成。 +- **用户与权限管理**: 支持管理员对用户进行增删改查和密码重置。 + +## 3. 技术栈 + +- **后端**: Python 3.9+, FastAPI +- **数据库**: MySQL 5.7+ +- **缓存与任务队列**: Redis +- **AI服务**: 阿里云通义千问 (语音识别、LLM) +- **前端**: React (Vite) + Ant Design +- **部署**: Docker, Nginx + +## 4. 异步任务设计 + +项目包含两大核心异步任务:**语音转录**和**AI总结**,均通过后台任务实现,以避免长时间阻塞API请求。 + +### 4.1. 语音转录 (Async Transcription) + +- **触发**: 用户上传音频文件 (`POST /meetings/upload-audio`) 成功后自动触发。 +- **实现**: `AsyncTranscriptionService` 调用阿里云 `Dashscope` 的 `paraformer-v2` 模型进行异步语音识别。 + 1. **启动任务**: 调用 `Transcription.async_call`,获取一个外部任务ID (`paraformer_task_id`)。 + 2. **创建内部任务**: 生成一个系统内部的业务ID (`business_task_id`),并将两个ID的映射关系及任务元数据存入 `transcript_tasks` 表和Redis缓存。 + 3. **状态查询**: 前端通过 `GET /transcription/tasks/{task_id}/status` 或 `GET /meetings/{meeting_id}/transcription/status` 轮询任务状态。 + 4. **获取结果**: 服务端在查询状态时,若发现外部任务已完成,则通过 `Transcription.fetch` 获取结果URL,下载JSON格式的转录数据。 + 5. **数据入库**: 解析JSON数据,将包含发言人ID、时间戳和文本的 `transcript_segments` 存入数据库。 +- **关键代码**: `backend/app/services/async_transcription_service.py` + +### 4.2. AI总结 (Async LLM Summary) + +- **触发**: 用户在会议详情页点击“生成纪要” (`POST /meetings/{meeting_id}/generate-summary-async`)。 +- **实现**: `AsyncLLMService` 利用 FastAPI 的 `BackgroundTasks` 实现轻量级异步处理。 + 1. **创建任务**: 生成一个任务ID (`task_id`),并将任务元数据(会议ID、用户提示词等)存入 `llm_tasks` 表和Redis缓存,立即返回任务ID给前端。 + 2. **后台执行**: `_process_task` 函数在后台运行,它按顺序执行:获取转录稿、构建Prompt、调用LLM API、保存结果。 + 3. **状态与进度更新**: 在执行的每个关键步骤,都会更新Redis中的任务状态和进度百分比 (`processing`, `10%`, `30%` ...)。 + 4. **状态查询**: 前端通过 `GET /llm-tasks/{task_id}/status` 轮询任务状态和进度。 + 5. **结果获取**: 任务完成后,状态变为 `completed`,结果会保存在 `llm_tasks` 表的 `result` 字段,并可通过状态查询接口获取。 +- **关键代码**: `backend/app/services/async_llm_service.py` + +### 4.3. 声纹采集 +## 前端UI要素 + +### Dashboard 声纹状态显示 +- **未采集**:显示"采集声纹"按钮(醒目样式,如橙色或主题色) +- **已采集**:显示波纹图标(可使用音频波形SVG或动画效果) + +### 声纹采集对话框 +- 标题:"声纹采集" +- 朗读文本显示区域(滚动文本) +- 录制按钮:"开始录制" / "正在录制..." +- 进度显示: + - 圆形进度环(推荐) + - 或倒计时文字:"10s" → "9s" → ... → "0s" +- 提示信息:"请在安静环境下,用自然语速朗读上述文字" +- 操作按钮:"取消" / "重新录制" + +### 音频波形图标示例 +可以使用类似这样的SVG图标: +```html + + + +``` +## 文件存储结构 + +``` +uploads/ +└── voiceprint/ + └── {user_id}/ + └── timestamp.wav # 采集时间为文件名。 +``` + +**存储说明:** +- 每个用户只保留一个声纹文件 +- 用户目录在首次采集时创建 + +## 声纹朗读模板配置 + +朗读模板配置在 `config/system_config.json` 中: + +```json +{ + "voiceprint": { + "template_text": "我正在进行声纹采集,这段语音将用于身份识别和验证。声纹技术能够准确识别每个人独特的声音特征,就像指纹一样独一无二。请保持自然的语速和音量进行朗读。", + "duration_seconds": 10, + "sample_rate": 16000, + "channels": 1 + } +} +``` + +**配置说明:** +- `template_text`: 用户朗读的标准文本 +- `duration_seconds`: 建议录制时长(秒) +- `sample_rate`: 音频采样率(Hz) +- `channels`: 声道数(1=单声道) + +## 5. API 接口文档 + +### 5.1. 认证接口 (`/auth`) + +- `POST /auth/login`: 用户登录。 + - **Request**: `LoginRequest` (username, password) + - **Response**: `LoginResponse` (user_info, token) +- `POST /auth/logout`: 用户登出,使当前Token失效。 +- `POST /auth/logout-all`: 登出该用户的所有设备。 +- `GET /auth/me`: 获取当前登录用户的信息。 +- `POST /auth/refresh`: 刷新当前用户的Token。 + +### 5.2. 用户管理接口 (`/users`) + +> **权限**: 以下接口均需要管理员权限 (role_id=1)。 + +- `GET /roles`: 获取所有角色列表。 +- `POST /users`: 创建新用户。 + - **Request**: `CreateUserRequest` +- `GET /users`: 分页获取用户列表。 +- `GET /users/{user_id}`: 获取指定用户的详细信息。 +- `PUT /users/{user_id}`: 更新用户信息。 + - **Request**: `UpdateUserRequest` +- `DELETE /users/{user_id}`: 删除用户。 +- `POST /users/{user_id}/reset-password`: 重置用户密码为默认值。 +- `PUT /users/{user_id}/password`: 修改用户密码 (管理员无需旧密码)。 + +### 5.3. 会议与转录接口 (`/meetings`) + +- `GET /meetings`: 获取会议列表,可通过 `user_id` 过滤。 +- `POST /meetings`: 创建新会议。 + - **Request**: `CreateMeetingRequest` +- `GET /meetings/{meeting_id}`: 获取单个会议的详细信息,包含转录状态。 +- `PUT /meetings/{meeting_id}`: 更新会议信息(标题、时间、参会人等)。 +- `DELETE /meetings/{meeting_id}`: 删除会议及所有相关数据。 +- `GET /meetings/{meeting_id}/edit`: 获取用于编辑页面的会议信息。 + +#### 音频与转录 + +- `POST /meetings/upload-audio`: 上传音频文件,并自动开始异步转录。 + - **Form Data**: `audio_file`, `meeting_id`, `force_replace` +- `GET /meetings/{meeting_id}/audio`: 获取会议关联的音频文件信息。 +- `GET /meetings/{meeting_id}/transcript`: 获取会议的完整转录稿 (`TranscriptSegment` 列表)。 +- `POST /meetings/{meeting_id}/transcription/start`: 手动触发指定会议的转录任务。 +- `GET /meetings/{meeting_id}/transcription/status`: 获取会议最新的转录任务状态。 +- `GET /transcription/tasks/{task_id}/status`: 根据任务ID获取转录状态。 + +#### 内容编辑 + +- `PUT /meetings/{meeting_id}/speaker-tags`: 更新单个发言人的标签。 +- `PUT /meetings/{meeting_id}/speaker-tags/batch`: 批量更新多个发言人的标签。 +- `PUT /meetings/{meeting_id}/transcript/batch`: 批量更新转录内容文本。 + +#### AI 总结 + +- `POST /meetings/{meeting_id}/generate-summary-async`: **异步**生成会议纪要。 + - **Request**: `GenerateSummaryRequest` (user_prompt) + - **Response**: 返回一个任务ID,用于轮询状态。 +- `GET /llm-tasks/{task_id}/status`: 获取AI总结任务的状态和进度。 +- `GET /meetings/{meeting_id}/llm-tasks`: 获取指定会议的所有AI总结任务历史。 +- `GET /meetings/{meeting_id}/latest-llm-task`: 获取会议最新的AI总结任务状态(此方法被替代)。 + +#### 其他 + +- `POST /meetings/{meeting_id}/upload-image`: 上传图片,用于在Markdown纪要中引用。 + +### 声纹采集功能 API + +### 1. 获取用户声纹状态 +- **GET** `/voiceprint/{user_id}` +- **描述**:获取指定用户的声纹采集状态 +- **权限**:需要登录,只能查询自己的声纹状态(管理员可查询所有) + +### 2. 获取朗读模板 +- **GET** `/voiceprint/template` +- **描述**:获取声纹采集的标准朗读文本 +- **权限**:需要登录 + +### 3. 上传声纹音频(同步处理) +- **POST** `/voiceprint/{user_id}` +- **描述**:上传声纹音频文件,同步处理并返回结果 +- **权限**:需要登录,只能上传自己的声纹(管理员可操作所有) + +### 4. 删除/重新采集声纹 +- **DELETE** `/voiceprint/{user_id}` +- **描述**:删除用户的声纹数据,允许重新采集 +- **权限**:需要登录,只能删除自己的声纹(管理员可操作所有) + + +## 6. 数据库设计 + +详细的数据库表结构、字段和关系图已被迁移到独立的文档中。 + +**[-> 点击查看数据库设计文档](./database.md)** + +## 7. 未来展望 + +- **实时转录**: 支持对正在进行的会议进行实时语音转文字。 +- **日历集成**: 与 Google Calendar, Outlook Calendar 集成,自动导入会议安排。 +- **行动项提取**: AI自动识别会议中的待办事项 (Action Items)。 +- **跨会议搜索**: 对用户的所有会议内容进行全文语义搜索。 +- **移动端应用**: 开发 iOS 和 Android 版本的原生应用。 \ No newline at end of file diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..bbad364 --- /dev/null +++ b/start.sh @@ -0,0 +1,333 @@ +#!/bin/bash + +# iMeeting Docker 快速启动脚本 +# 使用方法: ./start.sh [选项] + +set -e + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# 打印带颜色的消息 +print_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# 打印banner +print_banner() { + echo -e "${BLUE}" + cat << "EOF" + _ __ __ _ _ + (_) \/ | ___ ___| |_(_)_ __ __ _ + | | |\/| |/ _ \/ _ \ __| | '_ \ / _` | + | | | | | __/ __/ |_| | | | | (_| | + |_|_| |_|\___|\___|\__|_|_| |_|\__, | + |___/ + Docker Deployment Script +EOF + echo -e "${NC}" +} + +# 检查依赖 +check_dependencies() { + print_info "检查系统依赖..." + + if ! command -v docker &> /dev/null; then + print_error "未安装 Docker,请先安装 Docker" + exit 1 + fi + + if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then + print_error "未安装 Docker Compose,请先安装 Docker Compose" + exit 1 + fi + + print_success "系统依赖检查通过" +} + +# 检查环境变量文件 +check_env_file() { + print_info "检查环境变量配置..." + + if [ ! -f .env ]; then + print_warning ".env 文件不存在,从模板创建..." + cp .env.example .env + print_warning "请编辑 .env 文件,配置必要的参数(七牛云、LLM API等)" + print_warning "按任意键继续,或 Ctrl+C 退出..." + read -n 1 -s + else + print_success "环境变量文件已存在" + fi +} + +# 检查并创建后端环境变量文件# 创建必要的目录 +create_directories() { + print_info "创建必要的目录..." + + # MySQL和Nginx配置目录 + mkdir -p mysql/conf.d + mkdir -p nginx/conf.d + + # 数据持久化目录 + mkdir -p data/mysql + mkdir -p data/redis + mkdir -p data/uploads + mkdir -p data/logs/backend + mkdir -p data/logs/frontend + mkdir -p data/logs/nginx + + # 后端配置和备份目录 + mkdir -p backend/config + mkdir -p backups + + print_success "目录创建完成" +} + +# 生成Nginx配置 +generate_nginx_config() { + print_info "检查Nginx配置..." + + if [ ! -f nginx/nginx.conf ]; then + print_warning "nginx/nginx.conf 不存在,正在生成默认配置..." + cat > nginx/nginx.conf < nginx/conf.d/default.conf < /dev/null; then + COMPOSE_CMD="docker compose" + else + COMPOSE_CMD="docker-compose" + fi + + $COMPOSE_CMD up -d + + print_success "服务启动命令已执行" +} + +# 等待服务健康 +wait_for_health() { + print_info "等待服务启动..." + + local max_wait=120 + local waited=0 + + while [ $waited -lt $max_wait ]; do + if docker compose version &> /dev/null; then + COMPOSE_CMD="docker compose" + else + COMPOSE_CMD="docker-compose" + fi + + local healthy_count=$($COMPOSE_CMD ps --format json 2>/dev/null | grep -c '"Health":"healthy"' || echo "0") + local total_count=5 # mysql, redis, backend, frontend, nginx + + if [ "$healthy_count" -eq "$total_count" ]; then + print_success "所有服务已就绪" + return 0 + fi + + echo -ne "\r等待中... (${waited}s/${max_wait}s) 健康: ${healthy_count}/${total_count}" + sleep 5 + waited=$((waited + 5)) + done + + echo "" + print_warning "服务启动超时,请手动检查状态: docker-compose ps" + return 1 +} + +# 显示服务状态 +show_status() { + print_info "服务状态:" + + if docker compose version &> /dev/null; then + docker compose ps + else + docker-compose ps + fi +} + +# 显示访问信息 +show_access_info() { + echo "" + print_success "===================================" + print_success " iMeeting 部署完成!" + print_success "===================================" + echo "" + echo -e "${GREEN}访问地址:${NC}" + echo -e " HTTP访问: ${BLUE}http://localhost${NC}" + echo -e " (或通过服务器IP访问:${BLUE}http://服务器IP${NC})" + echo -e " API文档: ${BLUE}http://localhost/docs${NC}" + echo "" + echo -e "${YELLOW}域名访问(HTTPS):${NC}" + echo -e " 需要在接入服务器配置Nginx代理" + echo -e " 参考文档: ${BLUE}GATEWAY_NGINX_CONFIG.md${NC}" + echo "" + echo -e "${YELLOW}数据目录:${NC}" + echo -e " 数据持久化: ${BLUE}./data/${NC}" + echo -e " - MySQL: ${BLUE}./data/mysql/${NC}" + echo -e " - Redis: ${BLUE}./data/redis/${NC}" + echo -e " - 上传文件: ${BLUE}./data/uploads/${NC}" + echo -e " - 日志: ${BLUE}./data/logs/${NC}" + echo "" + echo -e "${YELLOW}常用命令:${NC}" + echo -e " 管理菜单: ${BLUE}./manage.sh${NC}" + echo -e " 查看日志: ${BLUE}docker-compose logs -f${NC}" + echo -e " 停止服务: ${BLUE}./stop.sh${NC}" + echo -e " 重启服务: ${BLUE}docker-compose restart${NC}" + echo -e " 查看状态: ${BLUE}docker-compose ps${NC}" + echo "" + echo -e "${YELLOW}更多信息请查看: ${BLUE}DOCKER_DEPLOYMENT.md${NC}" + echo "" +} + +# 主函数 +main() { + print_banner + + check_dependencies + check_env_file + check_backend_env + create_directories + generate_nginx_config + start_services + + echo "" + wait_for_health + + echo "" + show_status + show_access_info +} + +# 执行主函数 +main "$@" diff --git a/stop.sh b/stop.sh new file mode 100755 index 0000000..c3a1026 --- /dev/null +++ b/stop.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# iMeeting Docker 停止脚本 + +set -e + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +print_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +# 确定使用的命令 +if docker compose version &> /dev/null; then + COMPOSE_CMD="docker compose" +else + COMPOSE_CMD="docker-compose" +fi + +# 显示当前状态 +print_info "当前服务状态:" +$COMPOSE_CMD ps + +echo "" + +# 询问是否删除数据 +echo -e "${YELLOW}是否保留数据?${NC}" +echo "1) 仅停止服务(保留所有数据)" +echo "2) 停止服务并删除容器(保留数据卷)" +echo "3) 停止服务并删除所有数据(包括数据库)" +read -p "请选择 (1/2/3): " choice + +case $choice in + 1) + print_info "停止服务..." + $COMPOSE_CMD stop + print_success "服务已停止,数据已保留" + ;; + 2) + print_info "停止并删除容器..." + $COMPOSE_CMD down + print_success "容器已删除,数据卷已保留" + ;; + 3) + print_warning "警告: 这将删除所有数据,包括数据库!" + read -p "确认删除所有数据? (yes/no): " confirm + if [ "$confirm" = "yes" ]; then + print_info "停止并删除所有数据..." + $COMPOSE_CMD down -v + print_success "所有服务和数据已删除" + else + print_info "操作已取消" + fi + ;; + *) + print_warning "无效选择,仅停止服务" + $COMPOSE_CMD stop + ;; +esac diff --git a/资料/10寸产品页.png b/资料/10寸产品页.png new file mode 100644 index 0000000..aa3bf90 Binary files /dev/null and b/资料/10寸产品页.png differ diff --git a/资料/8寸产品页.png b/资料/8寸产品页.png new file mode 100644 index 0000000..8dedb3c Binary files /dev/null and b/资料/8寸产品页.png differ diff --git a/资料/iMeeting 产品介绍(第一版).docx b/资料/iMeeting 产品介绍(第一版).docx new file mode 100644 index 0000000..63936ab Binary files /dev/null and b/资料/iMeeting 产品介绍(第一版).docx differ diff --git a/资料/iMeeting-让每一次谈话都产生价值.png b/资料/iMeeting-让每一次谈话都产生价值.png new file mode 100644 index 0000000..88038b5 Binary files /dev/null and b/资料/iMeeting-让每一次谈话都产生价值.png differ diff --git a/资料/iMeeting_让每一次谈话都产生价值.pdf b/资料/iMeeting_让每一次谈话都产生价值.pdf new file mode 100644 index 0000000..fd290ac Binary files /dev/null and b/资料/iMeeting_让每一次谈话都产生价值.pdf differ diff --git a/资料/iMeeting算力一体机配置建议.xlsx b/资料/iMeeting算力一体机配置建议.xlsx new file mode 100644 index 0000000..2dea132 Binary files /dev/null and b/资料/iMeeting算力一体机配置建议.xlsx differ diff --git a/资料/slogan.png b/资料/slogan.png new file mode 100644 index 0000000..7be4621 Binary files /dev/null and b/资料/slogan.png differ diff --git a/资料/slogan_1280x800.png b/资料/slogan_1280x800.png new file mode 100644 index 0000000..5867f69 Binary files /dev/null and b/资料/slogan_1280x800.png differ diff --git a/资料/slogan_white.png b/资料/slogan_white.png new file mode 100644 index 0000000..38ac4bc Binary files /dev/null and b/资料/slogan_white.png differ diff --git a/资料/一键生成总结.png b/资料/一键生成总结.png new file mode 100644 index 0000000..9ec2586 Binary files /dev/null and b/资料/一键生成总结.png differ diff --git a/资料/产品介绍.md b/资料/产品介绍.md new file mode 100644 index 0000000..2c52a7b --- /dev/null +++ b/资料/产品介绍.md @@ -0,0 +1,317 @@ +# iMeeting 产品介绍 + +> **AI 驱动的智能会议管理与知识库系统** +> +> 让每一次会议都产生价值,让知识自动沉淀与传播 + +--- + +## 📌 产品定位 + +iMeeting 是一款面向企业和团队的智能会议管理工具,通过 AI 技术自动将会议录音转化为结构化知识,帮助团队高效管理会议、沉淀知识、提升协作效率。 + +### 核心价值 + +- **⏰ 节省时间**:自动生成会议纪要,无需人工整理 +- **🧠 知识沉淀**:从多次会议中提炼知识库,避免重复讨论 +- **🎯 精准检索**:AI 智能问答,快速找到需要的信息 +- **🎙️ 音频播客**:将知识转化为播客音频,随时随地学习 + +--- + +## ✨ 核心功能(Phase 1 - 已实现) + +### 🎤 智能会议管理 + +#### 一键转录 +- 上传会议录音,自动转写为文字 +- 支持多种音频格式(MP3、WAV、M4A) +- 基于阿里云语音识别,识别准确率 > 95% + +#### AI 自动总结 +- 使用大语言模型(通义千问)生成会议纪要 +- 支持自定义提示词模版,适配不同会议场景 +- 一键生成结构化总结:会议主题、关键决策、待办事项 + +#### 灵活标签分类 +- 为会议添加多个标签,方便分类管理 +- 按标签快速筛选和检索历史会议 + +--- + +### 📚 智能知识库 + +#### 会议知识提炼 +- 从多个会议纪要中自动提炼知识库内容 +- 支持自定义分析角度和总结需求 +- 生成 Markdown 格式的结构化知识文档 + +#### 知识共享 +- 支持个人知识库和共享知识库 +- 团队成员可协作构建组织知识资产 + +#### 标签与检索 +- 知识库标签分类 +- 全文搜索,快速定位内容 + +--- + +### 👥 权限与管理 + +#### 用户权限管理 +- 基于角色的权限控制(普通用户/管理员) +- JWT 安全认证 +- 动态菜单权限 + +#### 管理后台 +- 用户管理:创建、编辑、权限配置 +- 系统监控:在线用户、任务状态、资源监控 +- 提示词仓库:集中管理 AI 提示词模版 + +--- + +## 🚀 未来规划(Phase 2 - 开发中) + +### 🌟 全新升级:从会议工具到 AI 知识助手 + +参考 Google NotebookLM,iMeeting 即将升级为功能完整的 AI 知识助手,提供多维度的知识管理和智能交互能力。 + +--- + +### 📂 多源输入 + +不再局限于会议内容,支持更丰富的知识来源: + +| 输入类型 | 支持格式 | 说明 | +|---------|---------|------| +| **文档** | PDF、Word、TXT、Markdown | 上传技术文档、报告、笔记 | +| **音频** | MP3、WAV、M4A | 讲座录音、播客、培训音频 | +| **视频** | MP4、AVI、MOV | 自动提取音频并转录 | +| **会议** | 已有功能 | 从会议纪要中提炼知识 | + +**混合使用**:单个知识库可同时包含多种来源,全面汇总信息。 + +--- + +### 🎙️ 播客式音频概览 + +#### 文字转语音(TTS) +- 将知识库内容转换为音频,支持随时随地收听 +- 多种音色可选,语速可调 + +#### NotebookLM 风格的播客对话 +**创新功能**:自动生成双人对话式播客 + +- 🎭 **双人角色**:主持人(引导话题) + 专家(深度讲解) +- 💬 **自然对话**:通过问答形式展开知识点,生动易懂 +- 🎵 **专业制作**:自动添加片头片尾、背景音乐、音量均衡 + +**使用场景**: +- 上班通勤时听取项目汇报 +- 运动时学习技术文档 +- 团队培训音频分享 + +--- + +### 💬 NotebookLM 式智能问答 + +#### 基于知识库的对话 +- **精准回答**:基于向量检索(RAG 技术),从知识库中精准定位答案 +- **引用溯源**:回答时显示来源段落、章节、页码 +- **多轮对话**:支持上下文记忆,连续提问 +- **相关推荐**:基于提问智能推荐相关知识点 + +#### 交互示例 + +``` +用户: "上次会议讨论的产品发布日期是什么时候?" + +AI: "根据《产品规划会议纪要》(2024-03-15)第 2 章节, + 产品发布日期定为 2024年6月1日。 + + 📚 来源: + - 产品规划会议纪要 > 第二部分:时间规划 > 发布节点 + - 原文:"经过讨论,团队一致决定将正式发布日期定为6月1日..." +``` + +--- + +### 📊 结构化输出升级 + +#### 智能提示词组合 +- **基础模版**:从提示词仓库选择预设模版 +- **附加提示词**:在模版基础上追加自定义需求 +- **输出格式控制**:自动生成多级章节结构(标题、章节、小节) + +#### 示例 + +**输入**: +- 基础模版:技术文档总结模版 +- 附加提示词:"重点关注性能优化和安全性" + +**输出**: +```markdown +# XXX技术方案总结 + +## 1. 技术架构 +### 1.1 整体架构 +### 1.2 核心模块 + +## 2. 性能优化(重点) +### 2.1 数据库优化 +### 2.2 缓存策略 + +## 3. 安全性设计(重点) +### 3.1 认证与授权 +### 3.2 数据加密 +... +``` + +--- + +## 🎯 应用场景 + +### 企业协作 +- **项目管理**:自动记录项目会议,生成任务清单 +- **知识传承**:新员工快速了解历史项目和决策背景 +- **培训学习**:将培训内容转化为知识库和播客 + +### 研发团队 +- **技术评审**:自动整理技术评审会议,生成方案文档 +- **代码审查**:记录审查要点,形成最佳实践知识库 +- **团队同步**:定期会议自动生成周报、月报 + +### 教育培训 +- **课程记录**:将讲座、课程录音转化为文字和播客 +- **知识问答**:学生可向课程知识库提问,获得精准答案 +- **复习资料**:自动生成结构化复习材料 + +### 咨询与销售 +- **客户会议**:自动记录需求和承诺,生成跟进任务 +- **知识沉淀**:积累行业洞察和解决方案 +- **快速响应**:从历史案例中快速找到相似场景 + +--- + +## 💡 技术亮点 + +### AI 能力 +- **语音识别**:基于阿里云 DashScope,识别准确率 > 95% +- **大语言模型**:通义千问驱动,智能总结与问答 +- **向量检索**:基于 RAG 技术,精准定位知识 +- **语音合成**:自然流畅的多音色 TTS + +### 技术架构 +- **前端**:React 18 + Ant Design,现代化交互体验 +- **后端**:FastAPI(Python),高性能异步处理 +- **数据库**:MySQL 8.0 + Redis,稳定可靠 +- **存储**:七牛云 OSS,快速访问 + +### 安全与性能 +- **数据安全**:JWT 认证、角色权限控制 +- **高可用**:异步任务处理、系统监控 +- **可扩展**:模块化设计,支持功能灵活组合 + +--- + +## 📈 产品价值 + +### 效率提升 +- **节省 80% 会议记录时间**:自动转录和总结 +- **减少 50% 信息查找时间**:AI 智能问答 +- **提升 3 倍知识复用率**:知识库沉淀与共享 + +### 成本优势 +- **月运营成本 < 100 元**(中小规模团队) +- **无需额外硬件**:云端部署,按需使用 +- **灵活扩展**:根据团队规模调整 + +### 用户体验 +- **一键操作**:上传音频即可,无需复杂配置 +- **多端访问**:Web 端随时随地访问 +- **智能交互**:对话式问答,自然流畅 + +--- + +## 🎁 核心竞争力 + +### 与传统会议工具对比 + +| 特性 | 传统工具 | iMeeting | +|------|---------|----------| +| **录音转文字** | ✅ 支持 | ✅ 支持 | +| **AI 自动总结** | ❌ 不支持 | ✅ 支持 | +| **知识库提炼** | ❌ 不支持 | ✅ 支持 | +| **智能问答** | ❌ 不支持 | ✅ 支持(Phase 2) | +| **播客生成** | ❌ 不支持 | ✅ 支持(Phase 2) | +| **多源输入** | ❌ 仅会议 | ✅ 文档+音视频(Phase 2) | + +### 与 NotebookLM 对比 + +| 特性 | NotebookLM | iMeeting | +|------|-----------|----------| +| **文档上传** | ✅ 支持 | ✅ 支持(Phase 2) | +| **音频播客** | ✅ 支持 | ✅ 支持(Phase 2) | +| **智能问答** | ✅ 支持 | ✅ 支持(Phase 2) | +| **会议管理** | ❌ 不支持 | ✅ 核心功能 | +| **团队协作** | ⚠️ 有限 | ✅ 完整支持 | +| **私有部署** | ❌ 不支持 | ✅ 可私有部署 | + +--- + +## 🌟 适用对象 + +### 企业团队 +- 10-500 人规模的中小企业 +- 需要频繁开会和知识管理的团队 +- 重视知识沉淀的创新型公司 + +### 个人用户 +- 项目经理、产品经理 +- 研发工程师、技术负责人 +- 顾问、讲师、自媒体创作者 + +### 行业领域 +- 科技互联网 +- 咨询服务 +- 教育培训 +- 金融保险 +- 医疗健康 + +--- + +## 📅 发展路线 + +### Phase 1(已完成)✅ +- 会议录音转录 +- AI 自动总结 +- 基础知识库 +- 用户权限管理 + +### Phase 2(开发中)🚀 +- 多源输入(文档、音视频) +- 播客式音频生成 +- NotebookLM 式智能问答 +- 结构化输出升级 + +**预计上线时间**:1-1.5 个月 + +### Phase 3(规划中)💡 +- 实时会议转录 +- 多语言支持 +- 移动端 App +- 企业级功能(SSO、审计) + +--- + +## 💬 联系我们 + +如果您对 iMeeting 感兴趣,或有任何问题和建议,欢迎联系我们: + +- **产品咨询**:[联系邮箱] +- **技术支持**:[技术支持邮箱] +- **商务合作**:[商务邮箱] + +--- + +**iMeeting - 让每一次会议都产生价值** 🚀 diff --git a/资料/智能教育范式升级.pdf b/资料/智能教育范式升级.pdf new file mode 100644 index 0000000..994825c Binary files /dev/null and b/资料/智能教育范式升级.pdf differ diff --git a/资料/终端多场景录音页.png b/资料/终端多场景录音页.png new file mode 100644 index 0000000..7321de2 Binary files /dev/null and b/资料/终端多场景录音页.png differ diff --git a/资料/终端首页.png b/资料/终端首页.png new file mode 100644 index 0000000..4ffb603 Binary files /dev/null and b/资料/终端首页.png differ