Strip the audience for compacting (#6646)
Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use crate::routes::errors::ErrorResponse;
|
||||
use crate::routes::recipe_utils::{apply_recipe_to_agent, build_recipe_with_parameter_values};
|
||||
use crate::state::AppState;
|
||||
use axum::extract::State;
|
||||
use axum::extract::{DefaultBodyLimit, State};
|
||||
use axum::routing::post;
|
||||
use axum::{
|
||||
extract::Path,
|
||||
@@ -493,7 +493,10 @@ pub fn routes(state: Arc<AppState>) -> Router {
|
||||
.route("/sessions/{session_id}", get(get_session))
|
||||
.route("/sessions/{session_id}", delete(delete_session))
|
||||
.route("/sessions/{session_id}/export", get(export_session))
|
||||
.route("/sessions/import", post(import_session))
|
||||
.route(
|
||||
"/sessions/import",
|
||||
post(import_session).layer(DefaultBodyLimit::max(25 * 1024 * 1024)),
|
||||
)
|
||||
.route("/sessions/insights", get(get_session_insights))
|
||||
.route("/sessions/{session_id}/name", put(update_session_name))
|
||||
.route(
|
||||
|
||||
@@ -222,7 +222,7 @@ pub async fn check_if_compaction_needed(
|
||||
Ok(needs_compaction)
|
||||
}
|
||||
|
||||
fn filter_tool_responses<'a>(messages: &[&'a Message], remove_percent: u32) -> Vec<&'a Message> {
|
||||
fn filter_tool_responses(messages: &[Message], remove_percent: u32) -> Vec<&Message> {
|
||||
fn has_tool_response(msg: &Message) -> bool {
|
||||
msg.content
|
||||
.iter()
|
||||
@@ -230,7 +230,7 @@ fn filter_tool_responses<'a>(messages: &[&'a Message], remove_percent: u32) -> V
|
||||
}
|
||||
|
||||
if remove_percent == 0 {
|
||||
return messages.to_vec();
|
||||
return messages.iter().collect();
|
||||
}
|
||||
|
||||
let tool_indices: Vec<usize> = messages
|
||||
@@ -241,7 +241,7 @@ fn filter_tool_responses<'a>(messages: &[&'a Message], remove_percent: u32) -> V
|
||||
.collect();
|
||||
|
||||
if tool_indices.is_empty() {
|
||||
return messages.to_vec();
|
||||
return messages.iter().collect();
|
||||
}
|
||||
|
||||
let num_to_remove = ((tool_indices.len() * remove_percent as usize) / 100).max(1);
|
||||
@@ -268,7 +268,7 @@ fn filter_tool_responses<'a>(messages: &[&'a Message], remove_percent: u32) -> V
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(i, _)| !indices_to_remove.contains(i))
|
||||
.map(|(_, msg)| *msg)
|
||||
.map(|(_, msg)| msg)
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -277,9 +277,10 @@ async fn do_compact(
|
||||
session_id: &str,
|
||||
messages: &[Message],
|
||||
) -> Result<(Message, ProviderUsage), anyhow::Error> {
|
||||
let agent_visible_messages: Vec<&Message> = messages
|
||||
let agent_visible_messages: Vec<Message> = messages
|
||||
.iter()
|
||||
.filter(|msg| msg.is_agent_visible())
|
||||
.map(|msg| msg.agent_visible_content())
|
||||
.collect();
|
||||
|
||||
// Try progressively removing more tool response messages from the middle to reduce context length
|
||||
@@ -350,7 +351,7 @@ fn format_message_for_compacting(msg: &Message) -> String {
|
||||
format!(
|
||||
"tool_request({}): {}",
|
||||
call.name,
|
||||
serde_json::to_string_pretty(&call.arguments)
|
||||
serde_json::to_string(&call.arguments)
|
||||
.unwrap_or_else(|_| "<<invalid json>>".to_string())
|
||||
)
|
||||
} else {
|
||||
@@ -397,7 +398,7 @@ fn format_message_for_compacting(msg: &Message) -> String {
|
||||
"frontend_tool_request: [error]".to_string()
|
||||
}
|
||||
}
|
||||
MessageContent::Thinking(thinking) => format!("thinking: {}", thinking.thinking),
|
||||
MessageContent::Thinking(_) => "thinking".to_string(),
|
||||
MessageContent::RedactedThinking(_) => "redacted_thinking".to_string(),
|
||||
MessageContent::SystemNotification(notification) => {
|
||||
format!("system_notification: {}", notification.msg)
|
||||
|
||||
@@ -245,6 +245,64 @@ impl MessageContent {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn filter_for_audience(&self, audience: Role) -> Option<MessageContent> {
|
||||
match self {
|
||||
MessageContent::Text(text) => {
|
||||
if text
|
||||
.audience()
|
||||
.map(|roles| roles.contains(&audience))
|
||||
.unwrap_or(true)
|
||||
{
|
||||
Some(self.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
MessageContent::Image(img) => {
|
||||
if img
|
||||
.audience()
|
||||
.map(|roles| roles.contains(&audience))
|
||||
.unwrap_or(true)
|
||||
{
|
||||
Some(self.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
MessageContent::ToolResponse(res) => {
|
||||
let Ok(result) = &res.tool_result else {
|
||||
return Some(self.clone());
|
||||
};
|
||||
|
||||
let filtered_content: Vec<Content> = result
|
||||
.content
|
||||
.iter()
|
||||
.filter(|c| {
|
||||
c.audience()
|
||||
.map(|roles| roles.contains(&audience))
|
||||
.unwrap_or(true)
|
||||
})
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
if filtered_content.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(MessageContent::ToolResponse(ToolResponse {
|
||||
id: res.id.clone(),
|
||||
tool_result: Ok(CallToolResult {
|
||||
content: filtered_content,
|
||||
..result.clone()
|
||||
}),
|
||||
metadata: res.metadata.clone(),
|
||||
}))
|
||||
}
|
||||
MessageContent::Thinking(_) | MessageContent::RedactedThinking(_) => None,
|
||||
_ => Some(self.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn image<S: Into<String>, T: Into<String>>(data: S, mime_type: T) -> Self {
|
||||
MessageContent::Image(
|
||||
RawImageContent {
|
||||
@@ -621,6 +679,19 @@ impl Message {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
|
||||
pub fn agent_visible_content(&self) -> Message {
|
||||
let filtered_content = self
|
||||
.content
|
||||
.iter()
|
||||
.filter_map(|c| c.filter_for_audience(Role::Assistant))
|
||||
.collect();
|
||||
|
||||
Message {
|
||||
content: filtered_content,
|
||||
..self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new user message with the current timestamp
|
||||
pub fn user() -> Self {
|
||||
Message {
|
||||
|
||||
@@ -354,12 +354,6 @@ impl<'a> ApiRequestBuilder<'a> {
|
||||
}
|
||||
|
||||
pub async fn response_post(self, payload: &Value) -> Result<Response> {
|
||||
// Log the JSON payload being sent to the LLM
|
||||
tracing::debug!(
|
||||
"LLM_REQUEST: {}",
|
||||
serde_json::to_string(payload).unwrap_or_else(|_| "{}".to_string())
|
||||
);
|
||||
|
||||
let request = self.send_request(|url, client| client.post(url)).await?;
|
||||
Ok(request.json(payload).send().await?)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user