Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bindings/python/tests/test_roundtrip.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def load_test_snapshots(test_case_name: str) -> list[Snapshot]:
if not snapshots_dir.exists():
return snapshots

providers = ["openai-chat-completions", "openai-responses", "anthropic"]
providers = ["chat-completions", "responses", "anthropic"]
turns = ["first_turn", "followup_turn"]

for provider in providers:
Expand Down Expand Up @@ -228,7 +228,7 @@ def test_openai_roundtrips(self, test_cases):

for snapshot in snapshots:
if (
snapshot.provider != "openai-chat-completions"
snapshot.provider != "chat-completions"
or not snapshot.request
):
continue
Expand Down
557 changes: 248 additions & 309 deletions bindings/python/uv.lock

Large diffs are not rendered by default.

477 changes: 448 additions & 29 deletions crates/lingua/src/providers/openai/convert.rs

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion payloads/cases/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,20 @@ export * from "./models";
// Export all case collections
export { simpleCases } from "./simple";
export { advancedCases } from "./advanced";
export { paramsCases } from "./params";

// Import and merge all collections for convenience
import { simpleCases } from "./simple";
import { advancedCases } from "./advanced";
import { paramsCases } from "./params";
import { mergeCollections } from "./utils";

// Combined collection of all test cases
export const allTestCases = mergeCollections(simpleCases, advancedCases);
export const allTestCases = mergeCollections(
simpleCases,
advancedCases,
paramsCases
);

// Legacy export for backward compatibility (can be removed later)
export const unifiedTestCases = allTestCases;
246 changes: 246 additions & 0 deletions payloads/cases/params.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
import { TestCaseCollection } from "./types";
import { OPENAI_RESPONSES_MODEL } from "./models";

// OpenAI Responses API parameter test cases
// Each test case exercises specific parameters from the Responses API
// Note: temperature, top_p, and logprobs are not supported with reasoning models (gpt-5-nano)
export const paramsCases: TestCaseCollection = {
// === Reasoning Configuration ===

reasoningSummaryParam: {
"chat-completions": null,
responses: {
model: OPENAI_RESPONSES_MODEL,
input: [{ role: "user", content: "2+2" }],
reasoning: {
effort: "medium",
summary: "detailed",
},
},
anthropic: null,
google: null,
bedrock: null,
},

// === Text Response Configuration ===

textFormatJsonObjectParam: {
"chat-completions": null,
responses: {
model: OPENAI_RESPONSES_MODEL,
input: [{ role: "user", content: "Return JSON with a=1" }],
text: {
format: {
type: "json_object",
},
},
},
anthropic: null,
google: null,
bedrock: null,
},

textFormatJsonSchemaParam: {
"chat-completions": null,
responses: {
model: OPENAI_RESPONSES_MODEL,
input: [{ role: "user", content: "Name: John, Age: 25" }],
text: {
format: {
type: "json_schema",
name: "person_info",
schema: {
type: "object",
properties: {
name: { type: "string" },
age: { type: "number" },
},
required: ["name", "age"],
additionalProperties: false,
},
strict: true,
},
},
},
anthropic: null,
google: null,
bedrock: null,
},

// === Tool Configuration ===

webSearchToolParam: {
"chat-completions": null,
responses: {
model: OPENAI_RESPONSES_MODEL,
input: [{ role: "user", content: "Latest OpenAI news" }],
tools: [{ type: "web_search_preview" }],
},
anthropic: null,
google: null,
bedrock: null,
},

codeInterpreterToolParam: {
"chat-completions": null,
responses: {
model: OPENAI_RESPONSES_MODEL,
input: [
{
role: "user",
content: "Execute Python code to generate a random number",
},
],
tools: [{ type: "code_interpreter", container: { type: "auto" } }],
},
anthropic: null,
google: null,
bedrock: null,
},

toolChoiceRequiredParam: {
"chat-completions": null,
responses: {
model: OPENAI_RESPONSES_MODEL,
input: [{ role: "user", content: "Tokyo weather" }],
tools: [
{
type: "function",
name: "get_weather",
description: "Get weather",
strict: true,
parameters: {
type: "object",
properties: {
location: { type: "string" },
},
required: ["location"],
additionalProperties: false,
},
},
],
tool_choice: { type: "function", name: "get_weather" },
},
anthropic: null,
google: null,
bedrock: null,
},

parallelToolCallsDisabledParam: {
"chat-completions": null,
responses: {
model: OPENAI_RESPONSES_MODEL,
input: [{ role: "user", content: "NYC and LA weather" }],
tools: [
{
type: "function",
name: "get_weather",
description: "Get weather",
strict: true,
parameters: {
type: "object",
properties: {
location: { type: "string" },
},
required: ["location"],
additionalProperties: false,
},
},
],
parallel_tool_calls: false,
},
anthropic: null,
google: null,
bedrock: null,
},

// === Context & State Management ===

instructionsParam: {
"chat-completions": null,
responses: {
model: OPENAI_RESPONSES_MODEL,
input: [{ role: "user", content: "Hi" }],
instructions: "Reply with OK",
},
anthropic: null,
google: null,
bedrock: null,
},

truncationAutoParam: {
"chat-completions": null,
responses: {
model: OPENAI_RESPONSES_MODEL,
input: [{ role: "user", content: "Hi" }],
truncation: "auto",
},
anthropic: null,
google: null,
bedrock: null,
},

storeDisabledParam: {
"chat-completions": null,
responses: {
model: OPENAI_RESPONSES_MODEL,
input: [{ role: "user", content: "Hi" }],
store: false,
},
anthropic: null,
google: null,
bedrock: null,
},

// === Caching & Performance ===

serviceTierParam: {
"chat-completions": null,
responses: {
model: OPENAI_RESPONSES_MODEL,
input: [{ role: "user", content: "Hi" }],
service_tier: "default",
},
anthropic: null,
google: null,
bedrock: null,
},

promptCacheKeyParam: {
"chat-completions": null,
responses: {
model: OPENAI_RESPONSES_MODEL,
input: [{ role: "user", content: "Hi" }],
prompt_cache_key: "test-key",
},
anthropic: null,
google: null,
bedrock: null,
},

// === Metadata & Identification ===

metadataParam: {
"chat-completions": null,
responses: {
model: OPENAI_RESPONSES_MODEL,
input: [{ role: "user", content: "Hi" }],
metadata: { key: "value" },
},
anthropic: null,
google: null,
bedrock: null,
},

safetyIdentifierParam: {
"chat-completions": null,
responses: {
model: OPENAI_RESPONSES_MODEL,
input: [{ role: "user", content: "Hi" }],
safety_identifier: "test-user",
},
anthropic: null,
google: null,
bedrock: null,
},
};
2 changes: 1 addition & 1 deletion payloads/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"@anthropic-ai/sdk": "^0.63.0",
"@aws-sdk/client-bedrock-runtime": "^3.700.0",
"@google/genai": "^1.34.0",
"openai": "^5.22.0"
"openai": "^6.16.0"
},
"devDependencies": {
"@types/node": "^22.9.0",
Expand Down
6 changes: 6 additions & 0 deletions payloads/scripts/providers/openai-responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ export async function executeOpenAIResponses(
}
}

// Skip followup if store is disabled (responses aren't persisted)
if (payload.store === false) {
console.log(`⚠️ Skipping followup for ${caseName} - store is disabled`);
return result;
}

// Create follow-up conversation if we have a non-streaming response with valid output
if (
result.response &&
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"model": "gpt-5-nano",
"input": [
{
"role": "user",
"content": "Execute Python code to generate a random number"
},
{
"id": "rs_010121ebb5e188bb006967e4607ddc81a18c909c1d7e06c207",
"type": "reasoning",
"summary": []
},
{
"id": "ci_010121ebb5e188bb006967e463fc6c81a1a49c34d9bf2a46ee",
"type": "code_interpreter_call",
"status": "completed",
"code": "import random\nrandom.randint(1,100)",
"container_id": "cntr_6967e46040a881918bafe26339ea573d07ea9c1707add848",
"outputs": null
},
{
"id": "rs_010121ebb5e188bb006967e46885e481a1bc1bf28e97360474",
"type": "reasoning",
"summary": []
},
{
"id": "msg_010121ebb5e188bb006967e46aacec81a18809a200d9cfc0c1",
"type": "message",
"status": "completed",
"content": [
{
"type": "output_text",
"annotations": [],
"logprobs": [],
"text": "Here's a random number between 1 and 100: 25\n\nWant another one or a different range (e.g., 0-1 float, 1-1000 int)?"
}
],
"role": "assistant"
},
{
"role": "user",
"content": "What should I do next?"
}
],
"tools": [
{
"type": "code_interpreter",
"container": {
"type": "auto"
}
}
]
}
Loading