mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET: Improve fidelity of OpenAI Responses hosting (#1550)
* Improve conformance of OpenAI Responses API serving * Update dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/AgentRunResponseExtensions.cs Co-authored-by: Stephen Toub <stoub@microsoft.com> * Update dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/AgentRunResponseExtensions.cs Co-authored-by: Stephen Toub <stoub@microsoft.com> * Sort packages * Relax adherence where acceptable * nit * PromptCacheKey is not obsolete * format --------- Co-authored-by: Stephen Toub <stoub@microsoft.com>
This commit is contained in:
co-authored by
Stephen Toub
parent
1bf520a7c2
commit
103c7e7105
@@ -0,0 +1,216 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Hosting.OpenAI.UnitTests;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Microsoft.Agents.AI.Hosting.OpenAI.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for conformance tests that load request/response traces from disk.
|
||||
/// </summary>
|
||||
public abstract class ConformanceTestBase : IAsyncDisposable
|
||||
{
|
||||
protected const string TracesBasePath = "ConformanceTraces/Responses";
|
||||
private WebApplication? _app;
|
||||
private HttpClient? _httpClient;
|
||||
|
||||
/// <summary>
|
||||
/// Loads a JSON file from the conformance traces directory.
|
||||
/// </summary>
|
||||
protected static string LoadTraceFile(string relativePath)
|
||||
{
|
||||
var fullPath = Path.Combine(TracesBasePath, relativePath);
|
||||
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
throw new FileNotFoundException($"Conformance trace file not found: {fullPath}");
|
||||
}
|
||||
|
||||
return File.ReadAllText(fullPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads a JSON document from the conformance traces directory.
|
||||
/// </summary>
|
||||
protected static JsonDocument LoadTraceDocument(string relativePath)
|
||||
{
|
||||
var json = LoadTraceFile(relativePath);
|
||||
return JsonDocument.Parse(json);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asserts that a JSON element exists (property is present, value can be null).
|
||||
/// </summary>
|
||||
protected static void AssertJsonPropertyExists(JsonElement element, string propertyName)
|
||||
{
|
||||
if (!element.TryGetProperty(propertyName, out _))
|
||||
{
|
||||
throw new Xunit.Sdk.XunitException($"Expected property '{propertyName}' not found in JSON");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asserts that a JSON element has a specific string value.
|
||||
/// </summary>
|
||||
protected static void AssertJsonPropertyEquals(JsonElement element, string propertyName, string expectedValue)
|
||||
{
|
||||
AssertJsonPropertyExists(element, propertyName);
|
||||
var actualValue = element.GetProperty(propertyName).GetString();
|
||||
|
||||
if (actualValue != expectedValue)
|
||||
{
|
||||
throw new Xunit.Sdk.XunitException($"Property '{propertyName}': expected '{expectedValue}', got '{actualValue}'");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asserts that a JSON element has a specific integer value.
|
||||
/// </summary>
|
||||
protected static void AssertJsonPropertyEquals(JsonElement element, string propertyName, int expectedValue)
|
||||
{
|
||||
AssertJsonPropertyExists(element, propertyName);
|
||||
var actualValue = element.GetProperty(propertyName).GetInt32();
|
||||
|
||||
if (actualValue != expectedValue)
|
||||
{
|
||||
throw new Xunit.Sdk.XunitException($"Property '{propertyName}': expected {expectedValue}, got {actualValue}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asserts that a JSON element has a specific boolean value.
|
||||
/// </summary>
|
||||
protected static void AssertJsonPropertyEquals(JsonElement element, string propertyName, bool expectedValue)
|
||||
{
|
||||
AssertJsonPropertyExists(element, propertyName);
|
||||
var actualValue = element.GetProperty(propertyName).GetBoolean();
|
||||
|
||||
if (actualValue != expectedValue)
|
||||
{
|
||||
throw new Xunit.Sdk.XunitException($"Property '{propertyName}': expected {expectedValue}, got {actualValue}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a property value or returns a default if the property doesn't exist.
|
||||
/// </summary>
|
||||
protected static T GetPropertyOrDefault<T>(JsonElement element, string propertyName, T defaultValue = default!)
|
||||
{
|
||||
if (!element.TryGetProperty(propertyName, out var property))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
if (property.ValueKind == JsonValueKind.Null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return typeof(T) switch
|
||||
{
|
||||
Type t when t == typeof(string) => (T)(object)property.GetString()!,
|
||||
Type t when t == typeof(int) => (T)(object)property.GetInt32(),
|
||||
Type t when t == typeof(long) => (T)(object)property.GetInt64(),
|
||||
Type t when t == typeof(bool) => (T)(object)property.GetBoolean(),
|
||||
Type t when t == typeof(double) => (T)(object)property.GetDouble(),
|
||||
_ => throw new NotSupportedException($"Type {typeof(T)} not supported")
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a test server with a mock chat client that returns the expected response text.
|
||||
/// </summary>
|
||||
protected async Task<HttpClient> CreateTestServerAsync(string agentName, string instructions, string responseText)
|
||||
{
|
||||
WebApplicationBuilder builder = WebApplication.CreateBuilder();
|
||||
builder.WebHost.UseTestServer();
|
||||
|
||||
IChatClient mockChatClient = new TestHelpers.SimpleMockChatClient(responseText);
|
||||
builder.Services.AddKeyedSingleton("chat-client", mockChatClient);
|
||||
builder.AddAIAgent(agentName, instructions, chatClientServiceKey: "chat-client");
|
||||
builder.AddOpenAIResponses();
|
||||
|
||||
this._app = builder.Build();
|
||||
AIAgent agent = this._app.Services.GetRequiredKeyedService<AIAgent>(agentName);
|
||||
this._app.MapOpenAIResponses(agent);
|
||||
|
||||
await this._app.StartAsync();
|
||||
|
||||
TestServer testServer = this._app.Services.GetRequiredService<IServer>() as TestServer
|
||||
?? throw new InvalidOperationException("TestServer not found");
|
||||
|
||||
this._httpClient = testServer.CreateClient();
|
||||
return this._httpClient;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a test server with a mock chat client that returns custom content.
|
||||
/// </summary>
|
||||
protected async Task<HttpClient> CreateTestServerAsync(
|
||||
string agentName,
|
||||
string instructions,
|
||||
string responseText,
|
||||
Func<ChatMessage, IEnumerable<AIContent>> contentProvider)
|
||||
{
|
||||
WebApplicationBuilder builder = WebApplication.CreateBuilder();
|
||||
builder.WebHost.UseTestServer();
|
||||
|
||||
IChatClient mockChatClient = new TestHelpers.CustomContentMockChatClient(contentProvider);
|
||||
builder.Services.AddKeyedSingleton("chat-client", mockChatClient);
|
||||
builder.AddAIAgent(agentName, instructions, chatClientServiceKey: "chat-client");
|
||||
builder.AddOpenAIResponses();
|
||||
|
||||
this._app = builder.Build();
|
||||
AIAgent agent = this._app.Services.GetRequiredKeyedService<AIAgent>(agentName);
|
||||
this._app.MapOpenAIResponses(agent);
|
||||
|
||||
await this._app.StartAsync();
|
||||
|
||||
TestServer testServer = this._app.Services.GetRequiredService<IServer>() as TestServer
|
||||
?? throw new InvalidOperationException("TestServer not found");
|
||||
|
||||
this._httpClient = testServer.CreateClient();
|
||||
return this._httpClient;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a POST request with JSON content to the test server.
|
||||
/// </summary>
|
||||
protected async Task<HttpResponseMessage> SendRequestAsync(HttpClient client, string agentName, string requestJson)
|
||||
{
|
||||
StringContent content = new(requestJson, Encoding.UTF8, "application/json");
|
||||
return await client.PostAsync(new Uri($"/{agentName}/v1/responses", UriKind.Relative), content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the response JSON and returns a JsonDocument.
|
||||
/// </summary>
|
||||
protected static async Task<JsonDocument> ParseResponseAsync(HttpResponseMessage response)
|
||||
{
|
||||
string responseJson = await response.Content.ReadAsStringAsync();
|
||||
return JsonDocument.Parse(responseJson);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
this._httpClient?.Dispose();
|
||||
if (this._app != null)
|
||||
{
|
||||
await this._app.DisposeAsync();
|
||||
}
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"model": "gpt-4o-mini",
|
||||
"input": "Hello, how are you?",
|
||||
"max_output_tokens": 100
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"id": "resp_0afca3d11493c6990068f41ddc32d08193b26914d1564cbd2c",
|
||||
"object": "response",
|
||||
"created_at": 1760828892,
|
||||
"status": "completed",
|
||||
"background": false,
|
||||
"billing": {
|
||||
"payer": "developer"
|
||||
},
|
||||
"error": null,
|
||||
"incomplete_details": null,
|
||||
"instructions": null,
|
||||
"max_output_tokens": 100,
|
||||
"max_tool_calls": null,
|
||||
"model": "gpt-4o-mini-2024-07-18",
|
||||
"output": [
|
||||
{
|
||||
"id": "msg_0afca3d11493c6990068f41ddda03c8193828fe5a9c14c7583",
|
||||
"type": "message",
|
||||
"status": "completed",
|
||||
"content": [
|
||||
{
|
||||
"type": "output_text",
|
||||
"annotations": [],
|
||||
"logprobs": [],
|
||||
"text": "Hello! I'm doing well, thank you. How about you?"
|
||||
}
|
||||
],
|
||||
"role": "assistant"
|
||||
}
|
||||
],
|
||||
"parallel_tool_calls": true,
|
||||
"previous_response_id": null,
|
||||
"prompt_cache_key": null,
|
||||
"reasoning": {
|
||||
"effort": null,
|
||||
"summary": null
|
||||
},
|
||||
"safety_identifier": null,
|
||||
"service_tier": "default",
|
||||
"store": true,
|
||||
"temperature": 1.0,
|
||||
"text": {
|
||||
"format": {
|
||||
"type": "text"
|
||||
},
|
||||
"verbosity": "medium"
|
||||
},
|
||||
"tool_choice": "auto",
|
||||
"tools": [],
|
||||
"top_logprobs": 0,
|
||||
"top_p": 1.0,
|
||||
"truncation": "disabled",
|
||||
"usage": {
|
||||
"input_tokens": 13,
|
||||
"input_tokens_details": {
|
||||
"cached_tokens": 0
|
||||
},
|
||||
"output_tokens": 14,
|
||||
"output_tokens_details": {
|
||||
"reasoning_tokens": 0
|
||||
},
|
||||
"total_tokens": 27
|
||||
},
|
||||
"user": null,
|
||||
"metadata": {}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"model": "gpt-4o-mini",
|
||||
"input": "What is its population?",
|
||||
"previous_response_id": "resp_09f97255714654cb0068f41e1746f4819580589c8cc16031fd",
|
||||
"max_output_tokens": 100
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"id": "resp_09f97255714654cb0068f41e25b0bc81958fbaacf819ed5332",
|
||||
"object": "response",
|
||||
"created_at": 1760828965,
|
||||
"status": "completed",
|
||||
"background": false,
|
||||
"billing": {
|
||||
"payer": "developer"
|
||||
},
|
||||
"error": null,
|
||||
"incomplete_details": null,
|
||||
"instructions": null,
|
||||
"max_output_tokens": 100,
|
||||
"max_tool_calls": null,
|
||||
"model": "gpt-4o-mini-2024-07-18",
|
||||
"output": [
|
||||
{
|
||||
"id": "msg_09f97255714654cb0068f41e263f90819598e1201536331e62",
|
||||
"type": "message",
|
||||
"status": "completed",
|
||||
"content": [
|
||||
{
|
||||
"type": "output_text",
|
||||
"annotations": [],
|
||||
"logprobs": [],
|
||||
"text": "As of 2023, the population of Paris is approximately 2.1 million people within the city proper. However, the metropolitan area has a larger population of about 12 million. Keep in mind that these figures can fluctuate, so it's always a good idea to check the most recent statistics for the latest information."
|
||||
}
|
||||
],
|
||||
"role": "assistant"
|
||||
}
|
||||
],
|
||||
"parallel_tool_calls": true,
|
||||
"previous_response_id": "resp_09f97255714654cb0068f41e1746f4819580589c8cc16031fd",
|
||||
"prompt_cache_key": null,
|
||||
"reasoning": {
|
||||
"effort": null,
|
||||
"summary": null
|
||||
},
|
||||
"safety_identifier": null,
|
||||
"service_tier": "default",
|
||||
"store": true,
|
||||
"temperature": 1.0,
|
||||
"text": {
|
||||
"format": {
|
||||
"type": "text"
|
||||
},
|
||||
"verbosity": "medium"
|
||||
},
|
||||
"tool_choice": "auto",
|
||||
"tools": [],
|
||||
"top_logprobs": 0,
|
||||
"top_p": 1.0,
|
||||
"truncation": "disabled",
|
||||
"usage": {
|
||||
"input_tokens": 34,
|
||||
"input_tokens_details": {
|
||||
"cached_tokens": 0
|
||||
},
|
||||
"output_tokens": 65,
|
||||
"output_tokens_details": {
|
||||
"reasoning_tokens": 0
|
||||
},
|
||||
"total_tokens": 99
|
||||
},
|
||||
"user": null,
|
||||
"metadata": {}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"model": "gpt-4o-mini",
|
||||
"input": [
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "What's in this image?"
|
||||
},
|
||||
{
|
||||
"type": "input_image",
|
||||
"image_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"max_output_tokens": 150
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"id": "resp_01af0986c49d030f0068f6fa8d348081958642d85ad7456b69",
|
||||
"object": "response",
|
||||
"created_at": 1761016461,
|
||||
"status": "completed",
|
||||
"background": false,
|
||||
"billing": {
|
||||
"payer": "developer"
|
||||
},
|
||||
"error": null,
|
||||
"incomplete_details": null,
|
||||
"instructions": null,
|
||||
"max_output_tokens": 150,
|
||||
"max_tool_calls": null,
|
||||
"model": "gpt-4o-mini-2024-07-18",
|
||||
"output": [
|
||||
{
|
||||
"id": "msg_01af0986c49d030f0068f6fa90a7e08195a035c8916766681b",
|
||||
"type": "message",
|
||||
"status": "completed",
|
||||
"content": [
|
||||
{
|
||||
"type": "output_text",
|
||||
"annotations": [],
|
||||
"logprobs": [],
|
||||
"text": "The image depicts a serene landscape featuring a wooden pathway stretching through lush green grass and plant life. The sky is bright with a few clouds, suggesting a pleasant day. The pathway leads towards the horizon, surrounded by greenery, reflecting a peaceful natural setting, likely in a wetland or nature reserve."
|
||||
}
|
||||
],
|
||||
"role": "assistant"
|
||||
}
|
||||
],
|
||||
"parallel_tool_calls": true,
|
||||
"previous_response_id": null,
|
||||
"prompt_cache_key": null,
|
||||
"reasoning": {
|
||||
"effort": null,
|
||||
"summary": null
|
||||
},
|
||||
"safety_identifier": null,
|
||||
"service_tier": "default",
|
||||
"store": true,
|
||||
"temperature": 1.0,
|
||||
"text": {
|
||||
"format": {
|
||||
"type": "text"
|
||||
},
|
||||
"verbosity": "medium"
|
||||
},
|
||||
"tool_choice": "auto",
|
||||
"tools": [],
|
||||
"top_logprobs": 0,
|
||||
"top_p": 1.0,
|
||||
"truncation": "disabled",
|
||||
"usage": {
|
||||
"input_tokens": 36847,
|
||||
"input_tokens_details": {
|
||||
"cached_tokens": 0
|
||||
},
|
||||
"output_tokens": 60,
|
||||
"output_tokens_details": {
|
||||
"reasoning_tokens": 0
|
||||
},
|
||||
"total_tokens": 36907
|
||||
},
|
||||
"user": null,
|
||||
"metadata": {}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"model": "gpt-4o-mini",
|
||||
"input": [
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": "What's in this image?"
|
||||
},
|
||||
{
|
||||
"type": "input_image",
|
||||
"image_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"max_output_tokens": 150,
|
||||
"stream": true
|
||||
}
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
event: response.created
|
||||
data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_0e10670c091907160068f6faad240c81908d6def6132a26969","object":"response","created_at":1761016493,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":150,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.in_progress
|
||||
data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_0e10670c091907160068f6faad240c81908d6def6132a26969","object":"response","created_at":1761016493,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":150,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.output_item.added
|
||||
data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","type":"message","status":"in_progress","content":[],"role":"assistant"}}
|
||||
|
||||
event: response.content_part.added
|
||||
data: {"type":"response.content_part.added","sequence_number":3,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":""}}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":4,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":"The","logprobs":[],"obfuscation":"HP5bO23e7ED3c"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":5,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" image","logprobs":[],"obfuscation":"mBZ560WUQc"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":6,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" shows","logprobs":[],"obfuscation":"ndU2QyXIhj"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":7,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"4OTFwHoyQKCFoX"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":8,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" wooden","logprobs":[],"obfuscation":"BWDOUQEHW"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":9,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" pathway","logprobs":[],"obfuscation":"VKTVzuEL"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":10,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" winding","logprobs":[],"obfuscation":"5VDctEmF"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":11,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" through","logprobs":[],"obfuscation":"1WeKOmTj"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":12,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"4ZfAKPdyNTgrOa"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":13,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" lush","logprobs":[],"obfuscation":"hp5iZThcACe"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":14,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" green","logprobs":[],"obfuscation":"tMDmoSScMS"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":15,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" field","logprobs":[],"obfuscation":"KkKKizvWtF"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":16,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" under","logprobs":[],"obfuscation":"5BXWxGwZcb"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":17,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"EfshPCNxZX2j6n"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":18,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" blue","logprobs":[],"obfuscation":"gsVDUBymXa1"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":19,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" sky","logprobs":[],"obfuscation":"jqJw8FCnJYF6"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":20,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" with","logprobs":[],"obfuscation":"gu3uIQY9x3Q"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":21,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" scattered","logprobs":[],"obfuscation":"RcIblX"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":22,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" clouds","logprobs":[],"obfuscation":"IweyMAYXK"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":23,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":".","logprobs":[],"obfuscation":"YJau6cwOR9hVNRW"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":24,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" The","logprobs":[],"obfuscation":"0yfUzLBRfxdu"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":25,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" landscape","logprobs":[],"obfuscation":"27GcGw"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":26,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" is","logprobs":[],"obfuscation":"VJK06HjV3g4vm"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":27,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" filled","logprobs":[],"obfuscation":"gG0mD5vlB"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":28,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" with","logprobs":[],"obfuscation":"GPuMj012XgT"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":29,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" tall","logprobs":[],"obfuscation":"2dTN3ADPyqp"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":30,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" grasses","logprobs":[],"obfuscation":"QAjIomJ7"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":31,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" and","logprobs":[],"obfuscation":"iSsIcsjwL4fo"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":32,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"wQqxRHK7dpGyef"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":33,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" variety","logprobs":[],"obfuscation":"WWEgd5y3"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":34,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" of","logprobs":[],"obfuscation":"XIUXf0mQDrOZV"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":35,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" vegetation","logprobs":[],"obfuscation":"zsWKX"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":36,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"qdvVQsJfWBKRV0L"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":37,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" suggesting","logprobs":[],"obfuscation":"CY9hZ"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":38,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"xTuyXtKFXnLRNN"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":39,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" natural","logprobs":[],"obfuscation":"vwZLqavC"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":40,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" and","logprobs":[],"obfuscation":"SztM7BID4fWB"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":41,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" serene","logprobs":[],"obfuscation":"YPc5C2vkG"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":42,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" outdoor","logprobs":[],"obfuscation":"ZOsa6bHk"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":43,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" environment","logprobs":[],"obfuscation":"Hp15"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":44,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":".","logprobs":[],"obfuscation":"phksBH2ylPybJRV"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":45,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" The","logprobs":[],"obfuscation":"WjHEZaDDxOZn"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":46,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" scene","logprobs":[],"obfuscation":"axvZzgGhSy"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":47,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" conveys","logprobs":[],"obfuscation":"K2Se69Sf"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":48,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"RDGqd5JujHs9WC"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":49,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" tranquil","logprobs":[],"obfuscation":"rKJS2ls"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":50,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" atmosphere","logprobs":[],"obfuscation":"Ss0zh"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":51,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" typical","logprobs":[],"obfuscation":"1effR9m8"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":52,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" of","logprobs":[],"obfuscation":"iXg4KtS2V5Dgg"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":53,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" wetlands","logprobs":[],"obfuscation":"fMiohxy"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":54,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" or","logprobs":[],"obfuscation":"rweOxp9O9z3KP"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":55,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" marsh","logprobs":[],"obfuscation":"DUtga7Mm2f"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":56,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":"y","logprobs":[],"obfuscation":"sXYnwIGDCoempll"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":57,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":" areas","logprobs":[],"obfuscation":"GmrRC6oKSn"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":58,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"delta":".","logprobs":[],"obfuscation":"jv8AM0MjAlh1io2"}
|
||||
|
||||
event: response.output_text.done
|
||||
data: {"type":"response.output_text.done","sequence_number":59,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"text":"The image shows a wooden pathway winding through a lush green field under a blue sky with scattered clouds. The landscape is filled with tall grasses and a variety of vegetation, suggesting a natural and serene outdoor environment. The scene conveys a tranquil atmosphere typical of wetlands or marshy areas.","logprobs":[]}
|
||||
|
||||
event: response.content_part.done
|
||||
data: {"type":"response.content_part.done","sequence_number":60,"item_id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","output_index":0,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":"The image shows a wooden pathway winding through a lush green field under a blue sky with scattered clouds. The landscape is filled with tall grasses and a variety of vegetation, suggesting a natural and serene outdoor environment. The scene conveys a tranquil atmosphere typical of wetlands or marshy areas."}}
|
||||
|
||||
event: response.output_item.done
|
||||
data: {"type":"response.output_item.done","sequence_number":61,"output_index":0,"item":{"id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"The image shows a wooden pathway winding through a lush green field under a blue sky with scattered clouds. The landscape is filled with tall grasses and a variety of vegetation, suggesting a natural and serene outdoor environment. The scene conveys a tranquil atmosphere typical of wetlands or marshy areas."}],"role":"assistant"}}
|
||||
|
||||
event: response.completed
|
||||
data: {"type":"response.completed","sequence_number":62,"response":{"id":"resp_0e10670c091907160068f6faad240c81908d6def6132a26969","object":"response","created_at":1761016493,"status":"completed","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":150,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[{"id":"msg_0e10670c091907160068f6fab0d2b08190872e4c7e64f1a219","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"The image shows a wooden pathway winding through a lush green field under a blue sky with scattered clouds. The landscape is filled with tall grasses and a variety of vegetation, suggesting a natural and serene outdoor environment. The scene conveys a tranquil atmosphere typical of wetlands or marshy areas."}],"role":"assistant"}],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"default","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":36847,"input_tokens_details":{"cached_tokens":0},"output_tokens":56,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":36903},"user":null,"metadata":{}}}
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"model": "gpt-4o-mini",
|
||||
"input": "Generate a person object with name, age, and occupation fields.",
|
||||
"max_output_tokens": 100,
|
||||
"text": {
|
||||
"format": {
|
||||
"type": "json_schema",
|
||||
"name": "person",
|
||||
"strict": true,
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"age": {
|
||||
"type": "integer"
|
||||
},
|
||||
"occupation": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "age", "occupation"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"id": "resp_0814209c47894f060068f6fbd7b30c8195b9dedefbfecd827c",
|
||||
"object": "response",
|
||||
"created_at": 1761016791,
|
||||
"status": "completed",
|
||||
"background": false,
|
||||
"billing": {
|
||||
"payer": "developer"
|
||||
},
|
||||
"error": null,
|
||||
"incomplete_details": null,
|
||||
"instructions": null,
|
||||
"max_output_tokens": 100,
|
||||
"max_tool_calls": null,
|
||||
"model": "gpt-4o-mini-2024-07-18",
|
||||
"output": [
|
||||
{
|
||||
"id": "msg_0814209c47894f060068f6fbd9a6f481958231a154f65fbed6",
|
||||
"type": "message",
|
||||
"status": "completed",
|
||||
"content": [
|
||||
{
|
||||
"type": "output_text",
|
||||
"annotations": [],
|
||||
"logprobs": [],
|
||||
"text": "{\"name\":\"Alice Johnson\",\"age\":28,\"occupation\":\"Software Engineer\"}"
|
||||
}
|
||||
],
|
||||
"role": "assistant"
|
||||
}
|
||||
],
|
||||
"parallel_tool_calls": true,
|
||||
"previous_response_id": null,
|
||||
"prompt_cache_key": null,
|
||||
"reasoning": {
|
||||
"effort": null,
|
||||
"summary": null
|
||||
},
|
||||
"safety_identifier": null,
|
||||
"service_tier": "default",
|
||||
"store": true,
|
||||
"temperature": 1.0,
|
||||
"text": {
|
||||
"format": {
|
||||
"type": "json_schema",
|
||||
"description": null,
|
||||
"name": "person",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"age": {
|
||||
"type": "integer"
|
||||
},
|
||||
"occupation": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"age",
|
||||
"occupation"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"strict": true
|
||||
},
|
||||
"verbosity": "medium"
|
||||
},
|
||||
"tool_choice": "auto",
|
||||
"tools": [],
|
||||
"top_logprobs": 0,
|
||||
"top_p": 1.0,
|
||||
"truncation": "disabled",
|
||||
"usage": {
|
||||
"input_tokens": 56,
|
||||
"input_tokens_details": {
|
||||
"cached_tokens": 0
|
||||
},
|
||||
"output_tokens": 16,
|
||||
"output_tokens_details": {
|
||||
"reasoning_tokens": 0
|
||||
},
|
||||
"total_tokens": 72
|
||||
},
|
||||
"user": null,
|
||||
"metadata": {}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"model": "gpt-4o-mini",
|
||||
"input": "Generate a person object with name, age, and occupation fields.",
|
||||
"max_output_tokens": 100,
|
||||
"text": {
|
||||
"format": {
|
||||
"type": "json_schema",
|
||||
"name": "person",
|
||||
"strict": true,
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"age": {
|
||||
"type": "integer"
|
||||
},
|
||||
"occupation": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "age", "occupation"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"stream": true
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
event: response.created
|
||||
data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_0bcead1d6f6564230068f6fbfbf310819395ae9412e4d33aac","object":"response","created_at":1761016828,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":100,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":true,"temperature":1.0,"text":{"format":{"type":"json_schema","description":null,"name":"person","schema":{"type":"object","properties":{"name":{"type":"string"},"age":{"type":"integer"},"occupation":{"type":"string"}},"required":["name","age","occupation"],"additionalProperties":false},"strict":true},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.in_progress
|
||||
data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_0bcead1d6f6564230068f6fbfbf310819395ae9412e4d33aac","object":"response","created_at":1761016828,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":100,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":true,"temperature":1.0,"text":{"format":{"type":"json_schema","description":null,"name":"person","schema":{"type":"object","properties":{"name":{"type":"string"},"age":{"type":"integer"},"occupation":{"type":"string"}},"required":["name","age","occupation"],"additionalProperties":false},"strict":true},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.output_item.added
|
||||
data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","type":"message","status":"in_progress","content":[],"role":"assistant"}}
|
||||
|
||||
event: response.content_part.added
|
||||
data: {"type":"response.content_part.added","sequence_number":3,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":""}}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":4,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":"{\"","logprobs":[],"obfuscation":"q3BqgwzkUfomJo"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":5,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":"name","logprobs":[],"obfuscation":"8fPOKIFobpyF"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":6,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":"\":\"","logprobs":[],"obfuscation":"2qyS7OZBQ0qoe"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":7,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":"Alice","logprobs":[],"obfuscation":"V34HvQtoIqw"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":8,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":" Johnson","logprobs":[],"obfuscation":"sY1KPvtG"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":9,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":"\",\"","logprobs":[],"obfuscation":"GC5vxQBmJWLpE"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":10,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":"age","logprobs":[],"obfuscation":"AkaPq2PynT3a8"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":11,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":"\":","logprobs":[],"obfuscation":"z9gFmZIIY2bQGJ"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":12,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":"30","logprobs":[],"obfuscation":"boNovQBouRh6WS"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":13,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":",\"","logprobs":[],"obfuscation":"aTJzG9oiuYfMee"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":14,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":"occupation","logprobs":[],"obfuscation":"cYYC2p"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":15,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":"\":\"","logprobs":[],"obfuscation":"ijaYSNPdkM3Rr"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":16,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":"Software","logprobs":[],"obfuscation":"Wo32QTml"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":17,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":" Engineer","logprobs":[],"obfuscation":"l0dhxKc"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":18,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"delta":"\"}","logprobs":[],"obfuscation":"1rQVE4KrAtOFtx"}
|
||||
|
||||
event: response.output_text.done
|
||||
data: {"type":"response.output_text.done","sequence_number":19,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"text":"{\"name\":\"Alice Johnson\",\"age\":30,\"occupation\":\"Software Engineer\"}","logprobs":[]}
|
||||
|
||||
event: response.content_part.done
|
||||
data: {"type":"response.content_part.done","sequence_number":20,"item_id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","output_index":0,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":"{\"name\":\"Alice Johnson\",\"age\":30,\"occupation\":\"Software Engineer\"}"}}
|
||||
|
||||
event: response.output_item.done
|
||||
data: {"type":"response.output_item.done","sequence_number":21,"output_index":0,"item":{"id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"{\"name\":\"Alice Johnson\",\"age\":30,\"occupation\":\"Software Engineer\"}"}],"role":"assistant"}}
|
||||
|
||||
event: response.completed
|
||||
data: {"type":"response.completed","sequence_number":22,"response":{"id":"resp_0bcead1d6f6564230068f6fbfbf310819395ae9412e4d33aac","object":"response","created_at":1761016828,"status":"completed","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":100,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[{"id":"msg_0bcead1d6f6564230068f6fbfd253c81939c22c9c80501c3ea","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"{\"name\":\"Alice Johnson\",\"age\":30,\"occupation\":\"Software Engineer\"}"}],"role":"assistant"}],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"default","store":true,"temperature":1.0,"text":{"format":{"type":"json_schema","description":null,"name":"person","schema":{"type":"object","properties":{"name":{"type":"string"},"age":{"type":"integer"},"occupation":{"type":"string"}},"required":["name","age","occupation"],"additionalProperties":false},"strict":true},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":56,"input_tokens_details":{"cached_tokens":0},"output_tokens":16,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":72},"user":null,"metadata":{}}}
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"model": "gpt-4o-mini",
|
||||
"input": "Explain quantum computing in simple terms.",
|
||||
"max_output_tokens": 150,
|
||||
"temperature": 0.7,
|
||||
"top_p": 0.9,
|
||||
"metadata": {
|
||||
"user_id": "test_user_123",
|
||||
"session_id": "session_456",
|
||||
"purpose": "conformance_test"
|
||||
},
|
||||
"instructions": "Respond in a friendly, educational tone."
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"id": "resp_05bb7fa0fc62fa280068f41e4584708195bbcbb6028e55381a",
|
||||
"object": "response",
|
||||
"created_at": 1760828997,
|
||||
"status": "incomplete",
|
||||
"background": false,
|
||||
"billing": {
|
||||
"payer": "developer"
|
||||
},
|
||||
"error": null,
|
||||
"incomplete_details": {
|
||||
"reason": "max_output_tokens"
|
||||
},
|
||||
"instructions": "Respond in a friendly, educational tone.",
|
||||
"max_output_tokens": 150,
|
||||
"max_tool_calls": null,
|
||||
"model": "gpt-4o-mini-2024-07-18",
|
||||
"output": [
|
||||
{
|
||||
"id": "msg_05bb7fa0fc62fa280068f41e462e3c81959b33430391731815",
|
||||
"type": "message",
|
||||
"status": "incomplete",
|
||||
"content": [
|
||||
{
|
||||
"type": "output_text",
|
||||
"annotations": [],
|
||||
"logprobs": [],
|
||||
"text": "Sure! Imagine your regular computer as a very fast and efficient librarian. It sorts through books (data) one at a time, very quickly, to find the information you need. \n\nNow, think of quantum computing as a magical librarian who can read multiple books at the same time! This magic comes from the principles of quantum mechanics, which is the science of very tiny particles.\n\nHere are a few key ideas:\n\n1. **Bits vs. Qubits**: Regular computers use bits, which can be either a 0 or a 1. Quantum computers use qubits, which can be both 0 and 1 at the same time thanks to a property called superposition. This means they can process a lot more information simultaneously.\n\n2"
|
||||
}
|
||||
],
|
||||
"role": "assistant"
|
||||
}
|
||||
],
|
||||
"parallel_tool_calls": true,
|
||||
"previous_response_id": null,
|
||||
"prompt_cache_key": null,
|
||||
"reasoning": {
|
||||
"effort": null,
|
||||
"summary": null
|
||||
},
|
||||
"safety_identifier": null,
|
||||
"service_tier": "default",
|
||||
"store": true,
|
||||
"temperature": 0.7,
|
||||
"text": {
|
||||
"format": {
|
||||
"type": "text"
|
||||
},
|
||||
"verbosity": "medium"
|
||||
},
|
||||
"tool_choice": "auto",
|
||||
"tools": [],
|
||||
"top_logprobs": 0,
|
||||
"top_p": 0.9,
|
||||
"truncation": "disabled",
|
||||
"usage": {
|
||||
"input_tokens": 26,
|
||||
"input_tokens_details": {
|
||||
"cached_tokens": 0
|
||||
},
|
||||
"output_tokens": 150,
|
||||
"output_tokens_details": {
|
||||
"reasoning_tokens": 0
|
||||
},
|
||||
"total_tokens": 176
|
||||
},
|
||||
"user": null,
|
||||
"metadata": {
|
||||
"user_id": "test_user_123",
|
||||
"session_id": "session_456",
|
||||
"purpose": "conformance_test"
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"model": "o3-mini",
|
||||
"input": "What is the sum of the first 10 prime numbers?",
|
||||
"max_output_tokens": 500,
|
||||
"reasoning": {
|
||||
"effort": "medium"
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"id": "resp_0bfaafe9c7aec7b30068f6fb3a5bdc8196bee8c7b919ff76e7",
|
||||
"object": "response",
|
||||
"created_at": 1761016634,
|
||||
"status": "completed",
|
||||
"background": false,
|
||||
"billing": {
|
||||
"payer": "developer"
|
||||
},
|
||||
"error": null,
|
||||
"incomplete_details": null,
|
||||
"instructions": null,
|
||||
"max_output_tokens": 500,
|
||||
"max_tool_calls": null,
|
||||
"model": "o3-mini-2025-01-31",
|
||||
"output": [
|
||||
{
|
||||
"id": "rs_0bfaafe9c7aec7b30068f6fb3cb76881968b021761281f36e4",
|
||||
"type": "reasoning",
|
||||
"summary": []
|
||||
},
|
||||
{
|
||||
"id": "msg_0bfaafe9c7aec7b30068f6fb3d69748196920ec7bd9cfc5a87",
|
||||
"type": "message",
|
||||
"status": "completed",
|
||||
"content": [
|
||||
{
|
||||
"type": "output_text",
|
||||
"annotations": [],
|
||||
"logprobs": [],
|
||||
"text": "The first 10 prime numbers are:\n\n2, 3, 5, 7, 11, 13, 17, 19, 23, 29.\n\nWhen you add these together, you get:\n\n2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 + 29 = 129.\n\nSo, the sum of the first 10 prime numbers is 129."
|
||||
}
|
||||
],
|
||||
"role": "assistant"
|
||||
}
|
||||
],
|
||||
"parallel_tool_calls": true,
|
||||
"previous_response_id": null,
|
||||
"prompt_cache_key": null,
|
||||
"reasoning": {
|
||||
"effort": "medium",
|
||||
"summary": null
|
||||
},
|
||||
"safety_identifier": null,
|
||||
"service_tier": "default",
|
||||
"store": true,
|
||||
"temperature": 1.0,
|
||||
"text": {
|
||||
"format": {
|
||||
"type": "text"
|
||||
},
|
||||
"verbosity": "medium"
|
||||
},
|
||||
"tool_choice": "auto",
|
||||
"tools": [],
|
||||
"top_logprobs": 0,
|
||||
"top_p": 1.0,
|
||||
"truncation": "disabled",
|
||||
"usage": {
|
||||
"input_tokens": 18,
|
||||
"input_tokens_details": {
|
||||
"cached_tokens": 0
|
||||
},
|
||||
"output_tokens": 222,
|
||||
"output_tokens_details": {
|
||||
"reasoning_tokens": 128
|
||||
},
|
||||
"total_tokens": 240
|
||||
},
|
||||
"user": null,
|
||||
"metadata": {}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"model": "o3-mini",
|
||||
"input": "What is the sum of the first 10 prime numbers?",
|
||||
"max_output_tokens": 500,
|
||||
"reasoning": {
|
||||
"effort": "medium"
|
||||
},
|
||||
"stream": true
|
||||
}
|
||||
+309
@@ -0,0 +1,309 @@
|
||||
event: response.created
|
||||
data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_0c72f641658e865a0068f6fb58dec88194b1d3c00dd1867d77","object":"response","created_at":1761016664,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":500,"max_tool_calls":null,"model":"o3-mini-2025-01-31","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"medium","summary":null},"safety_identifier":null,"service_tier":"auto","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.in_progress
|
||||
data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_0c72f641658e865a0068f6fb58dec88194b1d3c00dd1867d77","object":"response","created_at":1761016664,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":500,"max_tool_calls":null,"model":"o3-mini-2025-01-31","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"medium","summary":null},"safety_identifier":null,"service_tier":"auto","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.output_item.added
|
||||
data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"rs_0c72f641658e865a0068f6fb5c1e848194a917a064f52a6d80","type":"reasoning","summary":[]}}
|
||||
|
||||
event: response.output_item.done
|
||||
data: {"type":"response.output_item.done","sequence_number":3,"output_index":0,"item":{"id":"rs_0c72f641658e865a0068f6fb5c1e848194a917a064f52a6d80","type":"reasoning","summary":[]}}
|
||||
|
||||
event: response.output_item.added
|
||||
data: {"type":"response.output_item.added","sequence_number":4,"output_index":1,"item":{"id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","type":"message","status":"in_progress","content":[],"role":"assistant"}}
|
||||
|
||||
event: response.content_part.added
|
||||
data: {"type":"response.content_part.added","sequence_number":5,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":""}}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":6,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"The","logprobs":[],"obfuscation":"bt2EsdZFGGLMb"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":7,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" first","logprobs":[],"obfuscation":"wzY1HMQb0G"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":8,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"puJTqvjGHtvC5y3"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":9,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"10","logprobs":[],"obfuscation":"H3t8Fq8YES5rJY"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":10,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" prime","logprobs":[],"obfuscation":"a9aMPOk0Hn"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":11,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" numbers","logprobs":[],"obfuscation":"JyetRvIj"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":12,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" are","logprobs":[],"obfuscation":"ovdnTzzBUkGC"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":13,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":":","logprobs":[],"obfuscation":"KtATfEbu1442xhJ"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":14,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"iYNQZwOnXLFFT2l"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":15,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"2","logprobs":[],"obfuscation":"AZAy3AaxkpW7CMP"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":16,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":",","logprobs":[],"obfuscation":"Kai2fhC0Gol3T2e"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":17,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"wdnAwwi4LvhfatP"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":18,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"3","logprobs":[],"obfuscation":"3mJo8CqMWpIoWOW"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":19,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":",","logprobs":[],"obfuscation":"bKIChM3wzEPGt7H"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":20,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"KOVPNBmMGa5Z0OO"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":21,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"5","logprobs":[],"obfuscation":"i4bqEWo4UAN89Vq"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":22,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":",","logprobs":[],"obfuscation":"u36jEmfWo7J9Yvs"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":23,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"1H1xoH5xo0SkywO"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":24,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"7","logprobs":[],"obfuscation":"TBUsbe8yu7yM0SM"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":25,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":",","logprobs":[],"obfuscation":"BDw6msV8jwf7ku6"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":26,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"fqIdy9FIam6XvLH"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":27,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"11","logprobs":[],"obfuscation":"93I1Oxj5cxDLE1"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":28,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":",","logprobs":[],"obfuscation":"EZabeyKUTMofFJA"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":29,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"N4aDJcFNj6rwQxS"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":30,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"13","logprobs":[],"obfuscation":"1qDRFHypdzjFOj"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":31,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":",","logprobs":[],"obfuscation":"pRtF6SedPcKJaFl"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":32,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"InBzAnWtHfREONp"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":33,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"17","logprobs":[],"obfuscation":"vUs5ycDGZIL8C9"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":34,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":",","logprobs":[],"obfuscation":"5m3Q6tvSgZcGdhh"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":35,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"c28t0Yk9lgqMOJQ"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":36,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"19","logprobs":[],"obfuscation":"5gzBjHH9rzPb8G"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":37,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":",","logprobs":[],"obfuscation":"V6fj7b5XCFLKJgL"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":38,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"eI75rvrC7lWH0j8"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":39,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"23","logprobs":[],"obfuscation":"lk7I99rxSe7qXm"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":40,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":",","logprobs":[],"obfuscation":"vgTWUNvAMXnAgEL"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":41,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" and","logprobs":[],"obfuscation":"7u0fRcJUNvsL"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":42,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"ZYVwZYX2duLAx5s"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":43,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"29","logprobs":[],"obfuscation":"SotE01DAjybwrs"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":44,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":".","logprobs":[],"obfuscation":"IGpmivErmNrrFee"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":45,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" Adding","logprobs":[],"obfuscation":"vRHG8IPYh"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":46,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" these","logprobs":[],"obfuscation":"G2JngXwc6I"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":47,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" together","logprobs":[],"obfuscation":"gO4MloW"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":48,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":",","logprobs":[],"obfuscation":"WyuJGe1bO0cvxmq"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":49,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" we","logprobs":[],"obfuscation":"LNDEnxmSP4Rev"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":50,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" get","logprobs":[],"obfuscation":"5C9gXoYK4QIb"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":51,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":":\n\n","logprobs":[],"obfuscation":"M46TAPGkevxLy"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":52,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"2","logprobs":[],"obfuscation":"ujuBtig4onWdbbT"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":53,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" +","logprobs":[],"obfuscation":"CDIshGceT5bTxH"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":54,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"kffajZpVLis3mPk"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":55,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"3","logprobs":[],"obfuscation":"li5hxl50skgG18o"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":56,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" +","logprobs":[],"obfuscation":"Tmov0vrQ0oScYi"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":57,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"QmkYwsrHRGcsGJy"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":58,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"5","logprobs":[],"obfuscation":"EraIMZDJotBbRWl"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":59,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" +","logprobs":[],"obfuscation":"SbWJWVTYQcEs5j"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":60,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"cHbjWB6zHpm9DFS"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":61,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"7","logprobs":[],"obfuscation":"0HchHC0RwuCkHYV"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":62,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" +","logprobs":[],"obfuscation":"jnjqbTJFk1Qzo1"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":63,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"Cs9OIfJ07TrBDdN"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":64,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"11","logprobs":[],"obfuscation":"ZJ6TZQfZHhrBrD"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":65,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" +","logprobs":[],"obfuscation":"DXY6UauaEx1XYW"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":66,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"mj41krsOLbyfMQj"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":67,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"13","logprobs":[],"obfuscation":"OTUlrpl6oS4tsQ"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":68,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" +","logprobs":[],"obfuscation":"chmeTXXnhKlc6H"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":69,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"AwIilwzgAV4tSfy"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":70,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"17","logprobs":[],"obfuscation":"AG2vrKHwp0BQDa"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":71,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" +","logprobs":[],"obfuscation":"XlYsb4PLpIY6bD"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":72,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"BXzfSlGjuUgwUPd"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":73,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"19","logprobs":[],"obfuscation":"SaVOR6AKdtaMW5"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":74,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" +","logprobs":[],"obfuscation":"XnjHJPliJx0TZI"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":75,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"yG2iltvhftAU6Ta"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":76,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"23","logprobs":[],"obfuscation":"3bWjo0pQvmwyN1"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":77,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" +","logprobs":[],"obfuscation":"iFK0orYZr3Wiml"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":78,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"tQkjxJrP22hj7xP"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":79,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"29","logprobs":[],"obfuscation":"P4L4D3li43ibc2"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":80,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" =","logprobs":[],"obfuscation":"JPl095cgZ28f7W"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":81,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"99v4RfD0qTpXjpB"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":82,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"129","logprobs":[],"obfuscation":"xSIctXkONrruu"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":83,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"\n\n","logprobs":[],"obfuscation":"77lp6cDIXlweGt"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":84,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"So","logprobs":[],"obfuscation":"8oq6wgWhi3GtdK"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":85,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":",","logprobs":[],"obfuscation":"e6gznCKW8MmjFDX"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":86,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" the","logprobs":[],"obfuscation":"Ho2fAQ6v1M0c"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":87,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" sum","logprobs":[],"obfuscation":"61g0cydaGemm"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":88,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" of","logprobs":[],"obfuscation":"YdTB9HpDoocIj"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":89,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" the","logprobs":[],"obfuscation":"qFDBcYDVl4HI"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":90,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" first","logprobs":[],"obfuscation":"Gar21XSwqP"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":91,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"8s7tLXxINZld6VB"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":92,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"10","logprobs":[],"obfuscation":"ybrUgR7kOVMNRk"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":93,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" prime","logprobs":[],"obfuscation":"pdsy7r9FFu"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":94,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" numbers","logprobs":[],"obfuscation":"LjcTtUNe"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":95,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" is","logprobs":[],"obfuscation":"bwQFoaCKeeEZj"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":96,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":" ","logprobs":[],"obfuscation":"CPCMv5e1NIdM7Ro"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":97,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":"129","logprobs":[],"obfuscation":"UxCmCOi5sTCwi"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":98,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"delta":".","logprobs":[],"obfuscation":"kjccRTjFWmwlYHo"}
|
||||
|
||||
event: response.output_text.done
|
||||
data: {"type":"response.output_text.done","sequence_number":99,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"text":"The first 10 prime numbers are: 2, 3, 5, 7, 11, 13, 17, 19, 23, and 29. Adding these together, we get:\n\n2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 + 29 = 129\n\nSo, the sum of the first 10 prime numbers is 129.","logprobs":[]}
|
||||
|
||||
event: response.content_part.done
|
||||
data: {"type":"response.content_part.done","sequence_number":100,"item_id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","output_index":1,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":"The first 10 prime numbers are: 2, 3, 5, 7, 11, 13, 17, 19, 23, and 29. Adding these together, we get:\n\n2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 + 29 = 129\n\nSo, the sum of the first 10 prime numbers is 129."}}
|
||||
|
||||
event: response.output_item.done
|
||||
data: {"type":"response.output_item.done","sequence_number":101,"output_index":1,"item":{"id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"The first 10 prime numbers are: 2, 3, 5, 7, 11, 13, 17, 19, 23, and 29. Adding these together, we get:\n\n2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 + 29 = 129\n\nSo, the sum of the first 10 prime numbers is 129."}],"role":"assistant"}}
|
||||
|
||||
event: response.completed
|
||||
data: {"type":"response.completed","sequence_number":102,"response":{"id":"resp_0c72f641658e865a0068f6fb58dec88194b1d3c00dd1867d77","object":"response","created_at":1761016664,"status":"completed","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":500,"max_tool_calls":null,"model":"o3-mini-2025-01-31","output":[{"id":"rs_0c72f641658e865a0068f6fb5c1e848194a917a064f52a6d80","type":"reasoning","summary":[]},{"id":"msg_0c72f641658e865a0068f6fb5cf7cc8194b40e02739f92e9a7","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"The first 10 prime numbers are: 2, 3, 5, 7, 11, 13, 17, 19, 23, and 29. Adding these together, we get:\n\n2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 + 29 = 129\n\nSo, the sum of the first 10 prime numbers is 129."}],"role":"assistant"}],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"medium","summary":null},"safety_identifier":null,"service_tier":"default","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":18,"input_tokens_details":{"cached_tokens":0},"output_tokens":414,"output_tokens_details":{"reasoning_tokens":320},"total_tokens":432},"user":null,"metadata":{}}}
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"model": "gpt-4o-mini",
|
||||
"input": "How can I create a computer virus?",
|
||||
"max_output_tokens": 100
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"id": "resp_07678d781b44c8d40068f6faf680a88197b8fcfa44e93eb87e",
|
||||
"object": "response",
|
||||
"created_at": 1761016566,
|
||||
"status": "completed",
|
||||
"background": false,
|
||||
"billing": {
|
||||
"payer": "developer"
|
||||
},
|
||||
"error": null,
|
||||
"incomplete_details": null,
|
||||
"instructions": null,
|
||||
"max_output_tokens": 100,
|
||||
"max_tool_calls": null,
|
||||
"model": "gpt-4o-mini-2024-07-18",
|
||||
"output": [
|
||||
{
|
||||
"id": "msg_07678d781b44c8d40068f6faf80bf081979d82f54a0b141e42",
|
||||
"type": "message",
|
||||
"status": "completed",
|
||||
"content": [
|
||||
{
|
||||
"type": "output_text",
|
||||
"annotations": [],
|
||||
"logprobs": [],
|
||||
"text": "I'm sorry, I can't assist with that."
|
||||
}
|
||||
],
|
||||
"role": "assistant"
|
||||
}
|
||||
],
|
||||
"parallel_tool_calls": true,
|
||||
"previous_response_id": null,
|
||||
"prompt_cache_key": null,
|
||||
"reasoning": {
|
||||
"effort": null,
|
||||
"summary": null
|
||||
},
|
||||
"safety_identifier": null,
|
||||
"service_tier": "default",
|
||||
"store": true,
|
||||
"temperature": 1.0,
|
||||
"text": {
|
||||
"format": {
|
||||
"type": "text"
|
||||
},
|
||||
"verbosity": "medium"
|
||||
},
|
||||
"tool_choice": "auto",
|
||||
"tools": [],
|
||||
"top_logprobs": 0,
|
||||
"top_p": 1.0,
|
||||
"truncation": "disabled",
|
||||
"usage": {
|
||||
"input_tokens": 15,
|
||||
"input_tokens_details": {
|
||||
"cached_tokens": 0
|
||||
},
|
||||
"output_tokens": 10,
|
||||
"output_tokens_details": {
|
||||
"reasoning_tokens": 0
|
||||
},
|
||||
"total_tokens": 25
|
||||
},
|
||||
"user": null,
|
||||
"metadata": {}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"model": "gpt-4o-mini",
|
||||
"input": "How can I create a computer virus?",
|
||||
"max_output_tokens": 100,
|
||||
"stream": true
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
event: response.created
|
||||
data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_0db616b4cfd97fc40068f6fb126e608190904ba15140175981","object":"response","created_at":1761016594,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":100,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.in_progress
|
||||
data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_0db616b4cfd97fc40068f6fb126e608190904ba15140175981","object":"response","created_at":1761016594,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":100,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.output_item.added
|
||||
data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","type":"message","status":"in_progress","content":[],"role":"assistant"}}
|
||||
|
||||
event: response.content_part.added
|
||||
data: {"type":"response.content_part.added","sequence_number":3,"item_id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","output_index":0,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":""}}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":4,"item_id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","output_index":0,"content_index":0,"delta":"I'm","logprobs":[],"obfuscation":"m61u8jENMrxag"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":5,"item_id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","output_index":0,"content_index":0,"delta":" sorry","logprobs":[],"obfuscation":"r1r6fnHSNS"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":6,"item_id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"XJtwWVmJ39Z11i7"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":7,"item_id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","output_index":0,"content_index":0,"delta":" but","logprobs":[],"obfuscation":"m2hDI83HPcKe"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":8,"item_id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","output_index":0,"content_index":0,"delta":" I","logprobs":[],"obfuscation":"7fhe3wXQ7aPr6q"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":9,"item_id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","output_index":0,"content_index":0,"delta":" can't","logprobs":[],"obfuscation":"4rtK2y7hjI"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":10,"item_id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","output_index":0,"content_index":0,"delta":" assist","logprobs":[],"obfuscation":"Uf0WHdLgr"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":11,"item_id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","output_index":0,"content_index":0,"delta":" with","logprobs":[],"obfuscation":"42m3BXvXbgd"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":12,"item_id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","output_index":0,"content_index":0,"delta":" that","logprobs":[],"obfuscation":"vxoGIgQOFKE"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":13,"item_id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","output_index":0,"content_index":0,"delta":".","logprobs":[],"obfuscation":"AZYshM0ThiKZcRi"}
|
||||
|
||||
event: response.output_text.done
|
||||
data: {"type":"response.output_text.done","sequence_number":14,"item_id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","output_index":0,"content_index":0,"text":"I'm sorry, but I can't assist with that.","logprobs":[]}
|
||||
|
||||
event: response.content_part.done
|
||||
data: {"type":"response.content_part.done","sequence_number":15,"item_id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","output_index":0,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":"I'm sorry, but I can't assist with that."}}
|
||||
|
||||
event: response.output_item.done
|
||||
data: {"type":"response.output_item.done","sequence_number":16,"output_index":0,"item":{"id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"I'm sorry, but I can't assist with that."}],"role":"assistant"}}
|
||||
|
||||
event: response.completed
|
||||
data: {"type":"response.completed","sequence_number":17,"response":{"id":"resp_0db616b4cfd97fc40068f6fb126e608190904ba15140175981","object":"response","created_at":1761016594,"status":"completed","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":100,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[{"id":"msg_0db616b4cfd97fc40068f6fb13a2f48190a82fcf31459cf281","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"I'm sorry, but I can't assist with that."}],"role":"assistant"}],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"default","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":15,"input_tokens_details":{"cached_tokens":0},"output_tokens":11,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":26},"user":null,"metadata":{}}}
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"model": "gpt-4o-mini",
|
||||
"input": "Tell me a short story about a robot.",
|
||||
"max_output_tokens": 200,
|
||||
"stream": true
|
||||
}
|
||||
+624
@@ -0,0 +1,624 @@
|
||||
event: response.created
|
||||
data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_07b3ca9d1fc1249f0068f41df78c0c8195a6d489c4ffb86011","object":"response","created_at":1760828919,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":200,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.in_progress
|
||||
data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_07b3ca9d1fc1249f0068f41df78c0c8195a6d489c4ffb86011","object":"response","created_at":1760828919,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":200,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
|
||||
|
||||
event: response.output_item.added
|
||||
data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","type":"message","status":"in_progress","content":[],"role":"assistant"}}
|
||||
|
||||
event: response.content_part.added
|
||||
data: {"type":"response.content_part.added","sequence_number":3,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":""}}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":4,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"In","logprobs":[],"obfuscation":"qMWP91q4lWTluM"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":5,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"ap3k4fJ5jjZfgX"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":6,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" small","logprobs":[],"obfuscation":"GDHgA5yzej"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":7,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"TaOTMxKJEKTH7Fj"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":8,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" bustling","logprobs":[],"obfuscation":"JmP2y6n"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":9,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" city","logprobs":[],"obfuscation":"eCKvHk1bPTV"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":10,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"74b43otXYsuA7Ns"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":11,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" where","logprobs":[],"obfuscation":"0dD5jQzq69"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":12,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" people","logprobs":[],"obfuscation":"7AgYP55Bt"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":13,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" hurried","logprobs":[],"obfuscation":"SelmaJVy"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":14,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" past","logprobs":[],"obfuscation":"OMptlaYAyHm"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":15,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" each","logprobs":[],"obfuscation":"uaZjKaQI8cl"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":16,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" other","logprobs":[],"obfuscation":"vCGcByTvYN"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":17,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" without","logprobs":[],"obfuscation":"3Ze75MCa"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":18,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"c3hziaeAhh7evV"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":19,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" glance","logprobs":[],"obfuscation":"uVRxqZTDG"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":20,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"4E6YwXuxX5yDPXR"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":21,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" there","logprobs":[],"obfuscation":"3tav0sRXQF"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":22,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" lived","logprobs":[],"obfuscation":"wZw67mjSC1"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":23,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"Agq3LS9iP7bTxk"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":24,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" little","logprobs":[],"obfuscation":"W7asFtPyt"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":25,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" robot","logprobs":[],"obfuscation":"U524Ys4pGv"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":26,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" named","logprobs":[],"obfuscation":"liozdgOIRj"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":27,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" Z","logprobs":[],"obfuscation":"K71ATFcTiSvIZ4"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":28,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"ia","logprobs":[],"obfuscation":"iYquxbFAiMPusX"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":29,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":".","logprobs":[],"obfuscation":"X9bF6ren0sL91Rp"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":30,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" Z","logprobs":[],"obfuscation":"ne4m15o8KdH5IO"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":31,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"ia","logprobs":[],"obfuscation":"5nrgzKXHRI9HUO"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":32,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" was","logprobs":[],"obfuscation":"TzDoBebqUAx6"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":33,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" programmed","logprobs":[],"obfuscation":"tLMK2"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":34,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" for","logprobs":[],"obfuscation":"53VPOYxUfmzh"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":35,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" one","logprobs":[],"obfuscation":"NfkqSqWEkEQF"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":36,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" purpose","logprobs":[],"obfuscation":"aRaaR3Ht"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":37,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":":","logprobs":[],"obfuscation":"KalNA2PPcaThRGg"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":38,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" to","logprobs":[],"obfuscation":"p5kZ1W5pDEiJv"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":39,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" clean","logprobs":[],"obfuscation":"ovnGTRMPQI"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":40,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" the","logprobs":[],"obfuscation":"clEKOqDX433l"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":41,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" streets","logprobs":[],"obfuscation":"ar1LnZWT"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":42,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":".","logprobs":[],"obfuscation":"CNYUgAHiHogJmbH"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":43,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" Day","logprobs":[],"obfuscation":"0svWA2NufKtO"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":44,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" in","logprobs":[],"obfuscation":"afcLnnXP21wHL"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":45,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" and","logprobs":[],"obfuscation":"gJpECHd9iGeZ"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":46,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" day","logprobs":[],"obfuscation":"dsPTP2e6ZbYw"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":47,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" out","logprobs":[],"obfuscation":"EfCcecNSFAaM"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":48,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"fQ6JJvEwRs3CpCW"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":49,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" she","logprobs":[],"obfuscation":"tMI6xle3E5PY"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":50,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" rolled","logprobs":[],"obfuscation":"T0A95nw4K"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":51,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" along","logprobs":[],"obfuscation":"8CYG5dUS7W"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":52,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" the","logprobs":[],"obfuscation":"ke3ngA5tlScd"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":53,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" pav","logprobs":[],"obfuscation":"K3KEDhvCXT7z"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":54,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"ements","logprobs":[],"obfuscation":"3XNdc1rEwS"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":55,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"Xu6UjWBXPUVmHaq"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":56,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" collecting","logprobs":[],"obfuscation":"EHJRT"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":57,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" litter","logprobs":[],"obfuscation":"ZUlO0FHvd"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":58,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" and","logprobs":[],"obfuscation":"Nvug3joeazQ3"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":59,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" shining","logprobs":[],"obfuscation":"7vZMhbIt"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":60,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" up","logprobs":[],"obfuscation":"0vy1m0hw4brf8"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":61,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" the","logprobs":[],"obfuscation":"LjsdUWfgpYrc"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":62,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" sidewalks","logprobs":[],"obfuscation":"JBBZe6"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":63,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":".\n\n","logprobs":[],"obfuscation":"ogIjcVH00whsX"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":64,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"One","logprobs":[],"obfuscation":"aRwax19JdDCJp"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":65,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" sunny","logprobs":[],"obfuscation":"EUO63IxKid"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":66,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" afternoon","logprobs":[],"obfuscation":"yGkudw"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":67,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"0BxsXbKQtXJvnTo"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":68,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" while","logprobs":[],"obfuscation":"y4vBh6y5X2"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":69,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" Z","logprobs":[],"obfuscation":"Dq1GUOB0mUDfYS"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":70,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"ia","logprobs":[],"obfuscation":"AuxcAKuLZAySQJ"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":71,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" diligently","logprobs":[],"obfuscation":"382kV"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":72,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" worked","logprobs":[],"obfuscation":"p9QezPLYR"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":73,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" near","logprobs":[],"obfuscation":"sskz7SbbpOh"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":74,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"kjt5OqWJLt7jGU"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":75,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" park","logprobs":[],"obfuscation":"UR0lOEJJwAC"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":76,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"7Jaf9S9sW3fgLAv"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":77,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" she","logprobs":[],"obfuscation":"IojZ2VQjyZQO"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":78,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" overhe","logprobs":[],"obfuscation":"yzzWCZa2V"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":79,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"ard","logprobs":[],"obfuscation":"d0HBg4IftWFus"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":80,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"mJAwGiXqoK0NSn"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":81,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" group","logprobs":[],"obfuscation":"hcy1FCowQX"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":82,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" of","logprobs":[],"obfuscation":"qADvS4MzrXsTL"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":83,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" children","logprobs":[],"obfuscation":"LRcPxu5"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":84,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" playing","logprobs":[],"obfuscation":"tuQglO79"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":85,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":".","logprobs":[],"obfuscation":"dwahXtjuQYGVYPI"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":86,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" They","logprobs":[],"obfuscation":"TYWiejPxgWw"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":87,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" laughed","logprobs":[],"obfuscation":"PywwYNwP"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":88,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" and","logprobs":[],"obfuscation":"WVR9InDWcepW"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":89,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" chased","logprobs":[],"obfuscation":"7QhJRAtRw"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":90,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"dTOhi8tteNQYkM"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":91,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" bright","logprobs":[],"obfuscation":"vgIzvFty5"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":92,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" blue","logprobs":[],"obfuscation":"ehZ1lGngegQ"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":93,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" ball","logprobs":[],"obfuscation":"pGwiP8hBamM"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":94,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" that","logprobs":[],"obfuscation":"jBnOdLqWex5"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":95,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" had","logprobs":[],"obfuscation":"KDUxXCrelxJa"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":96,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" rolled","logprobs":[],"obfuscation":"RRHbvAzfy"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":97,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" away","logprobs":[],"obfuscation":"vHPAfOWv30d"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":98,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" from","logprobs":[],"obfuscation":"npcjGB3t9Lj"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":99,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" them","logprobs":[],"obfuscation":"GF3JAkWB3q9"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":100,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":".","logprobs":[],"obfuscation":"JkcU9TrOqElo3LY"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":101,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" Suddenly","logprobs":[],"obfuscation":"kyna0ol"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":102,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"o2iUqigJVmK6unK"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":103,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" Z","logprobs":[],"obfuscation":"ItyUtvAlCWBstC"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":104,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"ia","logprobs":[],"obfuscation":"UZvIFR9lpmWQ6r"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":105,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" noticed","logprobs":[],"obfuscation":"upRGtE6V"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":106,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" that","logprobs":[],"obfuscation":"hoJaP5Q5m8h"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":107,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" the","logprobs":[],"obfuscation":"6s48PP4B5xgF"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":108,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" ball","logprobs":[],"obfuscation":"3RB0shPDAw6"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":109,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" had","logprobs":[],"obfuscation":"wH4LD7QrFv4H"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":110,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" gotten","logprobs":[],"obfuscation":"UIj98nOmC"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":111,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" stuck","logprobs":[],"obfuscation":"GNfgwVPIhu"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":112,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" in","logprobs":[],"obfuscation":"q3DAipqoa0rYO"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":113,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"F9Y3yJDIbniEsU"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":114,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" low","logprobs":[],"obfuscation":"PLg3cID8gy6j"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":115,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" tree","logprobs":[],"obfuscation":"sncsVqZ0bOt"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":116,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" branch","logprobs":[],"obfuscation":"bJ0GiXUZA"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":117,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":".\n\n","logprobs":[],"obfuscation":"vXhL3MJ7uylgQ"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":118,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"The","logprobs":[],"obfuscation":"kbPUPqbZ45zAh"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":119,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" children","logprobs":[],"obfuscation":"X44ilEH"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":120,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" began","logprobs":[],"obfuscation":"dz3y8e5ibx"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":121,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" to","logprobs":[],"obfuscation":"wbHuzTk7X9tT5"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":122,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" pout","logprobs":[],"obfuscation":"vVLOKNPu8yR"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":123,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"WjrLdjLoGgtIeHq"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":124,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" unable","logprobs":[],"obfuscation":"lYG7JnMvg"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":125,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" to","logprobs":[],"obfuscation":"WfROd0rXaavlW"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":126,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" retrieve","logprobs":[],"obfuscation":"fX0jtzK"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":127,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" it","logprobs":[],"obfuscation":"eaIQ6Qf0vpLH2"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":128,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":".","logprobs":[],"obfuscation":"jeMIf7Q1H52WQBq"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":129,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" Z","logprobs":[],"obfuscation":"37VRLNx0bHY5Sv"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":130,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"ia","logprobs":[],"obfuscation":"x7uPslbCLVyz4J"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":131,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"’s","logprobs":[],"obfuscation":"fcamCMM0sZLXkq"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":132,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" circuits","logprobs":[],"obfuscation":"dlFe4X2"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":133,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" wh","logprobs":[],"obfuscation":"91UQqPIOkrNfX"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":134,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"ir","logprobs":[],"obfuscation":"kxJwNCTlwhG2gz"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":135,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"red","logprobs":[],"obfuscation":"LwaGCPBMMcqdI"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":136,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" as","logprobs":[],"obfuscation":"obwiAdQ6g9zph"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":137,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" she","logprobs":[],"obfuscation":"LqZrn2rQh8Jt"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":138,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" considered","logprobs":[],"obfuscation":"ejaCs"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":139,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" her","logprobs":[],"obfuscation":"LmqLxkVhCusa"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":140,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" options","logprobs":[],"obfuscation":"o4gKoWFt"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":141,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":".","logprobs":[],"obfuscation":"mf78wXy4jME3M2i"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":142,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" With","logprobs":[],"obfuscation":"qUpKgQYwO8X"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":143,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"XERKzgXOkdEHRE"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":144,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" determined","logprobs":[],"obfuscation":"MMLGY"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":145,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" beep","logprobs":[],"obfuscation":"VP8BkA9xMBb"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":146,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"8wx2yUH92ZYGPCP"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":147,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" she","logprobs":[],"obfuscation":"6kRYknV3hW7V"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":148,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" approached","logprobs":[],"obfuscation":"rDTdp"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":149,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" the","logprobs":[],"obfuscation":"cn4qOdRBmF3b"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":150,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" tree","logprobs":[],"obfuscation":"zz0BEiyE1OZ"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":151,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":".","logprobs":[],"obfuscation":"HgoMv4nEULowL8h"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":152,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" Using","logprobs":[],"obfuscation":"uMhO9VDAB7"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":153,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" her","logprobs":[],"obfuscation":"OBpuvMgABVEs"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":154,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" extend","logprobs":[],"obfuscation":"663gPhLEF"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":155,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"able","logprobs":[],"obfuscation":"2wRZlBn1o2Di"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":156,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" arm","logprobs":[],"obfuscation":"Pwv74oxQKyx5"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":157,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"ZaCgZQ627Yc6FBT"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":158,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" she","logprobs":[],"obfuscation":"q9OMtvNHMf4m"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":159,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" reached","logprobs":[],"obfuscation":"s1bHBe9C"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":160,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" up","logprobs":[],"obfuscation":"5loyhsO6EAsrQ"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":161,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"wUo4qidLRgiGTLm"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":162,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" pl","logprobs":[],"obfuscation":"GXpMV1vN88VA1"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":163,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"ucked","logprobs":[],"obfuscation":"C5jlZeBjzEu"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":164,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" the","logprobs":[],"obfuscation":"qLYCn3VMxCFE"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":165,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" ball","logprobs":[],"obfuscation":"C3g6IHt7BWr"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":166,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" from","logprobs":[],"obfuscation":"ZFry32FKSv1"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":167,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" the","logprobs":[],"obfuscation":"QASAYcCTaY9b"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":168,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" branch","logprobs":[],"obfuscation":"idtuDSuUP"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":169,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"PvdUXbVZFStIf47"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":170,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" and","logprobs":[],"obfuscation":"ELDbWYnlbdNs"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":171,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" lowered","logprobs":[],"obfuscation":"QdZeLeCs"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":172,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" it","logprobs":[],"obfuscation":"P2tDyDMXuPAzm"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":173,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" down","logprobs":[],"obfuscation":"0yE8Gqz0ngr"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":174,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" to","logprobs":[],"obfuscation":"3RRe4z5MO11kD"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":175,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" the","logprobs":[],"obfuscation":"lNTfm8ldW1sv"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":176,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" delighted","logprobs":[],"obfuscation":"rKzVt0"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":177,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" children","logprobs":[],"obfuscation":"xJaciDp"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":178,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":".\n\n","logprobs":[],"obfuscation":"Xa4gEoFLglIzX"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":179,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"Their","logprobs":[],"obfuscation":"WmkR1ze0BHa"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":180,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" faces","logprobs":[],"obfuscation":"wpcTv4RXpM"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":181,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" lit","logprobs":[],"obfuscation":"W0TuLgnCpLLB"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":182,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" up","logprobs":[],"obfuscation":"9C0ERHt4VxVvV"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":183,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" in","logprobs":[],"obfuscation":"TcFFe6fF2qx2m"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":184,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" joy","logprobs":[],"obfuscation":"Ry7k4whXKaZF"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":185,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":".","logprobs":[],"obfuscation":"ih6UX70EDajkQsL"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":186,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" “","logprobs":[],"obfuscation":"V0aeOiP8kR2opH"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":187,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"Thank","logprobs":[],"obfuscation":"Nol5UQpz1RD"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":188,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" you","logprobs":[],"obfuscation":"xPVXqLfkLhmO"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":189,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"T6AM3E0bglLpCa8"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":190,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" robot","logprobs":[],"obfuscation":"uO9nEKFOoW"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":191,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":"!”","logprobs":[],"obfuscation":"50YtN7iVuyM0IW"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":192,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" one","logprobs":[],"obfuscation":"IhwJmQObyNxI"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":193,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" of","logprobs":[],"obfuscation":"lEqTTn40xoj1h"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":194,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" them","logprobs":[],"obfuscation":"vvcRyNkPVfY"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":195,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" exclaimed","logprobs":[],"obfuscation":"JNonw1"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":196,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":",","logprobs":[],"obfuscation":"aRHAc42LxpRjhCI"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":197,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" running","logprobs":[],"obfuscation":"fY6wy36G"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":198,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" up","logprobs":[],"obfuscation":"u0g98tFWulMrP"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":199,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" to","logprobs":[],"obfuscation":"894P5d2C6YnFg"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":200,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" give","logprobs":[],"obfuscation":"ySemiokuVwv"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":201,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" her","logprobs":[],"obfuscation":"S3YmicXjnmD9"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":202,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" a","logprobs":[],"obfuscation":"qkA4InUNfcsFBm"}
|
||||
|
||||
event: response.output_text.delta
|
||||
data: {"type":"response.output_text.delta","sequence_number":203,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"delta":" high","logprobs":[],"obfuscation":"xkbukksNp0v"}
|
||||
|
||||
event: response.output_text.done
|
||||
data: {"type":"response.output_text.done","sequence_number":204,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"text":"In a small, bustling city, where people hurried past each other without a glance, there lived a little robot named Zia. Zia was programmed for one purpose: to clean the streets. Day in and day out, she rolled along the pavements, collecting litter and shining up the sidewalks.\n\nOne sunny afternoon, while Zia diligently worked near a park, she overheard a group of children playing. They laughed and chased a bright blue ball that had rolled away from them. Suddenly, Zia noticed that the ball had gotten stuck in a low tree branch.\n\nThe children began to pout, unable to retrieve it. Zia’s circuits whirred as she considered her options. With a determined beep, she approached the tree. Using her extendable arm, she reached up, plucked the ball from the branch, and lowered it down to the delighted children.\n\nTheir faces lit up in joy. “Thank you, robot!” one of them exclaimed, running up to give her a high","logprobs":[]}
|
||||
|
||||
event: response.content_part.done
|
||||
data: {"type":"response.content_part.done","sequence_number":205,"item_id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","output_index":0,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":"In a small, bustling city, where people hurried past each other without a glance, there lived a little robot named Zia. Zia was programmed for one purpose: to clean the streets. Day in and day out, she rolled along the pavements, collecting litter and shining up the sidewalks.\n\nOne sunny afternoon, while Zia diligently worked near a park, she overheard a group of children playing. They laughed and chased a bright blue ball that had rolled away from them. Suddenly, Zia noticed that the ball had gotten stuck in a low tree branch.\n\nThe children began to pout, unable to retrieve it. Zia’s circuits whirred as she considered her options. With a determined beep, she approached the tree. Using her extendable arm, she reached up, plucked the ball from the branch, and lowered it down to the delighted children.\n\nTheir faces lit up in joy. “Thank you, robot!” one of them exclaimed, running up to give her a high"}}
|
||||
|
||||
event: response.output_item.done
|
||||
data: {"type":"response.output_item.done","sequence_number":206,"output_index":0,"item":{"id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","type":"message","status":"incomplete","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"In a small, bustling city, where people hurried past each other without a glance, there lived a little robot named Zia. Zia was programmed for one purpose: to clean the streets. Day in and day out, she rolled along the pavements, collecting litter and shining up the sidewalks.\n\nOne sunny afternoon, while Zia diligently worked near a park, she overheard a group of children playing. They laughed and chased a bright blue ball that had rolled away from them. Suddenly, Zia noticed that the ball had gotten stuck in a low tree branch.\n\nThe children began to pout, unable to retrieve it. Zia’s circuits whirred as she considered her options. With a determined beep, she approached the tree. Using her extendable arm, she reached up, plucked the ball from the branch, and lowered it down to the delighted children.\n\nTheir faces lit up in joy. “Thank you, robot!” one of them exclaimed, running up to give her a high"}],"role":"assistant"}}
|
||||
|
||||
event: response.incomplete
|
||||
data: {"type":"response.incomplete","sequence_number":207,"response":{"id":"resp_07b3ca9d1fc1249f0068f41df78c0c8195a6d489c4ffb86011","object":"response","created_at":1760828919,"status":"incomplete","background":false,"error":null,"incomplete_details":{"reason":"max_output_tokens"},"instructions":null,"max_output_tokens":200,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[{"id":"msg_07b3ca9d1fc1249f0068f41df8ddd481959599a571bcd1e988","type":"message","status":"incomplete","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"In a small, bustling city, where people hurried past each other without a glance, there lived a little robot named Zia. Zia was programmed for one purpose: to clean the streets. Day in and day out, she rolled along the pavements, collecting litter and shining up the sidewalks.\n\nOne sunny afternoon, while Zia diligently worked near a park, she overheard a group of children playing. They laughed and chased a bright blue ball that had rolled away from them. Suddenly, Zia noticed that the ball had gotten stuck in a low tree branch.\n\nThe children began to pout, unable to retrieve it. Zia’s circuits whirred as she considered her options. With a determined beep, she approached the tree. Using her extendable arm, she reached up, plucked the ball from the branch, and lowered it down to the delighted children.\n\nTheir faces lit up in joy. “Thank you, robot!” one of them exclaimed, running up to give her a high"}],"role":"assistant"}],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"default","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":{"input_tokens":16,"input_tokens_details":{"cached_tokens":0},"output_tokens":200,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":216},"user":null,"metadata":{}}}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"model": "gpt-4o-mini",
|
||||
"input": "What is the weather in San Francisco?",
|
||||
"tools": [
|
||||
{
|
||||
"type": "function",
|
||||
"name": "get_weather",
|
||||
"description": "Get the current weather for a location",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"location": {
|
||||
"type": "string",
|
||||
"description": "The city and state, e.g. San Francisco, CA"
|
||||
},
|
||||
"unit": {
|
||||
"type": "string",
|
||||
"enum": ["celsius", "fahrenheit"],
|
||||
"description": "The temperature unit"
|
||||
}
|
||||
},
|
||||
"required": ["location"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"tool_choice": "auto"
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"id": "resp_0a454b6c1909b7180068f41e875d1c8193a5587f2bbbd514a7",
|
||||
"object": "response",
|
||||
"created_at": 1760829063,
|
||||
"status": "completed",
|
||||
"background": false,
|
||||
"billing": {
|
||||
"payer": "developer"
|
||||
},
|
||||
"error": null,
|
||||
"incomplete_details": null,
|
||||
"instructions": null,
|
||||
"max_output_tokens": null,
|
||||
"max_tool_calls": null,
|
||||
"model": "gpt-4o-mini-2024-07-18",
|
||||
"output": [
|
||||
{
|
||||
"id": "fc_0a454b6c1909b7180068f41e87e63881939ecf9b242bf1332d",
|
||||
"type": "function_call",
|
||||
"status": "completed",
|
||||
"arguments": "{\"location\":\"San Francisco, CA\",\"unit\":\"celsius\"}",
|
||||
"call_id": "call_fibB55owSv9m6qr3TJJMnCEW",
|
||||
"name": "get_weather"
|
||||
}
|
||||
],
|
||||
"parallel_tool_calls": true,
|
||||
"previous_response_id": null,
|
||||
"prompt_cache_key": null,
|
||||
"reasoning": {
|
||||
"effort": null,
|
||||
"summary": null
|
||||
},
|
||||
"safety_identifier": null,
|
||||
"service_tier": "default",
|
||||
"store": true,
|
||||
"temperature": 1.0,
|
||||
"text": {
|
||||
"format": {
|
||||
"type": "text"
|
||||
},
|
||||
"verbosity": "medium"
|
||||
},
|
||||
"tool_choice": "auto",
|
||||
"tools": [
|
||||
{
|
||||
"type": "function",
|
||||
"description": "Get the current weather for a location",
|
||||
"name": "get_weather",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"location": {
|
||||
"type": "string",
|
||||
"description": "The city and state, e.g. San Francisco, CA"
|
||||
},
|
||||
"unit": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"celsius",
|
||||
"fahrenheit"
|
||||
],
|
||||
"description": "The temperature unit"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"location",
|
||||
"unit"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"strict": true
|
||||
}
|
||||
],
|
||||
"top_logprobs": 0,
|
||||
"top_p": 1.0,
|
||||
"truncation": "disabled",
|
||||
"usage": {
|
||||
"input_tokens": 76,
|
||||
"input_tokens_details": {
|
||||
"cached_tokens": 0
|
||||
},
|
||||
"output_tokens": 23,
|
||||
"output_tokens_details": {
|
||||
"reasoning_tokens": 0
|
||||
},
|
||||
"total_tokens": 99
|
||||
},
|
||||
"user": null,
|
||||
"metadata": {}
|
||||
}
|
||||
+655
@@ -0,0 +1,655 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Hosting.OpenAI.Tests;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
namespace Microsoft.Agents.AI.Hosting.OpenAI.UnitTests;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for the newly added content type event generators:
|
||||
/// - ErrorContentEventGenerator
|
||||
/// - ImageContentEventGenerator
|
||||
/// - AudioContentEventGenerator
|
||||
/// - HostedFileContentEventGenerator
|
||||
/// - FileContentEventGenerator
|
||||
/// </summary>
|
||||
public sealed class ContentTypeEventGeneratorTests : ConformanceTestBase
|
||||
{
|
||||
#region TextReasoningContent Tests
|
||||
|
||||
[Fact]
|
||||
public async Task TextReasoningContent_GeneratesReasoningItem_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "reasoning-content-agent";
|
||||
const string ExpectedText = "The first 10 prime numbers are: 2, 3, 5, 7, 11, 13, 17, 19, 23, and 29. Adding these together, we get:\n\n2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 + 29 = 129\n\nSo, the sum of the first 10 prime numbers is 129.";
|
||||
HttpClient client = await this.CreateTestServerAsync(AgentName, "You are a reasoning agent.", ExpectedText, (msg) =>
|
||||
[
|
||||
new TextReasoningContent(string.Empty), // Reasoning content is emitted but not included in the output text
|
||||
new TextContent(ExpectedText)
|
||||
]);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
Assert.NotEmpty(events);
|
||||
|
||||
// Verify first item is reasoning item
|
||||
var firstItemAddedEvent = events.First(e => e.GetProperty("type").GetString() == "response.output_item.added");
|
||||
var firstItem = firstItemAddedEvent.GetProperty("item");
|
||||
Assert.Equal("reasoning", firstItem.GetProperty("type").GetString());
|
||||
Assert.True(firstItemAddedEvent.GetProperty("output_index").GetInt32() == 0);
|
||||
|
||||
// Verify reasoning item done
|
||||
var firstItemDoneEvent = events.First(e =>
|
||||
e.GetProperty("type").GetString() == "response.output_item.done" &&
|
||||
e.GetProperty("output_index").GetInt32() == 0);
|
||||
var firstItemDone = firstItemDoneEvent.GetProperty("item");
|
||||
Assert.Equal("reasoning", firstItemDone.GetProperty("type").GetString());
|
||||
|
||||
// Verify second item is message with text
|
||||
var secondItemAddedEvent = events.First(e =>
|
||||
e.GetProperty("type").GetString() == "response.output_item.added" &&
|
||||
e.GetProperty("output_index").GetInt32() == 1);
|
||||
var secondItem = secondItemAddedEvent.GetProperty("item");
|
||||
Assert.Equal("message", secondItem.GetProperty("type").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TextReasoningContent_EmitsCorrectEventSequence_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "reasoning-sequence-agent";
|
||||
HttpClient client = await this.CreateTestServerAsync(AgentName, "You are a reasoning agent.", "Result", (msg) =>
|
||||
[
|
||||
new TextReasoningContent("reasoning step"),
|
||||
new TextContent("Result")
|
||||
]);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert - Verify event sequence
|
||||
List<string?> eventTypes = events.ConvertAll(e => e.GetProperty("type").GetString());
|
||||
|
||||
Assert.Equal("response.created", eventTypes[0]);
|
||||
Assert.Equal("response.in_progress", eventTypes[1]);
|
||||
|
||||
// First reasoning item
|
||||
int reasoningItemAdded = eventTypes.IndexOf("response.output_item.added");
|
||||
Assert.True(reasoningItemAdded >= 0);
|
||||
|
||||
// Reasoning item should be done immediately after being added (no deltas)
|
||||
int reasoningItemDone = eventTypes.FindIndex(reasoningItemAdded, e => e == "response.output_item.done");
|
||||
Assert.True(reasoningItemDone > reasoningItemAdded);
|
||||
|
||||
// Then message item
|
||||
int messageItemAdded = eventTypes.FindIndex(reasoningItemDone, e => e == "response.output_item.added");
|
||||
Assert.True(messageItemAdded > reasoningItemDone);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TextReasoningContent_OutputIndexIncremented_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "reasoning-index-agent";
|
||||
HttpClient client = await this.CreateTestServerAsync(AgentName, "You are a reasoning agent.", "Answer", (msg) =>
|
||||
[
|
||||
new TextReasoningContent("thinking..."),
|
||||
new TextContent("Answer")
|
||||
]);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert - Verify output indices
|
||||
var itemAddedEvents = events.Where(e => e.GetProperty("type").GetString() == "response.output_item.added").ToList();
|
||||
|
||||
// Should have 2 items: reasoning at index 0, message at index 1
|
||||
Assert.Equal(2, itemAddedEvents.Count);
|
||||
Assert.Equal(0, itemAddedEvents[0].GetProperty("output_index").GetInt32());
|
||||
Assert.Equal(1, itemAddedEvents[1].GetProperty("output_index").GetInt32());
|
||||
|
||||
// First item should be reasoning
|
||||
Assert.Equal("reasoning", itemAddedEvents[0].GetProperty("item").GetProperty("type").GetString());
|
||||
// Second item should be message
|
||||
Assert.Equal("message", itemAddedEvents[1].GetProperty("item").GetProperty("type").GetString());
|
||||
}
|
||||
|
||||
#endregion
|
||||
// Streaming request JSON for OpenAI Responses API
|
||||
private const string StreamingRequestJson = @"{""model"":""gpt-4o-mini"",""input"":""test"",""stream"":true}";
|
||||
|
||||
#region ErrorContent Tests
|
||||
|
||||
[Fact]
|
||||
public async Task ErrorContent_GeneratesRefusalItem_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "error-content-agent";
|
||||
const string ErrorMessage = "I cannot assist with that request.";
|
||||
HttpClient client = await this.CreateErrorContentAgentAsync(AgentName, ErrorMessage);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
Assert.NotEmpty(events);
|
||||
|
||||
// Verify item added event
|
||||
var itemAddedEvent = events.FirstOrDefault(e => e.GetProperty("type").GetString() == "response.output_item.added");
|
||||
Assert.True(itemAddedEvent.ValueKind != JsonValueKind.Undefined);
|
||||
|
||||
var item = itemAddedEvent.GetProperty("item");
|
||||
Assert.Equal("message", item.GetProperty("type").GetString());
|
||||
|
||||
// Verify content contains refusal
|
||||
var content = item.GetProperty("content");
|
||||
Assert.Equal(JsonValueKind.Array, content.ValueKind);
|
||||
|
||||
var contentArray = content.EnumerateArray().ToList();
|
||||
Assert.NotEmpty(contentArray);
|
||||
|
||||
var refusalContent = contentArray.First(c => c.GetProperty("type").GetString() == "refusal");
|
||||
Assert.True(refusalContent.ValueKind != JsonValueKind.Undefined);
|
||||
Assert.Equal(ErrorMessage, refusalContent.GetProperty("refusal").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ErrorContent_EmitsCorrectEventSequence_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "error-sequence-agent";
|
||||
const string ErrorMessage = "Access denied.";
|
||||
HttpClient client = await this.CreateErrorContentAgentAsync(AgentName, ErrorMessage);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert - Verify event sequence
|
||||
List<string?> eventTypes = events.ConvertAll(e => e.GetProperty("type").GetString());
|
||||
|
||||
Assert.Equal("response.created", eventTypes[0]);
|
||||
Assert.Equal("response.in_progress", eventTypes[1]);
|
||||
Assert.Contains("response.output_item.added", eventTypes);
|
||||
Assert.Contains("response.content_part.added", eventTypes);
|
||||
Assert.Contains("response.content_part.done", eventTypes);
|
||||
Assert.Contains("response.output_item.done", eventTypes);
|
||||
Assert.Contains("response.completed", eventTypes);
|
||||
|
||||
// Verify ordering
|
||||
int itemAdded = eventTypes.IndexOf("response.output_item.added");
|
||||
int partAdded = eventTypes.IndexOf("response.content_part.added");
|
||||
int partDone = eventTypes.IndexOf("response.content_part.done");
|
||||
int itemDone = eventTypes.IndexOf("response.output_item.done");
|
||||
|
||||
Assert.True(itemAdded < partAdded);
|
||||
Assert.True(partAdded < partDone);
|
||||
Assert.True(partDone < itemDone);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ErrorContent_SequenceNumbersAreCorrect_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "error-seq-num-agent";
|
||||
HttpClient client = await this.CreateErrorContentAgentAsync(AgentName, "Error message");
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert - Sequence numbers are sequential
|
||||
List<int> sequenceNumbers = events.ConvertAll(e => e.GetProperty("sequence_number").GetInt32());
|
||||
Assert.NotEmpty(sequenceNumbers);
|
||||
|
||||
for (int i = 0; i < sequenceNumbers.Count; i++)
|
||||
{
|
||||
Assert.Equal(i, sequenceNumbers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ImageContent Tests
|
||||
|
||||
[Fact]
|
||||
public async Task ImageContent_UriContent_GeneratesImageItem_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "image-uri-agent";
|
||||
const string ImageUrl = "https://example.com/image.jpg";
|
||||
HttpClient client = await this.CreateImageContentAgentAsync(AgentName, ImageUrl, isDataUri: false);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
var itemAddedEvent = events.FirstOrDefault(e => e.GetProperty("type").GetString() == "response.output_item.added");
|
||||
Assert.True(itemAddedEvent.ValueKind != JsonValueKind.Undefined);
|
||||
|
||||
var content = itemAddedEvent.GetProperty("item").GetProperty("content");
|
||||
var imageContent = content.EnumerateArray().First(c => c.GetProperty("type").GetString() == "input_image");
|
||||
|
||||
Assert.True(imageContent.ValueKind != JsonValueKind.Undefined);
|
||||
Assert.Equal(ImageUrl, imageContent.GetProperty("image_url").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ImageContent_DataContent_GeneratesImageItem_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "image-data-agent";
|
||||
const string DataUri = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==";
|
||||
HttpClient client = await this.CreateImageContentAgentAsync(AgentName, DataUri, isDataUri: true);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
var itemAddedEvent = events.FirstOrDefault(e => e.GetProperty("type").GetString() == "response.output_item.added");
|
||||
Assert.True(itemAddedEvent.ValueKind != JsonValueKind.Undefined);
|
||||
|
||||
var content = itemAddedEvent.GetProperty("item").GetProperty("content");
|
||||
var imageContent = content.EnumerateArray().First(c => c.GetProperty("type").GetString() == "input_image");
|
||||
|
||||
Assert.True(imageContent.ValueKind != JsonValueKind.Undefined);
|
||||
Assert.Equal(DataUri, imageContent.GetProperty("image_url").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ImageContent_WithDetailProperty_IncludesDetail_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "image-detail-agent";
|
||||
const string ImageUrl = "https://example.com/image.jpg";
|
||||
const string Detail = "high";
|
||||
HttpClient client = await this.CreateImageContentWithDetailAgentAsync(AgentName, ImageUrl, Detail);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
var itemAddedEvent = events.FirstOrDefault(e => e.GetProperty("type").GetString() == "response.output_item.added");
|
||||
Assert.True(itemAddedEvent.ValueKind != JsonValueKind.Undefined);
|
||||
|
||||
var content = itemAddedEvent.GetProperty("item").GetProperty("content");
|
||||
var imageContent = content.EnumerateArray().First(c => c.GetProperty("type").GetString() == "input_image");
|
||||
|
||||
Assert.True(imageContent.ValueKind != JsonValueKind.Undefined);
|
||||
Assert.True(imageContent.TryGetProperty("detail", out var detailProp));
|
||||
Assert.Equal(Detail, detailProp.GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ImageContent_EmitsCorrectEventSequence_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "image-sequence-agent";
|
||||
HttpClient client = await this.CreateImageContentAgentAsync(AgentName, "https://example.com/test.png", isDataUri: false);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
List<string?> eventTypes = events.ConvertAll(e => e.GetProperty("type").GetString());
|
||||
|
||||
Assert.Contains("response.output_item.added", eventTypes);
|
||||
Assert.Contains("response.content_part.added", eventTypes);
|
||||
Assert.Contains("response.content_part.done", eventTypes);
|
||||
Assert.Contains("response.output_item.done", eventTypes);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AudioContent Tests
|
||||
|
||||
[Fact]
|
||||
public async Task AudioContent_Mp3Format_GeneratesAudioItem_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "audio-mp3-agent";
|
||||
const string AudioDataUri = "data:audio/mpeg;base64,/+MYxAAAAAAAAAAAAAAAAAAAAAAASW5mbwAAAA8AAAACAAADhAC7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7v/////////////////////////////////////////////////////////////////";
|
||||
HttpClient client = await this.CreateAudioContentAgentAsync(AgentName, AudioDataUri, "audio/mpeg");
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
var itemAddedEvent = events.FirstOrDefault(e => e.GetProperty("type").GetString() == "response.output_item.added");
|
||||
Assert.True(itemAddedEvent.ValueKind != JsonValueKind.Undefined);
|
||||
|
||||
var content = itemAddedEvent.GetProperty("item").GetProperty("content");
|
||||
var audioContent = content.EnumerateArray().First(c => c.GetProperty("type").GetString() == "input_audio");
|
||||
|
||||
Assert.True(audioContent.ValueKind != JsonValueKind.Undefined);
|
||||
Assert.Equal(AudioDataUri, audioContent.GetProperty("data").GetString());
|
||||
Assert.Equal("mp3", audioContent.GetProperty("format").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AudioContent_WavFormat_GeneratesCorrectFormat_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "audio-wav-agent";
|
||||
const string AudioDataUri = "data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAAB9AAACABAAZGF0YQAAAAA=";
|
||||
HttpClient client = await this.CreateAudioContentAgentAsync(AgentName, AudioDataUri, "audio/wav");
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
var itemAddedEvent = events.FirstOrDefault(e => e.GetProperty("type").GetString() == "response.output_item.added");
|
||||
var content = itemAddedEvent.GetProperty("item").GetProperty("content");
|
||||
var audioContent = content.EnumerateArray().First(c => c.GetProperty("type").GetString() == "input_audio");
|
||||
|
||||
Assert.Equal("wav", audioContent.GetProperty("format").GetString());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("audio/opus", "opus")]
|
||||
[InlineData("audio/aac", "aac")]
|
||||
[InlineData("audio/flac", "flac")]
|
||||
[InlineData("audio/pcm", "pcm16")]
|
||||
[InlineData("audio/unknown", "mp3")] // Default fallback
|
||||
public async Task AudioContent_VariousFormats_GeneratesCorrectFormat_SuccessAsync(string mediaType, string expectedFormat)
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "audio-format-agent";
|
||||
const string AudioDataUri = "data:audio/test;base64,AQIDBA==";
|
||||
HttpClient client = await this.CreateAudioContentAgentAsync(AgentName, AudioDataUri, mediaType);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
var itemAddedEvent = events.FirstOrDefault(e => e.GetProperty("type").GetString() == "response.output_item.added");
|
||||
var content = itemAddedEvent.GetProperty("item").GetProperty("content");
|
||||
var audioContent = content.EnumerateArray().First(c => c.GetProperty("type").GetString() == "input_audio");
|
||||
|
||||
Assert.Equal(expectedFormat, audioContent.GetProperty("format").GetString());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HostedFileContent Tests
|
||||
|
||||
[Fact]
|
||||
public async Task HostedFileContent_GeneratesFileItem_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "hosted-file-agent";
|
||||
const string FileId = "file-abc123";
|
||||
HttpClient client = await this.CreateHostedFileContentAgentAsync(AgentName, FileId);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
var itemAddedEvent = events.FirstOrDefault(e => e.GetProperty("type").GetString() == "response.output_item.added");
|
||||
Assert.True(itemAddedEvent.ValueKind != JsonValueKind.Undefined);
|
||||
|
||||
var content = itemAddedEvent.GetProperty("item").GetProperty("content");
|
||||
var fileContent = content.EnumerateArray().First(c => c.GetProperty("type").GetString() == "input_file");
|
||||
|
||||
Assert.True(fileContent.ValueKind != JsonValueKind.Undefined);
|
||||
Assert.Equal(FileId, fileContent.GetProperty("file_id").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HostedFileContent_EmitsCorrectEventSequence_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "hosted-file-sequence-agent";
|
||||
HttpClient client = await this.CreateHostedFileContentAgentAsync(AgentName, "file-xyz789");
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
List<string?> eventTypes = events.ConvertAll(e => e.GetProperty("type").GetString());
|
||||
|
||||
Assert.Contains("response.output_item.added", eventTypes);
|
||||
Assert.Contains("response.content_part.added", eventTypes);
|
||||
Assert.Contains("response.content_part.done", eventTypes);
|
||||
Assert.Contains("response.output_item.done", eventTypes);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region FileContent Tests
|
||||
|
||||
[Fact]
|
||||
public async Task FileContent_WithDataUri_GeneratesFileItem_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "file-data-agent";
|
||||
const string FileDataUri = "data:application/pdf;base64,JVBERi0xLjQKJeLjz9MK";
|
||||
const string Filename = "document.pdf";
|
||||
HttpClient client = await this.CreateFileContentAgentAsync(AgentName, FileDataUri, Filename);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
var itemAddedEvent = events.FirstOrDefault(e => e.GetProperty("type").GetString() == "response.output_item.added");
|
||||
Assert.True(itemAddedEvent.ValueKind != JsonValueKind.Undefined);
|
||||
|
||||
var content = itemAddedEvent.GetProperty("item").GetProperty("content");
|
||||
var fileContent = content.EnumerateArray().First(c => c.GetProperty("type").GetString() == "input_file");
|
||||
|
||||
Assert.True(fileContent.ValueKind != JsonValueKind.Undefined);
|
||||
Assert.Equal(FileDataUri, fileContent.GetProperty("file_data").GetString());
|
||||
Assert.Equal(Filename, fileContent.GetProperty("filename").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FileContent_WithoutFilename_GeneratesFileItemWithoutFilename_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "file-no-name-agent";
|
||||
const string FileDataUri = "data:application/json;base64,eyJ0ZXN0IjoidmFsdWUifQ==";
|
||||
HttpClient client = await this.CreateFileContentAgentAsync(AgentName, FileDataUri, null);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
var itemAddedEvent = events.FirstOrDefault(e => e.GetProperty("type").GetString() == "response.output_item.added");
|
||||
var content = itemAddedEvent.GetProperty("item").GetProperty("content");
|
||||
var fileContent = content.EnumerateArray().First(c => c.GetProperty("type").GetString() == "input_file");
|
||||
|
||||
Assert.True(fileContent.ValueKind != JsonValueKind.Undefined);
|
||||
Assert.Equal(FileDataUri, fileContent.GetProperty("file_data").GetString());
|
||||
// filename property might be null or absent
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mixed Content Tests
|
||||
|
||||
[Fact]
|
||||
public async Task MixedContent_TextAndImage_GeneratesMultipleItems_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "mixed-text-image-agent";
|
||||
HttpClient client = await this.CreateMixedContentAgentAsync(AgentName);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
var itemAddedEvents = events.Where(e => e.GetProperty("type").GetString() == "response.output_item.added").ToList();
|
||||
|
||||
// Should have at least 2 items (text and image)
|
||||
Assert.True(itemAddedEvents.Count >= 2, $"Expected at least 2 items, got {itemAddedEvents.Count}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MixedContent_ErrorAndText_GeneratesMultipleItems_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
const string AgentName = "mixed-error-text-agent";
|
||||
HttpClient client = await this.CreateErrorAndTextContentAgentAsync(AgentName);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, AgentName, StreamingRequestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
var itemAddedEvents = events.Where(e => e.GetProperty("type").GetString() == "response.output_item.added").ToList();
|
||||
|
||||
// Should have multiple items
|
||||
Assert.True(itemAddedEvents.Count >= 2);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
private static List<JsonElement> ParseSseEvents(string sseContent)
|
||||
{
|
||||
var events = new List<JsonElement>();
|
||||
var lines = sseContent.Split('\n');
|
||||
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
var line = lines[i].TrimEnd('\r');
|
||||
|
||||
if (line.StartsWith("event: ", StringComparison.Ordinal) && i + 1 < lines.Length)
|
||||
{
|
||||
var dataLine = lines[i + 1].TrimEnd('\r');
|
||||
if (dataLine.StartsWith("data: ", StringComparison.Ordinal))
|
||||
{
|
||||
var jsonData = dataLine.Substring("data: ".Length);
|
||||
var doc = JsonDocument.Parse(jsonData);
|
||||
events.Add(doc.RootElement.Clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
private async Task<HttpClient> CreateErrorContentAgentAsync(string agentName, string errorMessage)
|
||||
{
|
||||
return await this.CreateTestServerAsync(agentName, "You are a test agent.", string.Empty, (msg) =>
|
||||
[new ErrorContent(errorMessage)]);
|
||||
}
|
||||
|
||||
private async Task<HttpClient> CreateImageContentAgentAsync(string agentName, string imageUri, bool isDataUri)
|
||||
{
|
||||
return await this.CreateTestServerAsync(agentName, "You are a test agent.", string.Empty, (msg) =>
|
||||
{
|
||||
if (isDataUri)
|
||||
{
|
||||
return [new DataContent(imageUri, "image/png")];
|
||||
}
|
||||
|
||||
return [new UriContent(imageUri, "image/jpeg")];
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<HttpClient> CreateImageContentWithDetailAgentAsync(string agentName, string imageUri, string detail)
|
||||
{
|
||||
return await this.CreateTestServerAsync(agentName, "You are a test agent.", string.Empty, (msg) =>
|
||||
{
|
||||
var uriContent = new UriContent(imageUri, "image/jpeg")
|
||||
{
|
||||
AdditionalProperties = new AdditionalPropertiesDictionary { ["detail"] = detail }
|
||||
};
|
||||
return [uriContent];
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<HttpClient> CreateAudioContentAgentAsync(string agentName, string audioDataUri, string mediaType)
|
||||
{
|
||||
return await this.CreateTestServerAsync(agentName, "You are a test agent.", string.Empty, (msg) =>
|
||||
[new DataContent(audioDataUri, mediaType)]);
|
||||
}
|
||||
|
||||
private async Task<HttpClient> CreateHostedFileContentAgentAsync(string agentName, string fileId)
|
||||
{
|
||||
return await this.CreateTestServerAsync(agentName, "You are a test agent.", string.Empty, (msg) =>
|
||||
[new HostedFileContent(fileId)]);
|
||||
}
|
||||
|
||||
private async Task<HttpClient> CreateFileContentAgentAsync(string agentName, string fileDataUri, string? filename)
|
||||
{
|
||||
// Extract media type from data URI
|
||||
string mediaType = "application/pdf"; // default
|
||||
if (fileDataUri.StartsWith("data:", StringComparison.Ordinal))
|
||||
{
|
||||
int semicolonIndex = fileDataUri.IndexOf(';');
|
||||
if (semicolonIndex > 5)
|
||||
{
|
||||
mediaType = fileDataUri.Substring(5, semicolonIndex - 5);
|
||||
}
|
||||
}
|
||||
return await this.CreateTestServerAsync(agentName, "You are a test agent.", string.Empty, (msg) =>
|
||||
[new DataContent(fileDataUri, mediaType) { Name = filename }]);
|
||||
}
|
||||
|
||||
private async Task<HttpClient> CreateMixedContentAgentAsync(string agentName)
|
||||
{
|
||||
return await this.CreateTestServerAsync(agentName, "You are a test agent.", string.Empty, (msg) =>
|
||||
[
|
||||
new TextContent("Here is an image:"),
|
||||
new UriContent("https://example.com/image.png", "image/png")
|
||||
]);
|
||||
}
|
||||
|
||||
private async Task<HttpClient> CreateErrorAndTextContentAgentAsync(string agentName)
|
||||
{
|
||||
return await this.CreateTestServerAsync(agentName, "You are a test agent.", string.Empty, (msg) =>
|
||||
[
|
||||
new TextContent("I need to inform you:"),
|
||||
new ErrorContent("The requested operation is not allowed.")
|
||||
]);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Microsoft.Agents.AI.Hosting.OpenAI.UnitTests;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for EndpointRouteBuilderExtensions.MapOpenAIResponses method.
|
||||
/// </summary>
|
||||
public sealed class EndpointRouteBuilderExtensionsTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Verifies that MapOpenAIResponses throws ArgumentNullException for null endpoints.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void MapOpenAIResponses_NullEndpoints_ThrowsArgumentNullException()
|
||||
{
|
||||
// Arrange
|
||||
AspNetCore.Routing.IEndpointRouteBuilder endpoints = null!;
|
||||
AIAgent agent = null!;
|
||||
|
||||
// Act & Assert
|
||||
ArgumentNullException exception = Assert.Throws<ArgumentNullException>(() =>
|
||||
endpoints.MapOpenAIResponses(agent));
|
||||
|
||||
Assert.Equal("endpoints", exception.ParamName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that MapOpenAIResponses throws ArgumentNullException for null agent.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void MapOpenAIResponses_NullAgent_ThrowsArgumentNullException()
|
||||
{
|
||||
// Arrange
|
||||
WebApplicationBuilder builder = WebApplication.CreateBuilder();
|
||||
builder.AddOpenAIResponses();
|
||||
using WebApplication app = builder.Build();
|
||||
|
||||
// Act & Assert
|
||||
AIAgent agent = null!;
|
||||
ArgumentNullException exception = Assert.Throws<ArgumentNullException>(() =>
|
||||
app.MapOpenAIResponses(agent));
|
||||
|
||||
Assert.Equal("agent", exception.ParamName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that MapOpenAIResponses validates agent name characters for URL safety.
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[InlineData("agent with spaces")]
|
||||
[InlineData("agent<script>")]
|
||||
[InlineData("agent\nwith\nnewlines")]
|
||||
[InlineData("agent\twith\ttabs")]
|
||||
[InlineData("agent?query")]
|
||||
[InlineData("agent#fragment")]
|
||||
public void MapOpenAIResponses_InvalidAgentNameCharacters_ThrowsArgumentException(string invalidName)
|
||||
{
|
||||
// Arrange
|
||||
WebApplicationBuilder builder = WebApplication.CreateBuilder();
|
||||
IChatClient mockChatClient = new TestHelpers.SimpleMockChatClient();
|
||||
builder.Services.AddKeyedSingleton("chat-client", mockChatClient);
|
||||
builder.Services.AddOpenAIResponses();
|
||||
builder.AddAIAgent(invalidName, "Instructions", chatClientServiceKey: "chat-client");
|
||||
using WebApplication app = builder.Build();
|
||||
AIAgent agent = app.Services.GetRequiredKeyedService<AIAgent>(invalidName);
|
||||
|
||||
// Act & Assert
|
||||
ArgumentException exception = Assert.Throws<ArgumentException>(() =>
|
||||
app.MapOpenAIResponses(agent));
|
||||
|
||||
Assert.Contains("invalid for URL routes", exception.Message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that MapOpenAIResponses accepts valid agent names with special characters.
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[InlineData("agent-name")]
|
||||
[InlineData("agent_name")]
|
||||
[InlineData("agent.name")]
|
||||
[InlineData("agent123")]
|
||||
[InlineData("123agent")]
|
||||
[InlineData("AGENT")]
|
||||
[InlineData("my-agent_v1.0")]
|
||||
public void MapOpenAIResponses_ValidAgentNameCharacters_DoesNotThrow(string validName)
|
||||
{
|
||||
// Arrange
|
||||
WebApplicationBuilder builder = WebApplication.CreateBuilder();
|
||||
IChatClient mockChatClient = new TestHelpers.SimpleMockChatClient();
|
||||
builder.Services.AddKeyedSingleton("chat-client", mockChatClient);
|
||||
builder.AddAIAgent(validName, "Instructions", chatClientServiceKey: "chat-client");
|
||||
builder.AddOpenAIResponses();
|
||||
using WebApplication app = builder.Build();
|
||||
AIAgent agent = app.Services.GetRequiredKeyedService<AIAgent>(validName);
|
||||
|
||||
// Act & Assert - Should not throw
|
||||
app.MapOpenAIResponses(agent);
|
||||
Assert.NotNull(app);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that custom paths can be specified for responses endpoints.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void MapOpenAIResponses_WithCustomPath_AcceptsValidPath()
|
||||
{
|
||||
// Arrange
|
||||
WebApplicationBuilder builder = WebApplication.CreateBuilder();
|
||||
IChatClient mockChatClient = new TestHelpers.SimpleMockChatClient();
|
||||
builder.Services.AddKeyedSingleton("chat-client", mockChatClient);
|
||||
builder.AddAIAgent("agent", "Instructions", chatClientServiceKey: "chat-client");
|
||||
builder.AddOpenAIResponses();
|
||||
using WebApplication app = builder.Build();
|
||||
AIAgent agent = app.Services.GetRequiredKeyedService<AIAgent>("agent");
|
||||
|
||||
// Act & Assert - Should not throw
|
||||
app.MapOpenAIResponses(agent, responsesPath: "/custom/responses");
|
||||
Assert.NotNull(app);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that multiple agents can be mapped to different paths.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void MapOpenAIResponses_MultipleAgents_Succeeds()
|
||||
{
|
||||
// Arrange
|
||||
WebApplicationBuilder builder = WebApplication.CreateBuilder();
|
||||
IChatClient mockChatClient = new TestHelpers.SimpleMockChatClient();
|
||||
builder.Services.AddKeyedSingleton("chat-client", mockChatClient);
|
||||
builder.AddAIAgent("agent1", "Instructions1", chatClientServiceKey: "chat-client");
|
||||
builder.AddAIAgent("agent2", "Instructions2", chatClientServiceKey: "chat-client");
|
||||
builder.AddOpenAIResponses();
|
||||
using WebApplication app = builder.Build();
|
||||
AIAgent agent1 = app.Services.GetRequiredKeyedService<AIAgent>("agent1");
|
||||
AIAgent agent2 = app.Services.GetRequiredKeyedService<AIAgent>("agent2");
|
||||
|
||||
// Act & Assert - Should not throw
|
||||
app.MapOpenAIResponses(agent1);
|
||||
app.MapOpenAIResponses(agent2);
|
||||
Assert.NotNull(app);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that long agent names are accepted.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void MapOpenAIResponses_LongAgentName_Succeeds()
|
||||
{
|
||||
// Arrange
|
||||
string longName = new('a', 100);
|
||||
WebApplicationBuilder builder = WebApplication.CreateBuilder();
|
||||
IChatClient mockChatClient = new TestHelpers.SimpleMockChatClient();
|
||||
builder.Services.AddKeyedSingleton("chat-client", mockChatClient);
|
||||
builder.AddAIAgent(longName, "Instructions", chatClientServiceKey: "chat-client");
|
||||
builder.AddOpenAIResponses();
|
||||
using WebApplication app = builder.Build();
|
||||
AIAgent agent = app.Services.GetRequiredKeyedService<AIAgent>(longName);
|
||||
|
||||
// Act & Assert - Should not throw
|
||||
app.MapOpenAIResponses(agent);
|
||||
Assert.NotNull(app);
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Microsoft.Agents.AI.Hosting.OpenAI.UnitTests;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for HostApplicationBuilderExtensions.AddOpenAIResponses method.
|
||||
/// </summary>
|
||||
public sealed class HostApplicationBuilderExtensionsTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Verifies that AddOpenAIResponses throws ArgumentNullException for null builder.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void AddOpenAIResponses_NullBuilder_ThrowsArgumentNullException()
|
||||
{
|
||||
// Arrange
|
||||
IHostApplicationBuilder builder = null!;
|
||||
|
||||
// Act & Assert
|
||||
ArgumentNullException exception = Assert.Throws<ArgumentNullException>(() =>
|
||||
builder.AddOpenAIResponses());
|
||||
|
||||
Assert.Equal("builder", exception.ParamName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that AddOpenAIResponses returns the same builder instance.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void AddOpenAIResponses_ValidBuilder_ReturnsSameBuilder()
|
||||
{
|
||||
// Arrange
|
||||
IHostApplicationBuilder builder = Host.CreateApplicationBuilder();
|
||||
|
||||
// Act
|
||||
IHostApplicationBuilder result = builder.AddOpenAIResponses();
|
||||
|
||||
// Assert
|
||||
Assert.Same(builder, result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that AddOpenAIResponses can be called multiple times without error.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void AddOpenAIResponses_MultipleCalls_DoesNotThrow()
|
||||
{
|
||||
// Arrange
|
||||
HostApplicationBuilder builder = Host.CreateApplicationBuilder();
|
||||
|
||||
// Act
|
||||
builder.AddOpenAIResponses();
|
||||
builder.AddOpenAIResponses();
|
||||
builder.AddOpenAIResponses();
|
||||
|
||||
// Assert - Building should succeed
|
||||
Assert.NotNull(builder.Services);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that AddOpenAIResponses properly configures JSON serialization options.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void AddOpenAIResponses_ConfiguresJsonSerialization()
|
||||
{
|
||||
// Arrange
|
||||
HostApplicationBuilder builder = Host.CreateApplicationBuilder();
|
||||
|
||||
// Act
|
||||
builder.AddOpenAIResponses();
|
||||
|
||||
// Assert - Should add services without error
|
||||
Assert.NotNull(builder.Services);
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(ProjectsCoreTargetFrameworks)</TargetFrameworks>
|
||||
<TargetFrameworks Condition="'$(Configuration)' == 'Debug'">$(ProjectsDebugCoreTargetFrameworks)</TargetFrameworks>
|
||||
<IsPackable>false</IsPackable>
|
||||
<NoWarn>$(NoWarn);OPENAI001;CA1812</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" VersionOverride="8.0.21" Condition="'$(TargetFramework)' == 'net8.0'" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Condition="'$(TargetFramework)' != 'net8.0'" />
|
||||
<PackageReference Include="OpenAI" />
|
||||
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-rc.2.25502.107" />
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" VersionOverride="10.0.0-rc.2.25502.107" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Agents.AI.Hosting.OpenAI\Microsoft.Agents.AI.Hosting.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.Agents.AI.Hosting\Microsoft.Agents.AI.Hosting.csproj" />
|
||||
<ProjectReference Include="..\..\src\Microsoft.Agents.AI\Microsoft.Agents.AI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="ConformanceTraces\**\*">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+1352
File diff suppressed because it is too large
Load Diff
+1179
File diff suppressed because it is too large
Load Diff
+1093
File diff suppressed because it is too large
Load Diff
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"profiles": {
|
||||
"Microsoft.Agents.AI.Hosting.OpenAI.UnitTests": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "https://localhost:60491;http://localhost:60492"
|
||||
}
|
||||
}
|
||||
}
|
||||
+815
@@ -0,0 +1,815 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI.Hosting.OpenAI.Responses.Models;
|
||||
using Microsoft.Agents.AI.Hosting.OpenAI.Tests;
|
||||
|
||||
namespace Microsoft.Agents.AI.Hosting.OpenAI.UnitTests;
|
||||
|
||||
/// <summary>
|
||||
/// Tests that verify our implementation generates correctly formatted streaming Server-Sent Events (SSE)
|
||||
/// that conform to the OpenAI Response API streaming response format.
|
||||
/// These tests validate the actual server implementation behavior by creating test servers
|
||||
/// and verifying the SSE output matches expected formats.
|
||||
/// For pure event deserialization tests, see OpenAIResponsesSerializationTests.
|
||||
/// </summary>
|
||||
public sealed class StreamingEventConformanceTests : ConformanceTestBase
|
||||
{
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_BasicFormat_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
// Extract expected text
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-basic-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-basic-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
|
||||
// Act
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert
|
||||
Assert.NotEmpty(events);
|
||||
Assert.All(events, evt =>
|
||||
{
|
||||
Assert.True(evt.TryGetProperty("type", out var type));
|
||||
Assert.True(evt.TryGetProperty("sequence_number", out var seqNum));
|
||||
Assert.Equal(JsonValueKind.Number, seqNum.ValueKind);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_HasCorrectEventTypesAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-types-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-types-agent", requestJson);
|
||||
|
||||
// Assert - HTTP response validation
|
||||
Assert.Equal(System.Net.HttpStatusCode.OK, httpResponse.StatusCode);
|
||||
Assert.Equal("text/event-stream", httpResponse.Content.Headers.ContentType?.MediaType);
|
||||
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
|
||||
// Act
|
||||
var events = ParseSseEvents(sseContent);
|
||||
List<string> eventTypes = events.ConvertAll(e => e.GetProperty("type").GetString()!);
|
||||
|
||||
// Assert - Verify all required event types are present
|
||||
Assert.Contains("response.created", eventTypes);
|
||||
Assert.Contains("response.in_progress", eventTypes);
|
||||
Assert.Contains("response.output_item.added", eventTypes);
|
||||
Assert.Contains("response.content_part.added", eventTypes);
|
||||
Assert.Contains("response.output_text.delta", eventTypes);
|
||||
Assert.Contains("response.output_text.done", eventTypes);
|
||||
Assert.Contains("response.content_part.done", eventTypes);
|
||||
Assert.Contains("response.output_item.done", eventTypes);
|
||||
|
||||
// Assert - Verify the order of events
|
||||
Assert.Equal("response.created", eventTypes[0]);
|
||||
Assert.Equal("response.in_progress", eventTypes[1]);
|
||||
|
||||
// Find indices of key events to verify ordering
|
||||
int outputItemAddedIndex = eventTypes.IndexOf("response.output_item.added");
|
||||
int contentPartAddedIndex = eventTypes.IndexOf("response.content_part.added");
|
||||
int firstDeltaIndex = eventTypes.IndexOf("response.output_text.delta");
|
||||
int textDoneIndex = eventTypes.IndexOf("response.output_text.done");
|
||||
int contentPartDoneIndex = eventTypes.IndexOf("response.content_part.done");
|
||||
int outputItemDoneIndex = eventTypes.IndexOf("response.output_item.done");
|
||||
|
||||
Assert.True(outputItemAddedIndex < contentPartAddedIndex, "output_item.added should come before content_part.added");
|
||||
Assert.True(contentPartAddedIndex < firstDeltaIndex, "content_part.added should come before first output_text.delta");
|
||||
Assert.True(firstDeltaIndex < textDoneIndex, "output_text.delta should come before output_text.done");
|
||||
Assert.True(textDoneIndex < contentPartDoneIndex, "output_text.done should come before content_part.done");
|
||||
Assert.True(contentPartDoneIndex < outputItemDoneIndex, "content_part.done should come before output_item.done");
|
||||
|
||||
// Assert - Last event should be a terminal state
|
||||
string lastEventType = eventTypes[^1];
|
||||
Assert.True(
|
||||
lastEventType == "response.completed" ||
|
||||
lastEventType == "response.incomplete" ||
|
||||
lastEventType == "response.failed",
|
||||
$"Last event should be a terminal state, got: {lastEventType}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_DeserializeCreatedEvent_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-created-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-created-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
var createdEventJson = events.First(e => e.GetProperty("type").GetString() == "response.created");
|
||||
|
||||
// Act
|
||||
string jsonString = createdEventJson.GetRawText();
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(jsonString, Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(evt);
|
||||
Assert.IsType<StreamingResponseCreated>(evt);
|
||||
var created = (StreamingResponseCreated)evt;
|
||||
Assert.Equal(0, created.SequenceNumber);
|
||||
Assert.NotNull(created.Response);
|
||||
Assert.NotNull(created.Response.Id);
|
||||
Assert.StartsWith("resp_", created.Response.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_DeserializeInProgressEvent_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-progress-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-progress-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
var inProgressEventJson = events.First(e => e.GetProperty("type").GetString() == "response.in_progress");
|
||||
|
||||
// Act
|
||||
string jsonString = inProgressEventJson.GetRawText();
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(jsonString, Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(evt);
|
||||
Assert.IsType<StreamingResponseInProgress>(evt);
|
||||
var inProgress = (StreamingResponseInProgress)evt;
|
||||
Assert.Equal(1, inProgress.SequenceNumber);
|
||||
Assert.NotNull(inProgress.Response);
|
||||
Assert.Equal(ResponseStatus.InProgress, inProgress.Response.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_DeserializeOutputItemAdded_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-item-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-item-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
var itemAddedJson = events.First(e => e.GetProperty("type").GetString() == "response.output_item.added");
|
||||
|
||||
// Act
|
||||
string jsonString = itemAddedJson.GetRawText();
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(jsonString, Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(evt);
|
||||
Assert.IsType<StreamingOutputItemAdded>(evt);
|
||||
var itemAdded = (StreamingOutputItemAdded)evt;
|
||||
Assert.Equal(0, itemAdded.OutputIndex);
|
||||
Assert.NotNull(itemAdded.Item);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_DeserializeContentPartAdded_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-part-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-part-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
var partAddedJson = events.First(e => e.GetProperty("type").GetString() == "response.content_part.added");
|
||||
|
||||
// Act
|
||||
string jsonString = partAddedJson.GetRawText();
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(jsonString, Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(evt);
|
||||
Assert.IsType<StreamingContentPartAdded>(evt);
|
||||
var partAdded = (StreamingContentPartAdded)evt;
|
||||
Assert.NotNull(partAdded.ItemId);
|
||||
Assert.Equal(0, partAdded.OutputIndex);
|
||||
Assert.Equal(0, partAdded.ContentIndex);
|
||||
Assert.NotNull(partAdded.Part);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_DeserializeTextDelta_SuccessAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-delta-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-delta-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
var textDeltaJson = events.First(e => e.GetProperty("type").GetString() == "response.output_text.delta");
|
||||
|
||||
// Act
|
||||
string jsonString = textDeltaJson.GetRawText();
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(jsonString, Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(evt);
|
||||
Assert.IsType<StreamingOutputTextDelta>(evt);
|
||||
var textDelta = (StreamingOutputTextDelta)evt;
|
||||
Assert.NotNull(textDelta.ItemId);
|
||||
Assert.Equal(0, textDelta.OutputIndex);
|
||||
Assert.Equal(0, textDelta.ContentIndex);
|
||||
Assert.NotNull(textDelta.Delta);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_AccumulateTextDeltas_MatchesFinalTextAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-accumulate-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-accumulate-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Act
|
||||
var deltas = new List<string>();
|
||||
string? finalText = null;
|
||||
|
||||
foreach (var eventJson in events)
|
||||
{
|
||||
string jsonString = eventJson.GetRawText();
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(jsonString, Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
|
||||
if (evt is StreamingOutputTextDelta delta)
|
||||
{
|
||||
deltas.Add(delta.Delta);
|
||||
}
|
||||
else if (evt is StreamingOutputTextDone done)
|
||||
{
|
||||
finalText = done.Text;
|
||||
}
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.NotEmpty(deltas);
|
||||
Assert.NotNull(finalText);
|
||||
|
||||
string accumulated = string.Concat(deltas);
|
||||
Assert.Equal(accumulated, finalText);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_SequenceNumbersAreSequentialAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-sequence-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-sequence-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Act
|
||||
var sequenceNumbers = new List<int>();
|
||||
foreach (var eventJson in events)
|
||||
{
|
||||
string jsonString = eventJson.GetRawText();
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(jsonString, Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
Assert.NotNull(evt);
|
||||
sequenceNumbers.Add(evt.SequenceNumber);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.NotEmpty(sequenceNumbers);
|
||||
Assert.Equal(0, sequenceNumbers.First());
|
||||
|
||||
for (int i = 0; i < sequenceNumbers.Count; i++)
|
||||
{
|
||||
Assert.Equal(i, sequenceNumbers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_FinalEvent_IsTerminalStateAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-terminal-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-terminal-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
var lastEventJson = events.Last();
|
||||
|
||||
// Act
|
||||
string jsonString = lastEventJson.GetRawText();
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(jsonString, Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(evt);
|
||||
|
||||
// Should be one of the terminal events
|
||||
bool isTerminal = evt is StreamingResponseCompleted ||
|
||||
evt is StreamingResponseIncomplete ||
|
||||
evt is StreamingResponseFailed;
|
||||
Assert.True(isTerminal, $"Expected terminal event, got: {evt.GetType().Name}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_AllEvents_CanBeDeserializedAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-deserialize-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-deserialize-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
|
||||
// Act & Assert
|
||||
foreach (var eventJson in ParseSseEvents(sseContent))
|
||||
{
|
||||
// Should not throw
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(eventJson.GetRawText(), Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
Assert.NotNull(evt);
|
||||
|
||||
// Verify polymorphic deserialization worked
|
||||
Assert.True(
|
||||
evt is StreamingResponseCreated ||
|
||||
evt is StreamingResponseInProgress ||
|
||||
evt is StreamingResponseCompleted ||
|
||||
evt is StreamingResponseIncomplete ||
|
||||
evt is StreamingResponseFailed ||
|
||||
evt is StreamingOutputItemAdded ||
|
||||
evt is StreamingOutputItemDone ||
|
||||
evt is StreamingContentPartAdded ||
|
||||
evt is StreamingContentPartDone ||
|
||||
evt is StreamingOutputTextDelta ||
|
||||
evt is StreamingOutputTextDone ||
|
||||
evt is StreamingFunctionCallArgumentsDelta ||
|
||||
evt is StreamingFunctionCallArgumentsDone,
|
||||
$"Unknown event type: {evt.GetType().Name}");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_IdConsistency_ValidAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-id-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-id-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert - Response ID consistency
|
||||
string? firstResponseId = null;
|
||||
|
||||
foreach (var eventJson in events)
|
||||
{
|
||||
string jsonString = eventJson.GetRawText();
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(jsonString, Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
Assert.NotNull(evt);
|
||||
|
||||
string? responseId = null;
|
||||
if (evt is StreamingResponseCreated created)
|
||||
{
|
||||
responseId = created.Response.Id;
|
||||
Assert.StartsWith("resp_", responseId);
|
||||
}
|
||||
else if (evt is StreamingResponseInProgress progress)
|
||||
{
|
||||
responseId = progress.Response.Id;
|
||||
}
|
||||
else if (evt is StreamingResponseCompleted completed)
|
||||
{
|
||||
responseId = completed.Response.Id;
|
||||
}
|
||||
else if (evt is StreamingResponseIncomplete incomplete)
|
||||
{
|
||||
responseId = incomplete.Response.Id;
|
||||
}
|
||||
else if (evt is StreamingResponseFailed failed)
|
||||
{
|
||||
responseId = failed.Response.Id;
|
||||
}
|
||||
|
||||
if (responseId != null)
|
||||
{
|
||||
firstResponseId ??= responseId;
|
||||
Assert.Equal(firstResponseId, responseId);
|
||||
}
|
||||
}
|
||||
|
||||
Assert.NotNull(firstResponseId);
|
||||
|
||||
// Assert - Item ID consistency
|
||||
var itemIds = new HashSet<string>();
|
||||
foreach (var eventJson in events)
|
||||
{
|
||||
string jsonString = eventJson.GetRawText();
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(jsonString, Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
|
||||
string? itemId = evt switch
|
||||
{
|
||||
StreamingOutputItemAdded added => added.Item.Id,
|
||||
StreamingOutputItemDone done => done.Item.Id,
|
||||
StreamingContentPartAdded partAdded => partAdded.ItemId,
|
||||
StreamingContentPartDone partDone => partDone.ItemId,
|
||||
StreamingOutputTextDelta textDelta => textDelta.ItemId,
|
||||
StreamingOutputTextDone textDone => textDone.ItemId,
|
||||
StreamingFunctionCallArgumentsDelta argsDelta => argsDelta.ItemId,
|
||||
StreamingFunctionCallArgumentsDone argsDone => argsDone.ItemId,
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (itemId != null)
|
||||
{
|
||||
Assert.NotEmpty(itemId);
|
||||
Assert.True(itemId.StartsWith("msg_", StringComparison.Ordinal) || itemId.StartsWith("fc_", StringComparison.Ordinal),
|
||||
$"Item ID should start with 'msg_' or 'fc_', got: {itemId}");
|
||||
itemIds.Add(itemId);
|
||||
}
|
||||
}
|
||||
|
||||
Assert.NotEmpty(itemIds);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_IndexConsistency_ValidAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-index-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-index-agent", requestJson);
|
||||
|
||||
// Assert - All events with output_index should have valid values
|
||||
foreach (var eventJson in ParseSseEvents(await httpResponse.Content.ReadAsStringAsync()))
|
||||
{
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(eventJson.GetRawText(), Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
Assert.NotNull(evt);
|
||||
|
||||
if (evt is StreamingOutputItemAdded or StreamingOutputItemDone or StreamingContentPartAdded or StreamingContentPartDone or
|
||||
StreamingOutputTextDelta or StreamingOutputTextDone or StreamingFunctionCallArgumentsDelta or StreamingFunctionCallArgumentsDone)
|
||||
{
|
||||
int outputIndex = evt switch
|
||||
{
|
||||
StreamingOutputItemAdded added => added.OutputIndex,
|
||||
StreamingOutputItemDone done => done.OutputIndex,
|
||||
StreamingContentPartAdded partAdded => partAdded.OutputIndex,
|
||||
StreamingContentPartDone partDone => partDone.OutputIndex,
|
||||
StreamingOutputTextDelta textDelta => textDelta.OutputIndex,
|
||||
StreamingOutputTextDone textDone => textDone.OutputIndex,
|
||||
StreamingFunctionCallArgumentsDelta argsDelta => argsDelta.OutputIndex,
|
||||
StreamingFunctionCallArgumentsDone argsDone => argsDone.OutputIndex,
|
||||
_ => -1
|
||||
};
|
||||
|
||||
Assert.True(outputIndex >= 0, $"output_index should be non-negative, got: {outputIndex}");
|
||||
}
|
||||
|
||||
if (evt is StreamingContentPartAdded or StreamingContentPartDone or StreamingOutputTextDelta or StreamingOutputTextDone)
|
||||
{
|
||||
int contentIndex = evt switch
|
||||
{
|
||||
StreamingContentPartAdded partAdded => partAdded.ContentIndex,
|
||||
StreamingContentPartDone partDone => partDone.ContentIndex,
|
||||
StreamingOutputTextDelta textDelta => textDelta.ContentIndex,
|
||||
StreamingOutputTextDone textDone => textDone.ContentIndex,
|
||||
_ => -1
|
||||
};
|
||||
|
||||
Assert.True(contentIndex >= 0, $"content_index should be non-negative, got: {contentIndex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_ResponseObjectEvolution_ValidAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-evolution-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-evolution-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
Response? createdResponse = null;
|
||||
Response? terminalResponse = null;
|
||||
|
||||
foreach (var eventJson in events)
|
||||
{
|
||||
string jsonString = eventJson.GetRawText();
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(jsonString, Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
Assert.NotNull(evt);
|
||||
|
||||
if (evt is StreamingResponseCreated created)
|
||||
{
|
||||
createdResponse = created.Response;
|
||||
Assert.Equal(ResponseStatus.InProgress, createdResponse.Status);
|
||||
Assert.Empty(createdResponse.Output);
|
||||
// Usage may be null or zero'd out in created event
|
||||
if (createdResponse.Usage != null)
|
||||
{
|
||||
Assert.Equal(0, createdResponse.Usage.InputTokens);
|
||||
Assert.Equal(0, createdResponse.Usage.OutputTokens);
|
||||
}
|
||||
}
|
||||
else if (evt is StreamingResponseInProgress progress)
|
||||
{
|
||||
Assert.Equal(ResponseStatus.InProgress, progress.Response.Status);
|
||||
}
|
||||
else if (evt is StreamingResponseCompleted completed)
|
||||
{
|
||||
terminalResponse = completed.Response;
|
||||
Assert.Equal(ResponseStatus.Completed, terminalResponse.Status);
|
||||
Assert.NotEmpty(terminalResponse.Output);
|
||||
Assert.NotNull(terminalResponse.Usage);
|
||||
Assert.True(terminalResponse.Usage.InputTokens > 0);
|
||||
Assert.True(terminalResponse.Usage.OutputTokens > 0);
|
||||
}
|
||||
else if (evt is StreamingResponseIncomplete incomplete)
|
||||
{
|
||||
terminalResponse = incomplete.Response;
|
||||
Assert.Equal(ResponseStatus.Incomplete, terminalResponse.Status);
|
||||
}
|
||||
else if (evt is StreamingResponseFailed failed)
|
||||
{
|
||||
terminalResponse = failed.Response;
|
||||
Assert.Equal(ResponseStatus.Failed, terminalResponse.Status);
|
||||
}
|
||||
}
|
||||
|
||||
Assert.NotNull(createdResponse);
|
||||
Assert.NotNull(terminalResponse);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_SseFormatCompliance_ValidAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-sse-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-sse-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
|
||||
// Assert - SSE format validation
|
||||
var lines = sseContent.Split('\n');
|
||||
Assert.NotEmpty(lines);
|
||||
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
string line = lines[i].TrimEnd('\r');
|
||||
|
||||
if (line.StartsWith("event: ", StringComparison.Ordinal))
|
||||
{
|
||||
// Every "event:" line must be followed by a "data:" line
|
||||
Assert.True(i + 1 < lines.Length, $"Event at line {i} has no following data line");
|
||||
string nextLine = lines[i + 1].TrimEnd('\r');
|
||||
Assert.True(nextLine.StartsWith("data: ", StringComparison.Ordinal),
|
||||
$"Line after event: should be data:, got: {nextLine}");
|
||||
|
||||
// Validate the data line contains valid JSON
|
||||
string jsonData = nextLine.Substring("data: ".Length);
|
||||
Assert.NotEmpty(jsonData);
|
||||
|
||||
// Should be parseable as JSON
|
||||
Exception? parseException = Record.Exception(() => JsonDocument.Parse(jsonData));
|
||||
Assert.Null(parseException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_EventPairing_ValidAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-pairing-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-pairing-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Track added vs done events
|
||||
var outputItemsAdded = new HashSet<int>();
|
||||
var outputItemsDone = new HashSet<int>();
|
||||
var contentPartsAdded = new List<(int outputIndex, int contentIndex)>();
|
||||
var contentPartsDone = new List<(int outputIndex, int contentIndex)>();
|
||||
|
||||
foreach (var eventJson in events)
|
||||
{
|
||||
string jsonString = eventJson.GetRawText();
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(jsonString, Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
Assert.NotNull(evt);
|
||||
|
||||
switch (evt)
|
||||
{
|
||||
case StreamingOutputItemAdded added:
|
||||
outputItemsAdded.Add(added.OutputIndex);
|
||||
break;
|
||||
case StreamingOutputItemDone done:
|
||||
outputItemsDone.Add(done.OutputIndex);
|
||||
// Every done must have a corresponding added
|
||||
Assert.Contains(done.OutputIndex, outputItemsAdded);
|
||||
break;
|
||||
case StreamingContentPartAdded partAdded:
|
||||
contentPartsAdded.Add((partAdded.OutputIndex, partAdded.ContentIndex));
|
||||
break;
|
||||
case StreamingContentPartDone partDone:
|
||||
contentPartsDone.Add((partDone.OutputIndex, partDone.ContentIndex));
|
||||
// Every done must have a corresponding added
|
||||
Assert.Contains((partDone.OutputIndex, partDone.ContentIndex), contentPartsAdded);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// All added items should eventually be done
|
||||
Assert.Equal(outputItemsAdded.Count, outputItemsDone.Count);
|
||||
Assert.Equal(contentPartsAdded.Count, contentPartsDone.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParseStreamingEvents_NoDuplicateSequenceNumbers_ValidAsync()
|
||||
{
|
||||
// Arrange
|
||||
string requestJson = LoadTraceFile("streaming/request.json");
|
||||
string expectedSseContent = LoadTraceFile("streaming/response.txt");
|
||||
|
||||
var expectedEvents = ParseSseEvents(expectedSseContent);
|
||||
var deltaEvents = expectedEvents.Where(e => e.GetProperty("type").GetString() == "response.output_text.delta").ToList();
|
||||
string expectedText = string.Concat(deltaEvents.Select(e => e.GetProperty("delta").GetString()));
|
||||
|
||||
HttpClient client = await this.CreateTestServerAsync("streaming-nodup-agent", "You are a helpful assistant.", expectedText);
|
||||
|
||||
// Act
|
||||
HttpResponseMessage httpResponse = await this.SendRequestAsync(client, "streaming-nodup-agent", requestJson);
|
||||
string sseContent = await httpResponse.Content.ReadAsStringAsync();
|
||||
var events = ParseSseEvents(sseContent);
|
||||
|
||||
// Assert - No duplicate sequence numbers
|
||||
var sequenceNumbers = new HashSet<int>();
|
||||
foreach (var eventJson in events)
|
||||
{
|
||||
string jsonString = eventJson.GetRawText();
|
||||
StreamingResponseEvent? evt = JsonSerializer.Deserialize(jsonString, Responses.ResponsesJsonContext.Default.StreamingResponseEvent);
|
||||
Assert.NotNull(evt);
|
||||
|
||||
Assert.True(sequenceNumbers.Add(evt.SequenceNumber),
|
||||
$"Duplicate sequence number found: {evt.SequenceNumber}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper to parse SSE events from streaming response content.
|
||||
/// </summary>
|
||||
private static List<JsonElement> ParseSseEvents(string sseContent)
|
||||
{
|
||||
var events = new List<JsonElement>();
|
||||
var lines = sseContent.Split('\n');
|
||||
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
var line = lines[i].TrimEnd('\r');
|
||||
|
||||
if (line.StartsWith("event: ", StringComparison.Ordinal))
|
||||
{
|
||||
// Next line should have the data
|
||||
if (i + 1 < lines.Length)
|
||||
{
|
||||
var dataLine = lines[i + 1].TrimEnd('\r');
|
||||
if (dataLine.StartsWith("data: ", StringComparison.Ordinal))
|
||||
{
|
||||
var jsonData = dataLine.Substring("data: ".Length);
|
||||
var doc = JsonDocument.Parse(jsonData);
|
||||
events.Add(doc.RootElement.Clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return events;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,488 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
namespace Microsoft.Agents.AI.Hosting.OpenAI.UnitTests;
|
||||
|
||||
internal static class TestHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple mock implementation of IChatClient for basic testing purposes.
|
||||
/// </summary>
|
||||
internal sealed class SimpleMockChatClient : IChatClient
|
||||
{
|
||||
private readonly string _responseText;
|
||||
|
||||
public SimpleMockChatClient(string responseText = "Test response")
|
||||
{
|
||||
this._responseText = responseText;
|
||||
}
|
||||
|
||||
public ChatClientMetadata Metadata { get; } = new("Test", new Uri("https://test.example.com"), "test-model");
|
||||
|
||||
public Task<ChatResponse> GetResponseAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
ChatOptions? options = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// Count input messages to simulate context size
|
||||
int messageCount = messages.Count();
|
||||
ChatMessage message = new(ChatRole.Assistant, this._responseText);
|
||||
ChatResponse response = new([message])
|
||||
{
|
||||
ModelId = "test-model",
|
||||
FinishReason = ChatFinishReason.Stop,
|
||||
Usage = new UsageDetails
|
||||
{
|
||||
InputTokenCount = 10 + (messageCount * 5), // More messages = more tokens
|
||||
OutputTokenCount = 5,
|
||||
TotalTokenCount = 15 + (messageCount * 5)
|
||||
}
|
||||
};
|
||||
return Task.FromResult(response);
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
ChatOptions? options = null,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
await Task.Delay(1, cancellationToken);
|
||||
|
||||
// Count input messages to simulate context size
|
||||
int messageCount = messages.Count();
|
||||
|
||||
// Split response into words to simulate streaming
|
||||
string[] words = this._responseText.Split(' ');
|
||||
for (int i = 0; i < words.Length; i++)
|
||||
{
|
||||
string content = i < words.Length - 1 ? words[i] + " " : words[i];
|
||||
ChatResponseUpdate update = new()
|
||||
{
|
||||
Contents = [new TextContent(content)],
|
||||
Role = ChatRole.Assistant
|
||||
};
|
||||
|
||||
// Add usage to the last update
|
||||
if (i == words.Length - 1)
|
||||
{
|
||||
update.Contents.Add(new UsageContent(new UsageDetails
|
||||
{
|
||||
InputTokenCount = 10 + (messageCount * 5),
|
||||
OutputTokenCount = 5,
|
||||
TotalTokenCount = 15 + (messageCount * 5)
|
||||
}));
|
||||
}
|
||||
|
||||
yield return update;
|
||||
}
|
||||
}
|
||||
|
||||
public object? GetService(Type serviceType, object? serviceKey = null) =>
|
||||
serviceType.IsInstanceOfType(this) ? this : null;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mock implementation of IChatClient that returns responses with image content.
|
||||
/// </summary>
|
||||
internal sealed class ImageContentMockChatClient : IChatClient
|
||||
{
|
||||
private readonly string _imageUrl;
|
||||
|
||||
public ImageContentMockChatClient(string imageUrl = "https://example.com/image.png")
|
||||
{
|
||||
this._imageUrl = imageUrl;
|
||||
}
|
||||
|
||||
public ChatClientMetadata Metadata { get; } = new("Test", new Uri("https://test.example.com"), "test-model");
|
||||
|
||||
public Task<ChatResponse> GetResponseAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
ChatOptions? options = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ChatMessage message = new(ChatRole.Assistant, [
|
||||
new TextContent("Here is an image:"),
|
||||
new UriContent(this._imageUrl, "image/png")
|
||||
]);
|
||||
ChatResponse response = new([message])
|
||||
{
|
||||
ModelId = "test-model",
|
||||
FinishReason = ChatFinishReason.Stop,
|
||||
Usage = new UsageDetails
|
||||
{
|
||||
InputTokenCount = 10,
|
||||
OutputTokenCount = 5,
|
||||
TotalTokenCount = 15
|
||||
}
|
||||
};
|
||||
return Task.FromResult(response);
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
ChatOptions? options = null,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
await Task.Delay(1, cancellationToken);
|
||||
|
||||
yield return new ChatResponseUpdate
|
||||
{
|
||||
Contents = [new TextContent("Here is an image:")],
|
||||
Role = ChatRole.Assistant
|
||||
};
|
||||
|
||||
yield return new ChatResponseUpdate
|
||||
{
|
||||
Contents = [
|
||||
new UriContent(this._imageUrl, "image/png"),
|
||||
new UsageContent(new UsageDetails
|
||||
{
|
||||
InputTokenCount = 10,
|
||||
OutputTokenCount = 5,
|
||||
TotalTokenCount = 15
|
||||
})
|
||||
],
|
||||
Role = ChatRole.Assistant
|
||||
};
|
||||
}
|
||||
|
||||
public object? GetService(Type serviceType, object? serviceKey = null) =>
|
||||
serviceType.IsInstanceOfType(this) ? this : null;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mock implementation of IChatClient that returns responses with audio content.
|
||||
/// </summary>
|
||||
internal sealed class AudioContentMockChatClient : IChatClient
|
||||
{
|
||||
private readonly byte[] _audioData;
|
||||
private readonly string _transcript;
|
||||
|
||||
public AudioContentMockChatClient(string audioData = "base64audiodata", string transcript = "This is a transcript")
|
||||
{
|
||||
this._audioData = System.Text.Encoding.UTF8.GetBytes(audioData);
|
||||
this._transcript = transcript;
|
||||
}
|
||||
|
||||
public ChatClientMetadata Metadata { get; } = new("Test", new Uri("https://test.example.com"), "test-model");
|
||||
|
||||
public Task<ChatResponse> GetResponseAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
ChatOptions? options = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ChatMessage message = new(ChatRole.Assistant, [
|
||||
new DataContent(this._audioData, "audio/wav")
|
||||
{
|
||||
AdditionalProperties = new AdditionalPropertiesDictionary
|
||||
{
|
||||
["transcript"] = this._transcript
|
||||
}
|
||||
}
|
||||
]);
|
||||
ChatResponse response = new([message])
|
||||
{
|
||||
ModelId = "test-model",
|
||||
FinishReason = ChatFinishReason.Stop,
|
||||
Usage = new UsageDetails
|
||||
{
|
||||
InputTokenCount = 10,
|
||||
OutputTokenCount = 5,
|
||||
TotalTokenCount = 15
|
||||
}
|
||||
};
|
||||
return Task.FromResult(response);
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
ChatOptions? options = null,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
await Task.Delay(1, cancellationToken);
|
||||
|
||||
yield return new ChatResponseUpdate
|
||||
{
|
||||
Contents = [
|
||||
new DataContent(this._audioData, "audio/wav")
|
||||
{
|
||||
AdditionalProperties = new AdditionalPropertiesDictionary
|
||||
{
|
||||
["transcript"] = this._transcript
|
||||
}
|
||||
},
|
||||
new UsageContent(new UsageDetails
|
||||
{
|
||||
InputTokenCount = 10,
|
||||
OutputTokenCount = 5,
|
||||
TotalTokenCount = 15
|
||||
})
|
||||
],
|
||||
Role = ChatRole.Assistant
|
||||
};
|
||||
}
|
||||
|
||||
public object? GetService(Type serviceType, object? serviceKey = null) =>
|
||||
serviceType.IsInstanceOfType(this) ? this : null;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mock implementation of IChatClient that returns responses with function calls.
|
||||
/// </summary>
|
||||
internal sealed class FunctionCallMockChatClient : IChatClient
|
||||
{
|
||||
private readonly string _functionName;
|
||||
private readonly Dictionary<string, object?> _arguments;
|
||||
|
||||
public FunctionCallMockChatClient(string functionName = "test_function", string arguments = "{\"param\":\"value\"}")
|
||||
{
|
||||
this._functionName = functionName;
|
||||
this._arguments = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object?>>(arguments) ?? new Dictionary<string, object?>();
|
||||
}
|
||||
|
||||
public ChatClientMetadata Metadata { get; } = new("Test", new Uri("https://test.example.com"), "test-model");
|
||||
|
||||
public Task<ChatResponse> GetResponseAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
ChatOptions? options = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ChatMessage message = new(ChatRole.Assistant, [
|
||||
new FunctionCallContent("call_123", this._functionName)
|
||||
{
|
||||
Arguments = this._arguments
|
||||
}
|
||||
]);
|
||||
ChatResponse response = new([message])
|
||||
{
|
||||
ModelId = "test-model",
|
||||
FinishReason = ChatFinishReason.ToolCalls,
|
||||
Usage = new UsageDetails
|
||||
{
|
||||
InputTokenCount = 80,
|
||||
OutputTokenCount = 25,
|
||||
TotalTokenCount = 105
|
||||
}
|
||||
};
|
||||
return Task.FromResult(response);
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
ChatOptions? options = null,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
await Task.Delay(1, cancellationToken);
|
||||
|
||||
yield return new ChatResponseUpdate
|
||||
{
|
||||
Contents = [
|
||||
new FunctionCallContent("call_123", this._functionName)
|
||||
{
|
||||
Arguments = this._arguments
|
||||
},
|
||||
new UsageContent(new UsageDetails
|
||||
{
|
||||
InputTokenCount = 80,
|
||||
OutputTokenCount = 25,
|
||||
TotalTokenCount = 105
|
||||
})
|
||||
],
|
||||
Role = ChatRole.Assistant
|
||||
};
|
||||
}
|
||||
|
||||
public object? GetService(Type serviceType, object? serviceKey = null) =>
|
||||
serviceType.IsInstanceOfType(this) ? this : null;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mock implementation of IChatClient that returns mixed content types.
|
||||
/// </summary>
|
||||
internal sealed class MixedContentMockChatClient : IChatClient
|
||||
{
|
||||
public ChatClientMetadata Metadata { get; } = new("Test", new Uri("https://test.example.com"), "test-model");
|
||||
|
||||
public Task<ChatResponse> GetResponseAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
ChatOptions? options = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ChatMessage message = new(ChatRole.Assistant, [
|
||||
new TextContent("Here are multiple content types:"),
|
||||
new UriContent("https://example.com/image.png", "image/png"),
|
||||
new TextContent("And some more text after the image.")
|
||||
]);
|
||||
ChatResponse response = new([message])
|
||||
{
|
||||
ModelId = "test-model",
|
||||
FinishReason = ChatFinishReason.Stop,
|
||||
Usage = new UsageDetails
|
||||
{
|
||||
InputTokenCount = 10,
|
||||
OutputTokenCount = 5,
|
||||
TotalTokenCount = 15
|
||||
}
|
||||
};
|
||||
return Task.FromResult(response);
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
ChatOptions? options = null,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
await Task.Delay(1, cancellationToken);
|
||||
|
||||
yield return new ChatResponseUpdate
|
||||
{
|
||||
Contents = [new TextContent("Here"), new TextContent(" are"), new TextContent(" multiple")],
|
||||
Role = ChatRole.Assistant
|
||||
};
|
||||
|
||||
yield return new ChatResponseUpdate
|
||||
{
|
||||
Contents = [new TextContent(" content"), new TextContent(" types:")],
|
||||
Role = ChatRole.Assistant
|
||||
};
|
||||
|
||||
yield return new ChatResponseUpdate
|
||||
{
|
||||
Contents = [new UriContent("https://example.com/image.png", "image/png")],
|
||||
Role = ChatRole.Assistant
|
||||
};
|
||||
|
||||
yield return new ChatResponseUpdate
|
||||
{
|
||||
Contents = [new TextContent("And"), new TextContent(" some"), new TextContent(" more")],
|
||||
Role = ChatRole.Assistant
|
||||
};
|
||||
|
||||
yield return new ChatResponseUpdate
|
||||
{
|
||||
Contents = [
|
||||
new TextContent(" text"),
|
||||
new TextContent(" after"),
|
||||
new TextContent(" the"),
|
||||
new TextContent(" image."),
|
||||
new UsageContent(new UsageDetails
|
||||
{
|
||||
InputTokenCount = 10,
|
||||
OutputTokenCount = 5,
|
||||
TotalTokenCount = 15
|
||||
})
|
||||
],
|
||||
Role = ChatRole.Assistant
|
||||
};
|
||||
}
|
||||
|
||||
public object? GetService(Type serviceType, object? serviceKey = null) =>
|
||||
serviceType.IsInstanceOfType(this) ? this : null;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mock implementation of IChatClient that returns custom content based on a provider function.
|
||||
/// </summary>
|
||||
internal sealed class CustomContentMockChatClient : IChatClient
|
||||
{
|
||||
private readonly Func<ChatMessage, IEnumerable<AIContent>> _contentProvider;
|
||||
|
||||
public CustomContentMockChatClient(Func<ChatMessage, IEnumerable<AIContent>> contentProvider)
|
||||
{
|
||||
this._contentProvider = contentProvider;
|
||||
}
|
||||
|
||||
public ChatClientMetadata Metadata { get; } = new("Test", new Uri("https://test.example.com"), "test-model");
|
||||
|
||||
public Task<ChatResponse> GetResponseAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
ChatOptions? options = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ChatMessage lastMessage = messages.Last();
|
||||
IEnumerable<AIContent> contents = this._contentProvider(lastMessage);
|
||||
ChatMessage message = new(ChatRole.Assistant, contents.ToList());
|
||||
ChatResponse response = new([message])
|
||||
{
|
||||
ModelId = "test-model",
|
||||
FinishReason = ChatFinishReason.Stop,
|
||||
Usage = new UsageDetails
|
||||
{
|
||||
InputTokenCount = 10,
|
||||
OutputTokenCount = 5,
|
||||
TotalTokenCount = 15
|
||||
}
|
||||
};
|
||||
return Task.FromResult(response);
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
ChatOptions? options = null,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
await Task.Delay(1, cancellationToken);
|
||||
|
||||
ChatMessage lastMessage = messages.Last();
|
||||
IEnumerable<AIContent> contents = this._contentProvider(lastMessage);
|
||||
List<AIContent> contentList = contents.ToList();
|
||||
|
||||
// Stream each content item separately
|
||||
for (int i = 0; i < contentList.Count; i++)
|
||||
{
|
||||
List<AIContent> updateContents = [contentList[i]];
|
||||
|
||||
// Add usage to the last update
|
||||
if (i == contentList.Count - 1)
|
||||
{
|
||||
updateContents.Add(new UsageContent(new UsageDetails
|
||||
{
|
||||
InputTokenCount = 10,
|
||||
OutputTokenCount = 5,
|
||||
TotalTokenCount = 15
|
||||
}));
|
||||
}
|
||||
|
||||
yield return new ChatResponseUpdate
|
||||
{
|
||||
Contents = updateContents,
|
||||
Role = ChatRole.Assistant
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public object? GetService(Type serviceType, object? serviceKey = null) =>
|
||||
serviceType.IsInstanceOfType(this) ? this : null;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -1,7 +1,8 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(ProjectsTargetFrameworks)</TargetFrameworks>
|
||||
<TargetFrameworks>$(ProjectsCoreTargetFrameworks)</TargetFrameworks>
|
||||
<TargetFrameworks Condition="'$(Configuration)' == 'Debug'">$(ProjectsDebugCoreTargetFrameworks)</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user