feat(kfc): 引入自定义决策提示并优化后续警告

增加了一个新的配置选项 `custom_decision_prompt`,允许用户提供具体指令来指导 Kokoro Flow Chatter 的决策过程。该提示会被整合到拆分和统一的提示生成中,以影响整体行为。

此外,系统的后续警告逻辑也得到了显著增强。警告现在更加细致和明确,提供了更清晰的建议,如在多次未响应的后续请求后选择 `do_nothing` 或结束对话,从而促进更健康的交互模式。配置模板中的内部版本已更新。
This commit is contained in:
tt-P607
2025-12-12 15:12:28 +08:00
parent 46bbf89f20
commit 5a1d5052ca
6 changed files with 123 additions and 12 deletions

View File

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

View File

@@ -72,6 +72,9 @@ class PromptBuilder:
# 1.5. 构建安全互动准则块 # 1.5. 构建安全互动准则块
safety_guidelines_block = self._build_safety_guidelines_block() safety_guidelines_block = self._build_safety_guidelines_block()
# 1.6. 构建自定义决策提示词块
custom_decision_block = self._build_custom_decision_block()
# 2. 使用 context_builder 获取关系、记忆、工具、表达习惯等 # 2. 使用 context_builder 获取关系、记忆、工具、表达习惯等
context_data = await self._build_context_data(user_name, chat_stream, user_id) context_data = await self._build_context_data(user_name, chat_stream, user_id)
relation_block = context_data.get("relation_info", f"你与 {user_name} 还不太熟悉,这是早期的交流阶段。") relation_block = context_data.get("relation_info", f"你与 {user_name} 还不太熟悉,这是早期的交流阶段。")
@@ -102,6 +105,7 @@ class PromptBuilder:
user_name=user_name, user_name=user_name,
persona_block=persona_block, persona_block=persona_block,
safety_guidelines_block=safety_guidelines_block, safety_guidelines_block=safety_guidelines_block,
custom_decision_block=custom_decision_block,
relation_block=relation_block, relation_block=relation_block,
memory_block=memory_block or "(暂无相关记忆)", memory_block=memory_block or "(暂无相关记忆)",
tool_info=tool_info or "(暂无工具信息)", tool_info=tool_info or "(暂无工具信息)",
@@ -232,6 +236,23 @@ class PromptBuilder:
{guidelines_text} {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: def _build_combined_expression_block(self, learned_habits: str) -> str:
""" """
构建合并后的表达习惯块 构建合并后的表达习惯块
@@ -693,8 +714,22 @@ class PromptBuilder:
# 添加真正追问次数警告(只有真正发了消息才算追问) # 添加真正追问次数警告(只有真正发了消息才算追问)
followup_count = extra_context.get("followup_count", 0) followup_count = extra_context.get("followup_count", 0)
if followup_count > 0: if followup_count >= 2:
timeout_context_parts.append(f"⚠️ 你已经连续追问了 {followup_count} 次,对方仍未回复。再追问可能会显得太急躁,请三思。") 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") 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} {safety_guidelines_block}
# 决策指导
{custom_decision_block}
# 相关信息 # 相关信息
{memory_block} {memory_block}

View File

@@ -100,6 +100,33 @@ def build_rules_module() -> str:
{kfc_rules}""" {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: 情境上下文 - 时间/场景/内在状态/关系/记忆 # 模块3: 情境上下文 - 时间/场景/内在状态/关系/记忆
# ============================================================ # ============================================================
@@ -354,6 +381,9 @@ def build_system_prompt(
# 角色框架不提AI直接进入角色 # 角色框架不提AI直接进入角色
role_frame = "你是一个真实的人,有自己的生活、想法和情绪。像平时和朋友聊天一样自然地交流。" role_frame = "你是一个真实的人,有自己的生活、想法和情绪。像平时和朋友聊天一样自然地交流。"
# 获取自定义决策提示词
custom_decision_block = build_custom_decision_module()
# 组装各模块 # 组装各模块
modules = [ modules = [
role_frame, role_frame,
@@ -363,6 +393,17 @@ def build_system_prompt(
"", "",
"## 2. 规则", "## 2. 规则",
build_rules_module(), build_rules_module(),
]
# 如果有自定义决策提示词,插入到规则后面
if custom_decision_block:
modules.extend([
"",
"## 2.5. 决策指导",
custom_decision_block,
])
modules.extend([
"", "",
"## 3. 现在的情况", "## 3. 现在的情况",
build_context_module(session, chat_stream, context_data), build_context_module(session, chat_stream, context_data),
@@ -372,7 +413,7 @@ def build_system_prompt(
"", "",
"## 5. 怎么回复", "## 5. 怎么回复",
build_output_module(context_data), build_output_module(context_data),
] ])
return "\n".join(modules) return "\n".join(modules)

View File

@@ -147,17 +147,35 @@ class UnifiedPromptGenerator:
# 生成连续追问警告(使用 followup_count 作为追问计数,只有真正发消息才算) # 生成连续追问警告(使用 followup_count 作为追问计数,只有真正发消息才算)
followup_count = session.waiting_config.followup_count followup_count = session.waiting_config.followup_count
max_followups = 3 # 最多追问3 max_followups = 2 # 建议最多追问2
if followup_count >= max_followups: if followup_count >= max_followups:
followup_warning = f"""⚠️ **重要提醒** followup_warning = f"""⚠️ **强烈建议**
你已经连续追问了 {followup_count} 次,对方都没有回复。 你已经连续追问了 {followup_count} 次,对方都没有回复。
**强烈建议不要再发消息了**——继续追问会显得很缠人、很不尊重对方的空间 **极度推荐选择 `do_nothing` 或设置 `max_wait_seconds: 0` 结束这个话题**
对方可能真的在忙,或者暂时不想回复,这都是正常的。
请选择 `do_nothing` 继续等待,或者直接结束对话(设置 `max_wait_seconds: 0`)。""" 对方很可能:
elif followup_count > 0: - 正在忙自己的事情,没有时间回复
followup_warning = f"""📝 提示:这已经是你第 {followup_count + 1} 次等待对方回复了。 - 需要一些个人空间和独处时间
如果对方持续没有回应,可能真的在忙或不方便,不需要急着追问。""" - 暂时不方便或不想聊天
这些都是完全正常的。不是所有人都能一直在线,每个人都有自己的生活节奏。
继续追问很可能会让对方感到压力和不适,不如给彼此一些空间。
**最好的选择**
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: else:
followup_warning = "" followup_warning = ""

View File

@@ -1,5 +1,5 @@
[inner] [inner]
version = "7.9.8" version = "7.9.9"
#----以下是给开发人员阅读的如果你只是部署了MoFox-Bot不需要阅读---- #----以下是给开发人员阅读的如果你只是部署了MoFox-Bot不需要阅读----
#如果你想要修改配置文件请递增version的值 #如果你想要修改配置文件请递增version的值
@@ -636,6 +636,13 @@ mode = "split"
max_wait_seconds_default = 300 # 默认的最大等待秒数AI发送消息后愿意等待用户回复的时间 max_wait_seconds_default = 300 # 默认的最大等待秒数AI发送消息后愿意等待用户回复的时间
enable_continuous_thinking = true # 是否在等待期间启用心理活动更新 enable_continuous_thinking = true # 是否在等待期间启用心理活动更新
# --- 自定义决策提示词 ---
# 类似于AFC的planner_custom_prompt_content允许用户自定义KFC的决策行为指导
# 在unified模式下会插入到完整提示词中影响整体思考和回复生成
# 在split模式下只会插入到planner提示词中影响决策规划不影响replyer的回复生成
# 留空则不生效
custom_decision_prompt = ""
# --- 等待策略 --- # --- 等待策略 ---
[kokoro_flow_chatter.waiting] [kokoro_flow_chatter.waiting]
default_max_wait_seconds = 300 # LLM 未给出等待时间时的默认值 default_max_wait_seconds = 300 # LLM 未给出等待时间时的默认值