fix: failure recovery forces modify_report intent bypassing LLM classify

- process_input sets _failure_recovery flag when injecting pending_failure_context
- classify_intent skips LLM classification when flag is set, directly routes to modify_jrxml
- Smart truncation for intent classify: keep head 200 + tail 300 chars instead of head 500
  (prevents user's actual message from being truncated away by long injected context)
- This fixes the bug where "retry" or pasted error messages were misclassified as
  consult_question or initial_generation after max retry exhaustion
This commit is contained in:
2026-05-23 11:18:02 +08:00
parent 23cdfa8c2b
commit 0af774ae9d
+12 -1
View File
@@ -109,6 +109,7 @@ def process_input(state: AgentState) -> Dict:
)
user_input = f"{failure_note}\n\n---\n用户新输入:\n{user_input}"
state["pending_failure_context"] = {}
state["_failure_recovery"] = True # 标记本轮为失败恢复,分类器强制 modify_report
# 维护工作对话历史
conv_history = state.get("conversation_history", [])
@@ -217,12 +218,22 @@ def classify_intent(state: AgentState) -> Dict:
user_input = state.get("user_input", "")
has_report = "" if state.get("current_jrxml", "").strip() else ""
# 失败恢复模式:跳过 LLM 分类,直接走修正流程
if state.pop("_failure_recovery", False):
state["intent"] = "modify_report"
return state
intent = "initial_generation"
try:
llm = get_llm(caller="classify_intent")
# 智能截断:保留首部 200 + 尾部 300,避免用户真正输入被中间的长 JRXML 挤掉
if len(user_input) > 500:
ui_snippet = user_input[:200] + "\n...[已截断]...\n" + user_input[-300:]
else:
ui_snippet = user_input
prompt = load_prompt("intent_classify").format(
has_report=has_report,
user_input=user_input[:500],
user_input=ui_snippet,
)
resp = llm.invoke(prompt)
raw = resp.content.strip().lower()