Skip to content

Commit 32dd637

Browse files
authored
Merge pull request #257 from NikkeTryHard/fix/thinking-budget-stability
Fix thinking budget across models; gate levels to Gemini 3 Pro
2 parents b3a537b + a155f34 commit 32dd637

8 files changed

Lines changed: 1196 additions & 309 deletions

File tree

browser_utils/page_controller.py

Lines changed: 958 additions & 272 deletions
Large diffs are not rendered by default.

browser_utils/thinking_normalizer.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -123,22 +123,11 @@ def _parse_budget_value(reasoning_effort: Any) -> Optional[int]:
123123
if isinstance(reasoning_effort, int) and reasoning_effort > 0:
124124
return reasoning_effort
125125

126-
# 如果是字符串,尝试匹配预设值或解析为数字
126+
# 如果是字符串,尝试解析为数字
127127
if isinstance(reasoning_effort, str):
128128
effort_str = reasoning_effort.strip().lower()
129129

130-
# 预设值映射
131-
effort_map = {
132-
"low": 1000,
133-
"medium": 8000,
134-
"high": 24000,
135-
}
136-
137-
# 先尝试预设值
138-
if effort_str in effort_map:
139-
return effort_map[effort_str]
140-
141-
# 再尝试解析为数字
130+
# 解析为数字
142131
try:
143132
value = int(effort_str)
144133
if value > 0:

config/selectors.py

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,53 +4,74 @@
44
"""
55

66
# --- 输入相关选择器 ---
7-
PROMPT_TEXTAREA_SELECTOR = 'ms-prompt-input-wrapper ms-autosize-textarea textarea'
7+
PROMPT_TEXTAREA_SELECTOR = "ms-prompt-input-wrapper ms-autosize-textarea textarea"
88
INPUT_SELECTOR = PROMPT_TEXTAREA_SELECTOR
99
INPUT_SELECTOR2 = PROMPT_TEXTAREA_SELECTOR
1010

1111
# --- 按钮选择器 ---
1212
# 发送按钮:优先匹配 aria-label="Run" 的按钮;如页面结构变更,可退化到容器内的提交按钮。
1313
SUBMIT_BUTTON_SELECTOR = 'button[aria-label="Run"].run-button, ms-run-button button[type="submit"].run-button'
14-
CLEAR_CHAT_BUTTON_SELECTOR = 'button[data-test-clear="outside"][aria-label="New chat"]'
15-
CLEAR_CHAT_CONFIRM_BUTTON_SELECTOR = 'button.ms-button-primary:has-text("Discard and continue")'
14+
CLEAR_CHAT_BUTTON_SELECTOR = 'button[data-test-clear="outside"][aria-label="New chat"], button[aria-label="New chat"]'
15+
CLEAR_CHAT_CONFIRM_BUTTON_SELECTOR = (
16+
'button.ms-button-primary:has-text("Discard and continue")'
17+
)
1618
UPLOAD_BUTTON_SELECTOR = 'button[aria-label^="Insert assets"]'
1719

1820
# --- 响应相关选择器 ---
19-
RESPONSE_CONTAINER_SELECTOR = 'ms-chat-turn .chat-turn-container.model'
20-
RESPONSE_TEXT_SELECTOR = 'ms-cmark-node.cmark-node'
21+
RESPONSE_CONTAINER_SELECTOR = "ms-chat-turn .chat-turn-container.model"
22+
RESPONSE_TEXT_SELECTOR = "ms-cmark-node.cmark-node"
2123

2224
# --- 加载和状态选择器 ---
2325
LOADING_SPINNER_SELECTOR = 'button[aria-label="Run"].run-button svg .stoppable-spinner'
24-
OVERLAY_SELECTOR = '.mat-mdc-dialog-inner-container'
26+
OVERLAY_SELECTOR = ".mat-mdc-dialog-inner-container"
2527

2628
# --- 错误提示选择器 ---
27-
ERROR_TOAST_SELECTOR = 'div.toast.warning, div.toast.error'
29+
ERROR_TOAST_SELECTOR = "div.toast.warning, div.toast.error"
2830

2931
# --- 编辑相关选择器 ---
30-
EDIT_MESSAGE_BUTTON_SELECTOR = 'ms-chat-turn:last-child .actions-container button.toggle-edit-button'
31-
MESSAGE_TEXTAREA_SELECTOR = 'ms-chat-turn:last-child ms-text-chunk ms-autosize-textarea'
32+
EDIT_MESSAGE_BUTTON_SELECTOR = (
33+
"ms-chat-turn:last-child .actions-container button.toggle-edit-button"
34+
)
35+
MESSAGE_TEXTAREA_SELECTOR = "ms-chat-turn:last-child ms-text-chunk ms-autosize-textarea"
3236
FINISH_EDIT_BUTTON_SELECTOR = 'ms-chat-turn:last-child .actions-container button.toggle-edit-button[aria-label="Stop editing"]'
3337

3438
# --- 菜单和复制相关选择器 ---
35-
MORE_OPTIONS_BUTTON_SELECTOR = 'div.actions-container div ms-chat-turn-options div > button'
36-
COPY_MARKDOWN_BUTTON_SELECTOR = 'button.mat-mdc-menu-item:nth-child(4)'
39+
MORE_OPTIONS_BUTTON_SELECTOR = (
40+
"div.actions-container div ms-chat-turn-options div > button"
41+
)
42+
COPY_MARKDOWN_BUTTON_SELECTOR = "button.mat-mdc-menu-item:nth-child(4)"
3743
COPY_MARKDOWN_BUTTON_SELECTOR_ALT = 'div[role="menu"] button:has-text("Copy Markdown")'
3844

3945
# --- 设置相关选择器 ---
4046
MAX_OUTPUT_TOKENS_SELECTOR = 'input[aria-label="Maximum output tokens"]'
4147
STOP_SEQUENCE_INPUT_SELECTOR = 'input[aria-label="Add stop token"]'
42-
MAT_CHIP_REMOVE_BUTTON_SELECTOR = 'mat-chip-set mat-chip-row button[aria-label*="Remove"]'
48+
MAT_CHIP_REMOVE_BUTTON_SELECTOR = (
49+
'mat-chip-set mat-chip-row button[aria-label*="Remove"]'
50+
)
4351
TOP_P_INPUT_SELECTOR = 'ms-slider input[type="number"][max="1"]'
4452
TEMPERATURE_INPUT_SELECTOR = 'ms-slider input[type="number"][max="2"]'
4553
USE_URL_CONTEXT_SELECTOR = 'button[aria-label="Browse the url context"]'
4654

4755
# --- 思考模式相关选择器 ---
4856
# 主思考开关:控制是否启用思考模式(总开关)
49-
ENABLE_THINKING_MODE_TOGGLE_SELECTOR = '[data-test-toggle="enable-thinking"] button'
57+
ENABLE_THINKING_MODE_TOGGLE_SELECTOR = (
58+
'mat-slide-toggle[data-test-toggle="enable-thinking"] button[role="switch"].mdc-switch, '
59+
'[data-test-toggle="enable-thinking"] button[role="switch"].mdc-switch'
60+
)
5061
# 手动预算开关:控制是否手动限制思考预算
51-
SET_THINKING_BUDGET_TOGGLE_SELECTOR = '[data-test-toggle="manual-budget"] button'
62+
SET_THINKING_BUDGET_TOGGLE_SELECTOR = (
63+
'mat-slide-toggle[data-test-toggle="manual-budget"] button[role="switch"].mdc-switch, '
64+
'[data-test-toggle="manual-budget"] button[role="switch"].mdc-switch'
65+
)
5266
# 思考预算输入框
5367
THINKING_BUDGET_INPUT_SELECTOR = '[data-test-slider] input[type="number"]'
5468

69+
# 思考等级下拉
70+
THINKING_LEVEL_SELECT_SELECTOR = '[role="combobox"][aria-label="Thinking Level"], mat-select[aria-label="Thinking Level"], [role="combobox"][aria-label="Thinking level"], mat-select[aria-label="Thinking level"]'
71+
THINKING_LEVEL_OPTION_LOW_SELECTOR = '[role="listbox"][aria-label="Thinking Level"] [role="option"]:has-text("Low"), [role="listbox"][aria-label="Thinking level"] [role="option"]:has-text("Low")'
72+
THINKING_LEVEL_OPTION_HIGH_SELECTOR = '[role="listbox"][aria-label="Thinking Level"] [role="option"]:has-text("High"), [role="listbox"][aria-label="Thinking level"] [role="option"]:has-text("High")'
73+
5574
# --- Google Search Grounding ---
56-
GROUNDING_WITH_GOOGLE_SEARCH_TOGGLE_SELECTOR = 'div[data-test-id="searchAsAToolTooltip"] mat-slide-toggle button'
75+
GROUNDING_WITH_GOOGLE_SEARCH_TOGGLE_SELECTOR = (
76+
'div[data-test-id="searchAsAToolTooltip"] mat-slide-toggle button'
77+
)

docs/api-usage.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,9 @@ response = requests.post(
177177
使用预设值:
178178
```json
179179
{
180-
"reasoning_effort": "low" // 1000 tokens
181-
// 或 "medium" (8000 tokens)
182-
// 或 "high" (24000 tokens)
180+
"reasoning_effort": 1000 // 使用具体数值限制预算
181+
// 或 8000
182+
// 或 32768
183183
}
184184
```
185185

index.html

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,45 @@ <h3>生成参数</h3>
240240
</div>
241241
</div>
242242

243+
<div class="settings-group" id="thinkingModeGroup">
244+
<label for="enableThinkingToggle">思考模式 (Thinking Mode):</label>
245+
<input type="checkbox" id="enableThinkingToggle">
246+
<div class="settings-description">
247+
关闭则不使用思考模式;开启时可选择“思考等级”或设置“思考预算”。
248+
</div>
249+
</div>
250+
251+
<div class="settings-group" id="thinkingLevelGroup">
252+
<label for="thinkingLevelSelector">思考等级 (Thinking Level):</label>
253+
<select id="thinkingLevelSelector" class="settings-input">
254+
<option value="">未指定</option>
255+
<option value="low">Low</option>
256+
<option value="high">High</option>
257+
</select>
258+
<div class="settings-description">
259+
对于使用“思考等级”的模型(如 Gemini 3 Pro Preview),这里的选择将被优先使用。
260+
</div>
261+
</div>
262+
263+
<div class="settings-group" id="manualBudgetGroup">
264+
<label for="enableManualBudgetToggle">限制思考预算 (Manual Budget):</label>
265+
<input type="checkbox" id="enableManualBudgetToggle">
266+
<div class="settings-description">
267+
打开以手动限制思考预算;关闭则不限制预算。
268+
</div>
269+
</div>
270+
271+
<div class="settings-group" id="thinkingBudgetGroup">
272+
<label for="thinkingBudgetValue">思考预算 (Thinking Budget):</label>
273+
<div id="thinkingBudgetControlsContainer" class="settings-slider-container">
274+
<input type="range" id="thinkingBudgetSlider" class="settings-slider" min="128" max="32768" step="1" value="8192">
275+
<input type="number" id="thinkingBudgetValue" class="settings-number" min="128" max="32768" step="1" value="8192">
276+
</div>
277+
<div class="settings-description">
278+
对于使用预算的模型,设定具体的思考 Token 数。若同时指定“思考等级”,将优先使用等级。
279+
</div>
280+
</div>
281+
243282
<div class="settings-group">
244283
<label for="stopSequences">停止序列 (Stop Sequences):</label>
245284
<input type="text" id="stopSequences" class="settings-input" placeholder="用逗号分隔多个停止序列">
@@ -250,6 +289,15 @@ <h3>生成参数</h3>
250289
</div>
251290
</div>
252291

292+
<div class="info-card">
293+
<h3>工具</h3>
294+
<div class="settings-group">
295+
<label for="enableGoogleSearchToggle">Grounding with Google Search</label>
296+
<input type="checkbox" id="enableGoogleSearchToggle">
297+
<div class="settings-description">启用搜索作为工具以改进事实性。</div>
298+
</div>
299+
</div>
300+
253301
<div class="info-card">
254302
<h3>设置保存状态</h3>
255303
<div id="settings-status" class="settings-status">
@@ -285,4 +333,4 @@ <h3>设置保存状态</h3>
285333
<script src="webui.js" defer></script>
286334
</body>
287335

288-
</html>
336+
</html>

stream/interceptors.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ def setup_logging():
2222
logging.StreamHandler()
2323
]
2424
)
25+
logging.getLogger('asyncio').setLevel(logging.ERROR)
26+
logging.getLogger('websockets').setLevel(logging.ERROR)
2527

2628
@staticmethod
2729
def should_intercept(host, path):

stream/main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ async def main():
3232
logging.StreamHandler()
3333
]
3434
)
35+
logging.getLogger('asyncio').setLevel(logging.ERROR)
36+
logging.getLogger('websockets').setLevel(logging.ERROR)
3537

3638
logger = logging.getLogger('main')
3739

0 commit comments

Comments
 (0)