feat: 调度器+并发管线+GPU优化+日志分级+前端修复
- scheduler: ffmpeg 异步线程 + GPU 串行调度 + 模型复用(2N→2 次加载) - pipeline: 阶段拆分(extract/asr/translate),中间数据存 Task 字段 - translate_service: 长度排序批处理,padding 浪费减少 91% - model_manager: ASR/翻译不共驻,BatchedInferencePipeline 批量解码 - 日志分级: INFO=任务流转里程碑,DEBUG=进度详情;默认 INFO - 前端: 日志最新在上+滚动感知+退避轮询;24h 时间;上传中状态显示 - /health: 返回完整 Whisper/NLLB 配置 - upload_service: 单事务 complete + 扩展名白名单 - task_router: 合并 UploadSession 虚拟任务到列表 - Dockerfile: CPU/GPU 独立构建链,deps 缓存稳定 - prefetch_models: 安装时预下载模型权重
This commit is contained in:
34
app/main.py
34
app/main.py
@@ -76,6 +76,12 @@ async def lifespan(app: FastAPI):
|
||||
await asyncio.to_thread(reap_stale_sessions)
|
||||
except Exception as exc: # pragma: no cover
|
||||
logger.warning("启动 reaper 失败:%s", exc)
|
||||
# 启动 GPU 调度线程(常驻,串行处理 ASR+翻译,模型复用)
|
||||
try:
|
||||
from .services.scheduler import start_scheduler
|
||||
start_scheduler()
|
||||
except Exception as exc: # pragma: no cover
|
||||
logger.warning("启动 GPU 调度线程失败:%s", exc)
|
||||
# 缓存清理:启动时跑一次 + 后台定时循环(守护线程,随进程退出)
|
||||
s = get_settings()
|
||||
try:
|
||||
@@ -144,7 +150,33 @@ def create_app() -> FastAPI:
|
||||
|
||||
@app.get("/health")
|
||||
def health() -> dict:
|
||||
return {"status": "ok"}
|
||||
"""存活探针 + 设备信息。
|
||||
|
||||
返回 torch 版本、cuda 可用性、GPU 名称、配置的 device,
|
||||
便于一眼区分 CPU/GPU 容器是否正确调度到对应硬件。
|
||||
torch 导入失败时(理论上不会,因为镜像已装 torch)降级为仅 status。
|
||||
"""
|
||||
info: dict = {"status": "ok"}
|
||||
try:
|
||||
import torch
|
||||
info["torch"] = torch.__version__
|
||||
info["cuda_available"] = torch.cuda.is_available()
|
||||
if torch.cuda.is_available():
|
||||
info["gpu"] = torch.cuda.get_device_name(0)
|
||||
info["gpu_count"] = torch.cuda.device_count()
|
||||
except Exception as e: # pragma: no cover
|
||||
info["torch_error"] = str(e)
|
||||
s = get_settings()
|
||||
info["asr_device"] = s.asr.device
|
||||
info["asr_model"] = s.asr.model
|
||||
info["asr_compute_type"] = s.asr.compute_type
|
||||
info["asr_batch_size"] = s.asr.batch_size
|
||||
info["asr_language"] = s.asr.language
|
||||
info["translation_device"] = s.translation.device
|
||||
info["translation_model"] = s.translation.model
|
||||
info["translation_batch_size"] = s.translation.batch_size
|
||||
info["translation_sort_by_length"] = s.translation.sort_by_length
|
||||
return info
|
||||
|
||||
@app.get("/history", response_class=HTMLResponse)
|
||||
def history_page() -> HTMLResponse:
|
||||
|
||||
Reference in New Issue
Block a user