mirror of
https://github.com/openai/codex.git
synced 2026-11-05 16:29:31 +00:00
Reduce cloning when building Responses requests (#34825)
## Why Preparing Responses API requests rebuilt tool definitions as a generic JSON tree, and incremental WebSocket requests cloned their full item prefix for comparison. ## What changed - Serialize tool definitions into shared raw JSON that can be embedded directly in HTTP and WebSocket requests. - Compare incremental request prefixes in place while still ignoring internal message metadata. ## Testing - Verify raw tool JSON matches the existing value encoding. - Preserve the serialized WebSocket request payload. GitOrigin-RevId: 66e2921792c332e8904954dafa597f6d39abcf29
This commit is contained in:
1 parent
bbfc3f0152
commit
12c115d558
12 files changed
+145
-42
No files matched your search
+35
-20
@@ -89,6 +89,7 @@ use codex_rollout_trace::CompactionTraceContext;
|
||||
use codex_rollout_trace::InferenceTraceAttempt;
|
||||
use codex_rollout_trace::InferenceTraceContext;
|
||||
use codex_tools::create_tools_json_for_responses_api;
|
||||
use codex_tools::create_tools_raw_json_for_responses_api;
|
||||
use eventsource_stream::Event;
|
||||
use eventsource_stream::EventStreamError;
|
||||
use futures::StreamExt;
|
||||
@@ -358,6 +359,21 @@ fn responses_request_properties_match(
|
||||
&& previous_text == current_text
|
||||
}
|
||||
|
||||
fn response_items_equal_ignoring_internal_metadata(
|
||||
previous: &ResponseItem,
|
||||
current: &ResponseItem,
|
||||
) -> bool {
|
||||
if previous == current {
|
||||
return true;
|
||||
}
|
||||
|
||||
let mut previous = previous.clone();
|
||||
previous.clear_internal_chat_message_metadata_passthrough();
|
||||
let mut current = current.clone();
|
||||
current.clear_internal_chat_message_metadata_passthrough();
|
||||
previous == current
|
||||
}
|
||||
|
||||
impl WebsocketSession {
|
||||
fn set_connection_reused(&self, connection_reused: bool) {
|
||||
*self
|
||||
@@ -836,8 +852,8 @@ impl ModelClient {
|
||||
.iter_mut()
|
||||
.for_each(ResponseItem::clear_internal_chat_message_metadata_passthrough);
|
||||
}
|
||||
let tools = create_tools_json_for_responses_api(&prompt.tools)?;
|
||||
let (instructions, tools) = if model_info.use_responses_lite {
|
||||
let tools = create_tools_json_for_responses_api(&prompt.tools)?;
|
||||
let mut prefix = vec![ResponseItem::AdditionalTools {
|
||||
id: None,
|
||||
role: "developer".to_string(),
|
||||
@@ -857,7 +873,10 @@ impl ModelClient {
|
||||
input.splice(0..0, prefix);
|
||||
(String::new(), None)
|
||||
} else {
|
||||
(prompt.base_instructions.text.clone(), Some(tools))
|
||||
(
|
||||
prompt.base_instructions.text.clone(),
|
||||
Some(create_tools_raw_json_for_responses_api(&prompt.tools)?.into()),
|
||||
)
|
||||
};
|
||||
let reasoning = Self::build_reasoning(model_info, effort, summary);
|
||||
let stream_options = (self.state.concurrent_reasoning_summaries_enabled
|
||||
@@ -1167,29 +1186,25 @@ impl ModelClientSession {
|
||||
return None;
|
||||
}
|
||||
|
||||
// To compare the inputs, we concatenate the previous request items with the response items,
|
||||
// then compare that against the equivalent slice of request items, ignoring metadata. If
|
||||
// they match, we can consider the remaining items the incremental request.
|
||||
let mut previous_items = previous_request.input.clone();
|
||||
if let Some(response) = last_response {
|
||||
previous_items.extend_from_slice(&response.items_added);
|
||||
}
|
||||
previous_items
|
||||
.iter_mut()
|
||||
.for_each(ResponseItem::clear_internal_chat_message_metadata_passthrough);
|
||||
|
||||
let response_items =
|
||||
last_response.map_or(&[][..], |response| response.items_added.as_slice());
|
||||
let previous_items_len = previous_request
|
||||
.input
|
||||
.len()
|
||||
.checked_add(response_items.len())?;
|
||||
let Some((request_items_to_compare, incremental_items)) =
|
||||
request.input.split_at_checked(previous_items.len())
|
||||
request.input.split_at_checked(previous_items_len)
|
||||
else {
|
||||
trace!("incremental request failed, incompatible request length");
|
||||
return None;
|
||||
};
|
||||
let mut request_prefix = request_items_to_compare.to_vec();
|
||||
request_prefix
|
||||
.iter_mut()
|
||||
.for_each(ResponseItem::clear_internal_chat_message_metadata_passthrough);
|
||||
|
||||
if previous_items != request_prefix {
|
||||
let previous_items = previous_request.input.iter().chain(response_items);
|
||||
if !previous_items
|
||||
.zip(request_items_to_compare)
|
||||
.all(|(previous, current)| {
|
||||
response_items_equal_ignoring_internal_metadata(previous, current)
|
||||
})
|
||||
{
|
||||
trace!("incremental request failed, items didn't match");
|
||||
return None;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user