本次提交重构了提示词修改逻辑,将之前独立的“注意力优化”和“内容混淆”功能合并为一个统一的概念:“提示词扰动”(Prompt Perturbation)。 主要变更包括: - 在模型配置中引入新的统一选项:`enable_prompt_perturbation`, `perturbation_strength` 和 `enable_semantic_variants`。 - 将原 `AttentionOptimizer` 中的噪声注入和语义变体逻辑迁移到 `llm_models` 模块中,作为扰动策略的一部分。 - 简化 `attention_optimizer.py`,使其专注于提示词块重排 (`BlockShuffler`)。 - 更新 `_PromptProcessor` 以根据新的统一配置来协调不同的扰动技术。 此项更改为用户简化了配置,并通过集中化相关逻辑,提供了一个更清晰、更易于维护的实现。 BREAKING CHANGE: 内容混淆的相关配置已被替换。`enable_content_obfuscation` 和 `obfuscation_intensity` 配置项已移除。用户需更新配置以使用新的 `enable_prompt_perturbation` 和 `perturbation_strength`。
80 lines
3.6 KiB
Python
80 lines
3.6 KiB
Python
"""
|
||
注意力优化器 - 提示词块重排
|
||
|
||
通过对可交换的block组进行随机排序,增加提示词结构多样性,
|
||
避免因固定的提示词结构导致模型注意力退化。
|
||
"""
|
||
|
||
import random
|
||
from typing import Any, ClassVar
|
||
|
||
from src.common.logger import get_logger
|
||
|
||
logger = get_logger("attention_optimizer_shuffle")
|
||
|
||
|
||
class BlockShuffler:
|
||
"""提示词Block重排器"""
|
||
|
||
# 可交换的block组定义(组内block可以随机排序)
|
||
# 每个组是一个列表,包含可以互换位置的block名称
|
||
SWAPPABLE_BLOCK_GROUPS: ClassVar = [
|
||
# 用户相关信息组(记忆、关系、表达习惯)
|
||
["memory_block", "relation_info_block", "expression_habits_block"],
|
||
# 上下文增强组(工具、知识、跨群)
|
||
["tool_info_block", "knowledge_prompt", "cross_context_block"],
|
||
# 元信息组(时间、身份、日程)
|
||
["time_block", "identity_block", "schedule_block"],
|
||
]
|
||
|
||
@staticmethod
|
||
def shuffle_prompt_blocks(prompt_template: str, context_data: dict[str, Any]) -> tuple[str, dict[str, Any]]:
|
||
"""
|
||
根据定义的SWAPPABLE_BLOCK_GROUPS,对上下文数据中的block进行随机重排,
|
||
并返回可能已修改的prompt模板和重排后的上下文。
|
||
|
||
Args:
|
||
prompt_template (str): 原始的提示词模板.
|
||
context_data (dict[str, Any]): 包含各个block内容的上下文数据.
|
||
|
||
Returns:
|
||
tuple[str, dict[str, Any]]: (可能被修改的模板, 重排后的上下文数据).
|
||
"""
|
||
try:
|
||
# 这是一个简化的示例实现。
|
||
# 实际的块重排需要在模板渲染前,通过操作占位符的顺序来实现。
|
||
# 这里我们假设一个更直接的实现,即重新构建模板字符串。
|
||
|
||
# 复制上下文以避免修改原始字典
|
||
shuffled_context = context_data.copy()
|
||
|
||
# 示例:假设模板中的占位符格式为 {block_name}
|
||
# 我们需要解析模板,找到可重排的组,并重新构建模板字符串。
|
||
|
||
# 注意:这是一个复杂的逻辑,通常需要一个简单的模板引擎或正则表达式来完成。
|
||
# 为保持此函数职责单一,这里仅演示核心的重排逻辑,
|
||
# 完整的模板重建逻辑应在调用此函数的地方处理。
|
||
|
||
for group in BlockShuffler.SWAPPABLE_BLOCK_GROUPS:
|
||
# 过滤出在当前上下文中实际存在的、非空的block
|
||
existing_blocks = [
|
||
block for block in group if block in context_data and context_data[block]
|
||
]
|
||
|
||
if len(existing_blocks) > 1:
|
||
# 随机打乱顺序
|
||
random.shuffle(existing_blocks)
|
||
logger.debug(f"重排block组: {group} -> {existing_blocks}")
|
||
|
||
# 这里的实现需要调用者根据 `existing_blocks` 的新顺序
|
||
# 去动态地重新组织 `prompt_template` 字符串。
|
||
# 例如,找到模板中与 `group` 相关的占位符部分,然后按新顺序替换它们。
|
||
|
||
# 在这个简化版本中,我们不修改模板,仅返回原始模板和(未被使用的)重排后上下文
|
||
# 实际应用中,调用方需要根据重排结果修改模板
|
||
return prompt_template, shuffled_context
|
||
|
||
except Exception as e:
|
||
logger.error(f"Block重排失败: {e}", exc_info=True)
|
||
return prompt_template, context_data
|