1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-10 07:55:21 +02:00

Rework Assistant, Provider, and tests for better domain boundaries

This commit is contained in:
Zach Gollwitzer 2025-03-28 19:39:48 -04:00
parent 56d78b50ce
commit b9681d9cee
10 changed files with 420 additions and 212 deletions

View file

@ -30,8 +30,8 @@ class Assistant
result = fn.call(args)
ToolCall::Function.new(
provider_id: function_request.provider_id,
provider_call_id: function_request.provider_call_id,
provider_id: function_request.id,
provider_call_id: function_request.call_id,
function_name: name,
function_arguments: args,
function_result: result
@ -70,7 +70,19 @@ class Assistant
ai_model: message.ai_model
)
streamer = proc do |chunk|
streamer2 = proc do |chunk|
case chunk.type
when "output_text"
stop_thinking
assistant_response.content += chunk.data
assistant_response.save!
when "response"
stop_thinking
chat.update!(latest_assistant_response_id: chunk.data.id)
end
end
streamer1 = proc do |chunk|
case chunk.type
when "output_text"
stop_thinking
@ -93,7 +105,7 @@ class Assistant
instructions: instructions,
functions: functions.map(&:to_h),
function_results: tool_calls.map(&:to_h),
streamer: streamer
streamer: streamer2
)
else
stop_thinking
@ -109,7 +121,7 @@ class Assistant
instructions: instructions,
functions: functions.map(&:to_h),
function_results: [],
streamer: streamer
streamer: streamer1
)
rescue => e
chat.add_error(e)
@ -151,7 +163,7 @@ class Assistant
- Format all responses in markdown
- Format all monetary values according to the user's preferred currency
- Format dates in the user's preferred format
- Format dates in the user's preferred format: #{preferred_date_format}
#### User's preferred currency
@ -165,7 +177,6 @@ class Assistant
- Default format: #{preferred_currency.default_format}
- Separator: #{preferred_currency.separator}
- Delimiter: #{preferred_currency.delimiter}
- Date format: #{preferred_date_format}
### Rules about financial advice

View file

@ -1,17 +1,13 @@
module Provider::LlmProvider
extend ActiveSupport::Concern
def chat_response(message, instructions: nil, available_functions: [], streamer: nil)
def chat_response(prompt, model:, instructions: nil, functions: [], function_results: [], streamer: nil, previous_response_id: nil)
raise NotImplementedError, "Subclasses must implement #chat_response"
end
private
StreamChunk = Data.define(:provider_type, :data)
ChatResponse = Data.define(:provider_id, :model, :messages, :function_calls) do
def final?
function_calls.empty?
end
end
Message = Data.define(:provider_id, :content)
FunctionCall = Data.define(:provider_id, :provider_call_id, :name, :arguments, :result)
Message = Data.define(:id, :output_text)
StreamChunk = Data.define(:type, :data)
ChatResponse = Data.define(:id, :model, :messages, :function_requests)
FunctionRequest = Data.define(:id, :call_id, :function_name, :function_args)
end

View file

@ -1,5 +1,5 @@
class Provider::Openai < Provider
include LlmProvider
include LlmProvider, Parser
# Subclass so errors caught in this provider are raised as Provider::Openai::Error
Error = Class.new(Provider::Error)
@ -14,10 +14,42 @@ class Provider::Openai < Provider
MODELS.include?(model)
end
def chat_response(prompt, model:, instructions: nil, functions: [], function_results: [], previous_response_id: nil)
def chat_response(prompt, model:, instructions: nil, functions: [], function_results: [], streamer: nil, previous_response_id: nil)
with_provider_response do
proxy_streamer = proc do |chunk|
type = chunk.dig("type")
case type
when "response.output_text.delta", "response.refusal.delta"
streamer.call(StreamChunk.new(type: "output_text", data: chunk.dig("delta")))
when "response.completed"
raw_response = chunk.dig("response")
messages = extract_messages(raw_response).map do |message|
Message.new(
id: message[:id],
output_text: message[:output_text]
)
end
function_requests = extract_function_requests(raw_response).map do |function_request|
FunctionRequest.new(
id: function_request[:id],
call_id: function_request[:call_id],
function_name: function_request[:name],
function_args: function_request[:arguments]
)
end
response = ChatResponse.new(
id: extract_id(raw_response),
model: extract_model(raw_response),
messages: messages,
function_requests: function_requests
)
streamer.call(StreamChunk.new(type: "response", data: response))
end
end
function_results_input = function_results.map do |fn_result|
@ -40,14 +72,37 @@ class Provider::Openai < Provider
}
end
client.responses.create(parameters: {
raw_response = client.responses.create(parameters: {
model: model,
input: prompt_input + function_results_input,
instructions: instructions,
tools: tools,
previous_response_id: previous_response_id,
stream: streamer
stream: streamer.present? ? proxy_streamer : nil
})
messages = extract_messages(raw_response).map do |message|
Message.new(
id: message[:id],
output_text: message[:output_text]
)
end
function_requests = extract_function_requests(raw_response).map do |function_request|
FunctionRequest.new(
id: function_request[:id],
call_id: function_request[:call_id],
function_name: function_request[:name],
function_args: function_request[:arguments]
)
end
ChatResponse.new(
id: extract_id(raw_response),
model: extract_model(raw_response),
messages: messages,
function_requests: function_requests
)
end
end

View file

@ -19,19 +19,14 @@ class AssistantTest < ActiveSupport::TestCase
test "responds to basic prompt" do
text_chunk = OpenStruct.new(type: "output_text", data: "Hello from assistant")
response_chunk = OpenStruct.new(
type: "response",
data: OpenStruct.new(
id: "1",
model: "gpt-4o",
messages: [
OpenStruct.new(
id: "1",
content: "Hello from assistant",
)
],
functions: []
type: "response",
data: OpenStruct.new(
id: "1",
model: "gpt-4o",
messages: [ OpenStruct.new(id: "1", output_text: "Hello from assistant") ],
function_requests: []
)
)
)
@provider.expects(:chat_response).with do |message, **options|
options[:streamer].call(text_chunk)
@ -45,37 +40,57 @@ class AssistantTest < ActiveSupport::TestCase
end
test "responds with tool function calls" do
function_request_chunk = OpenStruct.new(type: "function_request", data: "get_net_worth")
text_chunk = OpenStruct.new(type: "output_text", data: "Your net worth is $124,200")
response_chunk = OpenStruct.new(
Assistant::Function::GetAccounts.any_instance.stubs(:call).returns("test value")
# Call #1: Function requests
call1_response_chunk = OpenStruct.new(
type: "response",
data: OpenStruct.new(
id: "1",
model: "gpt-4o",
messages: [
OpenStruct.new(
id: "1",
content: "Your net worth is $124,200",
)
],
functions: [
messages: [],
function_requests: [
OpenStruct.new(
id: "1",
call_id: "1",
name: "get_net_worth",
arguments: "{}",
result: "$124,200"
function_name: "get_accounts",
function_arguments: "{}",
)
]
)
)
# Call #2: Text response (that uses function results)
call2_text_chunk = OpenStruct.new(type: "output_text", data: "Your net worth is $124,200")
call2_response_chunk = OpenStruct.new(type: "response", data: OpenStruct.new(
id: "2",
model: "gpt-4o",
messages: [ OpenStruct.new(id: "1", output_text: "Your net worth is $124,200") ],
function_requests: [],
function_results: [
OpenStruct.new(
provider_id: "1",
provider_call_id: "1",
name: "get_accounts",
arguments: "{}",
result: "test value"
)
],
previous_response_id: "1"
))
sequence = sequence("provider_chat_response")
@provider.expects(:chat_response).with do |message, **options|
options[:streamer].call(function_request_chunk)
options[:streamer].call(text_chunk)
options[:streamer].call(response_chunk)
options[:streamer].call(call2_text_chunk)
options[:streamer].call(call2_response_chunk)
true
end
end.returns(nil).once.in_sequence(sequence)
@provider.expects(:chat_response).with do |message, **options|
options[:streamer].call(call1_response_chunk)
true
end.returns(nil).once.in_sequence(sequence)
assert_difference "AssistantMessage.count", 1 do
@assistant.respond_to(@message)

View file

@ -6,16 +6,11 @@ class Provider::OpenaiTest < ActiveSupport::TestCase
setup do
@subject = @openai = Provider::Openai.new(ENV.fetch("OPENAI_ACCESS_TOKEN", "test-openai-token"))
@subject_model = "gpt-4o"
@chat = chats(:two)
end
test "openai errors are automatically raised" do
VCR.use_cassette("openai/chat/error") do
response = @openai.chat_response(UserMessage.new(
chat: @chat,
content: "Error test",
ai_model: "invalid-model-that-will-trigger-api-error"
))
response = @openai.chat_response("Test", model: "invalid-model-that-will-trigger-api-error")
assert_not response.success?
assert_kind_of Provider::Openai::Error, response.error
@ -24,19 +19,14 @@ class Provider::OpenaiTest < ActiveSupport::TestCase
test "basic chat response" do
VCR.use_cassette("openai/chat/basic_response") do
message = @chat.messages.create!(
type: "UserMessage",
content: "This is a chat test. If it's working, respond with a single word: Yes",
ai_model: @subject_model
response = @subject.chat_response(
"This is a chat test. If it's working, respond with a single word: Yes",
model: @subject_model
)
response = @subject.chat_response(message)
assert response.success?
assert_equal 1, response.data.size
assert response.data.first.final?
assert_equal 1, response.data.first.messages.size
assert_includes response.data.first.messages.first.content, "Yes"
assert_equal 1, response.data.messages.size
assert_includes response.data.messages.first.output_text, "Yes"
end
end
@ -44,89 +34,120 @@ class Provider::OpenaiTest < ActiveSupport::TestCase
VCR.use_cassette("openai/chat/basic_streaming_response") do
collected_chunks = []
mock_subscriber = proc do |chunk|
mock_streamer = proc do |chunk|
collected_chunks << chunk
end
message = @chat.messages.create!(
type: "UserMessage",
content: "This is a chat test. If it's working, respond with a single word: Yes",
ai_model: @subject_model
@subject.chat_response(
"This is a chat test. If it's working, respond with a single word: Yes",
model: @subject_model,
streamer: mock_streamer
)
@subject.chat_response(message, stream_subscriber: mock_subscriber)
tool_call_chunks = collected_chunks.select { |chunk| chunk.provider_type == "function_request" }
text_chunks = collected_chunks.select { |chunk| chunk.provider_type == "output_text" }
response_chunks = collected_chunks.select { |chunk| chunk.provider_type == "response" }
text_chunks = collected_chunks.select { |chunk| chunk.type == "output_text" }
response_chunks = collected_chunks.select { |chunk| chunk.type == "response" }
assert_equal 1, text_chunks.size
assert_equal 1, response_chunks.size
assert_equal 0, tool_call_chunks.size
assert_equal "Yes", text_chunks.first.data
assert_equal "Yes", response_chunks.first.data.messages.first.content
assert_equal "Yes", response_chunks.first.data.messages.first.output_text
end
end
test "chat response with tool calls" do
VCR.use_cassette("openai/chat/tool_calls") do
response = @subject.chat_response(
tool_call_message,
test "chat response with function calls" do
VCR.use_cassette("openai/chat/function_calls") do
first_response = @subject.chat_response(
"What is my net worth?",
model: @subject_model,
instructions: "Use the tools available to you to answer the user's question.",
available_functions: [ PredictableToolFunction.new(@chat) ]
functions: [ PredictableToolFunction.new.to_h ]
)
# Two responses: one for function requests, one follow-up for text output
assert response.success?
assert_equal 2, response.data.size
assert first_response.success?
# First response has function requests / results
assert_not response.data.first.final?
assert_equal 1, response.data.first.function_calls.size
function_request = first_response.data.function_requests.first
# Second response has text output that uses the function results
assert response.data.last.final?
assert_equal 0, response.data.last.function_calls.size
assert_equal 1, response.data.last.messages.size
assert_includes response.data.last.messages.first.content, PredictableToolFunction.expected_test_result
assert function_request.present?
second_response = @subject.chat_response(
"What is my net worth?",
model: @subject_model,
function_results: [
{
provider_id: function_request.id,
provider_call_id: function_request.call_id,
name: function_request.function_name,
arguments: function_request.function_args,
result: PredictableToolFunction.expected_test_result
}
],
previous_response_id: first_response.data.id
)
assert second_response.success?
assert_equal 1, second_response.data.messages.size
assert_includes second_response.data.messages.first.output_text, PredictableToolFunction.expected_test_result
end
end
test "streams chat response with tool calls" do
VCR.use_cassette("openai/chat/streaming_tool_calls") do
VCR.use_cassette("openai/chat/streaming_tool_calls", record: :all) do
collected_chunks = []
mock_streamer = proc do |chunk|
collected_chunks << chunk
end
# Call #1: First streaming call, will return a function request
@subject.chat_response(
tool_call_message,
"What is my net worth?",
model: @subject_model,
instructions: "Use the tools available to you to answer the user's question.",
available_functions: [ PredictableToolFunction.new(@chat) ],
functions: [ PredictableToolFunction.new.to_h ],
streamer: mock_streamer
)
text_chunks = collected_chunks.select { |chunk| chunk.provider_type == "output_text" }
tool_call_chunks = collected_chunks.select { |chunk| chunk.provider_type == "function_request" }
response_chunks = collected_chunks.select { |chunk| chunk.provider_type == "response" }
text_chunks = collected_chunks.select { |chunk| chunk.type == "output_text" }
response_chunks = collected_chunks.select { |chunk| chunk.type == "response" }
assert_equal 1, tool_call_chunks.count
assert text_chunks.count >= 1
assert_equal 2, response_chunks.count
assert_equal 0, text_chunks.size
assert_equal 1, response_chunks.size
assert_not response_chunks.first.data.final?
assert response_chunks.last.data.final?
assert_includes response_chunks.last.data.messages.first.content, PredictableToolFunction.expected_test_result
first_response = response_chunks.first.data
function_request = first_response.function_requests.first
# Reset collected chunks
collected_chunks = []
# Call #2: Second streaming call, will return a function result
@subject.chat_response(
"What is my net worth?",
model: @subject_model,
function_results: [
{
provider_id: function_request.id,
provider_call_id: function_request.call_id,
name: function_request.function_name,
arguments: function_request.function_args,
result: PredictableToolFunction.expected_test_result
}
],
previous_response_id: first_response.id,
streamer: mock_streamer
)
text_chunks = collected_chunks.select { |chunk| chunk.type == "output_text" }
response_chunks = collected_chunks.select { |chunk| chunk.type == "response" }
assert text_chunks.size >= 1
assert_equal 1, response_chunks.size
assert_includes response_chunks.first.data.messages.first.output_text, PredictableToolFunction.expected_test_result
end
end
private
def tool_call_message
UserMessage.new(chat: @chat, content: "What is my net worth?", ai_model: @subject_model)
end
class PredictableToolFunction < Assistant::Function
class PredictableToolFunction
class << self
def expected_test_result
"$124,200"
@ -144,5 +165,19 @@ class Provider::OpenaiTest < ActiveSupport::TestCase
def call(params = {})
self.class.expected_test_result
end
def to_h
{
name: self.class.name,
description: self.class.description,
params_schema: {
type: "object",
properties: {},
required: [],
additionalProperties: false
},
strict: true
}
end
end
end

View file

@ -24,7 +24,7 @@ http_interactions:
message: OK
headers:
Date:
- Fri, 28 Mar 2025 14:23:22 GMT
- Fri, 28 Mar 2025 23:39:00 GMT
Content-Type:
- application/json
Transfer-Encoding:
@ -36,34 +36,34 @@ http_interactions:
Openai-Organization:
- "<OPENAI_ORGANIZATION_ID>"
X-Request-Id:
- req_13900312235c86dca9983c43f884612f
- req_689cf45740d3775a003632347b9a99dd
Openai-Processing-Ms:
- '1103'
- '783'
Strict-Transport-Security:
- max-age=31536000; includeSubDomains; preload
Cf-Cache-Status:
- DYNAMIC
Set-Cookie:
- __cf_bm=ZxtRGPPVT3H1qcGwlqfVjC13JJboKjEOkFsJoUfcduA-1743171802-1.0.1.1-PKolgwX6T_lqh6cFQXy9f3CPACskAir7Sfyt1ZNEKIHPDz3Ehn7lNILDASLxhBRmYBDKTMQqaUeyvSolvp1U00OhqfgSr51HxKIZNeEDglg;
path=/; expires=Fri, 28-Mar-25 14:53:22 GMT; domain=.api.openai.com; HttpOnly;
- __cf_bm=dxhkvZmDt5CfO7l2sGWpb8NwK.mPMPhQk2s4iFSZ8L4-1743205140-1.0.1.1-KJ6xz1oZ.qGlgSe.OAhABVxRSZDurVEDB4iFjzkrzEPT_cieb1YukIYJ_SK4hd_K6OrU2GgO9cn.1rTOUQLZdmzuS1GqRWn44is2Q8QdzZw;
path=/; expires=Sat, 29-Mar-25 00:09:00 GMT; domain=.api.openai.com; HttpOnly;
Secure; SameSite=None
- _cfuvid=.uHFzkeaG4pJ9kcwsDW9PIfdKQgoEAz4Voe6QjxyH7E-1743171802602-0.0.1.1-604800000;
- _cfuvid=LVN78sd.dSrLtZPVzcO8KZ9oDBKuC3_qGMfcWvwWsbY-1743205140700-0.0.1.1-604800000;
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
X-Content-Type-Options:
- nosniff
Server:
- cloudflare
Cf-Ray:
- 9277c8eafdbe10c3-ORD
- 927af6dbba55cf77-CMH
Alt-Svc:
- h3=":443"; ma=86400
body:
encoding: ASCII-8BIT
string: |-
{
"id": "resp_67e6b0d97d34819296bd4e0d24c6f3db00ff3778b60aa4aa",
"id": "resp_67e73313e5ac8192b922490a56ce01e70bdc541b107b1aea",
"object": "response",
"created_at": 1743171801,
"created_at": 1743205139,
"status": "completed",
"error": null,
"incomplete_details": null,
@ -73,7 +73,7 @@ http_interactions:
"output": [
{
"type": "message",
"id": "msg_67e6b0da49b48192a610e3f3493f056600ff3778b60aa4aa",
"id": "msg_67e73314588881928506df6ae0995e700bdc541b107b1aea",
"status": "completed",
"role": "assistant",
"content": [
@ -103,7 +103,7 @@ http_interactions:
"top_p": 1.0,
"truncation": "disabled",
"usage": {
"input_tokens": 43,
"input_tokens": 25,
"input_tokens_details": {
"cached_tokens": 0
},
@ -111,10 +111,10 @@ http_interactions:
"output_tokens_details": {
"reasoning_tokens": 0
},
"total_tokens": 45
"total_tokens": 27
},
"user": null,
"metadata": {}
}
recorded_at: Fri, 28 Mar 2025 14:23:22 GMT
recorded_at: Fri, 28 Mar 2025 23:39:00 GMT
recorded_with: VCR 6.3.1

View file

@ -24,7 +24,7 @@ http_interactions:
message: OK
headers:
Date:
- Fri, 28 Mar 2025 15:39:24 GMT
- Fri, 28 Mar 2025 23:38:59 GMT
Content-Type:
- text/event-stream; charset=utf-8
Transfer-Encoding:
@ -36,57 +36,57 @@ http_interactions:
Openai-Organization:
- "<OPENAI_ORGANIZATION_ID>"
X-Request-Id:
- req_d322d0e3734ad9d7556c6acb446fc5f0
- req_052d0a691b0e031851c4d3259a02d240
Openai-Processing-Ms:
- '108'
- '182'
Strict-Transport-Security:
- max-age=31536000; includeSubDomains; preload
Cf-Cache-Status:
- DYNAMIC
Set-Cookie:
- __cf_bm=i3l062va7vbmU7I3NufOoYNcofDavIJwJDRXwQ0CXck-1743176364-1.0.1.1-BWKA2yUjk0GI0pHrKSQ0eaTFa6Ysu5ysjy__ArpQaO1b3LEMatIliQ6rQEMN6M_eH7XfbV.nokO3hqCjRcg9yPgzKLjbQ3hpRcvQwMWObCE;
path=/; expires=Fri, 28-Mar-25 16:09:24 GMT; domain=.api.openai.com; HttpOnly;
- __cf_bm=YtPVnUeLdKYDtnmKDmgjZqr4sv2ZB5xVj_XbYgpG4X4-1743205139-1.0.1.1-OERpBfzzhUctMtyx6RnJBUiSH2R.iW0Kl7GL5IYUuL8Mz3J1sVPVkLWQnNb0NUjEi1a247UUAJzGTJp1Np07nxSUEMEmfIRj2wqQENwoxg8;
path=/; expires=Sat, 29-Mar-25 00:08:59 GMT; domain=.api.openai.com; HttpOnly;
Secure; SameSite=None
- _cfuvid=1VMIq2Dlu_MQEWybPb9LkaURnoyi7_O2ueZQyKKUGss-1743176364050-0.0.1.1-604800000;
- _cfuvid=KzP7deBboQLeJCUnhcX2p2DrFANiz7VPWoHgBXdtf4M-1743205139131-0.0.1.1-604800000;
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
X-Content-Type-Options:
- nosniff
Server:
- cloudflare
Cf-Ray:
- 9278384d09ec0042-ORD
- 927af6d5b9651267-ORD
Alt-Svc:
- h3=":443"; ma=86400
body:
encoding: UTF-8
string: |+
event: response.created
data: {"type":"response.created","response":{"id":"resp_67e6c2abe9188192aad5b26bece9136f0e544b3cddf93be3","object":"response","created_at":1743176363,"status":"in_progress","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
data: {"type":"response.created","response":{"id":"resp_67e73312ebbc819296653e382c38b2de001b591cdf0f77e0","object":"response","created_at":1743205138,"status":"in_progress","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
event: response.in_progress
data: {"type":"response.in_progress","response":{"id":"resp_67e6c2abe9188192aad5b26bece9136f0e544b3cddf93be3","object":"response","created_at":1743176363,"status":"in_progress","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
data: {"type":"response.in_progress","response":{"id":"resp_67e73312ebbc819296653e382c38b2de001b591cdf0f77e0","object":"response","created_at":1743205138,"status":"in_progress","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
event: response.output_item.added
data: {"type":"response.output_item.added","output_index":0,"item":{"type":"message","id":"msg_67e6c2ac6df08192977335b57cb9e93b0e544b3cddf93be3","status":"in_progress","role":"assistant","content":[]}}
data: {"type":"response.output_item.added","output_index":0,"item":{"type":"message","id":"msg_67e73313805881929538dfdbc02be779001b591cdf0f77e0","status":"in_progress","role":"assistant","content":[]}}
event: response.content_part.added
data: {"type":"response.content_part.added","item_id":"msg_67e6c2ac6df08192977335b57cb9e93b0e544b3cddf93be3","output_index":0,"content_index":0,"part":{"type":"output_text","text":"","annotations":[]}}
data: {"type":"response.content_part.added","item_id":"msg_67e73313805881929538dfdbc02be779001b591cdf0f77e0","output_index":0,"content_index":0,"part":{"type":"output_text","text":"","annotations":[]}}
event: response.output_text.delta
data: {"type":"response.output_text.delta","item_id":"msg_67e6c2ac6df08192977335b57cb9e93b0e544b3cddf93be3","output_index":0,"content_index":0,"delta":"Yes"}
data: {"type":"response.output_text.delta","item_id":"msg_67e73313805881929538dfdbc02be779001b591cdf0f77e0","output_index":0,"content_index":0,"delta":"Yes"}
event: response.output_text.done
data: {"type":"response.output_text.done","item_id":"msg_67e6c2ac6df08192977335b57cb9e93b0e544b3cddf93be3","output_index":0,"content_index":0,"text":"Yes"}
data: {"type":"response.output_text.done","item_id":"msg_67e73313805881929538dfdbc02be779001b591cdf0f77e0","output_index":0,"content_index":0,"text":"Yes"}
event: response.content_part.done
data: {"type":"response.content_part.done","item_id":"msg_67e6c2ac6df08192977335b57cb9e93b0e544b3cddf93be3","output_index":0,"content_index":0,"part":{"type":"output_text","text":"Yes","annotations":[]}}
data: {"type":"response.content_part.done","item_id":"msg_67e73313805881929538dfdbc02be779001b591cdf0f77e0","output_index":0,"content_index":0,"part":{"type":"output_text","text":"Yes","annotations":[]}}
event: response.output_item.done
data: {"type":"response.output_item.done","output_index":0,"item":{"type":"message","id":"msg_67e6c2ac6df08192977335b57cb9e93b0e544b3cddf93be3","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Yes","annotations":[]}]}}
data: {"type":"response.output_item.done","output_index":0,"item":{"type":"message","id":"msg_67e73313805881929538dfdbc02be779001b591cdf0f77e0","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Yes","annotations":[]}]}}
event: response.completed
data: {"type":"response.completed","response":{"id":"resp_67e6c2abe9188192aad5b26bece9136f0e544b3cddf93be3","object":"response","created_at":1743176363,"status":"completed","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[{"type":"message","id":"msg_67e6c2ac6df08192977335b57cb9e93b0e544b3cddf93be3","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Yes","annotations":[]}]}],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":43,"input_tokens_details":{"cached_tokens":0},"output_tokens":2,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":45},"user":null,"metadata":{}}}
data: {"type":"response.completed","response":{"id":"resp_67e73312ebbc819296653e382c38b2de001b591cdf0f77e0","object":"response","created_at":1743205138,"status":"completed","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[{"type":"message","id":"msg_67e73313805881929538dfdbc02be779001b591cdf0f77e0","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Yes","annotations":[]}]}],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":25,"input_tokens_details":{"cached_tokens":0},"output_tokens":2,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":27},"user":null,"metadata":{}}}
recorded_at: Fri, 28 Mar 2025 15:39:24 GMT
recorded_at: Fri, 28 Mar 2025 23:38:59 GMT
recorded_with: VCR 6.3.1
...

View file

@ -5,8 +5,7 @@ http_interactions:
uri: https://api.openai.com/v1/responses
body:
encoding: UTF-8
string: '{"model":"invalid-model-that-will-trigger-api-error","input":[{"role":"user","content":"Error
test"}],"instructions":null,"tools":[],"previous_response_id":null,"stream":true}'
string: '{"model":"invalid-model-that-will-trigger-api-error","input":[{"role":"user","content":"Test"}],"instructions":null,"tools":[],"previous_response_id":null,"stream":null}'
headers:
Content-Type:
- application/json
@ -24,7 +23,7 @@ http_interactions:
message: Bad Request
headers:
Date:
- Wed, 26 Mar 2025 21:27:19 GMT
- Fri, 28 Mar 2025 23:39:02 GMT
Content-Type:
- application/json
Content-Length:
@ -36,25 +35,25 @@ http_interactions:
Openai-Organization:
- "<OPENAI_ORGANIZATION_ID>"
X-Request-Id:
- req_2b86e02f664e790dfa475f111402b722
- req_9c80c15dd6b50d198b621a05e3dd3c9d
Openai-Processing-Ms:
- '146'
- '115'
Strict-Transport-Security:
- max-age=31536000; includeSubDomains; preload
Cf-Cache-Status:
- DYNAMIC
Set-Cookie:
- __cf_bm=gAU0gS_ZQBfQmFkc_jKM73dhkNISbBY9FlQjGnZ6CfU-1743024439-1.0.1.1-bWRoC737.SOJPZrP90wTJLVmelTpxFqIsrunq2Lqgy4J3VvLtYBEBrqY0v4d94F5fMcm0Ju.TfQi0etmvqZtUSMRn6rvkMLmXexRcxP.1jE;
path=/; expires=Wed, 26-Mar-25 21:57:19 GMT; domain=.api.openai.com; HttpOnly;
- __cf_bm=w8NWB2SOQcLDDgXm2hVuP3Ik71FMhI28xRfzC9U4SAo-1743205142-1.0.1.1-lDe_WqVCTDI1eF7W2.8tS6ErxBo1kX6lUjoMZh1fnpUzr.fyLJfLsFqiU31FuoYrqX1YOCLF6qUlUttZ5iZbuPSO5wPLkbNIMVVgSFG8flI;
path=/; expires=Sat, 29-Mar-25 00:09:02 GMT; domain=.api.openai.com; HttpOnly;
Secure; SameSite=None
- _cfuvid=XnxX4KU80himuKAUavZYtkQasOjXJDJD.QLyMrfBSUU-1743024439792-0.0.1.1-604800000;
- _cfuvid=VQL2pQzIck2z8GzmzR3ZFHfkya6Cd2TO82aGFDZDOBs-1743205142788-0.0.1.1-604800000;
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
X-Content-Type-Options:
- nosniff
Server:
- cloudflare
Cf-Ray:
- 9269bb3b2c14cf74-CMH
- 927af6ed3b7f1050-ORD
Alt-Svc:
- h3=":443"; ma=86400
body:
@ -68,5 +67,5 @@ http_interactions:
"code": "model_not_found"
}
}
recorded_at: Wed, 26 Mar 2025 21:27:19 GMT
recorded_at: Fri, 28 Mar 2025 23:39:03 GMT
recorded_with: VCR 6.3.1

View file

@ -26,7 +26,7 @@ http_interactions:
message: OK
headers:
Date:
- Fri, 28 Mar 2025 14:26:28 GMT
- Fri, 28 Mar 2025 23:39:03 GMT
Content-Type:
- application/json
Transfer-Encoding:
@ -38,34 +38,34 @@ http_interactions:
Openai-Organization:
- "<OPENAI_ORGANIZATION_ID>"
X-Request-Id:
- req_a248d37b03c551b1c46bd378bb1222df
- req_acb002a07726b73124003bc11961db12
Openai-Processing-Ms:
- '844'
- '692'
Strict-Transport-Security:
- max-age=31536000; includeSubDomains; preload
Cf-Cache-Status:
- DYNAMIC
Set-Cookie:
- __cf_bm=z02SQd3cf0pSyMSllLTxVBBxPnoCRo.246XvQI3uWt8-1743171988-1.0.1.1-hR7THce0m_rGv7n1VCoCEziHmALE_MlWvIn6g3U70rjidYTqMkk4sui43cwZcBowvzGu51QGYgqGxYcNujkCU7otQh.6rJ7xwhluERZ1dVQ;
path=/; expires=Fri, 28-Mar-25 14:56:28 GMT; domain=.api.openai.com; HttpOnly;
- __cf_bm=yktQTGvoMAowiz7E3sLQgydW3Cy6tmHY_KGgLVGm.iE-1743205143-1.0.1.1-XGhvweZhPNRuqFMRcaIvMOyVb.Z1VOf4AtZmc4gPTArM1sU4T3mya2c0QwixjuCSJYuw2BwmWIKnZrDe_xdx6OtV6HQfwB1xASqg79FI6Bw;
path=/; expires=Sat, 29-Mar-25 00:09:03 GMT; domain=.api.openai.com; HttpOnly;
Secure; SameSite=None
- _cfuvid=uydeMYssjSrN96Tp7VCbfJ_0P.t29RCD.hgjMqpo4Ys-1743171988305-0.0.1.1-604800000;
- _cfuvid=I23nR.I1jT11eBu6591kDu2RxoXpHGpOn27Syvx7Zr8-1743205143976-0.0.1.1-604800000;
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
X-Content-Type-Options:
- nosniff
Server:
- cloudflare
Cf-Ray:
- 9277cd78fa721167-ORD
- 927af6f0ef5ccf7c-CMH
Alt-Svc:
- h3=":443"; ma=86400
body:
encoding: ASCII-8BIT
string: |-
{
"id": "resp_67e6b19371d08192912d64ea220597a40a63c04976d80348",
"id": "resp_67e733174818819294a51c6bc4e0814c08d69b77f6076b69",
"object": "response",
"created_at": 1743171987,
"created_at": 1743205143,
"status": "completed",
"error": null,
"incomplete_details": null,
@ -75,8 +75,8 @@ http_interactions:
"output": [
{
"type": "function_call",
"id": "fc_67e6b19421dc8192bea1cbade015ebf60a63c04976d80348",
"call_id": "call_nSDlhJck6mchpjJ7YtjRLPJ3",
"id": "fc_67e73317d104819287a21542e2484a4708d69b77f6076b69",
"call_id": "call_IoG6NAK8MNIoY6x9bzfHnpp6",
"name": "get_net_worth",
"arguments": "{}",
"status": "completed"
@ -113,7 +113,7 @@ http_interactions:
"top_p": 1.0,
"truncation": "disabled",
"usage": {
"input_tokens": 271,
"input_tokens": 55,
"input_tokens_details": {
"cached_tokens": 0
},
@ -121,21 +121,19 @@ http_interactions:
"output_tokens_details": {
"reasoning_tokens": 0
},
"total_tokens": 284
"total_tokens": 68
},
"user": null,
"metadata": {}
}
recorded_at: Fri, 28 Mar 2025 14:26:28 GMT
recorded_at: Fri, 28 Mar 2025 23:39:03 GMT
- request:
method: post
uri: https://api.openai.com/v1/responses
body:
encoding: UTF-8
string: '{"model":"gpt-4o","input":[{"role":"user","content":"What is my net
worth?"},{"type":"function_call_output","call_id":"call_nSDlhJck6mchpjJ7YtjRLPJ3","output":"\"$124,200\""}],"instructions":"Use
the tools available to you to answer the user''s question.","tools":[{"type":"function","name":"get_net_worth","description":"Gets
user net worth data","parameters":{"type":"object","properties":{},"required":[],"additionalProperties":false},"strict":true}],"previous_response_id":"resp_67e6b19371d08192912d64ea220597a40a63c04976d80348","stream":null}'
worth?"},{"type":"function_call_output","call_id":"call_IoG6NAK8MNIoY6x9bzfHnpp6","output":"\"$124,200\""}],"instructions":null,"tools":[],"previous_response_id":"resp_67e733174818819294a51c6bc4e0814c08d69b77f6076b69","stream":null}'
headers:
Content-Type:
- application/json
@ -153,7 +151,7 @@ http_interactions:
message: OK
headers:
Date:
- Fri, 28 Mar 2025 14:26:29 GMT
- Fri, 28 Mar 2025 23:39:04 GMT
Content-Type:
- application/json
Transfer-Encoding:
@ -165,44 +163,44 @@ http_interactions:
Openai-Organization:
- "<OPENAI_ORGANIZATION_ID>"
X-Request-Id:
- req_f98ef29da61f92624043f8811022723f
- req_107c55eac5d356ea6a092e179644be74
Openai-Processing-Ms:
- '955'
- '666'
Strict-Transport-Security:
- max-age=31536000; includeSubDomains; preload
Cf-Cache-Status:
- DYNAMIC
Set-Cookie:
- __cf_bm=c6fqCfvVVdaYCZkLcuE.7OouNNV80j6MO8EU00mTjrY-1743171989-1.0.1.1-ktPAaO3lTpJTpMCzUjPnsJmCc.30YWDEi4.yrCjvrrIULg.ipK29VdpexmtH_jo87DlQ1kndA3INl_gyhCra_zJYb0nJkfJD9vXkA6oHG3A;
path=/; expires=Fri, 28-Mar-25 14:56:29 GMT; domain=.api.openai.com; HttpOnly;
- __cf_bm=l1y3jPeCKUdL4YW9VR8SZAYbPJygY.O5iv8GEmHYyo0-1743205144-1.0.1.1-tuO_26bpHCwjp40gloE4Pu.Pi6wN7K9yV5rFTNDF.PhDjBb8N6TW5POC9qEhbSWWLzNV3nYn.U0E8ft3iXTOMX7i3mXGJOVb1t7TK6T5rVo;
path=/; expires=Sat, 29-Mar-25 00:09:04 GMT; domain=.api.openai.com; HttpOnly;
Secure; SameSite=None
- _cfuvid=IZ3AyFlt2EHqyn4B4VQp_xuendIynQkbNd1EvOcjBIg-1743171989763-0.0.1.1-604800000;
- _cfuvid=Vv42lFdIhJxtY593j4tNCHE5WmPd8d3kwT3Fe.CRYwU-1743205144880-0.0.1.1-604800000;
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
X-Content-Type-Options:
- nosniff
Server:
- cloudflare
Cf-Ray:
- 9277cd7fba29e82d-ORD
- 927af6f6affe114d-ORD
Alt-Svc:
- h3=":443"; ma=86400
body:
encoding: ASCII-8BIT
string: |-
{
"id": "resp_67e6b194cca08192af11a393c165ab300a63c04976d80348",
"id": "resp_67e733182f5c8192917aa9ffaf3f26e508d69b77f6076b69",
"object": "response",
"created_at": 1743171988,
"created_at": 1743205144,
"status": "completed",
"error": null,
"incomplete_details": null,
"instructions": "Use the tools available to you to answer the user's question.",
"instructions": null,
"max_output_tokens": null,
"model": "gpt-4o-2024-08-06",
"output": [
{
"type": "message",
"id": "msg_67e6b1957b5081928709cedc2b7d3f110a63c04976d80348",
"id": "msg_67e73318a7448192b0cc40fd88d9881408d69b77f6076b69",
"status": "completed",
"role": "assistant",
"content": [
@ -215,7 +213,7 @@ http_interactions:
}
],
"parallel_tool_calls": true,
"previous_response_id": "resp_67e6b19371d08192912d64ea220597a40a63c04976d80348",
"previous_response_id": "resp_67e733174818819294a51c6bc4e0814c08d69b77f6076b69",
"reasoning": {
"effort": null,
"generate_summary": null
@ -228,35 +226,22 @@ http_interactions:
}
},
"tool_choice": "auto",
"tools": [
{
"type": "function",
"description": "Gets user net worth data",
"name": "get_net_worth",
"parameters": {
"type": "object",
"properties": {},
"required": [],
"additionalProperties": false
},
"strict": true
}
],
"tools": [],
"top_p": 1.0,
"truncation": "disabled",
"usage": {
"input_tokens": 309,
"input_tokens": 51,
"input_tokens_details": {
"cached_tokens": 0
},
"output_tokens": 11,
"output_tokens": 10,
"output_tokens_details": {
"reasoning_tokens": 0
},
"total_tokens": 320
"total_tokens": 61
},
"user": null,
"metadata": {}
}
recorded_at: Fri, 28 Mar 2025 14:26:29 GMT
recorded_at: Fri, 28 Mar 2025 23:39:04 GMT
recorded_with: VCR 6.3.1

View file

@ -26,7 +26,7 @@ http_interactions:
message: OK
headers:
Date:
- Fri, 28 Mar 2025 16:00:21 GMT
- Fri, 28 Mar 2025 23:39:20 GMT
Content-Type:
- text/event-stream; charset=utf-8
Transfer-Encoding:
@ -38,51 +38,163 @@ http_interactions:
Openai-Organization:
- "<OPENAI_ORGANIZATION_ID>"
X-Request-Id:
- req_ad078d9f7585eeca17c02cefb4c42180
- req_416a3bb3593376c1829980cc11557c9e
Openai-Processing-Ms:
- '148'
- '171'
Strict-Transport-Security:
- max-age=31536000; includeSubDomains; preload
Cf-Cache-Status:
- DYNAMIC
Set-Cookie:
- __cf_bm=DeYZEoQ8_t7.BWV67SmSSxrDr9sFE5nnkoANG7Nlg9E-1743177621-1.0.1.1-ymQrM3gryBLo9KRlSh4lzlyMPwqDX1SeHkwfiWOKaNct.cKs.WBfgURo.mAmK14ZjlbbuwfPOf7FShuzpS2Irud6C3woK9juoi2rOtdcYGo;
path=/; expires=Fri, 28-Mar-25 16:30:21 GMT; domain=.api.openai.com; HttpOnly;
- __cf_bm=2mv3jCpb0SZRXFvlWu28X1mr3Oa6z9QgwtmcclI9J_g-1743205160-1.0.1.1-1P22aYvtQqY_byLJMPyJEYff2m.rYivVXc313sCETck2g4NIg66SHPLTkjOiyqHBYMyifOJ_EVXNFK3QeEDYlPbvB9OzNr_Vo.S.UqPYpJI;
path=/; expires=Sat, 29-Mar-25 00:09:20 GMT; domain=.api.openai.com; HttpOnly;
Secure; SameSite=None
- _cfuvid=WpIK2gkR1WKCUZWHMZKlTwVW73ibegrhn1ZhIpdswe0-1743177621976-0.0.1.1-604800000;
- _cfuvid=KTcsmNHnsQWuGiwS1hyyOm7vtycPv3d6yh6pOLElMAg-1743205160250-0.0.1.1-604800000;
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
X-Content-Type-Options:
- nosniff
Server:
- cloudflare
Cf-Ray:
- 92785706590bcf4e-CMH
- 927af7582c5ffa19-ORD
Alt-Svc:
- h3=":443"; ma=86400
body:
encoding: UTF-8
string: |+
event: response.created
data: {"type":"response.created","response":{"id":"resp_67e6c795ca8c8192b015934c18b8abe602f810c3e60dc7d6","object":"response","created_at":1743177621,"status":"in_progress","error":null,"incomplete_details":null,"instructions":"Use the tools available to you to answer the user's question.","max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[{"type":"function","description":"Gets user net worth data","name":"get_net_worth","parameters":{"type":"object","properties":{},"required":[],"additionalProperties":false},"strict":true}],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
data: {"type":"response.created","response":{"id":"resp_67e73328128881928023b1fa925c2bcc0c494b972720dd48","object":"response","created_at":1743205160,"status":"in_progress","error":null,"incomplete_details":null,"instructions":"Use the tools available to you to answer the user's question.","max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[{"type":"function","description":"Gets user net worth data","name":"get_net_worth","parameters":{"type":"object","properties":{},"required":[],"additionalProperties":false},"strict":true}],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
event: response.in_progress
data: {"type":"response.in_progress","response":{"id":"resp_67e6c795ca8c8192b015934c18b8abe602f810c3e60dc7d6","object":"response","created_at":1743177621,"status":"in_progress","error":null,"incomplete_details":null,"instructions":"Use the tools available to you to answer the user's question.","max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[{"type":"function","description":"Gets user net worth data","name":"get_net_worth","parameters":{"type":"object","properties":{},"required":[],"additionalProperties":false},"strict":true}],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
data: {"type":"response.in_progress","response":{"id":"resp_67e73328128881928023b1fa925c2bcc0c494b972720dd48","object":"response","created_at":1743205160,"status":"in_progress","error":null,"incomplete_details":null,"instructions":"Use the tools available to you to answer the user's question.","max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[{"type":"function","description":"Gets user net worth data","name":"get_net_worth","parameters":{"type":"object","properties":{},"required":[],"additionalProperties":false},"strict":true}],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
event: response.output_item.added
data: {"type":"response.output_item.added","output_index":0,"item":{"type":"function_call","id":"fc_67e6c796cbdc81928207d8649a4da80a02f810c3e60dc7d6","call_id":"call_ZpaYGc3RGRfles9vnoFgVQ1m","name":"get_net_worth","arguments":"","status":"in_progress"}}
data: {"type":"response.output_item.added","output_index":0,"item":{"type":"function_call","id":"fc_67e73329fa348192b5b5dafb6c2f018e0c494b972720dd48","call_id":"call_vZ9Poyn4ZFtvYwQOeTGFAUSU","name":"get_net_worth","arguments":"","status":"in_progress"}}
event: response.function_call_arguments.delta
data: {"type":"response.function_call_arguments.delta","item_id":"fc_67e6c796cbdc81928207d8649a4da80a02f810c3e60dc7d6","output_index":0,"delta":"{}"}
data: {"type":"response.function_call_arguments.delta","item_id":"fc_67e73329fa348192b5b5dafb6c2f018e0c494b972720dd48","output_index":0,"delta":"{}"}
event: response.function_call_arguments.done
data: {"type":"response.function_call_arguments.done","item_id":"fc_67e6c796cbdc81928207d8649a4da80a02f810c3e60dc7d6","output_index":0,"arguments":"{}"}
data: {"type":"response.function_call_arguments.done","item_id":"fc_67e73329fa348192b5b5dafb6c2f018e0c494b972720dd48","output_index":0,"arguments":"{}"}
event: response.output_item.done
data: {"type":"response.output_item.done","output_index":0,"item":{"type":"function_call","id":"fc_67e6c796cbdc81928207d8649a4da80a02f810c3e60dc7d6","call_id":"call_ZpaYGc3RGRfles9vnoFgVQ1m","name":"get_net_worth","arguments":"{}","status":"completed"}}
data: {"type":"response.output_item.done","output_index":0,"item":{"type":"function_call","id":"fc_67e73329fa348192b5b5dafb6c2f018e0c494b972720dd48","call_id":"call_vZ9Poyn4ZFtvYwQOeTGFAUSU","name":"get_net_worth","arguments":"{}","status":"completed"}}
event: response.completed
data: {"type":"response.completed","response":{"id":"resp_67e6c795ca8c8192b015934c18b8abe602f810c3e60dc7d6","object":"response","created_at":1743177621,"status":"completed","error":null,"incomplete_details":null,"instructions":"Use the tools available to you to answer the user's question.","max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[{"type":"function_call","id":"fc_67e6c796cbdc81928207d8649a4da80a02f810c3e60dc7d6","call_id":"call_ZpaYGc3RGRfles9vnoFgVQ1m","name":"get_net_worth","arguments":"{}","status":"completed"}],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[{"type":"function","description":"Gets user net worth data","name":"get_net_worth","parameters":{"type":"object","properties":{},"required":[],"additionalProperties":false},"strict":true}],"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":271,"input_tokens_details":{"cached_tokens":0},"output_tokens":13,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":284},"user":null,"metadata":{}}}
data: {"type":"response.completed","response":{"id":"resp_67e73328128881928023b1fa925c2bcc0c494b972720dd48","object":"response","created_at":1743205160,"status":"completed","error":null,"incomplete_details":null,"instructions":"Use the tools available to you to answer the user's question.","max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[{"type":"function_call","id":"fc_67e73329fa348192b5b5dafb6c2f018e0c494b972720dd48","call_id":"call_vZ9Poyn4ZFtvYwQOeTGFAUSU","name":"get_net_worth","arguments":"{}","status":"completed"}],"parallel_tool_calls":true,"previous_response_id":null,"reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[{"type":"function","description":"Gets user net worth data","name":"get_net_worth","parameters":{"type":"object","properties":{},"required":[],"additionalProperties":false},"strict":true}],"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":55,"input_tokens_details":{"cached_tokens":0},"output_tokens":13,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":68},"user":null,"metadata":{}}}
recorded_at: Fri, 28 Mar 2025 16:00:23 GMT
recorded_at: Fri, 28 Mar 2025 23:39:22 GMT
- request:
method: post
uri: https://api.openai.com/v1/responses
body:
encoding: UTF-8
string: '{"model":"gpt-4o","input":[{"role":"user","content":"What is my net
worth?"},{"type":"function_call_output","call_id":"call_vZ9Poyn4ZFtvYwQOeTGFAUSU","output":"\"$124,200\""}],"instructions":null,"tools":[],"previous_response_id":"resp_67e73328128881928023b1fa925c2bcc0c494b972720dd48","stream":true}'
headers:
Content-Type:
- application/json
Authorization:
- Bearer <OPENAI_ACCESS_TOKEN>
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Date:
- Fri, 28 Mar 2025 23:39:22 GMT
Content-Type:
- text/event-stream; charset=utf-8
Transfer-Encoding:
- chunked
Connection:
- keep-alive
Openai-Version:
- '2020-10-01'
Openai-Organization:
- "<OPENAI_ORGANIZATION_ID>"
X-Request-Id:
- req_96db0e490c091fd28d3849cb2b7494dd
Openai-Processing-Ms:
- '127'
Strict-Transport-Security:
- max-age=31536000; includeSubDomains; preload
Cf-Cache-Status:
- DYNAMIC
Set-Cookie:
- __cf_bm=uCEzdEuc0NlONCs9_aE4Zlk_.gTSlFJ8f1Wih1A8C.4-1743205162-1.0.1.1-3O16QsxbyafPXR1z4aXLAf.s9MlH8j1NF_DLrC.5MvWO3j6c7X2Xao1ro6jiM8QSE62d5TnzfnWaqz.HPmtpaBOdD4l3r3Uf_7vKltr27T4;
path=/; expires=Sat, 29-Mar-25 00:09:22 GMT; domain=.api.openai.com; HttpOnly;
Secure; SameSite=None
- _cfuvid=Daug1DTioODhGs.oCPbiMGRU8rN4cooGraWTg30zUH4-1743205162681-0.0.1.1-604800000;
path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None
X-Content-Type-Options:
- nosniff
Server:
- cloudflare
Cf-Ray:
- 927af7696faa10ee-ORD
Alt-Svc:
- h3=":443"; ma=86400
body:
encoding: UTF-8
string: |+
event: response.created
data: {"type":"response.created","response":{"id":"resp_67e7332a89f48192a7c5da3f21bd48940c494b972720dd48","object":"response","created_at":1743205162,"status":"in_progress","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":"resp_67e73328128881928023b1fa925c2bcc0c494b972720dd48","reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
event: response.in_progress
data: {"type":"response.in_progress","response":{"id":"resp_67e7332a89f48192a7c5da3f21bd48940c494b972720dd48","object":"response","created_at":1743205162,"status":"in_progress","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":"resp_67e73328128881928023b1fa925c2bcc0c494b972720dd48","reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
event: response.output_item.added
data: {"type":"response.output_item.added","output_index":0,"item":{"type":"message","id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","status":"in_progress","role":"assistant","content":[]}}
event: response.content_part.added
data: {"type":"response.content_part.added","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"part":{"type":"output_text","text":"","annotations":[]}}
event: response.output_text.delta
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":"Your"}
event: response.output_text.delta
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":" net"}
event: response.output_text.delta
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":" worth"}
event: response.output_text.delta
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":" is"}
event: response.output_text.delta
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":" $"}
event: response.output_text.delta
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":"124"}
event: response.output_text.delta
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":","}
event: response.output_text.delta
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":"200"}
event: response.output_text.delta
data: {"type":"response.output_text.delta","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"delta":"."}
event: response.output_text.done
data: {"type":"response.output_text.done","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"text":"Your net worth is $124,200."}
event: response.content_part.done
data: {"type":"response.content_part.done","item_id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","output_index":0,"content_index":0,"part":{"type":"output_text","text":"Your net worth is $124,200.","annotations":[]}}
event: response.output_item.done
data: {"type":"response.output_item.done","output_index":0,"item":{"type":"message","id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Your net worth is $124,200.","annotations":[]}]}}
event: response.completed
data: {"type":"response.completed","response":{"id":"resp_67e7332a89f48192a7c5da3f21bd48940c494b972720dd48","object":"response","created_at":1743205162,"status":"completed","error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"model":"gpt-4o-2024-08-06","output":[{"type":"message","id":"msg_67e7332af2a0819291cf0cebaf49ad960c494b972720dd48","status":"completed","role":"assistant","content":[{"type":"output_text","text":"Your net worth is $124,200.","annotations":[]}]}],"parallel_tool_calls":true,"previous_response_id":"resp_67e73328128881928023b1fa925c2bcc0c494b972720dd48","reasoning":{"effort":null,"generate_summary":null},"store":true,"temperature":1.0,"text":{"format":{"type":"text"}},"tool_choice":"auto","tools":[],"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":51,"input_tokens_details":{"cached_tokens":0},"output_tokens":10,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":61},"user":null,"metadata":{}}}
recorded_at: Fri, 28 Mar 2025 23:39:23 GMT
recorded_with: VCR 6.3.1
...