feat: 增强消息处理,清理不完整的 tool_call 序列以防止数据污染
This commit is contained in:
parent
cb0d3d932d
commit
d7ff969560
@ -899,7 +899,32 @@ impl AgentLoop {
|
|||||||
|
|
||||||
// Sanitize: remove any trailing incomplete tool call sequences
|
// Sanitize: remove any trailing incomplete tool call sequences
|
||||||
// that may have been persisted before a process interruption.
|
// that may have been persisted before a process interruption.
|
||||||
crate::bus::message::sanitize_incomplete_tool_call_sequences(&mut messages);
|
{
|
||||||
|
let tool_call_ids: Vec<_> = messages.iter()
|
||||||
|
.filter(|m| m.role == "assistant")
|
||||||
|
.filter_map(|m| m.tool_calls.as_ref())
|
||||||
|
.flatten()
|
||||||
|
.map(|tc| tc.id.clone())
|
||||||
|
.collect();
|
||||||
|
let tool_result_ids: Vec<_> = messages.iter()
|
||||||
|
.filter(|m| m.role == "tool")
|
||||||
|
.filter_map(|m| m.tool_call_id.clone())
|
||||||
|
.collect();
|
||||||
|
tracing::debug!(
|
||||||
|
total_messages = messages.len(),
|
||||||
|
tool_call_ids = ?tool_call_ids,
|
||||||
|
tool_result_ids = ?tool_result_ids,
|
||||||
|
"Pre-process message state before sanitize"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let removed = crate::bus::message::sanitize_incomplete_tool_call_sequences(&mut messages);
|
||||||
|
if removed > 0 {
|
||||||
|
tracing::warn!(
|
||||||
|
removed_count = removed,
|
||||||
|
after_len = messages.len(),
|
||||||
|
"Pre-process sanitize removed incomplete tool_call sequences"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Track tool calls for loop detection
|
// Track tool calls for loop detection
|
||||||
let mut loop_detector = LoopDetector::new(LoopDetectorConfig::default());
|
let mut loop_detector = LoopDetector::new(LoopDetectorConfig::default());
|
||||||
@ -1152,6 +1177,18 @@ impl AgentLoop {
|
|||||||
let tool_results = if self.cancel_token.is_some() {
|
let tool_results = if self.cancel_token.is_some() {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
_ = self.cancel_signal() => {
|
_ = self.cancel_signal() => {
|
||||||
|
// 为所有 tool_calls 补充取消结果,避免孤立 assistant(tool_calls)
|
||||||
|
for tool_call in &response.tool_calls {
|
||||||
|
let cancel_result = ChatMessage::tool_with_state(
|
||||||
|
tool_call.id.clone(),
|
||||||
|
tool_call.name.clone(),
|
||||||
|
"[Tool execution cancelled by user]".to_string(),
|
||||||
|
ToolMessageState::Completed,
|
||||||
|
);
|
||||||
|
messages.push(cancel_result.clone());
|
||||||
|
emitted_messages.push(cancel_result.clone());
|
||||||
|
self.emit_tool_result(cancel_result, Some(0)).await;
|
||||||
|
}
|
||||||
let cancel = Self::build_cancel_result(iteration, emitted_messages);
|
let cancel = Self::build_cancel_result(iteration, emitted_messages);
|
||||||
self.emit_live_tool_call_message(cancel.final_response.clone()).await;
|
self.emit_live_tool_call_message(cancel.final_response.clone()).await;
|
||||||
return Ok(cancel);
|
return Ok(cancel);
|
||||||
@ -1230,6 +1267,12 @@ impl AgentLoop {
|
|||||||
// Max iterations reached - ask LLM for a summary based on completed work
|
// Max iterations reached - ask LLM for a summary based on completed work
|
||||||
tracing::warn!("Max iterations reached, requesting final summary from LLM");
|
tracing::warn!("Max iterations reached, requesting final summary from LLM");
|
||||||
|
|
||||||
|
// Defense: sanitize before final summary request
|
||||||
|
let removed = crate::bus::message::sanitize_incomplete_tool_call_sequences(&mut messages);
|
||||||
|
if removed > 0 {
|
||||||
|
tracing::warn!(removed_count = removed, "Sanitized before max-iterations summary");
|
||||||
|
}
|
||||||
|
|
||||||
// Add a message asking for summary
|
// Add a message asking for summary
|
||||||
let summary_request = ChatMessage::user(
|
let summary_request = ChatMessage::user(
|
||||||
"You have reached the maximum number of tool call iterations. \
|
"You have reached the maximum number of tool call iterations. \
|
||||||
|
|||||||
@ -65,7 +65,7 @@ impl SessionHistory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 如果提供了 topic_id,按 topic 加载;否则按 session 加载
|
// 如果提供了 topic_id,按 topic 加载;否则按 session 加载
|
||||||
let history = if let Some(tid) = topic_id {
|
let mut history = if let Some(tid) = topic_id {
|
||||||
let sid = self.persistent_session_id(chat_id);
|
let sid = self.persistent_session_id(chat_id);
|
||||||
self.conversations
|
self.conversations
|
||||||
.load_messages_for_topic(tid, Some(&sid))
|
.load_messages_for_topic(tid, Some(&sid))
|
||||||
@ -75,6 +75,17 @@ impl SessionHistory {
|
|||||||
.load_messages(&self.persistent_session_id(chat_id))
|
.load_messages(&self.persistent_session_id(chat_id))
|
||||||
.map_err(|err| AgentError::Other(format!("session history load error: {}", err)))?
|
.map_err(|err| AgentError::Other(format!("session history load error: {}", err)))?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 清理 DB 加载的历史中可能存在的不完整 tool_call 序列
|
||||||
|
let removed = crate::bus::message::sanitize_incomplete_tool_call_sequences(&mut history);
|
||||||
|
if removed > 0 {
|
||||||
|
tracing::warn!(
|
||||||
|
chat_id = %chat_id,
|
||||||
|
removed_count = removed,
|
||||||
|
"Sanitized incomplete tool_call sequences on history load"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
self.chat_histories.insert(chat_id.to_string(), history);
|
self.chat_histories.insert(chat_id.to_string(), history);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -159,6 +170,19 @@ impl SessionHistory {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 在追加新消息前,先清理内存历史中的不完整 tool_call 序列
|
||||||
|
// 这防止脏数据(如取消时产生的孤立 assistant(tool_calls))在内存历史中累积
|
||||||
|
if let Some(history) = self.chat_histories.get_mut(chat_id) {
|
||||||
|
let removed = crate::bus::message::sanitize_incomplete_tool_call_sequences(history);
|
||||||
|
if removed > 0 {
|
||||||
|
tracing::warn!(
|
||||||
|
chat_id = %chat_id,
|
||||||
|
removed_count = removed,
|
||||||
|
"Sanitized in-memory history before appending persisted messages"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for message in messages {
|
for message in messages {
|
||||||
self.add_message(chat_id, message);
|
self.add_message(chat_id, message);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user