Files
life-echo/.github/workflows/legacy-data-migrate.yml
Kevin e4bf0710c7 feat(memory,conversation): 记忆富化/证据包、时间线幂等字段与对话分段全链路
数据库
- 新增迁移 0003:timeline_events.memory_source_id 外键 → memory_sources,便于按 ingest 源做时间线幂等

后端 - 记忆
- 新增 ingest 后 LLM 富化(摘要/事实/时间线),可配置开关与最大字符数
- 新增证据包组装:合并 chunk、摘要、事实、时间线、故事等检索结果;支持空 query 时是否仍带 rolling 等开关
- repo/retriever/service/router/schemas/summarizer/timeline/extractor 等扩展;文档 memory-retrieval.md 更新

后端 - 对话 WS
- 增加 PING/PONG;分段 ASR 日志与空音频处理;转写失败与「无助手回复」错误提示更明确
- 助手多段回复持久化使用统一分隔符,与分段逻辑一致

后端 - Agent
- reply_limits:按 [SPLIT] 与段落拆段,并保证非空 fallback,供 WS 与 TTS 多段下发

后端 - 回忆录任务
- transcript ingest 记录 source_id;任务成功结?
2026-03-27 16:24:43 +08:00

165 lines
6.7 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 一次性:将旧 pg_dump 数据迁入当前 Alembic schemaapi/scripts/migrate_legacy_to_current.py
#
# 目标库须已是 alembic upgrade head与线上一致占号用户清理逻辑依赖当前全部迁移后的表结构。
#
# 不会在 push / 部署时自动运行,仅手动 workflow_dispatch避免每次构建误迁库。
# 远端需已用 docker compose 部署(目录约定与 docker-build-deploy 一致STAGING_DEPLOY_PATH / PROD_DEPLOY_PATH
#
# 备份文件:提交在仓库 api/backups/<dump_filename>(默认 life_echo_20260313_182756.sql
# workflow 会先 scp 到远端再迁移。其他 *.sql 仍被 gitignore需按需增加 ! 例外行。
#
# Secrets与 Docker Build and Deploy 相同STAGING_* / PROD_*)。
name: Legacy DB migrate (one-shot)
on:
workflow_dispatch:
inputs:
environment:
description: 'staging 或 production'
required: true
type: choice
options:
- staging
- production
confirm:
description: '确认执行迁移(必须完整输入 MIGRATE'
required: true
type: string
dump_filename:
description: '仓库 api/backups/ 与远端同名 SQL 文件(须已提交)'
required: true
type: string
default: life_echo_20260313_182756.sql
recreate_legacy_database:
description: 'true=DROP 并重建 life_echo_legacy + 重新导入 SQLfalse=仅运行迁移脚本'
required: true
type: boolean
default: true
concurrency:
group: legacy-migrate-${{ github.ref }}
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
migrate:
name: Legacy migrate on server
runs-on: ubuntu-latest
steps:
- name: Require confirm MIGRATE
run: |
if [ "${{ github.event.inputs.confirm }}" != "MIGRATE" ]; then
echo "::error::确认字段必须精确为 MIGRATE当前未执行任何操作"
exit 1
fi
- name: Checkout
uses: actions/checkout@v5
- name: Verify backup file in repo
env:
DUMP_FILENAME: ${{ github.event.inputs.dump_filename }}
run: |
set -euo pipefail
f="api/backups/$DUMP_FILENAME"
if [ ! -f "$f" ]; then
echo "::error::仓库中不存在 $f请提交该文件或改正 dump_filename并在 .gitignore 中为该文件增加 ! 例外"
exit 1
fi
ls -la "$f"
- name: Set up SSH (production)
if: github.event.inputs.environment == 'production'
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
- name: Set up SSH (staging)
if: github.event.inputs.environment != 'production'
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.STAGING_SSH_PRIVATE_KEY }}
- name: Export deploy connection env
run: |
if [ "${{ github.event.inputs.environment }}" = "production" ]; then
{
echo "SSH_HOST=${{ secrets.PROD_SSH_HOST }}"
echo "SSH_USER=${{ secrets.PROD_SSH_USER }}"
echo "SSH_PORT=${{ secrets.PROD_SSH_PORT || '22' }}"
echo "COMPOSE_DIR=${{ secrets.PROD_DEPLOY_PATH || '/opt/life-echo' }}"
} >> "$GITHUB_ENV"
else
{
echo "SSH_HOST=${{ secrets.STAGING_SSH_HOST }}"
echo "SSH_USER=${{ secrets.STAGING_SSH_USER }}"
echo "SSH_PORT=${{ secrets.STAGING_SSH_PORT || '22' }}"
echo "COMPOSE_DIR=${{ secrets.STAGING_DEPLOY_PATH || '/opt/life-echo' }}"
} >> "$GITHUB_ENV"
fi
- name: Add server to known hosts
run: |
mkdir -p ~/.ssh
ssh-keyscan -H -p "${SSH_PORT:-22}" "${SSH_HOST}" >> ~/.ssh/known_hosts
- name: Upload dump to server
env:
DUMP_FILENAME: ${{ github.event.inputs.dump_filename }}
run: |
set -euo pipefail
ssh -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" "mkdir -p \"$COMPOSE_DIR/api/backups\""
scp -P "$SSH_PORT" "api/backups/$DUMP_FILENAME" "$SSH_USER@$SSH_HOST:$COMPOSE_DIR/api/backups/$DUMP_FILENAME"
echo "已上传 api/backups/$DUMP_FILENAME -> $COMPOSE_DIR/api/backups/"
- name: Run legacy migrate on remote
env:
DUMP_FILENAME: ${{ github.event.inputs.dump_filename }}
RECREATE_LEGACY: ${{ github.event.inputs.recreate_legacy_database }}
run: |
set -euo pipefail
# 通过环境变量传入远端,避免 heredoc 引号问题
ssh -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" \
"export COMPOSE_DIR=$(printf '%q' "$COMPOSE_DIR"); export DUMP_FILENAME=$(printf '%q' "$DUMP_FILENAME"); export RECREATE_LEGACY=$(printf '%q' "$RECREATE_LEGACY"); bash -s" << 'REMOTE'
set -euo pipefail
cd "$COMPOSE_DIR/api"
DUMP="$PWD/backups/$DUMP_FILENAME"
if [ ! -f "$DUMP" ]; then
echo "::error::远端缺少备份文件: $DUMP"
exit 1
fi
if [ ! -f .env ]; then
echo "::error::缺少 $PWD/.env"
exit 1
fi
# DATABASE_URL 可能含特殊字符,取第一个等号后的整行
DB_URL=$(grep -m1 '^DATABASE_URL=' .env | cut -d= -f2- | tr -d '\r' | sed 's/^"//;s/"$//;s/^'"'"'//;s/'"'"'$//')
PG_USER=$(grep -m1 '^POSTGRES_USER=' .env 2>/dev/null | cut -d= -f2- | tr -d '\r' | sed 's/^"//;s/"$//' || true)
PG_PASS=$(grep -m1 '^POSTGRES_PASSWORD=' .env 2>/dev/null | cut -d= -f2- | tr -d '\r' | sed 's/^"//;s/"$//' || true)
PG_USER=${PG_USER:-postgres}
PG_PASS=${PG_PASS:-postgres}
LEGACY_URL="postgresql://${PG_USER}:${PG_PASS}@postgres:5432/life_echo_legacy"
if [ "$RECREATE_LEGACY" = "true" ]; then
echo "重建 life_echo_legacy 并导入 SQL..."
docker compose exec -T postgres psql -U postgres -d postgres -v ON_ERROR_STOP=1 -c \
"DROP DATABASE IF EXISTS life_echo_legacy WITH (FORCE);"
docker compose exec -T postgres psql -U postgres -d postgres -v ON_ERROR_STOP=1 -c \
"CREATE DATABASE life_echo_legacy;"
docker exec -i life-echo-postgres psql -U postgres -d life_echo_legacy -v ON_ERROR_STOP=1 < "$DUMP"
else
echo "跳过 DROP/导入,假定 life_echo_legacy 已就绪"
fi
echo "执行 Python 迁移api 容器内)..."
docker compose exec -T api uv run python scripts/migrate_legacy_to_current.py \
--legacy-url "$LEGACY_URL" \
--target-url "$DB_URL" \
--phone-conflict replace_target
echo "完成。"
REMOTE