diff --git a/agentmain.py b/agentmain.py index be751462..d58b7d0d 100644 --- a/agentmain.py +++ b/agentmain.py @@ -107,6 +107,7 @@ class GenericAgent: if isinstance(b, dict): return 'BADCONFIG_MIXIN' if model: return b.backend.model.lower() return f"{type(b.backend).__name__}/{b.backend.name}" + def get_ctx_multiplier(self): return getattr(self.llmclient.backend, 'maxlen_multiplier', 1.0) def abort(self): if not self.is_running: return diff --git a/assets/configure_mykey.py b/assets/configure_mykey.py index b9ed19d7..755fae8f 100644 --- a/assets/configure_mykey.py +++ b/assets/configure_mykey.py @@ -732,7 +732,7 @@ def _configure_advanced(provider, cfg): proxy = ask_input("HTTP 代理地址 (proxy)", default='', hint='如 http://127.0.0.1:2082,留空跳过') if proxy: cfg['proxy'] = proxy - cw = ask_input("上下文窗口阈值 (context_win)", default='', hint='NativeClaude 默认 28000,其他默认 24000') + cw = ask_input("上下文窗口阈值 (context_win)", default='', hint='默认 30000,DeepSeek 默认 70000;联动压缩与工具上限') if cw: cfg['context_win'] = int(cw) if cfg.get('thinking_type') == 'enabled': diff --git a/ga.py b/ga.py index 82182e64..fb075016 100644 --- a/ga.py +++ b/ga.py @@ -288,6 +288,9 @@ class GenericAgentHandler(BaseHandler): self._done_hooks = [] self.print = safe_print + def _get_tool_maxlen(self, l, args, growth_rate=1.0): + multiplier = 1 + (self.parent.get_ctx_multiplier() - 1) * growth_rate + return int(l * multiplier / args.get('_tool_num', 1)) def _get_abs_path(self, path): if not path: return "" return os.path.abspath(os.path.join(self.cwd, path)) @@ -308,7 +311,7 @@ class GenericAgentHandler(BaseHandler): raw_path = os.path.join(self.cwd, args.get("cwd", './')) cwd = os.path.normpath(os.path.abspath(raw_path)) code_cwd = os.path.normpath(self.cwd) - maxlen = 10000 // args.get('_tool_num', 1) + maxlen = self._get_tool_maxlen(10000, args) if code_type == 'python' and _arg(args, "inline_eval", False, bool): ns = {'handler':self, 'parent':self.parent, 'history':json.dumps(self.parent.llmclient.backend.history)} old_cwd = os.getcwd() @@ -337,7 +340,7 @@ class GenericAgentHandler(BaseHandler): tabs_only = _arg(args, "tabs_only", False, bool) switch_tab_id = args.get("switch_tab_id", None) text_only = _arg(args, "text_only", False, bool) - maxlen = 35000 // args.get('_tool_num', 1) + maxlen = self._get_tool_maxlen(35000, args, growth_rate=0.5) result = web_scan(tabs_only=tabs_only, switch_tab_id=switch_tab_id, text_only=text_only, maxlen=maxlen) content = result.pop("content", None) yield f'[Info] {str(result)}\n' @@ -369,7 +372,7 @@ class GenericAgentHandler(BaseHandler): yield f"JS 执行结果:\n{show}\n" next_prompt = self._get_anchor_prompt(skip=args.get('_index', 0) > 0) result = json.dumps(result, ensure_ascii=False, default=json_default) - maxlen = 8000 // args.get('_tool_num', 1) + maxlen = self._get_tool_maxlen(8000, args) return StepOutcome(smart_format(result, max_str_len=maxlen), next_prompt=next_prompt) def do_file_patch(self, args, response): @@ -432,7 +435,7 @@ class GenericAgentHandler(BaseHandler): count=count, show_linenos=show_linenos) if show_linenos and not result.startswith("Error:"): result = '由于设置了show_linenos,以下返回信息为:(行号|)内容 。\n' + result if ' ... [TRUNCATED]' in result: result += '\n\n(某些行被截断,如需完整内容可改用 code_run 读取)' - maxlen = 15000 // args.get('_tool_num', 1) + maxlen = self._get_tool_maxlen(15000, args) result = smart_format(result, max_str_len=maxlen, omit_str='\n\n[omitted long content]\n\n') next_prompt = self._get_anchor_prompt(skip=args.get('_index', 0) > 0) log_memory_access(path) diff --git a/llmcore.py b/llmcore.py index 684d21ad..89d2d978 100644 --- a/llmcore.py +++ b/llmcore.py @@ -533,10 +533,12 @@ class BaseSession: self.api_key = cfg['apikey'] self.api_base = cfg['apibase'].rstrip('/') self.model = cfg.get('model', '') - default_context_win = 30000 + default_context_win = 30000; default_cut_msg_interval = 5 if 'deepseek' in self.model.lower(): - default_context_win = 70000; self.cut_msg_interval = 25; self.trim_keep_rate = 0.3 + default_context_win = 70000; default_cut_msg_interval = 25; self.trim_keep_rate = 0.3 self.context_win = cfg.get('context_win', default_context_win) + self.maxlen_multiplier = min(max(self.context_win / default_context_win * 0.85, 1.0), 3.0) + self.cut_msg_interval = int(default_cut_msg_interval * self.maxlen_multiplier) self.history = []; self.lock = threading.Lock(); self.system = "" self.name = cfg.get('name', self.model) self.extra_sys_prompt = cfg.get('extra_sys_prompt', '') diff --git a/mykey_template.py b/mykey_template.py index 4907c686..a519add3 100644 --- a/mykey_template.py +++ b/mykey_template.py @@ -65,8 +65,8 @@ # proxy 可选。单 session 代理,'http://127.0.0.1:2082' 这种。不填则 # 即使全局设置了 proxy 也不走。 # ─── 容量 / 超时 ───────────────────────────────────────────────────────────── -# context_win 默认 24000(NativeClaudeSession 默认 28000)。仅作为历史裁 -# 剪阈值,不是硬上下文限制。 +# context_win 默认 30000(DeepSeek 默认 70000)。用于历史裁剪,并联动 +# 压缩频率和工具结果上限;不是硬上下文限制。 # max_retries 默认 1。_openai_stream 遇到 429/408/5xx 的自动重试次数。 # connect_timeout 连接超时秒数,默认 5。 # read_timeout 流式读取超时秒数,默认 30。 @@ -181,7 +181,7 @@ mixin_config = { # # 'reasoning_effort': 'high', # 'temperature': 1, # float 默认 1.0 # 'max_tokens': 32768, # int 默认 8192;Claude 回复最大 token 数 -# # 'context_win': 800000, # int 默认 28000(NativeClaudeSession);历史裁剪阈值 +# # 'context_win': 800000, # int 默认 30000;历史裁剪及工具上限参考 # # 'stream': True, # bool 默认 True;False → 一次性 JSON(CDN 截断 SSE 时用) # # 'max_retries': 3, # int 默认 1 # # 'connect_timeout': 10, # int 秒 默认 5(最小 1) @@ -250,7 +250,7 @@ mixin_config = { # # 'temperature': 1.0, # float 默认 1.0 # # 'max_tokens': 8192, # int 默认 8192 # # 'proxy': 'http://127.0.0.1:2082', # 可选单 session HTTP 代理 -# # 'context_win': 16000, # int 默认 24000;历史裁剪阈值 +# # 'context_win': 16000, # int 默认 30000;历史裁剪及工具上限参考 # } # ── 也可以走 Responses API ──────────────────────────────────────────────────