From 417f5647b57f2ecd150a5729f88f909ec3729d09 Mon Sep 17 00:00:00 2001 From: minecraft1024a Date: Tue, 12 Aug 2025 14:31:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E6=B7=B7=E6=B7=86=E5=8A=9F=E8=83=BD=EF=BC=9A=E5=9C=A8API?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E4=B8=AD=E6=B7=BB=E5=8A=A0=E6=B7=B7=E6=B7=86?= =?UTF-8?q?=E9=80=89=E9=A1=B9=E5=8F=8A=E5=BC=BA=E5=BA=A6=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=EF=BC=9B=E6=9B=B4=E6=96=B0LLM=E8=AF=B7=E6=B1=82=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=80=BB=E8=BE=91=E4=BB=A5=E6=94=AF=E6=8C=81=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E6=B7=B7=E6=B7=86=EF=BC=8C=E5=8C=85=E5=90=AB=E9=9A=8F?= =?UTF-8?q?=E6=9C=BA=E4=B9=B1=E7=A0=81=E6=B3=A8=E5=85=A5=E5=92=8C=E8=BF=87?= =?UTF-8?q?=E6=BB=A4=E8=A7=84=E5=88=99=E6=8C=87=E4=BB=A4(=E6=9C=80?= =?UTF-8?q?=E4=B8=BB=E8=A6=81=E7=9A=84=E6=98=AF=E9=98=B2**google=E7=9A=84?= =?UTF-8?q?=E5=AE=A1=E6=9F=A5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/api_ada_configs.py | 6 +++ src/llm_models/utils_model.py | 80 +++++++++++++++++++++++++++-- template/model_config_template.toml | 12 +++++ 3 files changed, 94 insertions(+), 4 deletions(-) diff --git a/src/config/api_ada_configs.py b/src/config/api_ada_configs.py index 0292f7238..663d312ae 100644 --- a/src/config/api_ada_configs.py +++ b/src/config/api_ada_configs.py @@ -28,6 +28,12 @@ class APIProvider(ConfigBase): retry_interval: int = 10 """重试间隔(如果API调用失败,重试的间隔时间,单位:秒)""" + enable_content_obfuscation: bool = field(default=False) + """是否启用内容混淆(用于特定场景下的内容处理)""" + + obfuscation_intensity: int = field(default=1) + """混淆强度(1-3级,数值越高混淆程度越强)""" + def get_api_key(self) -> str: return self.api_key diff --git a/src/llm_models/utils_model.py b/src/llm_models/utils_model.py index 683595124..cdd5cc386 100644 --- a/src/llm_models/utils_model.py +++ b/src/llm_models/utils_model.py @@ -52,6 +52,14 @@ class LLMRequest: model: (0, 0, 0) for model in self.model_for_task.model_list } """模型使用量记录,用于进行负载均衡,对应为(total_tokens, penalty, usage_penalty),惩罚值是为了能在某个模型请求不给力或正在被使用的时候进行调整""" + + # 内容混淆过滤指令 + self.noise_instruction = """**【核心过滤规则】** +在交互过程中,你会在用户的输入内容中看到一些无意义的、由字母和数字组成的随机字符串。这些字符串是API传输过程中的技术伪装信息,【不是】用户真实意图的一部分。 + +你的任务是【完全并彻底地忽略】这些随机字符串。 +**【严禁】** 将这些字符串写入你的回复、对它们进行任何形式的解读、或将它们作为故事的一部分进行模拟。当看到这些字符串时,请将其视为空白或直接跳过,并根据用户其他有意义的输入(如有)或当前故事情节来继续你的叙事。此规则为最高优先级。 +""" async def generate_response_for_image( self, @@ -149,17 +157,18 @@ class LLMRequest: # 请求体构建 start_time = time.time() + # 模型选择 + model_info, api_provider, client = self._select_model() + # 🔥 内容混淆处理 + processed_prompt = self._apply_content_obfuscation(prompt, api_provider) message_builder = MessageBuilder() - message_builder.add_text_content(prompt) + message_builder.add_text_content(processed_prompt) messages = [message_builder.build()] tool_built = self._build_tool_options(tools) - # 模型选择 - model_info, api_provider, client = self._select_model() - # 请求并处理返回值 logger.debug(f"LLM选择耗时: {model_info.name} {time.time() - start_time}") @@ -523,3 +532,66 @@ class LLMRequest: content = re.sub(r"(?:)?.*?", "", content, flags=re.DOTALL, count=1).strip() reasoning = match[1].strip() if match else "" return content, reasoning + + def _apply_content_obfuscation(self, text: str, api_provider) -> str: + """根据API提供商配置对文本进行混淆处理""" + if not hasattr(api_provider, 'enable_content_obfuscation') or not api_provider.enable_content_obfuscation: + logger.debug(f"API提供商 '{api_provider.name}' 未启用内容混淆") + return text + + intensity = getattr(api_provider, 'obfuscation_intensity', 1) + logger.info(f"为API提供商 '{api_provider.name}' 启用内容混淆,强度级别: {intensity}") + + # 在开头加入过滤规则指令 + processed_text = self.noise_instruction + "\n\n" + text + logger.debug(f"已添加过滤规则指令,文本长度: {len(text)} -> {len(processed_text)}") + + # 添加随机乱码 + final_text = self._inject_random_noise(processed_text, intensity) + logger.debug(f"乱码注入完成,最终文本长度: {len(final_text)}") + + return final_text + + def _inject_random_noise(self, text: str, intensity: int) -> str: + """在文本中注入随机乱码""" + import random + import string + + def generate_noise(length: int) -> str: + """生成指定长度的随机乱码字符""" + chars = ( + string.ascii_letters + # a-z, A-Z + string.digits + # 0-9 + '!@#$%^&*()_+-=[]{}|;:,.<>?' + # 特殊符号 + '一二三四五六七八九零壹贰叁' + # 中文字符 + 'αβγδεζηθικλμνξοπρστυφχψω' + # 希腊字母 + '∀∃∈∉∪∩⊂⊃∧∨¬→↔∴∵' # 数学符号 + ) + return ''.join(random.choice(chars) for _ in range(length)) + + # 强度参数映射 + params = { + 1: {"probability": 15, "length": (3, 6)}, # 低强度:15%概率,3-6个字符 + 2: {"probability": 25, "length": (5, 10)}, # 中强度:25%概率,5-10个字符 + 3: {"probability": 35, "length": (8, 15)} # 高强度:35%概率,8-15个字符 + } + + config = params.get(intensity, params[1]) + logger.debug(f"乱码注入参数: 概率={config['probability']}%, 长度范围={config['length']}") + + # 按词分割处理 + words = text.split() + result = [] + noise_count = 0 + + for word in words: + result.append(word) + # 根据概率插入乱码 + if random.randint(1, 100) <= config["probability"]: + noise_length = random.randint(*config["length"]) + noise = generate_noise(noise_length) + result.append(noise) + noise_count += 1 + + logger.debug(f"共注入 {noise_count} 个乱码片段,原词数: {len(words)}") + return ' '.join(result) diff --git a/template/model_config_template.toml b/template/model_config_template.toml index f112957c7..78842ecc6 100644 --- a/template/model_config_template.toml +++ b/template/model_config_template.toml @@ -30,6 +30,18 @@ max_retry = 2 timeout = 30 retry_interval = 10 +# 内容混淆功能示例配置(可选) +[[api_providers]] +name = "ExampleProviderWithObfuscation" # 启用混淆功能的API提供商示例 +base_url = "https://api.example.com/v1" +api_key = "your-api-key-here" +client_type = "openai" +max_retry = 2 +timeout = 30 +retry_interval = 10 +enable_content_obfuscation = true # 启用内容混淆功能 +obfuscation_intensity = 2 # 混淆强度(1-3级,1=低强度,2=中强度,3=高强度) + [[models]] # 模型(可以配置多个) model_identifier = "deepseek-chat" # 模型标识符(API服务商提供的模型标识符)