v 1.0.2
|
|
@ -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_*/
|
||||
|
|
@ -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
|
||||
|
After Width: | Height: | Size: 237 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
|
@ -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
|
||||
|
|
@ -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 <<EOF
|
||||
[Service]
|
||||
Environment="OLLAMA_HOST=0.0.0.0"
|
||||
Environment="OLLAMA_NUM_PARALLEL=2"
|
||||
Environment="OLLAMA_MAX_LOADED_MODELS=2"
|
||||
Environment="OLLAMA_GPU_MEMORY_FRACTION=0.8"
|
||||
EOF
|
||||
|
||||
# 重新加载配置并重启服务
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart ollama
|
||||
```
|
||||
|
||||
#### 3.4 安装Python客户端
|
||||
```bash
|
||||
# 安装Ollama Python客户端
|
||||
pip install ollama
|
||||
|
||||
# 安装其他依赖
|
||||
pip install requests
|
||||
```
|
||||
|
||||
#### 3.5 LLM摘要生成使用示例
|
||||
```python
|
||||
import ollama
|
||||
import json
|
||||
|
||||
class MeetingSummarizer:
|
||||
def __init__(self, model_name="qwen2.5:7b"):
|
||||
self.model_name = model_name
|
||||
self.client = ollama.Client()
|
||||
|
||||
def generate_summary(self, transcript_text, speakers_info):
|
||||
"""生成会议摘要"""
|
||||
|
||||
# 构建提示词
|
||||
prompt = f"""
|
||||
请根据以下会议转录内容生成详细的会议摘要:
|
||||
|
||||
转录内容:
|
||||
{transcript_text}
|
||||
|
||||
请按以下格式输出摘要:
|
||||
1. 会议概述
|
||||
2. 主要讨论点
|
||||
3. 决策事项
|
||||
4. 待办事项
|
||||
5. 参会人员发言要点
|
||||
|
||||
请用中文回答,保持简洁明了。
|
||||
"""
|
||||
|
||||
try:
|
||||
response = self.client.chat(
|
||||
model=self.model_name,
|
||||
messages=[
|
||||
{
|
||||
'role': 'user',
|
||||
'content': prompt
|
||||
}
|
||||
],
|
||||
options={
|
||||
'temperature': 0.3,
|
||||
'top_p': 0.9,
|
||||
'max_tokens': 2000
|
||||
}
|
||||
)
|
||||
|
||||
return response['message']['content']
|
||||
|
||||
except Exception as e:
|
||||
print(f"摘要生成错误: {e}")
|
||||
return None
|
||||
|
||||
# 使用示例
|
||||
# summarizer = MeetingSummarizer()
|
||||
# summary = summarizer.generate_summary(transcript_text, speakers_info)
|
||||
# print(summary)
|
||||
```
|
||||
|
||||
### 4. 完整集成部署脚本
|
||||
|
||||
#### 4.1 创建部署脚本
|
||||
```bash
|
||||
# 创建部署脚本
|
||||
cat > 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
|
||||
- 实现会议摘要自动生成
|
||||
- 添加关键信息提取功能
|
||||
|
||||
### 阶段四:系统优化
|
||||
- 性能优化和错误处理
|
||||
- 用户界面完善
|
||||
- 部署和运维自动化
|
||||
|
|
@ -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
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**祝您使用愉快!** 🎉
|
||||
|
|
@ -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 原生应用
|
||||
- [ ] 多语言支持 - 支持中英文等多语言界面
|
||||
- [ ] 会议协作 - 支持多人实时协作编辑会议纪要
|
||||
- [ ] 数据分析 - 会议统计分析和可视化报表
|
||||
|
||||
## 许可证
|
||||
|
||||
[请添加许可证信息]
|
||||
|
||||
## 联系方式
|
||||
|
||||
[请添加联系方式]
|
||||
|
|
@ -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 (
|
||||
<div className="audio-player-container">
|
||||
<h3>🎧 音频概览</h3>
|
||||
<ReactAudioPlayer
|
||||
src={audioUrl}
|
||||
controls
|
||||
autoPlay={false}
|
||||
controlsList="nodownload"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// 智能问答组件
|
||||
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 (
|
||||
<div className="chatbot-container">
|
||||
<div className="chat-history">
|
||||
{messages.map((msg, idx) => (
|
||||
<div key={idx} className={`message ${msg.role}`}>
|
||||
<div className="message-content">{msg.content}</div>
|
||||
{msg.sources && (
|
||||
<div className="message-sources">
|
||||
<h4>📚 来源</h4>
|
||||
{msg.sources.map((src, i) => (
|
||||
<div key={i} className="source-card">
|
||||
<strong>{src.section}</strong>
|
||||
<p>{src.text}...</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="chat-input">
|
||||
<input
|
||||
value={input}
|
||||
onChange={(e) => setInput(e.target.value)}
|
||||
placeholder="向知识库提问..."
|
||||
onKeyPress={(e) => e.key === 'Enter' && handleAsk()}
|
||||
/>
|
||||
<button onClick={handleAsk} disabled={loading}>
|
||||
{loading ? '思考中...' : '发送'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 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 问答)。
|
||||
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 61952852d72b8803072fa792eb61553c5986a01c
|
||||
|
|
@ -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"
|
||||
|
||||
```
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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';
|
||||
|
||||
// 在管理员路由中添加
|
||||
<Route path="/admin/clients" element={<ClientManagement user={user} />} />
|
||||
```
|
||||
|
||||
#### 在首页添加下载组件:
|
||||
|
||||
```jsx
|
||||
import ClientDownloads from './components/ClientDownloads';
|
||||
|
||||
// 在Dashboard或任何页面中添加
|
||||
<ClientDownloads />
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 管理员创建新版本
|
||||
|
||||
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. **版本管理**:
|
||||
- 同一平台只能有一个"最新版本"
|
||||
- 设置新版本为最新时,会自动将旧版本的最新标记<E6A087><E8AEB0>除
|
||||
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
|
||||
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 6cbe02fbf637e8cd3004c7947be5706a8cb814d7
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "imeeting",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -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
|
||||
<svg viewBox="0 0 24 24" class="voice-wave-icon">
|
||||
<path d="M12 2v20M8 6v12M16 6v12M4 9v6M20 9v6" />
|
||||
</svg>
|
||||
```
|
||||
## 文件存储结构
|
||||
|
||||
```
|
||||
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 版本的原生应用。
|
||||
|
|
@ -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 <<EOF
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
|
||||
'\$status \$body_bytes_sent "\$http_referer" '
|
||||
'"\$http_user_agent" "\$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
}
|
||||
EOF
|
||||
print_success "nginx/nginx.conf 已生成"
|
||||
fi
|
||||
|
||||
if [ ! -f nginx/conf.d/default.conf ]; then
|
||||
print_warning "nginx/conf.d/default.conf 不存在,正在生成默认站点配置..."
|
||||
cat > nginx/conf.d/default.conf <<EOF
|
||||
upstream frontend_server {
|
||||
server frontend:80;
|
||||
}
|
||||
|
||||
upstream backend_server {
|
||||
server backend:8000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
# 增加上传文件大小限制
|
||||
client_max_body_size 100M;
|
||||
|
||||
# 后端API直连
|
||||
location /api/ {
|
||||
proxy_pass http://backend_server;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||
|
||||
# 增加API超时时间
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
}
|
||||
|
||||
# 上传文件直连
|
||||
location /uploads/ {
|
||||
proxy_pass http://backend_server;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||
|
||||
# 静态资源缓存配置
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, no-transform";
|
||||
}
|
||||
|
||||
# 前端代理 (其他请求)
|
||||
location / {
|
||||
proxy_pass http://frontend_server;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade \$http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host \$host;
|
||||
proxy_cache_bypass \$http_upgrade;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
print_success "nginx/conf.d/default.conf 已生成"
|
||||
fi
|
||||
}
|
||||
|
||||
# 检查并创建后端环境变量文件
|
||||
check_backend_env() {
|
||||
print_info "检查后端环境变量配置..."
|
||||
|
||||
if [ ! -f backend/.env ]; then
|
||||
print_warning "backend/.env 文件不存在,从模板创建..."
|
||||
|
||||
if [ -f backend/.env.example ]; then
|
||||
cp backend/.env.example backend/.env
|
||||
print_success "已创建 backend/.env"
|
||||
else
|
||||
print_warning "backend/.env.example 不存在,跳过"
|
||||
fi
|
||||
else
|
||||
print_success "后端环境变量文件已存在"
|
||||
fi
|
||||
}
|
||||
|
||||
# 启动服务
|
||||
start_services() {
|
||||
print_info "启动 Docker 服务..."
|
||||
|
||||
# 使用 docker compose 或 docker-compose
|
||||
if docker compose version &> /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 "$@"
|
||||
|
|
@ -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
|
||||
|
After Width: | Height: | Size: 200 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 5.7 MiB |
|
After Width: | Height: | Size: 3.3 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 3.1 MiB |
|
After Width: | Height: | Size: 87 KiB |
|
|
@ -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 - 让每一次会议都产生价值** 🚀
|
||||
|
After Width: | Height: | Size: 101 KiB |
|
After Width: | Height: | Size: 181 KiB |