feat(runtime): 为上下文超限错误添加自动重试机制
添加 RuntimeError::is_retryable_context_error 方法,用于识别可重试的上下文错误(如令牌超限、上下文窗口超限等)。当对话执行遇到此类错误时,自动触发会话压缩并重试,而非直接失败,提高系统的鲁棒性。
This commit is contained in:
parent
8fc9296fed
commit
2a985c1cc7
|
|
@ -95,6 +95,22 @@ impl RuntimeError {
|
||||||
message: message.into(),
|
message: message.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if this error is eligible for automatic retry and self-healing (e.g., via session compaction).
|
||||||
|
/// This list can be expanded in the future as new retryable error types are identified.
|
||||||
|
#[must_use]
|
||||||
|
pub fn is_retryable_context_error(&self) -> bool {
|
||||||
|
let msg = self.message.to_lowercase();
|
||||||
|
let retryable_markers = [
|
||||||
|
// Context window limits that can be fixed by compaction
|
||||||
|
"maximum context length",
|
||||||
|
"too many tokens",
|
||||||
|
"context_length_exceeded",
|
||||||
|
"prompt is too long",
|
||||||
|
"context window",
|
||||||
|
];
|
||||||
|
retryable_markers.iter().any(|marker| msg.contains(marker))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for RuntimeError {
|
impl Display for RuntimeError {
|
||||||
|
|
@ -358,24 +374,28 @@ where
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
self.record_turn_failed(iterations, &error);
|
self.record_turn_failed(iterations, &error);
|
||||||
|
|
||||||
let result = compact_session(
|
if error.is_retryable_context_error() {
|
||||||
&self.session,
|
let result = compact_session(
|
||||||
CompactionConfig {
|
&self.session,
|
||||||
max_estimated_tokens: 0,
|
CompactionConfig {
|
||||||
..Default::default()
|
max_estimated_tokens: 0,
|
||||||
},
|
..Default::default()
|
||||||
);
|
},
|
||||||
if result.removed_message_count > 0 {
|
);
|
||||||
self.session = result.compacted_session;
|
if result.removed_message_count > 0 {
|
||||||
|
self.session = result.compacted_session;
|
||||||
|
}
|
||||||
|
|
||||||
|
let error_msg = format!("API request failed with error: {error}\nI have automatically truncated the earlier conversation history to reduce context length. Please analyze the error, review your task, and continue.");
|
||||||
|
if let Err(e) = self.session.push_user_text(error_msg) {
|
||||||
|
return Err(RuntimeError::new(format!(
|
||||||
|
"Failed to push error message: {e}"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let error_msg = format!("API request failed with error: {error}\nI have automatically truncated the earlier conversation history to reduce context length. Please analyze the error, review your task, and continue.");
|
return Err(error);
|
||||||
if let Err(e) = self.session.push_user_text(error_msg) {
|
|
||||||
return Err(RuntimeError::new(format!(
|
|
||||||
"Failed to push error message: {e}"
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let (assistant_message, usage, turn_prompt_cache_events) =
|
let (assistant_message, usage, turn_prompt_cache_events) =
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue