perf(google): avoid accumulating thoughtSignatures across conversation history (#6462)
Signed-off-by: rabi <ramishra@redhat.com>
This commit is contained in:
@@ -31,7 +31,7 @@ pub fn get_thought_signature(metadata: &Option<ProviderMetadata>) -> Option<&str
|
|||||||
|
|
||||||
/// Convert internal Message format to Google's API message specification
|
/// Convert internal Message format to Google's API message specification
|
||||||
pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
||||||
messages
|
let filtered: Vec<_> = messages
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|m| m.is_agent_visible())
|
.filter(|m| m.is_agent_visible())
|
||||||
.filter(|message| {
|
.filter(|message| {
|
||||||
@@ -42,12 +42,28 @@ pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.map(|message| {
|
.collect();
|
||||||
|
|
||||||
|
let last_assistant_idx = filtered
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(_, m)| m.role != Role::User)
|
||||||
|
.map(|(i, _)| i)
|
||||||
|
.next_back();
|
||||||
|
|
||||||
|
filtered
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(idx, message)| {
|
||||||
let role = if message.role == Role::User {
|
let role = if message.role == Role::User {
|
||||||
"user"
|
"user"
|
||||||
} else {
|
} else {
|
||||||
"model"
|
"model"
|
||||||
};
|
};
|
||||||
|
let include_signature = match last_assistant_idx {
|
||||||
|
Some(last_idx) => idx >= last_idx,
|
||||||
|
None => false,
|
||||||
|
};
|
||||||
let mut parts = Vec::new();
|
let mut parts = Vec::new();
|
||||||
for message_content in message.content.iter() {
|
for message_content in message.content.iter() {
|
||||||
match message_content {
|
match message_content {
|
||||||
@@ -74,8 +90,13 @@ pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
|||||||
let mut part = Map::new();
|
let mut part = Map::new();
|
||||||
part.insert("functionCall".to_string(), json!(function_call_part));
|
part.insert("functionCall".to_string(), json!(function_call_part));
|
||||||
|
|
||||||
if let Some(signature) = get_thought_signature(&request.metadata) {
|
if include_signature {
|
||||||
part.insert(THOUGHT_SIGNATURE_KEY.to_string(), json!(signature));
|
if let Some(signature) = get_thought_signature(&request.metadata) {
|
||||||
|
part.insert(
|
||||||
|
THOUGHT_SIGNATURE_KEY.to_string(),
|
||||||
|
json!(signature),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parts.push(json!(part));
|
parts.push(json!(part));
|
||||||
@@ -144,11 +165,15 @@ pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
|||||||
"functionResponse".to_string(),
|
"functionResponse".to_string(),
|
||||||
json!(function_response),
|
json!(function_response),
|
||||||
);
|
);
|
||||||
if let Some(signature) = get_thought_signature(&response.metadata) {
|
if include_signature {
|
||||||
part.insert(
|
if let Some(signature) =
|
||||||
THOUGHT_SIGNATURE_KEY.to_string(),
|
get_thought_signature(&response.metadata)
|
||||||
json!(signature),
|
{
|
||||||
);
|
part.insert(
|
||||||
|
THOUGHT_SIGNATURE_KEY.to_string(),
|
||||||
|
json!(signature),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
parts.push(json!(part));
|
parts.push(json!(part));
|
||||||
}
|
}
|
||||||
@@ -164,11 +189,15 @@ pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
|||||||
"functionResponse".to_string(),
|
"functionResponse".to_string(),
|
||||||
json!(function_response),
|
json!(function_response),
|
||||||
);
|
);
|
||||||
if let Some(signature) = get_thought_signature(&response.metadata) {
|
if include_signature {
|
||||||
part.insert(
|
if let Some(signature) =
|
||||||
THOUGHT_SIGNATURE_KEY.to_string(),
|
get_thought_signature(&response.metadata)
|
||||||
json!(signature),
|
{
|
||||||
);
|
part.insert(
|
||||||
|
THOUGHT_SIGNATURE_KEY.to_string(),
|
||||||
|
json!(signature),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
parts.push(json!(part));
|
parts.push(json!(part));
|
||||||
}
|
}
|
||||||
@@ -177,7 +206,9 @@ pub fn format_messages(messages: &[Message]) -> Vec<Value> {
|
|||||||
MessageContent::Thinking(thinking) => {
|
MessageContent::Thinking(thinking) => {
|
||||||
let mut part = Map::new();
|
let mut part = Map::new();
|
||||||
part.insert("text".to_string(), json!(thinking.thinking));
|
part.insert("text".to_string(), json!(thinking.thinking));
|
||||||
part.insert("thoughtSignature".to_string(), json!(thinking.signature));
|
if include_signature {
|
||||||
|
part.insert("thoughtSignature".to_string(), json!(thinking.signature));
|
||||||
|
}
|
||||||
parts.push(json!(part));
|
parts.push(json!(part));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1230,10 +1261,21 @@ mod tests {
|
|||||||
Ok(tool_result("output")),
|
Ok(tool_result("output")),
|
||||||
req1.metadata.as_ref(),
|
req1.metadata.as_ref(),
|
||||||
);
|
);
|
||||||
let google_out = format_messages(&[native, tool_response]);
|
let google_out = format_messages(&[native.clone(), tool_response.clone()]);
|
||||||
assert_eq!(google_out[0]["parts"][0]["thoughtSignature"], SIG);
|
assert_eq!(google_out[0]["parts"][0]["thoughtSignature"], SIG);
|
||||||
assert_eq!(google_out[1]["parts"][0]["thoughtSignature"], SIG);
|
assert_eq!(google_out[1]["parts"][0]["thoughtSignature"], SIG);
|
||||||
|
|
||||||
|
let second_assistant =
|
||||||
|
Message::assistant().with_thinking("More thinking".to_string(), "sig_456".to_string());
|
||||||
|
let google_multi = format_messages(&[native, tool_response, second_assistant]);
|
||||||
|
assert!(google_multi[0]["parts"][0]
|
||||||
|
.get("thoughtSignature")
|
||||||
|
.is_none());
|
||||||
|
assert!(google_multi[1]["parts"][0]
|
||||||
|
.get("thoughtSignature")
|
||||||
|
.is_none());
|
||||||
|
assert_eq!(google_multi[2]["parts"][0]["thoughtSignature"], "sig_456");
|
||||||
|
|
||||||
// Text-only response WITH signature but WITHOUT function calls should be regular text
|
// Text-only response WITH signature but WITHOUT function calls should be regular text
|
||||||
// (per original behavior: thinking is only when reasoning before tool calls)
|
// (per original behavior: thinking is only when reasoning before tool calls)
|
||||||
let final_response_with_sig =
|
let final_response_with_sig =
|
||||||
|
|||||||
Reference in New Issue
Block a user