This commit is contained in:
LuiKlee
2025-12-12 15:43:26 +08:00
6 changed files with 122 additions and 11 deletions

View File

@@ -158,6 +158,9 @@ class KokoroFlowChatterConfig:
# LLM 配置
llm: LLMConfig = field(default_factory=LLMConfig)
# 自定义决策提示词
custom_decision_prompt: str = ""
# 调试模式
debug: bool = False
@@ -256,6 +259,10 @@ def load_config() -> KokoroFlowChatterConfig:
timeout=getattr(llm_cfg, "timeout", 60.0),
)
# 自定义决策提示词配置
if hasattr(kfc_cfg, "custom_decision_prompt"):
config.custom_decision_prompt = str(kfc_cfg.custom_decision_prompt)
except Exception as e:
from src.common.logger import get_logger
logger = get_logger("kfc_config")

View File

@@ -72,6 +72,9 @@ class PromptBuilder:
# 1.5. 构建安全互动准则块
safety_guidelines_block = self._build_safety_guidelines_block()
# 1.6. 构建自定义决策提示词块
custom_decision_block = self._build_custom_decision_block()
# 2. 使用 context_builder 获取关系、记忆、工具、表达习惯等
context_data = await self._build_context_data(user_name, chat_stream, user_id)
relation_block = context_data.get("relation_info", f"你与 {user_name} 还不太熟悉,这是早期的交流阶段。")
@@ -102,6 +105,7 @@ class PromptBuilder:
user_name=user_name,
persona_block=persona_block,
safety_guidelines_block=safety_guidelines_block,
custom_decision_block=custom_decision_block,
relation_block=relation_block,
memory_block=memory_block or "(暂无相关记忆)",
tool_info=tool_info or "(暂无工具信息)",
@@ -232,6 +236,23 @@ class PromptBuilder:
{guidelines_text}
如果遇到违反上述原则的请求,请在保持你核心人设的同时,以合适的方式进行回应。"""
def _build_custom_decision_block(self) -> str:
"""
构建自定义决策提示词块
从配置中读取 custom_decision_prompt用于指导KFC的决策行为
类似于AFC的planner_custom_prompt_content
"""
from ..config import get_config
kfc_config = get_config()
custom_prompt = getattr(kfc_config, "custom_decision_prompt", "")
if not custom_prompt or not custom_prompt.strip():
return ""
return custom_prompt.strip()
def _build_combined_expression_block(self, learned_habits: str) -> str:
"""
构建合并后的表达习惯块
@@ -693,8 +714,22 @@ class PromptBuilder:
# 添加真正追问次数警告(只有真正发了消息才算追问)
followup_count = extra_context.get("followup_count", 0)
if followup_count > 0:
timeout_context_parts.append(f"⚠️ 你已经连续追问了 {followup_count} 次,对方仍未回复。再追问可能会显得太急躁,请三思。")
if followup_count >= 2:
timeout_context_parts.append(
f"⚠️ **强烈建议**: 你已经连续追问了 {followup_count} 次,对方仍未回复。"
"**极度推荐选择 `do_nothing` 或主动结束话题**。"
"对方可能在忙或需要空间,不是所有人都能一直在线。给彼此一些空间会更好。"
)
elif followup_count == 1:
timeout_context_parts.append(
"📝 温馨提醒这是你第2次等待回复已追问1次"
"可以再试着追问一次,但如果对方还是没回复,**强烈建议**之后选择 `do_nothing` 或结束话题。"
)
elif followup_count == 0:
timeout_context_parts.append(
"💭 追问提示:如果对方一段时间未回复,可以适当追问一次。"
"但要记住对方可能在忙建议最多追问2次左右之后给对方一些空间。"
)
# 添加距离用户上次回复的时间
time_since_user_reply_str = extra_context.get("time_since_user_reply_str")

View File

@@ -24,6 +24,9 @@ kfc_MAIN_PROMPT = Prompt(
# 安全互动准则
{safety_guidelines_block}
# 决策指导
{custom_decision_block}
# 相关信息
{memory_block}

View File

@@ -100,6 +100,33 @@ def build_rules_module() -> str:
{kfc_rules}"""
# ============================================================
# 模块2.5: 自定义决策提示词 - 用户自定义的决策行为指导
# ============================================================
def build_custom_decision_module() -> str:
"""
构建自定义决策提示词模块
允许用户通过配置文件自定义KFC的决策行为指导
类似于AFC的planner_custom_prompt_content
"""
from .config import get_config
kfc_config = get_config()
custom_prompt = getattr(kfc_config, "custom_decision_prompt", "")
# 调试输出
logger.debug(f"[自定义决策提示词] 原始值: {repr(custom_prompt)}, 类型: {type(custom_prompt)}")
if not custom_prompt or not custom_prompt.strip():
logger.debug("[自定义决策提示词] 为空或仅含空白字符,跳过")
return ""
logger.info(f"[自定义决策提示词] 已加载: {custom_prompt.strip()}")
return custom_prompt.strip()
# ============================================================
# 模块3: 情境上下文 - 时间/场景/内在状态/关系/记忆
# ============================================================
@@ -354,6 +381,9 @@ def build_system_prompt(
# 角色框架不提AI直接进入角色
role_frame = "你是一个真实的人,有自己的生活、想法和情绪。像平时和朋友聊天一样自然地交流。"
# 获取自定义决策提示词
custom_decision_block = build_custom_decision_module()
# 组装各模块
modules = [
role_frame,
@@ -363,6 +393,17 @@ def build_system_prompt(
"",
"## 2. 规则",
build_rules_module(),
]
# 如果有自定义决策提示词,插入到规则后面
if custom_decision_block:
modules.extend([
"",
"## 2.5. 决策指导",
custom_decision_block,
])
modules.extend([
"",
"## 3. 现在的情况",
build_context_module(session, chat_stream, context_data),
@@ -372,7 +413,7 @@ def build_system_prompt(
"",
"## 5. 怎么回复",
build_output_module(context_data),
]
])
return "\n".join(modules)

View File

@@ -147,17 +147,35 @@ class UnifiedPromptGenerator:
# 生成连续追问警告(使用 followup_count 作为追问计数,只有真正发消息才算)
followup_count = session.waiting_config.followup_count
max_followups = 3 # 最多追问3
max_followups = 2 # 建议最多追问2
if followup_count >= max_followups:
followup_warning = f"""⚠️ **重要提醒**
followup_warning = f"""⚠️ **强烈建议**
你已经连续追问了 {followup_count} 次,对方都没有回复。
**强烈建议不要再发消息了**——继续追问会显得很缠人、很不尊重对方的空间
对方可能真的在忙,或者暂时不想回复,这都是正常的。
请选择 `do_nothing` 继续等待,或者直接结束对话(设置 `max_wait_seconds: 0`)。"""
elif followup_count > 0:
followup_warning = f"""📝 提示:这已经是你第 {followup_count + 1} 次等待对方回复了。
如果对方持续没有回应,可能真的在忙或不方便,不需要急着追问。"""
**极度推荐选择 `do_nothing` 或设置 `max_wait_seconds: 0` 结束这个话题**
对方很可能:
- 正在忙自己的事情,没有时间回复
- 需要一些个人空间和独处时间
- 暂时不方便或不想聊天
这些都是完全正常的。不是所有人都能一直在线,每个人都有自己的生活节奏。
继续追问很可能会让对方感到压力和不适,不如给彼此一些空间。
**最好的选择**
1. 选择 `do_nothing` 安静等待对方主动联系
2. 或者主动结束这个话题(`max_wait_seconds: 0`),让对方知道你理解他们可能在忙"""
elif followup_count == 1:
followup_warning = """📝 温馨提醒:
这是你第2次等待对方回复已追问1次
可以再试着温柔地追问一次,但要做好对方可能真的在忙的心理准备。
如果这次之后对方还是没回复,**强烈建议**不要再继续追问了——
选择 `do_nothing` 给对方空间,或者主动结束话题,都是尊重对方的表现。"""
elif followup_count == 0:
followup_warning = """💭 追问提示:
如果对方一段时间没回复,可以适当追问一次,用轻松的语气提醒一下。
但要记住:不是所有人都能一直在线,对方可能在忙。
建议最多追问2次左右之后就给对方一些空间吧。"""
else:
followup_warning = ""

View File

@@ -631,6 +631,13 @@ mode = "split"
max_wait_seconds_default = 300 # 默认的最大等待秒数AI发送消息后愿意等待用户回复的时间
enable_continuous_thinking = true # 是否在等待期间启用心理活动更新
# --- 自定义决策提示词 ---
# 类似于AFC的planner_custom_prompt_content允许用户自定义KFC的决策行为指导
# 在unified模式下会插入到完整提示词中影响整体思考和回复生成
# 在split模式下只会插入到planner提示词中影响决策规划不影响replyer的回复生成
# 留空则不生效
custom_decision_prompt = ""
# --- 等待策略 ---
[kokoro_flow_chatter.waiting]
default_max_wait_seconds = 300 # LLM 未给出等待时间时的默认值