1919from config import (
2020 CLICK_TIMEOUT_MS , WAIT_FOR_ELEMENT_TIMEOUT_MS , CLEAR_CHAT_VERIFY_TIMEOUT_MS ,
2121 DEFAULT_TEMPERATURE , DEFAULT_MAX_OUTPUT_TOKENS , DEFAULT_STOP_SEQUENCES , DEFAULT_TOP_P ,
22- ENABLE_URL_CONTEXT
22+ ENABLE_URL_CONTEXT , ENABLE_THINKING_BUDGET , DEFAULT_THINKING_BUDGET , ENABLE_GOOGLE_SEARCH
2323)
2424from models import ClientDisconnectedError
2525from .operations import save_error_snapshot , _wait_for_response_completion , _get_final_response_content
@@ -68,34 +68,65 @@ async def adjust_parameters(self, request_params: Dict[str, Any], page_params_ca
6868 else :
6969 self .logger .info (f"[{ self .req_id } ] URL Context 功能已禁用,跳过调整。" )
7070
71- # 调整“思考预算”开关
72- await self ._set_thinking_budget_toggle_checked (check_client_disconnected )
73-
74- # 在函数末尾,await self._set_thinking_budget_toggle_checked(...) 之后添加:
75- self .logger .info (f"[{ self .req_id } ] 检查预算...{ request_params .get ('reasoning_effort' )} " )
76- if 'reasoning_effort' in request_params :
77- await self ._adjust_thinking_budget (request_params .get ('reasoning_effort' ), check_client_disconnected )
71+ # 调整“思考预算”
72+ await self ._handle_thinking_budget (request_params , check_client_disconnected )
7873
7974 # 调整 Google Search 开关
8075 await self ._adjust_google_search (request_params , check_client_disconnected )
8176
82- async def _adjust_thinking_budget (self , reasoning_effort : Optional [str ], check_client_disconnected : Callable ):
77+ async def _handle_thinking_budget (self , request_params : Dict [str , Any ], check_client_disconnected : Callable ):
78+ """处理思考预算的调整逻辑。"""
79+ reasoning_effort = request_params .get ('reasoning_effort' )
80+ if reasoning_effort is not None :
81+ # 用户指定了,则开启并设置
82+ self .logger .info (f"[{ self .req_id } ] 用户指定了 reasoning_effort: { reasoning_effort } 。" )
83+ await self ._control_thinking_budget_toggle (should_be_checked = True , check_client_disconnected = check_client_disconnected )
84+ await self ._adjust_thinking_budget (reasoning_effort , check_client_disconnected )
85+ else :
86+ # 用户未指定,根据默认配置
87+ self .logger .info (f"[{ self .req_id } ] 用户未指定 reasoning_effort,根据默认配置 ENABLE_THINKING_BUDGET: { ENABLE_THINKING_BUDGET } 。" )
88+ await self ._control_thinking_budget_toggle (should_be_checked = ENABLE_THINKING_BUDGET , check_client_disconnected = check_client_disconnected )
89+ if ENABLE_THINKING_BUDGET :
90+ # 如果默认开启,则使用默认值
91+ await self ._adjust_thinking_budget (None , check_client_disconnected )
92+
93+ def _parse_thinking_budget (self , reasoning_effort : Optional [Any ]) -> Optional [int ]:
94+ """从 reasoning_effort 解析出 token_budget。"""
95+ token_budget = None
96+ if reasoning_effort is None :
97+ token_budget = DEFAULT_THINKING_BUDGET
98+ self .logger .info (f"[{ self .req_id } ] 'reasoning_effort' 为空,使用默认思考预算: { token_budget } " )
99+ elif isinstance (reasoning_effort , int ):
100+ token_budget = reasoning_effort
101+ elif isinstance (reasoning_effort , str ):
102+ if reasoning_effort .lower () == 'none' :
103+ token_budget = DEFAULT_THINKING_BUDGET
104+ self .logger .info (f"[{ self .req_id } ] 'reasoning_effort' 为 'none' 字符串,使用默认思考预算: { token_budget } " )
105+ else :
106+ effort_map = {
107+ "low" : 1000 ,
108+ "medium" : 8000 ,
109+ "high" : 24000
110+ }
111+ token_budget = effort_map .get (reasoning_effort .lower ())
112+ if token_budget is None :
113+ try :
114+ token_budget = int (reasoning_effort )
115+ except (ValueError , TypeError ):
116+ pass # token_budget remains None
117+
118+ if token_budget is None :
119+ self .logger .warning (f"[{ self .req_id } ] 无法从 '{ reasoning_effort } ' (类型: { type (reasoning_effort )} ) 解析出有效的 token_budget。" )
120+
121+ return token_budget
122+
123+ async def _adjust_thinking_budget (self , reasoning_effort : Optional [Any ], check_client_disconnected : Callable ):
83124 """根据 reasoning_effort 调整思考预算。"""
84- self .logger .info (f"[{ self .req_id } ] 检查并调整思考预算... " )
125+ self .logger .info (f"[{ self .req_id } ] 检查并调整思考预算,输入值: { reasoning_effort } " )
85126
86- token_budget = None
87- if reasoning_effort is None or reasoning_effort .lower () == 'none' :
88- token_budget = 8192
89- self .logger .info (f"[{ self .req_id } ] 'reasoning_effort' 为空或 'none',使用默认思考预算: { token_budget } " )
90- else :
91- effort_map = {
92- "low" : 1000 ,
93- "medium" : 8000 ,
94- "high" : 24000
95- }
96- token_budget = effort_map .get (reasoning_effort .lower ())
97-
98- if not token_budget :
127+ token_budget = self ._parse_thinking_budget (reasoning_effort )
128+
129+ if token_budget is None :
99130 self .logger .warning (f"[{ self .req_id } ] 无效的 reasoning_effort 值: '{ reasoning_effort } '。跳过调整。" )
100131 return
101132
@@ -122,18 +153,32 @@ async def _adjust_thinking_budget(self, reasoning_effort: Optional[str], check_c
122153 if isinstance (e , ClientDisconnectedError ):
123154 raise
124155
156+ def _should_enable_google_search (self , request_params : Dict [str , Any ]) -> bool :
157+ """根据请求参数或默认配置决定是否应启用 Google Search。"""
158+ if 'tools' in request_params and request_params .get ('tools' ) is not None :
159+ tools = request_params .get ('tools' )
160+ has_google_search_tool = False
161+ if isinstance (tools , list ):
162+ for tool in tools :
163+ if isinstance (tool , dict ):
164+ if tool .get ('google_search_retrieval' ) is not None :
165+ has_google_search_tool = True
166+ break
167+ if tool .get ('function' , {}).get ('name' ) == 'googleSearch' :
168+ has_google_search_tool = True
169+ break
170+ self .logger .info (f"[{ self .req_id } ] 请求中包含 'tools' 参数。检测到 Google Search 工具: { has_google_search_tool } 。" )
171+ return has_google_search_tool
172+ else :
173+ self .logger .info (f"[{ self .req_id } ] 请求中不包含 'tools' 参数。使用默认配置 ENABLE_GOOGLE_SEARCH: { ENABLE_GOOGLE_SEARCH } 。" )
174+ return ENABLE_GOOGLE_SEARCH
175+
125176 async def _adjust_google_search (self , request_params : Dict [str , Any ], check_client_disconnected : Callable ):
126- """根据请求参数中的 'googleSearch' 工具存在与否 ,双向控制 Google Search 开关。"""
177+ """根据请求参数或默认配置 ,双向控制 Google Search 开关。"""
127178 self .logger .info (f"[{ self .req_id } ] 检查并调整 Google Search 开关..." )
128179
129- tools = request_params .get ('tools' )
130- has_google_search = False
131- if isinstance (tools , list ):
132- for tool in tools :
133- if isinstance (tool , dict ) and tool .get ('function' , {}).get ('name' ) == 'googleSearch' :
134- has_google_search = True
135- break
136-
180+ should_enable_search = self ._should_enable_google_search (request_params )
181+
137182 toggle_selector = GROUNDING_WITH_GOOGLE_SEARCH_TOGGLE_SELECTOR
138183
139184 try :
@@ -142,39 +187,25 @@ async def _adjust_google_search(self, request_params: Dict[str, Any], check_clie
142187 await self ._check_disconnect (check_client_disconnected , "Google Search 开关 - 元素可见后" )
143188
144189 is_checked_str = await toggle_locator .get_attribute ("aria-checked" )
145- self .logger .info (f"[{ self .req_id } ] Google Search 开关 'aria-checked' 状态: '{ is_checked_str } '。是否需要搜索: { has_google_search } " )
146-
147- if has_google_search :
148- # 需要搜索,但开关是关闭的,则打开它
149- if is_checked_str == "false" :
150- self .logger .info (f"[{ self .req_id } ] 'googleSearch' 工具存在,但开关关闭。正在点击以打开..." )
151- await toggle_locator .click (timeout = CLICK_TIMEOUT_MS )
152- await self ._check_disconnect (check_client_disconnected , "Google Search 开关 - 点击打开后" )
153- await asyncio .sleep (0.5 ) # 等待UI更新
154- new_state = await toggle_locator .get_attribute ("aria-checked" )
155- if new_state == "true" :
156- self .logger .info (f"[{ self .req_id } ] ✅ Google Search 开关已成功打开。" )
157- else :
158- self .logger .warning (f"[{ self .req_id } ] ⚠️ Google Search 开关打开失败。当前状态: '{ new_state } '" )
190+ is_currently_checked = is_checked_str == "true"
191+ self .logger .info (f"[{ self .req_id } ] Google Search 开关当前状态: '{ is_checked_str } '。期望状态: { should_enable_search } " )
192+
193+ if should_enable_search != is_currently_checked :
194+ action = "打开" if should_enable_search else "关闭"
195+ self .logger .info (f"[{ self .req_id } ] Google Search 开关状态与期望不符。正在点击以{ action } ..." )
196+ await toggle_locator .click (timeout = CLICK_TIMEOUT_MS )
197+ await self ._check_disconnect (check_client_disconnected , f"Google Search 开关 - 点击{ action } 后" )
198+ await asyncio .sleep (0.5 ) # 等待UI更新
199+ new_state = await toggle_locator .get_attribute ("aria-checked" )
200+ if (new_state == "true" ) == should_enable_search :
201+ self .logger .info (f"[{ self .req_id } ] ✅ Google Search 开关已成功{ action } 。" )
159202 else :
160- self .logger .info (f"[{ self .req_id } ] 'googleSearch' 工具存在,且开关已打开,无需操作。 " )
203+ self .logger .warning (f"[{ self .req_id } ] ⚠️ Google Search 开关 { action } 失败。当前状态: ' { new_state } ' " )
161204 else :
162- # 不需要搜索,但开关是打开的,则关闭它
163- if is_checked_str == "true" :
164- self .logger .info (f"[{ self .req_id } ] 'googleSearch' 工具不存在,但开关打开。正在点击以关闭..." )
165- await toggle_locator .click (timeout = CLICK_TIMEOUT_MS )
166- await self ._check_disconnect (check_client_disconnected , "Google Search 开关 - 点击关闭后" )
167- await asyncio .sleep (0.5 ) # 等待UI更新
168- new_state = await toggle_locator .get_attribute ("aria-checked" )
169- if new_state == "false" :
170- self .logger .info (f"[{ self .req_id } ] ✅ Google Search 开关已成功关闭。" )
171- else :
172- self .logger .warning (f"[{ self .req_id } ] ⚠️ Google Search 开关关闭失败。当前状态: '{ new_state } '" )
173- else :
174- self .logger .info (f"[{ self .req_id } ] 'googleSearch' 工具不存在,且开关已关闭,无需操作。" )
205+ self .logger .info (f"[{ self .req_id } ] Google Search 开关已处于期望状态,无需操作。" )
175206
176207 except Exception as e :
177- self .logger .error (f"[{ self .req_id } ] ❌ 操作 'Google Search toggle' 开关 ' { toggle_selector } ' 时发生错误 : { e } " )
208+ self .logger .error (f"[{ self .req_id } ] ❌ 操作 'Google Search toggle' 开关时发生错误 : { e } " )
178209 if isinstance (e , ClientDisconnectedError ):
179210 raise
180211
@@ -200,53 +231,43 @@ async def _open_url_content(self,check_client_disconnected: Callable):
200231 except Exception as e :
201232 self .logger .error (f"[{ self .req_id } ] ❌ 操作USE_URL_CONTEXT_SELECTOR时发生错误:{ e } 。" )
202233
203- async def _set_thinking_budget_toggle_checked (self , check_client_disconnected : Callable ):
234+ async def _control_thinking_budget_toggle (self , should_be_checked : bool , check_client_disconnected : Callable ):
204235 """
205- 确保 "Thinking Budget" 滑块开关处于选中状态 。
236+ 根据 should_be_checked 的值,控制 "Thinking Budget" 滑块开关的状态 。
206237 """
207238 toggle_selector = SET_THINKING_BUDGET_TOGGLE_SELECTOR
208- self .logger .info (f"[{ self .req_id } ] 检查并设置 'Thinking Budget toggle' 滑块开关 ' { toggle_selector } ' 的状态 ..." )
239+ self .logger .info (f"[{ self .req_id } ] 控制 'Thinking Budget' 开关,期望状态: { '选中' if should_be_checked else '未选中' } ..." )
209240
210241 try :
211242 toggle_locator = self .page .locator (toggle_selector )
212-
213- # 等待元素在 DOM 中可见
214243 await expect_async (toggle_locator ).to_be_visible (timeout = 5000 )
215244 await self ._check_disconnect (check_client_disconnected , "思考预算开关 - 元素可见后" )
216245
217- # 1. 检查当前 ' aria-checked' 属性
218- is_checked = await toggle_locator . get_attribute ( "aria-checked" )
219- self .logger .info (f"[{ self .req_id } ] 思考预算开关当前 'aria-checked' 状态: { is_checked } " )
246+ is_checked_str = await toggle_locator . get_attribute ( " aria-checked" )
247+ current_state_is_checked = is_checked_str == "true"
248+ self .logger .info (f"[{ self .req_id } ] 思考预算开关当前 'aria-checked' 状态: { is_checked_str } (当前是否选中: { current_state_is_checked } ) " )
220249
221- # 2. 如果开关未选中 (aria-checked="false"),则点击它
222- if is_checked == "false" :
223- self .logger .info (f"[{ self .req_id } ] 思考预算开关当前未选中,正在点击以启用 ..." )
250+ if current_state_is_checked != should_be_checked :
251+ action = "启用" if should_be_checked else "禁用"
252+ self .logger .info (f"[{ self .req_id } ] 思考预算开关当前状态与期望不符,正在点击以 { action } ..." )
224253 await toggle_locator .click (timeout = CLICK_TIMEOUT_MS )
225- await self ._check_disconnect (check_client_disconnected , "思考预算开关 - 点击后" )
226-
227- # 3. 验证操作是否成功
228- await asyncio .sleep (0.5 ) # 短暂等待,让 UI 状态更新
229- new_state = await toggle_locator .get_attribute ("aria-checked" )
230- if new_state == "true" :
231- self .logger .info (f"[{ self .req_id } ] ✅ 'Thinking Budget toggle' 已成功启用。新状态: { new_state } " )
232- else :
233- self .logger .warning (f"[{ self .req_id } ] ⚠️ 'Thinking Budget toggle' 点击后验证失败。期望状态: 'true', 实际状态: '{ new_state } '" )
234- # 如果需要,可以在此处添加错误快照
235- # await save_error_snapshot(f"thinking_budget_toggle_verify_fail_{self.req_id}")
254+ await self ._check_disconnect (check_client_disconnected , f"思考预算开关 - 点击{ action } 后" )
255+
256+ await asyncio .sleep (0.5 )
257+ new_state_str = await toggle_locator .get_attribute ("aria-checked" )
258+ new_state_is_checked = new_state_str == "true"
236259
237- elif is_checked == "true" :
238- self .logger .info (f"[{ self .req_id } ] 'Thinking Budget toggle' 已处于选中状态,无需操作。" )
260+ if new_state_is_checked == should_be_checked :
261+ self .logger .info (f"[{ self .req_id } ] ✅ 'Thinking Budget' 开关已成功{ action } 。新状态: { new_state_str } " )
262+ else :
263+ self .logger .warning (f"[{ self .req_id } ] ⚠️ 'Thinking Budget' 开关{ action } 后验证失败。期望状态: '{ should_be_checked } ', 实际状态: '{ new_state_str } '" )
239264 else :
240- # 处理 'aria-checked' 属性不存在或值无效的情况
241- self .logger .warning (f"[{ self .req_id } ] 无法确定 'Thinking Budget toggle' 的状态,'aria-checked' 值为: '{ is_checked } '。" )
265+ self .logger .info (f"[{ self .req_id } ] 'Thinking Budget' 开关已处于期望状态,无需操作。" )
242266
243267 except Exception as e :
244- self .logger .error (f"[{ self .req_id } ] ❌ 操作 'Thinking Budget toggle' 滑块开关 '{ toggle_selector } ' 时发生错误: { e } " )
245- # 如果需要,可以在此处添加错误快照
246- # await save_error_snapshot(f"thinking_budget_toggle_error_{self.req_id}")
247- # 如果是客户端断开连接的特定错误,则重新抛出
268+ self .logger .error (f"[{ self .req_id } ] ❌ 操作 'Thinking Budget toggle' 开关时发生错误: { e } " )
248269 if isinstance (e , ClientDisconnectedError ):
249- raise
270+ raise
250271 async def _adjust_temperature (self , temperature : float , page_params_cache : dict , params_cache_lock : asyncio .Lock , check_client_disconnected : Callable ):
251272 """调整温度参数。"""
252273 async with params_cache_lock :
0 commit comments