把长音视频内容转化为可核验、可复用、可发现的知识卡片 —— 转写、结构化摘要、关键点、待办与配图。
这是产品的后端(FastAPI + Celery);前端为独立的 Next.js 应用 ai-audio-assistant-ui,鉴权、提示词等经共享服务打通。
以下均为代码中已落地的能力:
- 多厂商 ASR 转写 —— 腾讯云 / 阿里云 / 火山引擎;支持说话人分离、标准/极速变体,配额感知的智能调度(
ASRScheduler)。送云前统一转 16k 单声道 mp3,绕开单文件体积上限。 - 转写自动润色 —— 转写与摘要之间的
polishing阶段,用固定高性价比模型做机械式纠错(错别字/术语/标点),分组独立、段数 1:1、失败保留原文。 - 结构化摘要 —— 7 种规范风格 +
auto自动识别;概览 / 关键点 / 待办;多模型并排对比、版本管理与一键激活、regenerate、SSE 流式输出。 - 渐进式配图 —— 摘要完成后异步为概览生成插图(远端 image-service),占位锚点先落库、生图后合并。
- 转写全文检索 ——
GET /api/v1/tasks/search,PostgreSQLtsvector+ pg_jieba 中文分词 + GIN 索引 + 应用层高亮。纯词法匹配、零 LLM 成本(语义 / 向量检索为刻意关闭的非目标)。 - YouTube 集成 —— OAuth 连接、订阅同步为「待处理收件箱」、频道浏览、加星、批量自动转写、按链接/关键词直接转写。
- /discover 发现页(公开) —— 关键词搜索(yt-dlp
ytsearch,零配额,≤6h 缓存)、「大家在搜」热门词、按播放量 harvest 的热门推荐;整体受 discover kill-switch 开关。 - 公开探索页(匿名) —— 浏览管理员公开的已完成任务及其转写/摘要,配短期作用域媒体票据。
- 内容治理 —— 接入 CMS / 腾讯 TMS 审核(
search_query/ugc_publish/ugc_display三场景 ×off/shadow/enforce三模式,enforce 下 fail-closed);人工黑名单/白名单(屏蔽频道、屏蔽词、频道白名单)与频道标记复核队列。 - 成本与配额 —— 管理员按用户成本看板(¥ ASR+配图 / $ LLM,双币种分列不相加)、ASR 月度配额管理与预警。
- 平台能力 —— WebSocket 实时进度、站内通知、用户偏好、运行时配置中心、统计分析、客户端错误上报、管理后台查看用户转写明细。
| 组件 | 技术 / 说明 |
|---|---|
| API | FastAPI(容器监听 8000,docker-compose 对外映射 8088);统一响应体 {code, message, data, traceId} |
| 异步 Worker | Celery(--autoscale=8,1)+ Celery Beat 定时任务;Redis 作 broker / backend |
| 数据库 | PostgreSQL(asyncpg)+ Alembic 迁移 + pg_jieba 中文分词 |
| 对象存储 | MinIO(开发)/ 腾讯云 COS / 阿里云 OSS / 火山 TOS(生产多厂商) |
| ASR | 腾讯云 / 阿里云 / 火山引擎(厂商直连 SDK) |
| 文本 LLM | 统一经 LiteLLM Proxy;模型目录直接代理 LiteLLM,增删模型只在 LiteLLM 侧操作 |
| 生图 | 远端 image-service(Gemini 系模型) |
| 鉴权 | auth-service 签发 RS256 JWT,后端经 JWKS 校验(SSO) |
| 本地可编辑依赖 | prompthub-sdk(经 [tool.uv.sources] 指向工作区上层目录 ../../prompthub) |
| 认证 SDK | seanfield-auth-client[fastapi]==0.3.0(从 PyPI 安装并固定版本) |
服务选型(SmartFactory):外部服务经 @register_service 注册,SmartFactory 支持 health_first(默认)/ cost_first / performance_first / balanced 策略。已注册:ASR = tencent / aliyun / volcengine,存储 = minio / cos / oss / tos,LLM = proxy(LiteLLM 统一入口)+ image_service。生产中文本 LLM 恒走 proxy,ASR 真实调度由配额感知的 ASRScheduler 负责。
任务流水线:
pending → extracting(10%) → transcribing(40%) → polishing(72%) → summarizing(82%) → completed(100%)
│ 任一阶段异常
▼
failed
摘要文字失败不连带整任务失败(转写已可展示);completed 之后异步补概览配图。
- Python 3.11+(容器基镜像
python:3.11-slim;ruff 语法目标py312) - PostgreSQL、Redis、FFmpeg
- 包管理器 uv(依赖唯一来源
pyproject.toml,不维护requirements.txt)
cp .env.example .env
uv sync --dev # 装运行时 + 开发依赖(pytest 等);仅运行时用 uv sync
source .venv/bin/activate
# 启动 API(本地 --reload 默认监听 8000)
uvicorn app.main:app --reload
# 启动 Celery Worker
celery -A worker.celery_app worker --loglevel=info
# 启动 Celery Beat(定时任务)
celery -A worker.celery_app beat --loglevel=info
# 数据库迁移
alembic upgrade headlint 提示:CI 的 lint 门禁是 ruff,但 ruff 不在
uv sync --dev的依赖组里(dev 组为历史遗留的 pytest/black/… )。本地要与 CI 对齐,单独uvx ruff或pip install ruff即可。
docker-compose.yml 只定义 4 个服务:api、worker、beat、migrate(migrate 属 manual profile,按需运行)。
⚠️ 不是开箱即用的全栈:PostgreSQL / Redis / MinIO 不在 compose 内(配置指向外部主机),且依赖一个已存在的外部网络ai-audio-network。请先自备这些外部依赖与网络,再up。
docker-compose up -d # 起 api / worker / beat(需外部 PG/Redis/MinIO + 外部网络)
docker compose run --rm migrate # 手动执行迁移(alembic upgrade head)容器内 api 命令为 uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload,端口映射 8088:8000(即 http://localhost:8088)。
ruff check app/ worker/ tests/ # lint —— CI 实际门禁
ruff format app/ worker/ tests/ # 格式化
pytest tests/ -v # 测试 —— CI 实际门禁
pytest tests/ -v --cov=app --cov=worker # 带覆盖率CI 的 PR 门禁在 .github/workflows/pr-ci.yml;master 发布由
.github/workflows/build-and-deploy.yml 串行执行镜像构建、迁移、候选部署与验收。
发布前会保存当前 api/worker/beat 的不可变镜像引用和内容 ID;候选部署或
readiness 失败时恢复该镜像并重新验收,但原发布仍保持失败状态。手动回滚通过
同一 workflow 的 rollback_sha 和 rollback_reason 输入执行,并跳过 Windows
构建、镜像推送及 Alembic 迁移。
数据库变更必须采用 expand/contract:先发布向后兼容的扩展 schema,待旧镜像
不再需要后再删除旧结构。镜像回滚绝不自动执行 alembic downgrade,因此每次
迁移都必须保证上一个已部署镜像仍能在新 schema 上运行。
pyproject.toml dev 组里仍列着 black/isort/flake8/mypy/bandit,但它们均非当前
CI 门禁,实际 lint 以 ruff 为准。
配置由 pydantic-settings 的 Settings 集中定义(app/config.py),从 .env 加载。变量的权威定义在 app/config.py;.env.example 是常用变量样例(并非全量),下表只列关键分组;真实密钥由 secret manager 注入,.env 已被 .gitignore 忽略,切勿提交。
pydantic 层所有项都有默认值;但当 APP_ENV=production 时,校验器会强制下列密钥,缺失即启动失败:
| 变量名 | 说明 |
|---|---|
FIELD_ENCRYPTION_KEY |
落库 OAuth token 等敏感字段的 Fernet 加密密钥;逗号分隔多把可轮换(首把加密、全部解密)。生产必填 |
JWT_SECRET |
媒体 / SSE 短期票据的 HS256 自签密钥。生产必填 |
AUTH_SERVICE_URL |
auth-service 对外 issuer;空白或规范化后为空会启动失败。生产必填 |
AUTH_SERVICE_CLIENT_ID |
本应用在 auth-service 注册的 client_id,同时用于校验访问令牌 aud。生产必填 |
其余关键分组(完整见 .env.example):
| 分组 | 代表变量 | 备注 |
|---|---|---|
| 数据库 / Redis | DATABASE_URL、REDIS_URL、DB_POOL_SIZE、DB_MAX_OVERFLOW |
应用/Worker 运行必需;worker 翻倍须同步减池以护共享 PG |
| 鉴权 | AUTH_SERVICE_URL、AUTH_SERVICE_CLIENT_ID、AUTH_SERVICE_INTERNAL_URL、AUTH_SERVICE_JWKS_URL |
强制校验 issuer、audience 和 type=access;JWKS 优先走内网基址避公网隧道尾延 |
| 对象存储(四选一) | MINIO_* / COS_* / OSS_* / TOS_* |
选用哪家配哪组 |
| ASR(三厂商) | TENCENT_* / ALIYUN_* / VOLC_ASR_* |
按凭证自动发现;另有引擎/说话人分离调参 |
| 文本 LLM | LITELLM_BASE_URL、LITELLM_API_KEY、LITELLM_MODEL、LITELLM_HEALTH_ENABLED |
所有 chat/completion 统一经 LiteLLM Proxy;健康探测默认关闭(见下) |
| 生图 | IMAGE_SERVICE_BASE_URL、IMAGE_SERVICE_API_KEY |
配图功能必需 |
| 提示词 | PROMPTHUB_BASE_URL、PROMPTHUB_API_KEY |
摘要/配图提示词唯一活源,无本地回落;未配则相关任务运行时失败(非启动校验强制) |
| 内容审核 | MODERATION_*_MODE、MODERATION_API_KEY |
三场景三态,默认全 off;enforce 时需 key |
| 发现页 / YouTube | YOUTUBE_SEARCH_*、GOOGLE_CLIENT_ID/SECRET |
搜索紧超时/缓存/限流;OAuth 凭证 |
| 限流 / 开关 | RATE_LIMIT_*、DEAD_TASK_SWEEP_ENABLED、CONFIG_CENTER_DB_ENABLED |
各端点每分钟限流、巡检与配置中心开关 |
注:部分变量(
JWT_SECRET、DB_POOL_SIZE/DB_MAX_OVERFLOW、COS_*、MODERATION_*、RATE_LIMIT_*等)未写入.env.example,以app/config.py为准;ENABLE_DOCS由app/main.py直接读取。
模型选择器展示的健康状态来自 app/core/litellm_health.py 的后台缓存。LiteLLM
/health 会对每个模型打真实 completion(qwen reasoning 模型每次数百
reasoning token),多 worker(--workers 2)与 fusion-api 等共享同一 LiteLLM 的
服务各自探测会重复烧钱(历史上 dev 约 432 次 Qwen 推理/天)。
LITELLM_HEALTH_ENABLED=false(默认):startup 不启动/health后台循环, 模型列表照常返回,健康状态回退unknown(前端按可用处理)。LITELLM_HEALTH_ENABLED=true:开启后台探测,并用 Redis round-claim (litellm:health:probe:claim:v1)+ 共享快照(litellm:health:snapshot:v1) 跨 worker/跨服务协调,每周期全集群最多一轮/health。- 与 fusion-api 的实现共用同一组 Redis key,改 key 必须两边同步。
全部端点统一挂在 /api/v1 前缀下(app/api/v1/router.py):
/tasks、/tasks/search(转写全文检索)、/transcripts、/summaries、/summary-styles/upload、/media(媒体票据与字节流)、/ws(实时进度 WebSocket)/users、/notifications、/stats、/llm、/public(匿名探索)/youtube(订阅 / 发现 / 搜索 / 回调)、/asr/quotas、/asr/usage/configs(配置中心)、/admin/*(成本看板、任务明细、屏蔽 / 白名单 / 复核队列)/health、/readiness、/client-errors
交互式文档(
/docs、/redoc、/openapi.json)由ENABLE_DOCS闸控,默认关闭(compose 中显式设为false)。本地查看:启动前设ENABLE_DOCS=true,访问http://localhost:8000/docs。
ai-audio-assistant-web/
├── app/ # FastAPI 应用
│ ├── api/ # 路由(api/v1/*)与依赖注入(deps.py)
│ ├── core/ # SmartFactory / 中间件 / 响应 / 异常 / 监控 / 容错
│ ├── services/ # asr/ llm/ storage/ moderation/ youtube/ … 外部服务实现
│ ├── models/ # SQLAlchemy 模型
│ ├── schemas/ # Pydantic 出入参
│ ├── prompts/ # 提示词模板管理
│ ├── i18n/ # 错误码与多语言文案
│ ├── config.py # 配置(pydantic-settings)
│ ├── db.py # 异步会话工厂
│ └── main.py # 应用装配(create_app)
├── worker/ # Celery 任务与 beat 调度
├── alembic/ # 数据库迁移
├── tests/ # pytest 测试
├── scripts/ # 运维 / 一次性脚本
├── loadtest/ # 压测装置
└── docs/ # 设计与接口文档
| 文档 | 位置 | 说明 |
|---|---|---|
| API 规范 | docs/API.md |
端点、请求/响应、错误码 |
| 环境变量样例 | .env.example |
全量环境变量(以此为准) |
其余为本地开发文档,未随仓公开:
CLAUDE.md(工程约定 / SmartFactory / 编码规范)、docs/ARCH.md(架构详解)、docs/ADR.md(架构决策,含「LLM 收敛 LiteLLM Proxy」「RAG 刻意停用」等)、docs/PRD.md(产品需求)、docs/superpowers/{specs,plans}/(按特性归档的 spec 与实现计划)。
English version: README_EN.md