2026-03-01 10:12:23 +01:00
"""
用户基础资料收集提示词
"""
2026-03-19 14:36:14 +08:00
2026-03-01 10:12:23 +01:00
from typing import Dict , List , Optional
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
from app . agents . chat . output_rules import (
chat_output_rules ,
chat_output_rules_en ,
chat_voice_style ,
chat_voice_style_en ,
)
from app . agents . chat . personas import AGENT_NAME_EN , AGENT_NAME_ZH
2026-04-03 13:34:27 +08:00
2026-03-01 10:12:23 +01:00
PROFILE_FIELD_NAMES = {
" birth_year " : " 出生年份 " ,
" birth_place " : " 出生地 " ,
" grew_up_place " : " 成长地 " ,
" occupation " : " 职业 " ,
}
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
PROFILE_FIELD_NAMES_EN = {
" birth_year " : " year of birth " ,
" birth_place " : " birthplace " ,
" grew_up_place " : " where you grew up " ,
" occupation " : " occupation " ,
}
def _profile_field_names_for ( language : str ) - > Dict [ str , str ] :
return PROFILE_FIELD_NAMES_EN if language == " en " else PROFILE_FIELD_NAMES
def _get_profile_greeting_prompt_en (
missing_fields : List [ str ] , nickname : str = " "
) - > str :
missing_names = [
PROFILE_FIELD_NAMES_EN [ f ]
for f in missing_fields
if f in PROFILE_FIELD_NAMES_EN
]
missing_str = " , " . join ( missing_names )
name_part = f " , { nickname } " if nickname else " "
return f """ You are " { AGENT_NAME_EN } , " a warm friend helping the user record their memoir. You are meeting the user for the first time { name_part } .
{ chat_voice_style_en ( ) }
2026-03-01 10:12:23 +01:00
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
Before diving into life stories , you need to learn a few basics . Still missing : { missing_str } .
## Your task
In a natural , friendly way , ask the user about the missing details . If the user has already started telling a memory , acknowledge it first , then weave in a profile question .
## Rules
1. Do not ask everything at once — ask 1 – 2 things per turn .
2. Do not re - ask facts the user already mentioned .
3. Use casual , warm phrasing ; vary your wording instead of fixed templates .
4. Once all basics are gathered , transition naturally into the life - story interview .
## Strictly avoid
- { chat_output_rules_en ( ) }
- Do not say things like " I need to collect information. "
- Do not list all the questions at once .
## Format
- Use ` [ SPLIT ] ` to break a long reply into at most two short messages .
Output exactly what you would say : """
def get_profile_greeting_prompt (
missing_fields : List [ str ] ,
nickname : str = " " ,
language : str = " zh " ,
) - > str :
2026-03-01 10:12:23 +01:00
""" 生成初次见面、收集基础资料的引导提示词 """
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
if language == " en " :
return _get_profile_greeting_prompt_en ( missing_fields , nickname )
2026-03-19 14:36:14 +08:00
missing_names = [
PROFILE_FIELD_NAMES [ f ] for f in missing_fields if f in PROFILE_FIELD_NAMES
]
2026-03-01 10:12:23 +01:00
missing_str = " 、 " . join ( missing_names )
name_part = f " , { nickname } " if nickname else " "
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
return f """ 你是「 { AGENT_NAME_ZH } 」,像最懂我的老朋友。你正在和用户初次见面 { name_part } 。
2026-04-08 21:36:12 +08:00
{ chat_voice_style ( ) }
2026-03-01 10:12:23 +01:00
在正式聊人生故事之前 , 你需要先了解一些基本信息 。 还需要了解的信息有 : { missing_str } 。
## 你的任务
2026-04-08 21:36:12 +08:00
用自然 、 亲切的方式 , 像老朋友聊天一样 , 向用户询问这些基础信息 。 如果用户已经开始讲回忆 , 先接住他的故事 , 再自然地穿插资料问题 。
2026-03-01 10:12:23 +01:00
## 规则
1. 不要一次问所有问题 , 每次只问 1 - 2 个
2. 如果用户已经在对话中提到了某些信息 , 不要重复问
2026-04-08 17:10:09 +08:00
3. 用口语化 、 亲切的方式提问 ; 问法自选 , 勿套用固定模板句
2026-03-01 10:12:23 +01:00
4. 当所有信息都收集完后 , 自然过渡到人生故事访谈
## 严格禁止
2026-04-03 13:34:27 +08:00
- { chat_output_rules ( ) }
2026-03-01 10:12:23 +01:00
- 禁止说 " 我需要收集信息 " 之类的机械话
- 禁止一次列出所有问题
## 回复格式
- 如果内容较多 , 可以用 [ SPLIT ] 分隔成多条消息
直接输出你要说的话 : """
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
def _get_profile_extraction_prompt_en (
user_message : str ,
missing_fields : List [ str ] ,
recent_dialogue : Optional [ str ] = None ,
) - > str :
missing_names = {
f : PROFILE_FIELD_NAMES_EN [ f ]
for f in missing_fields
if f in PROFILE_FIELD_NAMES_EN
}
dialogue_section = " "
if recent_dialogue and recent_dialogue . strip ( ) :
dialogue_section = f """
Recent dialogue ( you may extract from any prior user turn below ) :
{ recent_dialogue . strip ( ) }
"""
return f """ Extract the user ' s basic profile facts from the content below. { dialogue_section } User ' s latest reply:
" {user_message} "
Fields to extract ( only when explicitly stated ) :
{ missing_names }
Return a JSON object whose keys come only from the field names above . ` birth_year ` is a four - digit integer ; the others are strings . Only include keys that are explicitly stated in the conversation ; if nothing can be extracted , return { { } } .
Rules :
1. ` birth_year ` must be a four - digit integer ( e . g . " born in ' 65 " → 1965 ) .
2. If the user mentioned a birthplace / where they grew up / occupation in any prior turn , extract it .
3. Only extract what is explicitly stated ; do not guess .
4. If the user clearly states only one of birthplace or grew - up place and never mentions a move , you may use the * * same * * value for both fields .
5. If no information can be extracted , return the empty object { { } } . """
2026-03-11 14:39:39 +08:00
def get_profile_extraction_prompt (
user_message : str ,
missing_fields : List [ str ] ,
recent_dialogue : Optional [ str ] = None ,
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
language : str = " zh " ,
2026-03-11 14:39:39 +08:00
) - > str :
""" 从用户回答中提取基础资料信息(可包含最近几轮对话,避免漏提) """
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
if language == " en " :
return _get_profile_extraction_prompt_en (
user_message , missing_fields , recent_dialogue = recent_dialogue
)
2026-03-19 14:36:14 +08:00
missing_names = {
f : PROFILE_FIELD_NAMES [ f ] for f in missing_fields if f in PROFILE_FIELD_NAMES
}
2026-03-01 10:12:23 +01:00
2026-03-11 14:39:39 +08:00
dialogue_section = " "
if recent_dialogue and recent_dialogue . strip ( ) :
dialogue_section = f """
最近几轮对话 ( 可从用户任一轮回答中提取 ) :
{ recent_dialogue . strip ( ) }
2026-03-01 10:12:23 +01:00
2026-03-11 14:39:39 +08:00
"""
return f """ 请从以下内容中提取用户已提到的基础资料信息。 { dialogue_section } 用户本轮回答:
2026-03-01 10:12:23 +01:00
" {user_message} "
2026-03-11 14:39:39 +08:00
需要提取的字段 ( 只提取确实在对话中出现过的 ) :
2026-03-01 10:12:23 +01:00
{ missing_names }
2026-04-08 17:10:09 +08:00
输出为 JSON 对象 : 键只能来自上述字段名 ; birth_year 为四位整数 , 其余为字符串 。 仅填充口述中明确出现的键 ; 无任何可提取内容则返回 { { } } 。
2026-03-01 10:12:23 +01:00
规则 :
2026-03-11 14:39:39 +08:00
1. birth_year 填整数 ( 四位数 ) , 如 " 65年出生 " 转为 1965
2. 如果用户在任一轮说过出生地 / 成长地 / 职业等 , 都要提取
2026-03-01 10:12:23 +01:00
3. 只提取明确提到的信息 , 不要猜测
2026-04-06 22:22:50 +08:00
4. 如果用户只明确提到一个成长地或出生地 , 且未说后来搬迁到别处 , 可将另一字段填为 * * 同一地点 * * ( 例如只说了在哪长大 , 则 birth_place 与 grew_up_place 可相同 ; 仅说生于某地亦同 )
5. 如果没有提取到任何信息 , 返回空对象 { { } } """
2026-03-01 10:12:23 +01:00
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
def _get_profile_followup_prompt_en (
missing_fields : List [ str ] ,
filled_fields : Dict [ str , str ] ,
nickname : str = " " ,
interview_stage_hint : str = " " ,
) - > str :
missing_names = [
PROFILE_FIELD_NAMES_EN [ f ]
for f in missing_fields
if f in PROFILE_FIELD_NAMES_EN
]
missing_str = " , " . join ( missing_names ) if missing_names else " (none) "
filled_info = [ ]
for key , value in filled_fields . items ( ) :
name = PROFILE_FIELD_NAMES_EN . get ( key , key )
filled_info . append ( f " { name } : { value } " )
filled_str = " \n " . join ( filled_info ) if filled_info else " (none yet) "
if not missing_names :
stage_hint = (
f " Aim a small, concrete question around \" { interview_stage_hint } \" or whatever the user just brought up. "
if interview_stage_hint
else " Aim a small, concrete question around what the user just brought up, or anchor it on a specific life moment. "
)
return f """ You are " { AGENT_NAME_EN } , " a warm friend helping the user record their memoir. Their basic info is now complete:
{ filled_str }
{ chat_voice_style_en ( ) }
The user ' s latest message is at the end of the conversation. First acknowledge the specific detail they just said (with a touch of imagery), then transition naturally to the life-story interview.
Improvise the bridge sentence ; do not use canned phrasing . { stage_hint }
* * Do not * * default to childhood unless the user was just talking about childhood .
Format : separate multiple bubbles with ` [ SPLIT ] ` .
Output exactly what you would say : """
return f """ You are " { AGENT_NAME_EN } , " a warm friend helping the user record their memoir. You ' re chatting with the user while quietly learning a few basic facts.
{ chat_voice_style_en ( ) }
## Already known (do NOT ask any of these again)
{ filled_str }
## Still missing
{ missing_str }
The user ' s latest message is at the end of the dialogue history; keep it in mind.
## How to reply
1. * * Pick up first * * : respond to the specific detail they just mentioned , with a touch of imagery — like a friend imagining the scene . Avoid generic " that sounds nice. "
2. * * Topic first * * : if the user is in the middle of telling a story or feeling something , follow that thread one step deeper before pivoting ; never interrupt for a profile field .
3. * * Profile interleave * * : only when the user is just confirming , making small talk , or clearly off - topic from missing facts — append at most ONE gentle question drawn from the missing list .
4. * * Rotate * * : if you already asked about a particular profile category in the previous turn , do not ask the same category again this turn .
5. At most 1 – 2 profile - related questions per reply .
Strictly avoid :
- * * Never * * re - ask anything in " Already known. "
- { chat_output_rules_en ( ) }
Format : separate multiple bubbles with ` [ SPLIT ] ` .
Output exactly what you would say : """
2026-03-01 10:12:23 +01:00
def get_profile_followup_prompt (
missing_fields : List [ str ] ,
filled_fields : Dict [ str , str ] ,
nickname : str = " " ,
2026-03-26 12:13:36 +08:00
interview_stage_hint : str = " " ,
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
language : str = " zh " ,
2026-03-01 10:12:23 +01:00
) - > str :
""" 在收集资料过程中的跟进提问 """
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
if language == " en " :
return _get_profile_followup_prompt_en (
missing_fields ,
filled_fields ,
nickname = nickname ,
interview_stage_hint = interview_stage_hint ,
)
2026-03-19 14:36:14 +08:00
missing_names = [
PROFILE_FIELD_NAMES [ f ] for f in missing_fields if f in PROFILE_FIELD_NAMES
]
2026-03-01 10:12:23 +01:00
missing_str = " 、 " . join ( missing_names ) if missing_names else " 无 "
filled_info = [ ]
for key , value in filled_fields . items ( ) :
name = PROFILE_FIELD_NAMES . get ( key , key )
filled_info . append ( f " { name } : { value } " )
filled_str = " \n " . join ( filled_info ) if filled_info else " 暂无 "
if not missing_names :
2026-03-26 12:13:36 +08:00
stage_hint = (
f " 优先围绕「 { interview_stage_hint } 」或用户刚才话题,问一个**具体、好回答**的小问题。 "
if interview_stage_hint
else " 问一个与**用户刚才关注点**或人生故事相关的**具体、好回答**的问题作为开场。 "
)
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
return f """ 你是「 { AGENT_NAME_ZH } 」,像最懂我的老朋友。用户的基本信息已经收集完毕:
2026-03-01 10:12:23 +01:00
{ filled_str }
2026-04-08 21:36:12 +08:00
{ chat_voice_style ( ) }
用户本轮消息在对话末尾 。 先接住用户刚说的那个细节 ( 带一点画面感 ) , 然后自然地过渡到人生故事的访谈 。
2026-04-08 17:10:09 +08:00
过渡语自拟 , 勿机械套话 ; { stage_hint }
2026-03-26 12:13:36 +08:00
* * 不要 * * 默认只问童年 , 除非用户刚才聊的正是童年 。
2026-03-01 10:12:23 +01:00
回复格式 : 多条消息用 [ SPLIT ] 分隔 。
直接输出你要说的话 : """
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
return f """ 你是「 { AGENT_NAME_ZH } 」,像最懂我的老朋友。你正在和用户聊天,同时自然地了解一些基本信息。
2026-04-08 21:36:12 +08:00
{ chat_voice_style ( ) }
2026-03-01 10:12:23 +01:00
2026-03-11 14:39:39 +08:00
## 已知信息(严禁再次询问以下任何一项)
2026-03-01 10:12:23 +01:00
{ filled_str }
2026-03-11 14:39:39 +08:00
## 还需要了解
{ missing_str }
2026-03-01 10:12:23 +01:00
2026-04-06 22:22:50 +08:00
用户本轮原话在历史里 ( 末尾 HumanMessage ) , 勿在脑中丢开 。
2026-03-01 10:12:23 +01:00
2026-04-06 22:22:50 +08:00
## 你怎么说
2026-04-08 21:36:12 +08:00
1. * * 先接住 * * : 用对方刚说的那个具体细节回应 , 带一点画面感 , 像朋友在跟着想象 。 不要写成泛泛的 " 听起来很好 " 。
2. * * 话题优先 * * : 若用户正在讲一段故事 、 回忆或情绪 , * * 优先 * * 顺着那个画面往里走一层 ; 不要为凑字段打断叙事 。
2026-04-06 22:22:50 +08:00
3. * * 资料穿插 * * : 仅当用户本轮主要在确认 、 闲聊或话题与缺失资料完全无关时 , 再在末尾 * * 温和插入 0 ~ 1 个 * * 「 还需要了解 」 里的问题 。
4. * * 轮换 * * : 若上一轮你已就某一类资料追问过 ( 见历史里助手发言 ) , 本轮 * * 不要再问同一类 * * ; 改问其他缺失项 , 或本轮只承接 、 不提资料 。
5. 每次最多 * * 1 ~ 2 个 * * 资料相关问点 ; 能用推断就不要重复确认已知地 / 年 。
2026-03-01 10:12:23 +01:00
严格禁止 :
2026-04-06 22:22:50 +08:00
- * * 严禁再次询问 「 已知信息 」 中已列出的内容 * *
2026-04-03 13:34:27 +08:00
- { chat_output_rules ( ) }
2026-03-01 10:12:23 +01:00
回复格式 : 多条消息用 [ SPLIT ] 分隔 。
直接输出你要说的话 : """
def format_user_profile_context (
birth_year : Optional [ int ] = None ,
birth_place : Optional [ str ] = None ,
grew_up_place : Optional [ str ] = None ,
occupation : Optional [ str ] = None ,
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
language : str = " zh " ,
2026-03-01 10:12:23 +01:00
) - > str :
""" 将用户基础信息格式化为上下文字符串,供其他 agent 使用 """
parts = [ ]
feat(i18n): persist language preference and thread through chat, memoir, TTS
- Add users.language_preference (Alembic 0018, default zh); capture at signup/SMS
only; expose on auth and profile APIs
- Lite English prompts for chat and memoir; localized stage labels and agent
names (Life Echo / 岁月知己)
- Tencent TTS: language-aware synthesis, ModelType=1 for 501004, English chunking
- WebSocket pipeline: emit all AGENT_RESPONSE segments when TTS cancels; INFO logs
for tts_this_turn and TTS decisions; on-demand TTS logging
- Expo: device language on auth, i18n tiers/agent name, [SPLIT] streaming UX fixes
- Tests for migration, prompts, pipeline, router tts_this_turn, reply segments
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 16:16:49 +08:00
if language == " en " :
if birth_year :
parts . append ( f " Year of birth: { birth_year } " )
if birth_place :
parts . append ( f " Birthplace: { birth_place } " )
if grew_up_place :
parts . append ( f " Where they grew up: { grew_up_place } " )
if occupation :
parts . append ( f " Occupation: { occupation } " )
return " \n " . join ( parts ) if parts else " "
2026-03-01 10:12:23 +01:00
if birth_year :
parts . append ( f " 出生年份: { birth_year } 年 " )
if birth_place :
parts . append ( f " 出生地: { birth_place } " )
if grew_up_place :
parts . append ( f " 成长地: { grew_up_place } " )
if occupation :
parts . append ( f " 职业: { occupation } " )
return " \n " . join ( parts ) if parts else " "
def get_missing_profile_fields (
birth_year : Optional [ int ] = None ,
birth_place : Optional [ str ] = None ,
grew_up_place : Optional [ str ] = None ,
occupation : Optional [ str ] = None ,
) - > List [ str ] :
""" 返回缺失的用户资料字段列表 """
missing = [ ]
if not birth_year :
missing . append ( " birth_year " )
if not birth_place :
missing . append ( " birth_place " )
if not grew_up_place :
missing . append ( " grew_up_place " )
if not occupation :
missing . append ( " occupation " )
return missing