Compaction overhaul (#5186)
Co-authored-by: Douwe Osinga <douwe@squareup.com> Co-authored-by: David Katz <dkatz@squareup.com> Co-authored-by: Alex Hancock <alexhancock@block.xyz>
This commit is contained in:
@@ -112,12 +112,7 @@ pub struct FrontendToolRequest {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
|
||||
pub struct ContextLengthExceeded {
|
||||
pub msg: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
|
||||
pub struct SummarizationRequested {
|
||||
pub struct ConversationCompacted {
|
||||
pub msg: String,
|
||||
}
|
||||
|
||||
@@ -133,8 +128,7 @@ pub enum MessageContent {
|
||||
FrontendToolRequest(FrontendToolRequest),
|
||||
Thinking(ThinkingContent),
|
||||
RedactedThinking(RedactedThinkingContent),
|
||||
ContextLengthExceeded(ContextLengthExceeded),
|
||||
SummarizationRequested(SummarizationRequested),
|
||||
ConversationCompacted(ConversationCompacted),
|
||||
}
|
||||
|
||||
impl fmt::Display for MessageContent {
|
||||
@@ -162,10 +156,7 @@ impl fmt::Display for MessageContent {
|
||||
},
|
||||
MessageContent::Thinking(t) => write!(f, "[Thinking: {}]", t.thinking),
|
||||
MessageContent::RedactedThinking(_r) => write!(f, "[RedactedThinking]"),
|
||||
MessageContent::ContextLengthExceeded(r) => {
|
||||
write!(f, "[ContextLengthExceeded: {}]", r.msg)
|
||||
}
|
||||
MessageContent::SummarizationRequested(r) => {
|
||||
MessageContent::ConversationCompacted(r) => {
|
||||
write!(f, "[SummarizationRequested: {}]", r.msg)
|
||||
}
|
||||
}
|
||||
@@ -246,17 +237,13 @@ impl MessageContent {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn context_length_exceeded<S: Into<String>>(msg: S) -> Self {
|
||||
MessageContent::ContextLengthExceeded(ContextLengthExceeded { msg: msg.into() })
|
||||
}
|
||||
|
||||
pub fn summarization_requested<S: Into<String>>(msg: S) -> Self {
|
||||
MessageContent::SummarizationRequested(SummarizationRequested { msg: msg.into() })
|
||||
pub fn conversation_compacted<S: Into<String>>(msg: S) -> Self {
|
||||
MessageContent::ConversationCompacted(ConversationCompacted { msg: msg.into() })
|
||||
}
|
||||
|
||||
// Add this new method to check for summarization requested content
|
||||
pub fn as_summarization_requested(&self) -> Option<&SummarizationRequested> {
|
||||
if let MessageContent::SummarizationRequested(ref summarization_requested) = self {
|
||||
pub fn as_summarization_requested(&self) -> Option<&ConversationCompacted> {
|
||||
if let MessageContent::ConversationCompacted(ref summarization_requested) = self {
|
||||
Some(summarization_requested)
|
||||
} else {
|
||||
None
|
||||
@@ -390,10 +377,8 @@ impl From<PromptMessage> for Message {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MessageMetadata {
|
||||
/// Whether the message should be visible to the user in the UI
|
||||
#[serde(default = "default_true")]
|
||||
pub user_visible: bool,
|
||||
/// Whether the message should be included in the agent's context window
|
||||
#[serde(default = "default_true")]
|
||||
pub agent_visible: bool,
|
||||
}
|
||||
|
||||
@@ -464,28 +449,18 @@ impl MessageMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
fn default_true() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[derive(ToSchema, Clone, PartialEq, Serialize, Deserialize, Debug)]
|
||||
/// A message to or from an LLM
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Message {
|
||||
pub id: Option<String>,
|
||||
pub role: Role,
|
||||
#[serde(default = "default_created")]
|
||||
pub created: i64,
|
||||
#[serde(deserialize_with = "deserialize_sanitized_content")]
|
||||
pub content: Vec<MessageContent>,
|
||||
#[serde(default)]
|
||||
pub metadata: MessageMetadata,
|
||||
}
|
||||
|
||||
fn default_created() -> i64 {
|
||||
0 // old messages do not have timestamps.
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn new(role: Role, created: i64, content: Vec<MessageContent>) -> Self {
|
||||
Message {
|
||||
@@ -605,11 +580,6 @@ impl Message {
|
||||
self.with_content(MessageContent::redacted_thinking(data))
|
||||
}
|
||||
|
||||
/// Add context length exceeded content to the message
|
||||
pub fn with_context_length_exceeded<S: Into<String>>(self, msg: S) -> Self {
|
||||
self.with_content(MessageContent::context_length_exceeded(msg))
|
||||
}
|
||||
|
||||
/// Get the concatenated text content of the message, separated by newlines
|
||||
pub fn as_concat_text(&self) -> String {
|
||||
self.content
|
||||
@@ -680,9 +650,8 @@ impl Message {
|
||||
.all(|c| matches!(c, MessageContent::Text(_)))
|
||||
}
|
||||
|
||||
/// Add summarization requested to the message
|
||||
pub fn with_summarization_requested<S: Into<String>>(self, msg: S) -> Self {
|
||||
self.with_content(MessageContent::summarization_requested(msg))
|
||||
pub fn with_conversation_compacted<S: Into<String>>(self, msg: S) -> Self {
|
||||
self.with_content(MessageContent::conversation_compacted(msg))
|
||||
}
|
||||
|
||||
/// Set the visibility metadata for the message
|
||||
@@ -837,7 +806,8 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"metadata": { "agentVisible": true, "userVisible": true }
|
||||
}"#;
|
||||
|
||||
let message: Message = serde_json::from_str(json_str).unwrap();
|
||||
@@ -1045,7 +1015,8 @@ mod tests {
|
||||
"data": "base64data",
|
||||
"mimeType": "image/png"
|
||||
}}
|
||||
]
|
||||
],
|
||||
"metadata": {{ "agentVisible": true, "userVisible": true }}
|
||||
}}"#,
|
||||
malicious_text
|
||||
);
|
||||
@@ -1073,7 +1044,8 @@ mod tests {
|
||||
"content": [{
|
||||
"type": "text",
|
||||
"text": "Hello world 世界 🌍"
|
||||
}]
|
||||
}],
|
||||
"metadata": { "agentVisible": true, "userVisible": true }
|
||||
}"#;
|
||||
|
||||
let message: Message = serde_json::from_str(clean_json).unwrap();
|
||||
@@ -1142,20 +1114,6 @@ mod tests {
|
||||
let message: Message = serde_json::from_str(json_with_metadata).unwrap();
|
||||
assert!(!message.is_user_visible());
|
||||
assert!(message.is_agent_visible());
|
||||
|
||||
// Test without metadata (should use defaults)
|
||||
let json_without_metadata = r#"{
|
||||
"role": "user",
|
||||
"created": 1640995200,
|
||||
"content": [{
|
||||
"type": "text",
|
||||
"text": "Test"
|
||||
}]
|
||||
}"#;
|
||||
|
||||
let message: Message = serde_json::from_str(json_without_metadata).unwrap();
|
||||
assert!(message.is_user_visible());
|
||||
assert!(message.is_agent_visible());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user