Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebdc9c4265 |
@@ -242,7 +242,7 @@ class TaskRunner(threading.Thread):
|
|||||||
[{'role': 'system',
|
[{'role': 'system',
|
||||||
'content': VISION_SYSTEM_PROMPT if self.vision else SYSTEM_PROMPT},
|
'content': VISION_SYSTEM_PROMPT if self.vision else SYSTEM_PROMPT},
|
||||||
{'role': 'user', 'content': user_content}],
|
{'role': 'user', 'content': user_content}],
|
||||||
cfg=self.llm_cfg, temperature=0.2, max_tokens=500)
|
cfg=self.llm_cfg, max_tokens=1024)
|
||||||
except LLMError as e:
|
except LLMError as e:
|
||||||
self._log(f'LLM 错误: {e}')
|
self._log(f'LLM 错误: {e}')
|
||||||
self._finish(browser, 'error', f'LLM 决策失败: {e}', steps)
|
self._finish(browser, 'error', f'LLM 决策失败: {e}', steps)
|
||||||
@@ -403,7 +403,7 @@ class TaskRunner(threading.Thread):
|
|||||||
'content': VISION_SYSTEM_PROMPT if self.vision else SYSTEM_PROMPT},
|
'content': VISION_SYSTEM_PROMPT if self.vision else SYSTEM_PROMPT},
|
||||||
{'role': 'user',
|
{'role': 'user',
|
||||||
'content': self._build_user_content(retry_msg, browser, self.current.get('step', 0) + 99)}],
|
'content': self._build_user_content(retry_msg, browser, self.current.get('step', 0) + 99)}],
|
||||||
cfg=self.llm_cfg, temperature=0.2, max_tokens=400)
|
cfg=self.llm_cfg, max_tokens=800)
|
||||||
new_action = retry_dec.get('action', '')
|
new_action = retry_dec.get('action', '')
|
||||||
if new_action == 'fail':
|
if new_action == 'fail':
|
||||||
return 'error', f'自愈放弃: {retry_dec.get("summary", last_err)}', {}
|
return 'error', f'自愈放弃: {retry_dec.get("summary", last_err)}', {}
|
||||||
|
|||||||
@@ -89,11 +89,25 @@ def chat(messages, cfg=None, temperature=None, max_tokens=None, timeout=None):
|
|||||||
raise LLMError(f'LLM 调用失败: {e}')
|
raise LLMError(f'LLM 调用失败: {e}')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return data['choices'][0]['message']['content']
|
msg = data['choices'][0]['message']
|
||||||
|
content = msg.get('content') or ''
|
||||||
|
if not content.strip():
|
||||||
|
# thinking 模型(如 qwen3/deepseek-r1 系):最终答案可能为空,
|
||||||
|
# 思考过程放在 reasoning_content 里(常包含最终 JSON),用它兜底
|
||||||
|
reasoning = msg.get('reasoning_content') or ''
|
||||||
|
if reasoning.strip():
|
||||||
|
return reasoning
|
||||||
|
return content
|
||||||
except (KeyError, IndexError, TypeError):
|
except (KeyError, IndexError, TypeError):
|
||||||
raise LLMError(f'LLM 响应异常: {str(data)[:300]}')
|
raise LLMError(f'LLM 响应异常: {str(data)[:300]}')
|
||||||
|
|
||||||
|
|
||||||
|
def _trim_content(text, limit=300):
|
||||||
|
"""截断过长的模型输出(避免超长思考内容反复进入上下文)"""
|
||||||
|
text = (text or '').strip()
|
||||||
|
return text if len(text) <= limit else text[:limit] + '...(已截断)'
|
||||||
|
|
||||||
|
|
||||||
def chat_json(messages, cfg=None, temperature=None, max_tokens=None, retries=2):
|
def chat_json(messages, cfg=None, temperature=None, max_tokens=None, retries=2):
|
||||||
"""调用 LLM 并强制解析 JSON,失败重试"""
|
"""调用 LLM 并强制解析 JSON,失败重试"""
|
||||||
last_err = None
|
last_err = None
|
||||||
@@ -110,8 +124,8 @@ def chat_json(messages, cfg=None, temperature=None, max_tokens=None, retries=2):
|
|||||||
last_err = str(e)
|
last_err = str(e)
|
||||||
if i < retries:
|
if i < retries:
|
||||||
messages = messages + [
|
messages = messages + [
|
||||||
{'role': 'assistant', 'content': last_content or ''},
|
{'role': 'assistant', 'content': _trim_content(last_content)},
|
||||||
{'role': 'user',
|
{'role': 'user',
|
||||||
'content': f'刚才的输出不是合法 JSON,请只输出严格的 JSON 对象。错误: {last_err}'},
|
'content': f'刚才的输出不是合法 JSON,请只输出严格的 JSON 对象,不要输出思考过程和代码块。错误: {last_err}'},
|
||||||
]
|
]
|
||||||
raise LLMError(f'LLM JSON 解析失败: {last_err}')
|
raise LLMError(f'LLM JSON 解析失败: {last_err}')
|
||||||
Reference in New Issue
Block a user