From 8b77a7b9ba3785a4b316915ef4d4a85839a65ef7 Mon Sep 17 00:00:00 2001 From: liyizhouAI Date: Fri, 17 Apr 2026 08:36:58 +0800 Subject: [PATCH] fix: report 429 retry + theme toggle on all pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LLMClient: increase retries 5→8, backoff 1s→2s, max 30s→60s for GLM rate limit recovery - Report agent: add 3s delay between sections to avoid sustained 429 - Add theme-toggle-anchor to SimulationRun/Report/Interaction/Replay views - All pages now have dark/light theme toggle button --- backend/app/services/report_agent.py | 7 ++++++- backend/app/utils/llm_client.py | 6 +++--- frontend/src/views/InteractionView.vue | 9 +++++++++ frontend/src/views/ReportView.vue | 9 +++++++++ frontend/src/views/SimulationReplayView.vue | 2 ++ frontend/src/views/SimulationRunView.vue | 9 +++++++++ 6 files changed, 38 insertions(+), 4 deletions(-) diff --git a/backend/app/services/report_agent.py b/backend/app/services/report_agent.py index 791a1d6d..be9a01b7 100644 --- a/backend/app/services/report_agent.py +++ b/backend/app/services/report_agent.py @@ -1684,7 +1684,12 @@ class ReportAgent: ) logger.info(t('report.sectionSaved', reportId=report_id, sectionNum=f"{section_num:02d}")) - + + # 章节间延迟,避免连续请求触发 LLM 速率限制 + if section_num < total_sections: + import time + time.sleep(3) + # 更新进度 ReportManager.update_progress( report_id, "generating", diff --git a/backend/app/utils/llm_client.py b/backend/app/utils/llm_client.py index af3ee611..523cb0d7 100644 --- a/backend/app/utils/llm_client.py +++ b/backend/app/utils/llm_client.py @@ -16,9 +16,9 @@ from ..config import Config logger = logging.getLogger('foresight.llm_client') # 重试配置(针对 429 / 5xx / 超时 / 连接错误) -_MAX_RETRIES = 5 -_BASE_BACKOFF = 1.0 # 首次重试等 1s -_MAX_BACKOFF = 30.0 # 单次最多等 30s +_MAX_RETRIES = 8 +_BASE_BACKOFF = 2.0 # 首次重试等 2s +_MAX_BACKOFF = 60.0 # 单次最多等 60s def _is_rate_limit_error(err: Exception) -> bool: diff --git a/frontend/src/views/InteractionView.vue b/frontend/src/views/InteractionView.vue index fa1b7608..fdb36772 100644 --- a/frontend/src/views/InteractionView.vue +++ b/frontend/src/views/InteractionView.vue @@ -28,6 +28,7 @@
+
Step 5/5 @@ -358,4 +359,12 @@ onMounted(() => { .panel-wrapper.left { border-right: 1px solid #EAEAEA; } +.theme-toggle-slot { + width: 18px; + height: 18px; + flex-shrink: 0; + display: inline-flex; + align-items: center; + justify-content: center; +} diff --git a/frontend/src/views/ReportView.vue b/frontend/src/views/ReportView.vue index d36cc29d..4ca4d141 100644 --- a/frontend/src/views/ReportView.vue +++ b/frontend/src/views/ReportView.vue @@ -28,6 +28,7 @@
+
Step 4/5 @@ -356,4 +357,12 @@ onMounted(() => { .panel-wrapper.left { border-right: 1px solid #EAEAEA; } +.theme-toggle-slot { + width: 18px; + height: 18px; + flex-shrink: 0; + display: inline-flex; + align-items: center; + justify-content: center; +} diff --git a/frontend/src/views/SimulationReplayView.vue b/frontend/src/views/SimulationReplayView.vue index 33f8ceb5..f2aa953a 100644 --- a/frontend/src/views/SimulationReplayView.vue +++ b/frontend/src/views/SimulationReplayView.vue @@ -24,6 +24,7 @@
+
@@ -964,4 +965,5 @@ onUnmounted(() => { .task-icon { color: #4CAF50; font-weight: 700; } .task-label { color: #E8E8E8; flex: 1; } .task-progress { color: #666; } +.theme-toggle-slot { width: 18px; height: 18px; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; } diff --git a/frontend/src/views/SimulationRunView.vue b/frontend/src/views/SimulationRunView.vue index bc4bfe1f..02a72076 100644 --- a/frontend/src/views/SimulationRunView.vue +++ b/frontend/src/views/SimulationRunView.vue @@ -28,6 +28,7 @@
+
Step 3/5 @@ -454,5 +455,13 @@ onUnmounted(() => { .panel-wrapper.left { border-right: 1px solid #EAEAEA; } +.theme-toggle-slot { + width: 18px; + height: 18px; + flex-shrink: 0; + display: inline-flex; + align-items: center; + justify-content: center; +}