Files
life-echo/api
Kevin 22d282dc01 feat(api): use Tencent 16k_zh_large ASR and remove local Whisper
Standardize ASR on Tencent's dialect-capable engine across all environments,
drop faster-whisper from dependencies and deployment images, and add an
expo-sqlite iOS vendor sync plus pod install in prebuild to prevent native
build failures after npm install.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-25 10:21:41 +08:00
..
2026-01-18 15:58:05 +08:00
2026-03-19 14:36:40 +08:00

Life Echo API

Life Echo 后端服务,基于 FastAPI 构建的实时语音对话回忆录生成系统。

项目简介

Life Echo API 是一个智能对话系统,通过 WebSocket 实时连接,使用 LangChain Agent 引导用户进行回忆录访谈对话,并将口语内容自动整理为结构化的书面章节,最终生成回忆录 PDF。

架构要点(多 Agent 收敛)

  • 会话真源conversation_messagesDB+ Redis 缓存;实时编排入口ChatOrchestrator
  • 图像管线:正文主图 generate_story_image;章节封面 try_enqueue_generate_chapter_covergenerate_chapter_cover
  • 回忆录批次MemoirOrchestrator.prepare_batches 显式分桶后,process_memoir_phase1 派发 Phase 2 按类别调用 run_story_pipeline_for_category_batch(含 StoryRouteAgent.plan_batch 多 unit 写入)。

LLM 与记忆(约定文档)

  • JSON 模式:结构化抽取/路由/叙事 JSON 使用 app/core/langchain_llm.pybind_json_object_mode(与 DeepSeek JSON Output 一致);详见 docs/llm-json-mode.md。适配器说明见 app/adapters/llm/deepseek.py
  • 记忆检索:异步与 Celery 均使用 向量pgvector chunksdocs/memory-retrieval.md(含 async/sync 行为矩阵)。
  • AI 相关代码扫描uv run python scripts/ai_touchpoints_scan.py --markdown docs/ai-touchpoints.md(在 api/ 目录下执行)生成带标签的触点列表,见 docs/ai-touchpoints.md
  • 与 AI 强相关的配置项:产品调参 SSOT 为 config/*.toml(经 app/features/*/constants.pyapp/core/runtime_constants.py re-export密钥见 .env.example。详见 docs/configuration.md
  • Memory compaction:默认在 config/default.toml[memory] 中开启。须运行 Celery workercelery-beatdocker-compose.yml 已包含 celery-beat,用于定期 memory_compaction_sweep)。
  • Memory LLM enrichment单次 LLM会话摘要 + 事实):任务路由到 memory_idle 队列(config/default.toml[celery] memory_enrichment_queue)。本地与 compose 内 worker 已使用 -Q celery,memory_idle;生产可单独起低并发 worker 只消费 memory_idle,与主队列隔离。

技术栈

  • Web 框架: FastAPI 0.115.0
  • WebSocket: websockets 14.1
  • AI 框架: LangChain 0.3.7 + DeepSeek/兼容 OpenAI 的 LLM
  • 数据库: PostgreSQL 17 + SQLAlchemy 2.0.36 (asyncpg)
  • 缓存/队列: Redis 7 + Celery 5.3
  • PDF 生成: ReportLab 4.2.2 + WeasyPrint 62.3
  • ASR/TTS: 腾讯云 ASR16k_zh_large/ TTS
  • 认证: JWT (python-jose) + bcrypt
  • 其他: Pydantic, python-dotenv
  • 可观测性: OpenTelemetry → Grafana LGTMTempo / Prometheus / Lokidocs/observability.md

可观测性(本地)

docker compose -f docker-compose.dev.yml -f docker-compose.observability.yml up -d
# Grafana: http://127.0.0.1:48300

config/*.toml[deploy] 中配置 otel_enabledotel_exporter_otlp_endpoint;采样策略等细项见 [otel] section 与 docs/observability.md

项目结构

api/
├── main.py                 # 应用入口uvicorn 启动)
├── app/                    # 应用主包
│   ├── main.py            # FastAPI 应用定义
│   ├── core/               # 核心基础设施
│   │   ├── config.py      # secrets / bootstrapSettings + facade
│   │   ├── app_config*.py # TOML 加载与 AppConfig
│   │   ├── runtime_constants.py  # re-export config/*.toml runtime sections
│   │   ├── db.py          # 数据库连接
│   │   ├── redis.py       # Redis 服务
│   │   ├── security.py    # JWT、密码哈希
│   │   └── task_tracker.py # 任务状态追踪
│   ├── features/          # 功能模块(各模块含 router、service、repo
│   │   ├── auth/          # 认证(注册、登录、短信验证码)
│   │   ├── user/          # 用户信息
│   │   ├── conversation/  # 对话、WebSocket
│   │   ├── memory/        # 记忆检索
│   │   ├── memoir/        # 回忆录、章节、PDF、图像生成
│   │   ├── payment/       # 支付
│   │   ├── plan/          # 套餐
│   │   ├── quota/         # 配额
│   │   ├── tasks/         # 任务状态 API
│   │   └── content/       # 内容TTS 等)
│   ├── adapters/          # 外部能力适配器ASR、TTS、LLM、短信、存储等
│   ├── ports/             # 能力契约Protocol
│   └── agents/            # LangChain Agent
├── tasks/                 # Celery 后台任务
│   └── memoir_tasks.py    # 回忆录处理任务
└── docs/                  # 详细文档

环境配置

1. 安装依赖

cd api
pip install -r requirements.txt

2. 配置TOML + .env

配置分两层 SSOT详见 docs/configuration.md

来源 内容
Secrets / bootstrap .env.example DATABASE_URLSECRET_KEY、API/支付/Liblib 密钥
非密钥 config/default.toml + config/{APP_ENV}.toml 功能开关、SMS 模板、Chat/Memoir/Memory/Eval 调参、OTel 等

本地开发:.env.development(密钥)+ config/development.toml(行为);development.sh 将前者同步为 .env。预发/生产:.env.staging / .env.production + 对应 config/*.toml

最小 .env 示例:

APP_ENV=development
DATABASE_URL=postgresql://postgres:postgres@localhost:48291/life_echo
REDIS_URL=redis://localhost:48307/0
SECRET_KEY=your-secret-key-here
DEEPSEEK_API_KEY=sk-...
ZHIPU_API_KEY=...
TENCENT_SECRET_ID=...
TENCENT_SECRET_KEY=...

腾讯云:凭证仍在 envTENCENT_SECRET_ID/KEY);短信模板 ID、COS 桶名等在 config/*.toml[deploy] section。

业务代码读取 TOML 值仍可用原有 importre-export

模块 路径
访谈 / 聊天 app/features/conversation/constants.pychat
回忆录流水线 app/features/memoir/constants.pymemoir
Story / 章节 app/features/story/constants.pystory
记忆富化 / compaction app/features/memory/constants.pymemory
内网评测 app/features/evaluation/constants.pyeval_cfg
ASR/TTS/LLM/Celery 等 app/core/runtime_constants.py

3. 数据库迁移

数据库 schema 由 Alembic 管理。app/main.py 启动时会在线程中执行 alembic upgrade head(见 app/core/alembic_startup.py):对连接类错误自动重试;生产环境建议设置 ALEMBIC_STARTUP_FAIL_FAST=true,迁移失败则进程退出。

规范与跨环境排障见 docs/alembic-migrations.md(禁止改已部署 revision id、老库用显式 0019 补列等)。

cd api
uv run alembic upgrade head
uv run pytest tests/test_alembic_migration_policy.py -q

若库中仍为已撤回的 0020_* revision部署前先执行 uv run python scripts/repair_alembic_version_after_withdrawn_0020.py(见上文文档)。

快速启动

本地开发

推荐使用一键脚本(会自动启动 PostgreSQL/Redis、检查 .venv、安装依赖并拉起 FastAPI + Celery

cd api
./dev-up.sh

可选环境变量:

  • SKIP_INSTALL=1:跳过依赖安装
  • API_HOST / API_PORT:覆盖 API 启动地址和端口
  • CELERY_POOL:覆盖 Celery 池类型macOS 推荐 solo

也可以使用手动方式:

cd api

# 1. 启动 PostgreSQL + Redis
docker compose -f docker-compose.dev.yml up -d

# 2. 安装依赖
pip install -r requirements.txt

# 3. 配置环境变量(与 docker-compose.dev.yml 固定宿主端口一致Postgres 48291、Redis 48307
export DATABASE_URL=postgresql://postgres:postgres@localhost:48291/life_echo
export REDIS_URL=redis://localhost:48307/0

# 4. 启动 API终端 1
uvicorn main:app --reload --host 0.0.0.0 --port 8000

# 5. 启动 Celery Worker终端 2
# macOS 使用 solo 池避免 fork 崩溃问题;须同时消费 memory_idleMemory 富化)
celery -A app.tasks.celery_app worker --loglevel=info --pool=solo -Q celery,memory_idle

# Linux/生产环境可以使用 prefork 池
# celery -A app.tasks.celery_app worker --loglevel=info --concurrency=4 -Q celery,memory_idle

验证服务

# 检查 PostgreSQL
docker exec life-echo-postgres-dev psql -U postgres -c "SELECT 1"

# 检查 Redis  
docker exec life-echo-redis-dev redis-cli ping

生产部署(一键)

cd api

# 创建生产配置
cp .env .env.prod
# 编辑 .env.prod

# 启动所有服务
docker compose up -d

# 查看日志
docker compose logs -f

服务启动后,访问:

📚 详细文档

更多详细文档请参考 docs/README.md

API 文档

认证系统

系统使用 JWTJSON Web Token进行认证采用访问令牌Access Token+ 刷新令牌Refresh Token机制

  • 访问令牌:有效期 2 小时,用于 API 请求认证
  • 刷新令牌:有效期 30 天,用于刷新访问令牌

认证流程

  1. 用户注册POST /api/auth/register
  2. 用户登录POST /api/auth/login → 返回 access_tokenrefresh_token
  3. API 请求:在 Header 中携带 Authorization: Bearer {access_token}
  4. 刷新令牌POST /api/auth/refresh → 使用 refresh_token 获取新的 access_token
  5. 用户登出POST /api/auth/logout → 撤销 refresh_token

认证 API (/api/auth)

用户注册
POST /api/auth/register
Content-Type: application/json

{
  "phone": "13800138000",
  "password": "password123",
  "nickname": "用户昵称",
  "email": "user@example.com"  // 可选
}

响应

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "random-refresh-token-string",
  "token_type": "bearer"
}
用户登录
POST /api/auth/login
Content-Type: application/json

{
  "phone": "13800138000",
  "password": "password123"
}

响应:同注册接口

刷新访问令牌
POST /api/auth/refresh
Content-Type: application/json

{
  "refresh_token": "your-refresh-token"
}

响应

{
  "access_token": "new-access-token",
  "refresh_token": "new-refresh-token-string",
  "token_type": "bearer"
}

每次刷新会轮换 refresh token返回新的 refresh token旧 token 立即失效)。在 REFRESH_TOKEN_REUSE_GRACE_SECONDS(默认 30 秒)窗口内重复使用已轮换的旧 token 视为幂等重试,返回新 access token 与当前 replacement refresh tokengrace 窗口外再次使用则吊销该用户全部会话并返回 REFRESH_TOKEN_REUSE

用户登出
POST /api/auth/logout
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "refresh_token": "your-refresh-token"
}
获取当前用户信息
GET /api/auth/me
Authorization: Bearer {access_token}

响应

{
  "id": "user-id",
  "phone": "13800138000",
  "email": "user@example.com",
  "nickname": "用户昵称",
  "avatar_url": null,
  "subscription_type": "free",
  "created_at": "2024-01-15T10:00:00Z"
}

使用认证令牌

所有需要认证的 API 请求都需要在 Header 中携带访问令牌:

Authorization: Bearer {access_token}

HTTP 错误契约

所有 HTTP 错误响应均为 application/json,统一格式:

{
  "error_code": "NOT_FOUND",
  "message": "资源不存在",
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}
  • error_code:机器可读错误码(见 OpenAPI ErrorResponse / ErrorCode 组件)
  • message:面向用户的说明
  • request_id:与响应头 X-Request-Id 一致,便于排查

429 状态码语义HTTP 429 被两种错误码共用,客户端必须根据 error_code 分支,不能只看 status

error_code 含义
QUOTA_EXCEEDED 配额已用尽(如对话次数)
RATE_LIMITED 请求频率超限(如 SMS 发送冷却)

遗留 HTTPException(status_code=429) 默认映射为 RATE_LIMITED

CORS 与 credentialsapi_cors_origins 留空时,服务端使用 allow_origins=["*"]allow_credentials=False;生产/staging 必须在 config/staging.toml / config/production.toml[deploy] 中配置逗号分隔的前端域名。

REST API

对话管理 (/api/conversations)

注意:所有对话相关接口都需要认证。

  • POST /api/conversations - 创建新对话(需要认证)
  • GET /api/conversations/{conversation_id} - 获取对话详情(需要认证,只能访问自己的对话)
  • POST /api/conversations/{conversation_id}/end - 结束对话(需要认证,只能结束自己的对话)

章节管理 (/api/chapters)

注意:所有章节相关接口都需要认证。

  • GET /api/chapters - 获取用户所有章节(需要认证)
  • GET /api/chapters/{chapter_id} - 获取章节详情(需要认证,只能访问自己的章节)
  • POST /api/chapters/{chapter_id}/regenerate - 重新整理章节(需要认证,只能操作自己的章节)

回忆录管理 (/api/books)

注意:所有回忆录相关接口都需要认证。

  • GET /api/books/current - 获取当前回忆录(需要认证)
  • POST /api/books/export-pdf - 导出 PDF需要认证只能导出自己的回忆录

WebSocket API

对话 WebSocket (/ws/conversation/{conversation_id})

注意WebSocket 连接需要认证,通过查询参数传递访问令牌。

连接地址

ws://localhost:8000/ws/conversation/{conversation_id}?token={access_token}

实时双向通信,支持:

  • 接收客户端音频数据
  • 发送 Agent 响应文本
  • 实时语音识别ASR
  • 实时语音合成TTS

认证要求

  • 必须在查询参数中提供有效的 access_token
  • 只能连接属于当前用户的对话
  • 如果对话不存在,将自动创建并关联到当前用户

消息格式:

客户端 → 服务端:

{
  "type": "audio",
  "data": "base64_encoded_audio_data"
}

服务端 → 客户端:

{
  "type": "transcript",
  "text": "识别出的文本",
  "agent_response": "Agent 的回复"
}
{
  "type": "audio",
  "data": "base64_encoded_tts_audio"
}

WebSocket 错误消息(与 HTTP 错误契约不同,勿混用 parseApiError

服务端 → 客户端(配额不足等):

{
  "type": "error",
  "data": {
    "message": "本月对话次数已用尽",
    "code": "QUOTA_EXCEEDED"
  },
  "timestamp": "2024-01-15T10:00:00Z"
}
  • WS 帧使用 data.code(如 QUOTA_EXCEEDED不是 HTTP 的 error_code 字段
  • HTTP 客户端错误解析器(parseApiError)不适用于 WebSocket 消息

数据库模型

User用户

  • id: 用户 ID
  • phone: 手机号(唯一,必填)
  • password_hash: 密码哈希
  • email: 邮箱(可选)
  • openid: 微信 OpenID可选
  • nickname: 昵称
  • avatar_url: 头像 URL
  • subscription_type: 订阅类型free/premium
  • created_at: 创建时间

RefreshToken刷新令牌

  • id: 令牌 ID
  • user_id: 用户 ID外键
  • token: 刷新令牌(唯一)
  • expires_at: 过期时间30天后
  • created_at: 创建时间
  • is_revoked: 是否已撤销

Conversation对话

  • id: 对话 ID
  • user_id: 用户 ID
  • started_at: 开始时间
  • ended_at: 结束时间
  • duration_seconds: 持续时间(秒)
  • summary: 对话摘要
  • status: 状态active/ended/processing
  • current_topic: 当前话题
  • conversation_stage: 对话阶段childhood/education/career/family/beliefs/summary

Segment对话段落

  • id: 段落 ID
  • conversation_id: 对话 ID
  • audio_url: 音频 URL
  • user_input_text: 用户输入正文(语音 ASR 或文字输入;历史列名 transcript_text
  • created_at: 创建时间
  • processed: 是否已处理
  • topic_category: 话题分类
  • agent_response: Agent 响应

Chapter章节

  • id: 章节 ID
  • user_id: 用户 ID
  • title: 标题
  • content: 内容
  • order_index: 排序索引
  • status: 状态draft/completed
  • images: 图片 URL 列表JSON
  • updated_at: 更新时间
  • category: 章节分类

Book回忆录

  • id: 回忆录 ID
  • user_id: 用户 ID
  • title: 标题
  • total_pages: 总页数
  • total_words: 总字数
  • cover_image_url: 封面图片 URL
  • updated_at: 更新时间

核心功能

1. 对话引导 Agent

使用 LangChain 构建的对话 Agent根据传记结构引导用户回忆

  • 童年时光
  • 教育经历
  • 职业生涯
  • 家庭生活
  • 人生信念
  • 总结回顾

2. 记忆整理 Agent

将口语对话内容整理为结构化的书面章节:

  • 口语转书面语
  • 内容结构化
  • 章节分类
  • 自动生成标题

3. 语音服务

  • ASR (语音识别): 腾讯云一句话识别(引擎 16k_zh_large,含多方言)
  • TTS (语音合成): 使用 OpenAI TTS API 将文本转为语音

4. PDF 生成

使用 ReportLab 和 WeasyPrint 生成精美的回忆录 PDF 文档。

开发指南

添加新的 API 路由

  1. routers/ 目录创建新的路由文件
  2. 定义路由函数
  3. main.py 中注册路由:
from routers import your_router
app.include_router(your_router.router)

添加新的数据库模型

  1. 在对应 feature 的 app/features/<feature_name>/models.py 中定义模型类
  2. 继承 Base(从 app.core.db 导入)
  3. app/main.py 中 import 该 models 模块以注册到 Base.metadata
  4. 运行 Alembic 迁移

添加新的服务

  1. app/features/<feature_name>/service.py 中实现业务逻辑
  2. 通过 deps.py 提供依赖注入
  3. 在对应 feature 的 router 中通过 Depends(get_xxx_service) 使用

安全注意事项

  1. CORS 配置: 本地开发默认可用 allow_origins=["*"]deploy.api_cors_origins 留空);生产/staging 必须在 config/staging.toml / config/production.toml[deploy] 中设置逗号分隔前端域名
  2. API Key 安全: 确保 .env 文件不被提交到版本控制
  3. SECRET_KEY 安全: 使用强随机字符串作为 JWT 签名密钥,生产环境必须更换
  4. 密码安全: 密码使用 bcrypt 哈希存储,不会以明文形式保存
  5. 令牌安全:
    • 访问令牌短期有效2小时降低泄露风险
    • 刷新令牌存储在数据库中,支持撤销;每次 /api/auth/refresh 会轮换 refresh token
    • 已轮换的 refresh token 被再次使用时,服务端吊销全部会话并返回 REFRESH_TOKEN_REUSE
    • 令牌过期后必须使用刷新令牌重新获取
  6. 数据库备份: 定期备份 PostgreSQL 数据库
  7. 错误处理: 所有 API 都包含适当的错误处理和权限验证
  8. 日志记录: 建议添加日志记录功能以便调试和监控

许可证

MIT License