增加LLM相关错误处理
This commit is contained in:
parent
3d42f22f83
commit
99a57a816a
@ -2,6 +2,7 @@ use async_trait::async_trait;
|
||||
use reqwest::Client;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::bus::message::ContentBlock;
|
||||
use super::{ChatCompletionRequest, ChatCompletionResponse, LLMProvider, Tool, ToolCall};
|
||||
@ -9,6 +10,8 @@ use super::traits::Usage;
|
||||
use std::sync::Arc;
|
||||
use crate::storage::Storage;
|
||||
|
||||
const LLM_REQUEST_TIMEOUT_SECS: u64 = 300;
|
||||
|
||||
fn convert_content_blocks(blocks: &[ContentBlock]) -> Vec<serde_json::Value> {
|
||||
blocks.iter().map(|b| match b {
|
||||
ContentBlock::Text { text } => {
|
||||
@ -72,7 +75,10 @@ impl AnthropicProvider {
|
||||
model_extra: HashMap<String, serde_json::Value>,
|
||||
) -> Self {
|
||||
Self {
|
||||
client: Client::new(),
|
||||
client: Client::builder()
|
||||
.timeout(Duration::from_secs(LLM_REQUEST_TIMEOUT_SECS))
|
||||
.build()
|
||||
.unwrap_or_else(|_| Client::new()),
|
||||
name,
|
||||
api_key,
|
||||
base_url,
|
||||
@ -238,7 +244,19 @@ impl LLMProvider for AnthropicProvider {
|
||||
let req_body_str = serde_json::to_string_pretty(&body).unwrap_or_default();
|
||||
tracing::debug!(req_body = %req_body_str, "LLM request");
|
||||
|
||||
let resp = req_builder.json(&body).send().await?;
|
||||
let resp = req_builder.json(&body).send().await
|
||||
.inspect_err(|e| {
|
||||
let is_timeout = e.is_timeout();
|
||||
tracing::error!(
|
||||
provider = %self.name,
|
||||
model = %self.model_id,
|
||||
url = %url,
|
||||
timeout = is_timeout,
|
||||
error = %e,
|
||||
elapsed_ms = %start.elapsed().as_millis(),
|
||||
"LLM API request failed"
|
||||
);
|
||||
})?;
|
||||
|
||||
let status = resp.status();
|
||||
let body_text = resp.text().await?;
|
||||
@ -254,6 +272,14 @@ impl LLMProvider for AnthropicProvider {
|
||||
.map(|s| s.to_string())
|
||||
})
|
||||
.unwrap_or_else(|| body_text.clone());
|
||||
tracing::error!(
|
||||
provider = %self.name,
|
||||
model = %self.model_id,
|
||||
http_status = %status,
|
||||
error = %error_msg,
|
||||
elapsed_ms = %start.elapsed().as_millis(),
|
||||
"LLM API returned error"
|
||||
);
|
||||
if let Some(ref storage) = self.storage {
|
||||
let _ = storage.append_llm_call(
|
||||
&self.name, &self.model_id, &req_body_str,
|
||||
|
||||
@ -3,6 +3,7 @@ use reqwest::Client;
|
||||
use serde::Deserialize;
|
||||
use serde_json::{json, Value};
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::bus::message::ContentBlock;
|
||||
use super::{ChatCompletionRequest, ChatCompletionResponse, LLMProvider, ToolCall};
|
||||
@ -10,6 +11,8 @@ use super::traits::Usage;
|
||||
use std::sync::Arc;
|
||||
use crate::storage::Storage;
|
||||
|
||||
const LLM_REQUEST_TIMEOUT_SECS: u64 = 300;
|
||||
|
||||
fn convert_content_blocks(blocks: &[ContentBlock]) -> Value {
|
||||
if blocks.len() == 1
|
||||
&& let ContentBlock::Text { text } = &blocks[0] {
|
||||
@ -48,7 +51,10 @@ impl OpenAIProvider {
|
||||
model_extra: HashMap<String, serde_json::Value>,
|
||||
) -> Self {
|
||||
Self {
|
||||
client: Client::new(),
|
||||
client: Client::builder()
|
||||
.timeout(Duration::from_secs(LLM_REQUEST_TIMEOUT_SECS))
|
||||
.build()
|
||||
.unwrap_or_else(|_| Client::new()),
|
||||
name,
|
||||
api_key,
|
||||
base_url,
|
||||
@ -206,7 +212,19 @@ impl LLMProvider for OpenAIProvider {
|
||||
let req_body_str = serde_json::to_string_pretty(&body).unwrap_or_default();
|
||||
tracing::debug!(req_body = %req_body_str, "LLM request");
|
||||
|
||||
let resp = req_builder.json(&body).send().await?;
|
||||
let resp = req_builder.json(&body).send().await
|
||||
.inspect_err(|e| {
|
||||
let is_timeout = e.is_timeout();
|
||||
tracing::error!(
|
||||
provider = %self.name,
|
||||
model = %self.model_id,
|
||||
url = %url,
|
||||
timeout = is_timeout,
|
||||
error = %e,
|
||||
elapsed_ms = %start.elapsed().as_millis(),
|
||||
"LLM API request failed"
|
||||
);
|
||||
})?;
|
||||
|
||||
let status = resp.status();
|
||||
let text = resp.text().await?;
|
||||
@ -214,6 +232,14 @@ impl LLMProvider for OpenAIProvider {
|
||||
|
||||
if !status.is_success() {
|
||||
let error = format!("API error {}: {}", status, text);
|
||||
tracing::error!(
|
||||
provider = %self.name,
|
||||
model = %self.model_id,
|
||||
http_status = %status,
|
||||
error = %error,
|
||||
elapsed_ms = %start.elapsed().as_millis(),
|
||||
"LLM API returned error"
|
||||
);
|
||||
if let Some(ref storage) = self.storage
|
||||
&& let Err(e) = storage.append_llm_call(
|
||||
&self.name, &self.model_id, &req_body_str,
|
||||
|
||||
@ -1360,7 +1360,10 @@ impl SessionManager {
|
||||
|
||||
let result = session_guard.compressor
|
||||
.compress_if_needed(history)
|
||||
.await?;
|
||||
.await
|
||||
.inspect_err(|e| {
|
||||
tracing::warn!(error = %e, "Context compression failed in handle_message");
|
||||
})?;
|
||||
if result.created_timelines {
|
||||
session_guard.last_compressed_message_at = Some(chrono::Utc::now().timestamp_millis());
|
||||
}
|
||||
@ -1401,9 +1404,19 @@ impl SessionManager {
|
||||
}
|
||||
let mut retry = retry_result.history;
|
||||
retry.insert(0, ChatMessage::system(system_prompt));
|
||||
agent.process(retry).await?
|
||||
agent.process(retry).await
|
||||
.inspect_err(|e| {
|
||||
tracing::error!(error = %e, "Agent retry after context compression failed");
|
||||
})?
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
Err(e) => {
|
||||
tracing::error!(
|
||||
error = %e,
|
||||
elapsed = ?"LLM call in handle_message failed",
|
||||
"Agent processing error — propagating to caller"
|
||||
);
|
||||
return Err(e);
|
||||
},
|
||||
};
|
||||
|
||||
for msg in result.emitted_messages {
|
||||
@ -1515,13 +1528,19 @@ impl SessionManager {
|
||||
// in context compression (system prompt is dynamic and should not be persisted).
|
||||
let mut history = session_guard.compressor
|
||||
.compress_if_needed(history)
|
||||
.await?
|
||||
.await
|
||||
.inspect_err(|e| {
|
||||
tracing::warn!(error = %e, "Context compression failed in handle_cron_message");
|
||||
})?
|
||||
.history;
|
||||
|
||||
history.insert(0, ChatMessage::system(full_system_prompt));
|
||||
|
||||
let agent = session_guard.create_agent_with_notify(notify_tx)?;
|
||||
let result = agent.process(history).await?;
|
||||
let result = agent.process(history).await
|
||||
.inspect_err(|e| {
|
||||
tracing::error!(error = %e, "Agent processing error in handle_cron_message");
|
||||
})?;
|
||||
|
||||
for msg in result.emitted_messages {
|
||||
session_guard.add_message(msg, true).await
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user