diff --git a/.github/workflows/docker-build-deploy.yml b/.github/workflows/docker-build-deploy.yml index 16c2628..c55fa83 100644 --- a/.github/workflows/docker-build-deploy.yml +++ b/.github/workflows/docker-build-deploy.yml @@ -308,7 +308,7 @@ jobs: exit 1 fi # 仅检查「有效配置行」:跳过整行注释,避免 # KEY=your_* 示例误伤部署 - if grep -Ev '^[[:space:]]*#' "$ENV_SRC" | grep -Eq '=(your_|replace_with_|\\.{3})$'; then + if grep -Ev '^[[:space:]]*#' "$ENV_SRC" | grep -Eq '=(your_|replace_with_|\.{3}$)'; then echo "::error::$ENV_SRC 仍包含占位符值,请先完善环境文件。" exit 1 fi diff --git a/api/.env.staging b/api/.env.staging index 7ce2dcd..7a6dcc6 100644 --- a/api/.env.staging +++ b/api/.env.staging @@ -1,18 +1,20 @@ +# ============================================================================= +# Life Echo API — staging(预发) +# +# 基于 .env.production 生成;staging 发布时 workflow 会上传并复制为运行时 .env。 +# 不要把生产密钥误填进本文件(当前与 production 共用同一套三方密钥)。 +# ============================================================================= + +# ============================================================================= +# Docker Compose(宿主机独立 Caddy 反代到本 API) +# ============================================================================= LIFE_ECHO_API_HOST_BIND=0.0.0.0 LIFE_ECHO_API_HOST_PORT=8000 POSTGRES_HOST_PORT=15432 -# ============================================================================= -# Life Echo API — staging(预发) -# -# 仓库维护本文件;staging 发布时 workflow 会上传并复制为运行时 .env。 -# 不要把生产密钥误填进本文件。 -# ============================================================================= - # ============================================================================= # Logging(loguru sink 最低级别:TRACE / DEBUG / INFO / WARNING / ERROR / CRITICAL) # ============================================================================= -# 预发默认 INFO;勿长期 DEBUG。查慢路径可短时 LOG_AGENT_VERBOSE=1。 LOG_LEVEL=INFO # Agent 单行 INFO 摘要;与 LOG_LEVEL 独立 # LOG_AGENT_VERBOSE=0 @@ -33,79 +35,69 @@ LOG_LEVEL=INFO # ============================================================================= # LLM / DeepSeek # ============================================================================= -DEEPSEEK_API_KEY=your_deepseek_api_key +DEEPSEEK_API_KEY=sk-09f17fb61c5a4299a3afc2a01de7af75 DEEPSEEK_BASE_URL=https://api.deepseek.com DEEPSEEK_MODEL=deepseek-v4-flash +# ============================================================================= +# Memory 向量(智谱 BigModel 国内 embedding-3;与 DeepSeek/OpenAI 用途分离) +# ============================================================================= +ZHIPU_API_KEY=524eda18eb3848e881eefe4c7ef17ec2.xBmGUabYDEa44m3M +EMBEDDING_MODEL=embedding-3 + +# Chat 访谈 +CHAT_ERA_CONTEXT_ENABLED=true +CHAT_INTERVIEW_PERSONA=warm_listener +CHAT_INTERVIEW_TEMPERATURE=0.65 +CHAT_MEMORY_TOP_K=4 +CHAT_MEMORY_EVIDENCE_MAX_CHARS=1400 +CHAT_REPLY_PLANNER_LLM_ENABLED=true + +# Memoir:叙事前口述归一 +MEMOIR_ORAL_NORMALIZE_ENABLED=true +MEMOIR_ORAL_NORMALIZE_MODE=llm +MEMOIR_ORAL_NORMALIZE_LLM_MAX_TOKENS=512 +MEMOIR_ORAL_NORMALIZE_LLM_MAX_INPUT_CHARS=8000 + # ============================================================================= # Database # ============================================================================= -# 本地开发: -# DATABASE_URL=postgresql://postgres:postgres@localhost:5432/life_echo -# Docker / 服务端(主机名一般为 compose 服务名 postgres): -# DATABASE_URL=postgresql://postgres:postgres@postgres:5432/life_echo DATABASE_URL=postgresql://postgres:postgres@postgres:5432/life_echo # ============================================================================= # Redis # ============================================================================= -# 本地开发: -# REDIS_URL=redis://localhost:6379/0 -# Docker / 服务端: -# REDIS_URL=redis://redis:6379/0 REDIS_URL=redis://redis:6379/0 REDIS_SESSION_TTL=86400 -# Celery:ingest 后 Memory LLM 富化任务投递队列(须被 worker 消费;见 README) -# CELERY_MEMORY_ENRICHMENT_QUEUE=memory_idle - # ============================================================================= -# Memory compaction(近重复 memory chunk 软排除;Celery + Redis 防抖) -# 与 example / development / production 一致默认开启;预发须跑 worker + celery-beat。 +# Memory compaction # ============================================================================= MEMORY_COMPACTION_ENABLED=true -# MEMORY_COMPACTION_DEBOUNCE_SECONDS=105 -# MEMORY_COMPACTION_LOCK_TTL_SECONDS=600 -# MEMORY_COMPACTION_CHUNK_SIMILARITY_THRESHOLD=0.92 -# MEMORY_COMPACTION_MIN_LAYERS_FOR_EXCLUDE=2 -# MEMORY_COMPACTION_MAX_CHUNKS_PER_RUN=200 -# MEMORY_COMPACTION_MAX_EXCLUDES_PER_RUN=50 -# MEMORY_COMPACTION_MAX_NEIGHBORS_PER_CHUNK=25 -# MEMORY_COMPACTION_TEXT_JACCARD_MIN=0.55 -# MEMORY_COMPACTION_METADATA_EVENT_YEAR_WINDOW=1 -# MEMORY_COMPACTION_SWEEP_RECENT_HOURS=24 # ============================================================================= # Auth # ============================================================================= -# 建议使用: openssl rand -hex 32 -SECRET_KEY=replace_with_a_strong_random_secret +SECRET_KEY=cf47555c7ecbe5ddb7fd2113c59e08a8bcb110810c42f7c644e06a5acc898608 ALGORITHM=HS256 ACCESS_TOKEN_EXPIRE_MINUTES=120 -# 预发环境:允许内网/端到端评测使用 mock 短信登录(生产禁用) APP_ENV=staging MOCK_SMS_LOGIN_ENABLED=1 # ============================================================================= # Tencent Cloud — 短信 # ============================================================================= -# 短信、一句话 ASR/TTS、COS 为不同产品;同一主账号可共用同一对 SecretId/SecretKey(分别填三处)。 -TENCENT_SMS_SECRET_ID=your_tencent_sms_secret_id -TENCENT_SMS_SECRET_KEY=your_tencent_sms_secret_key -# 短信应用 SDK AppID -TENCENT_SMS_SDK_APP_ID=your_sms_sdk_app_id -# 短信签名内容(不包含【】符号) -TENCENT_SMS_SIGN_NAME=your_sms_sign_name -# 短信模板 ID -TENCENT_SMS_TEMPLATE_ID=your_sms_template_id -# 短信模板参数数量(1=仅验证码,2=验证码+过期时间) -# 若遇 TemplateParamSetNotMatchApprovedTemplate,请对照控制台模板配置 +TENCENT_SMS_SECRET_ID=AKIDa2ILCwUr56uVt31oU0JOHxPfGhvvkLiq +TENCENT_SMS_SECRET_KEY=xiFbjlZ9XheS2NWYLvHRPAh2A5nGYcR2 +TENCENT_SMS_SDK_APP_ID=1401010099 +TENCENT_SMS_SIGN_NAME=上海华嘎科技有限公司 +TENCENT_SMS_TEMPLATE_ID=2592163 TENCENT_SMS_TEMPLATE_PARAM_COUNT=1 # ============================================================================= # ASR Provider(whisper | tencent) # ============================================================================= -ASR_PROVIDER=whisper +ASR_PROVIDER=tencent # ============================================================================= # Whisper ASR(ASR_PROVIDER=whisper 时使用) @@ -114,89 +106,70 @@ ASR_MODEL_SIZE=small ASR_DEVICE=cpu ASR_COMPUTE_TYPE=int8 -# GPU 环境(示例,按需启用) -# ASR_MODEL_SIZE=medium -# ASR_DEVICE=cuda -# ASR_COMPUTE_TYPE=float16 +# ============================================================================= +# Tencent Cloud — 一句话 ASR + TTS +# ============================================================================= +TENCENT_SECRET_ID=AKIDa2ILCwUr56uVt31oU0JOHxPfGhvvkLiq +TENCENT_SECRET_KEY=xiFbjlZ9XheS2NWYLvHRPAh2A5nGYcR2 # ============================================================================= -# Tencent Cloud — 一句话 ASR + TTS(ASR_PROVIDER=tencent 或 TTS_PROVIDER=tencent) +# TTS # ============================================================================= -TENCENT_SECRET_ID=your_tencent_asr_secret_id -TENCENT_SECRET_KEY=your_tencent_asr_secret_key - -# ============================================================================= -# TTS(文字转语音,Agent 回复朗读)— 与 ASR 独立 -# ============================================================================= -# ENABLE_TTS:是否启用「助手回复朗读」服务端能力(TTS 适配器与密钥配置)。关则永远不合成。 -# 每轮是否实际合成:由客户端在 WebSocket `text` / `audio_segment` / `audio_message` 的 `data.tts_this_turn` 控制(未传或 false 仅返回文字)。 -# 若 ENABLE_TTS=true 且该轮 `tts_this_turn=true`:每一段助手文案先下发 `tts_audio`,再下发对应段的 `agent_response`。 ENABLE_TTS=true TTS_PROVIDER=tencent -# 仅 TTS_PROVIDER=openai 时需要 -# OPENAI_API_KEY=your_openai_api_key -# 音色 ID 见 https://cloud.tencent.com/document/product/1073/92668 TTS_VOICE_TYPE=501004 TTS_CODEC=mp3 # ============================================================================= # WeChat Pay # ============================================================================= -WECHAT_PAY_APP_ID=your_wechat_pay_app_id -WECHAT_PAY_MCH_ID=your_wechat_mch_id -WECHAT_PAY_API_V3_KEY=your_wechat_api_v3_key -# 商户私钥:推荐使用文件路径,避免 .env 中长 PEM 转义问题 +WECHAT_PAY_APP_ID=wx1df508452e06cfb8 +WECHAT_PAY_MCH_ID=1662979099 +WECHAT_PAY_API_V3_KEY=xjvGSJLGJAJfjgskfjslafjsajsdjals WECHAT_PAY_PRIVATE_KEY_PATH=certs/apiclient_key.pem -# 若不用文件,可配置 WECHAT_PAY_PRIVATE_KEY(PEM,换行用 \n) -# WECHAT_PAY_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----" -WECHAT_PAY_CERT_SERIAL_NO=your_wechat_cert_serial_no -WECHAT_PAY_NOTIFY_URL=https://your-domain.com/api/payment/notify/wechat -# 平台公钥模式(仅当无法走平台证书自动拉取时使用);勿填商户私钥路径 -# WECHAT_PAY_PLATFORM_PUBLIC_KEY_PATH=certs/wechat_platform_public_key.pem -# WECHAT_PAY_PLATFORM_PUBLIC_KEY_ID=your_wechat_platform_public_key_id +WECHAT_PAY_CERT_SERIAL_NO=1AA82328AC1456C6F115B014606F22CD621D2032 +WECHAT_PAY_NOTIFY_URL=https://lifecho.worldsplats.com/api/payment/notify/wechat # ============================================================================= -# Alipay +# Alipay(未接入时保持空字符串) # ============================================================================= -ALIPAY_APP_ID=your_alipay_app_id -ALIPAY_PRIVATE_KEY=your_alipay_private_key -ALIPAY_PUBLIC_KEY=your_alipay_public_key -ALIPAY_NOTIFY_URL=https://your-domain.com/api/payment/notify/alipay +ALIPAY_APP_ID= +ALIPAY_PRIVATE_KEY= +ALIPAY_PUBLIC_KEY= +ALIPAY_NOTIFY_URL=https://lifecho.worldsplats.com/api/payment/notify/alipay # ============================================================================= # Misc # ============================================================================= -ENABLE_TEST_SUBSCRIPTION=0 +ENABLE_TEST_SUBSCRIPTION=1 # ============================================================================= -# Memoir image generation(Story 主图等;轮询 Liblib 任务) +# Memoir image generation # ============================================================================= -MEMOIR_IMAGE_ENABLED=false +MEMOIR_IMAGE_ENABLED=true MEMOIR_IMAGE_POLL_INTERVAL=3 MEMOIR_IMAGE_MAX_ATTEMPTS=20 MEMOIR_IMAGE_PROVIDER=liblib MEMOIR_IMAGE_STYLE_DEFAULT=watercolor MEMOIR_IMAGE_SIZE_DEFAULT=1280x720 -# 章节正文内至少多少张 asset:// 插图才生成/展示章节封面(≥1 即有一张图可出封面) MEMOIR_MIN_INLINE_IMAGES_FOR_CHAPTER_COVER=1 -# 可选,Liblib 返回图片域名不在默认白名单时(逗号分隔) -# MEMOIR_IMAGE_DOWNLOAD_HOSTS=liblib.cloud,liblibai.cloud +STORY_IMAGE_MIN_BODY_CHARS=800 +MEMOIR_NARRATIVE_FALLBACK_BODY_RATIO=0.5 +MEMOIR_NARRATIVE_FALLBACK_MIN_CHARS=20 # ============================================================================= # Liblib image provider # ============================================================================= -LIBLIB_ACCESS_KEY=your_liblib_access_key -LIBLIB_SECRET_KEY=your_liblib_secret_key +LIBLIB_ACCESS_KEY=zrDp6quCOKlLwcewOEfrog +LIBLIB_SECRET_KEY=iTVHo5Nf3KA-xpC1Mja80bC93u6chJem LIBLIB_BASE_URL=https://openapi.liblibai.cloud -LIBLIB_TEMPLATE_UUID=your_liblib_template_uuid +LIBLIB_TEMPLATE_UUID=5d7e67009b344550bc1aa6ccbfa1d7f4 # ============================================================================= # Tencent Cloud — COS(回忆录图片存储) # ============================================================================= -TENCENT_COS_SECRET_ID=your_tencent_cos_secret_id -TENCENT_COS_SECRET_KEY=your_tencent_cos_secret_key +TENCENT_COS_SECRET_ID=AKIDa2ILCwUr56uVt31oU0JOHxPfGhvvkLiq +TENCENT_COS_SECRET_KEY=xiFbjlZ9XheS2NWYLvHRPAh2A5nGYcR2 TENCENT_COS_REGION=ap-shanghai -TENCENT_COS_BUCKET=your_bucket_name -TENCENT_COS_BASE_URL=https://your_bucket_name.cos.ap-shanghai.myqcloud.com -# 可选临时凭证 -# TENCENT_COS_TOKEN= +TENCENT_COS_BUCKET=life-echo-dev-1319381411 +TENCENT_COS_BASE_URL=https://life-echo-dev-1319381411.cos.ap-shanghai.myqcloud.com