From f28d73f1bbfb76828bea0d0f10a34c2a320228b6 Mon Sep 17 00:00:00 2001 From: hz4th_coder Date: Wed, 12 Aug 2026 17:08:16 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=A4=9AAgent=E5=8D=8F=E4=BD=9C=20JSON?= =?UTF-8?q?=20=E6=88=AA=E6=96=AD=E5=AF=BC=E8=87=B4=E4=B8=BB=E7=AE=A1?= =?UTF-8?q?=E8=A7=84=E5=88=92=E8=A7=A3=E6=9E=90=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 根因: deepseek-v4-flash 规划输出超 max_tokens=2000 被截断,JSON 不完整解析失败 - agents.py: 新增 _chat_json() 统一处理 JSON 类调用,解析失败自动加大 max_tokens 重试(×1/×2/×3) - 主管规划/辩论质询/辩论裁决/评审 全部改用 _chat_json 并提高初始上限(3000/1200/2500/2000) - 实测: 主管(计算器网页版4子任务)✅ 评审(92分)✅ 辩论(指定阵容)✅ --- agents.py | 57 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/agents.py b/agents.py index 6f76756..3bd7528 100644 --- a/agents.py +++ b/agents.py @@ -92,6 +92,23 @@ def _extract_score(text): return 60.0, text +def _chat_json(worker, messages, max_tokens=2000, temperature=None): + """调用 LLM 并解析 JSON;解析失败自动加大 max_tokens 重试(防止长文截断)。 + 返回 (data, raw_text, usage);全部失败抛最后异常。""" + last_err = None + for attempt in range(3): + mt = max_tokens * (attempt + 1) # 2000 → 4000 → 6000 + text, usage = _chat_worker(worker, messages, temperature=temperature, max_tokens=mt) + try: + data = _extract_json(text) + if isinstance(data, dict) and not data: + raise ValueError('空 JSON') + return data, text, usage + except Exception as e: + last_err = e + raise last_err or ValueError('JSON 解析失败') + + # --------------------------------------------------------------------------- # 主管模式 # --------------------------------------------------------------------------- @@ -114,17 +131,17 @@ SUPERVISOR_SYNTH_PROMPT = ( def run_supervisor(run_id, run, workers): _log(run_id, 'supervisor', None, 'plan', f'主管开始规划:{run["topic"][:200]}') - # 1) 主管拆解 - plan_text, u1 = _chat_worker( - workers[0], - [{'role': 'system', 'content': '你只输出 JSON。'}, - {'role': 'user', 'content': SUPERVISOR_PLAN_PROMPT.format( - topic=run['topic'], context=run['context'] or '无')}], - temperature=0.3, max_tokens=2000) + # 1) 主管拆解(JSON 解析失败自动加大 max_tokens 重试) try: - subtasks = _extract_json(plan_text) - if isinstance(subtasks, dict): - subtasks = subtasks.get('subtasks') or subtasks.get('tasks') or [] + data, _, u1 = _chat_json( + workers[0], + [{'role': 'system', 'content': '你只输出 JSON。'}, + {'role': 'user', 'content': SUPERVISOR_PLAN_PROMPT.format( + topic=run['topic'], context=run['context'] or '无')}], + max_tokens=3000, temperature=0.3) + subtasks = data.get('subtasks') or data.get('tasks') or [] + if isinstance(data, list): + subtasks = data except Exception as e: _update_run(run_id, status='failed', error=f'主管规划解析失败: {e}') _log(run_id, 'supervisor', None, 'plan', f'❌ 规划解析失败: {e}') @@ -216,15 +233,19 @@ def run_review(run_id, run, workers): # 评审 review_usage = None try: - review_text, u2 = _chat_worker( + review_data, review_text, u2 = _chat_json( reviewer_w, [{'role': 'system', 'content': '你只输出 JSON。'}, {'role': 'user', 'content': REVIEWER_PROMPT.format( topic=run['topic'], output=final_output, rubric=rubric)}], - temperature=0.2, max_tokens=1500) - score, judgment = _extract_score(review_text) + max_tokens=2000, temperature=0.2) review_usage = u2 total_tokens += u2['total_tokens']; total_cost += u2['cost'] + if isinstance(review_data, dict): + score = float(review_data.get('score', review_data.get('总分', 60))) + judgment = review_data.get('judgment') or review_data.get('意见') or review_text + else: + score, judgment = _extract_score(review_text) except Exception as e: score, judgment = 0, f'评审调用失败: {e}' final_score = score @@ -325,14 +346,13 @@ def run_debate(run_id, run, workers): f"【{v['stance']}】(#{k}):{v['view'][:500]}" for k, v in views.items() if k != w['id']) try: - text, u = _chat_worker( + data, _, u = _chat_json( w, [{'role': 'system', 'content': '你只输出 JSON。'}, {'role': 'user', 'content': DEBATE_REBUT_PROMPT.format( stance=mine['stance'], topic=run['topic'], my_view=mine['view'], others=others)}], - temperature=0.7, max_tokens=800) - data = _extract_json(text) + max_tokens=1200, temperature=0.7) rebut = data.get('rebuttal') if isinstance(data, dict) else text mine['view'] = mine['view'] + '\n\n【质询回应】' + str(rebut) total_tokens += u['total_tokens']; total_cost += u['cost'] @@ -346,12 +366,11 @@ def run_debate(run_id, run, workers): f"【{v['stance']}】{v['view']}" for v in views.values()) _log(run_id, 'judge', judge_w['id'], 'verdict', '裁判综合裁决中…') try: - verdict, u4 = _chat_worker( + data, verdict, u4 = _chat_json( judge_w, [{'role': 'system', 'content': '你只输出 JSON。你是公正严明的首席裁判。'}, {'role': 'user', 'content': JUDGE_PROMPT.format(topic=run['topic'], transcript=transcript)}], - temperature=0.3, max_tokens=1500) - data = _extract_json(verdict) + max_tokens=2500, temperature=0.3) if isinstance(data, dict): consensus = data.get('consensus') or data.get('结论') or verdict summary = data.get('summary') or data.get('摘要') or ''