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
14 changes: 7 additions & 7 deletions .castiron.stats.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
schema_version: 1
generation_id: faf10787-3bdc-4568-b380-0861d1d6e36a
openapi_spec_hash: e767920c3fa8361ad29a90c8ea8397f2
openapi_transformed_spec_hash: 0ed231f6f1bee5e6180d6d4e4691cf92
config_hash: 83d6d59dd355a0913b94b00a8e37347f
codegen_sha: 1723773fd709b9e05fe6b2a0dba6bd89a0e7b644
codegen_hash: 209068bfadf82bbebdd982054c230b05718b15083751c01b498c1eb01bd4de3b
public_codegen_sha: e91edab5b26cd158367b0faa4b3a13d323988180
generation_id: 87b7588c-bf2a-41c6-9369-25b7fac9406c
openapi_spec_hash: 5dc81283fba93dcfeaeca3da5226d157
openapi_transformed_spec_hash: 42319a087893dfea0fdd818494eb2a8d
config_hash: c1867d38e1fb20037598907749312f81
codegen_sha: 0312112d44322208df3d1587c5b6eac1867be196
codegen_hash: c6efe506a6d3c692825695e888a088db61e9f7c1115801a7138ba4b3ec8b1d00
public_codegen_sha: 54359420e01e63cc0b61838459b07fcf8cc3a7bd
1 change: 1 addition & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ from openai.types import (
DecisionInputMessageParam,
DecisionInputPartUnionParam,
DecisionInputTextParam,
DecisionPromptCacheBreakpointParam,
)
```

Expand Down
53 changes: 21 additions & 32 deletions api_reference/openapi.transformed.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81847,22 +81847,9 @@ components:
minLength: 0
maxLength: 10485760
prompt_cache_breakpoint:
type:
- object
- 'null'
properties:
mode:
type: string
enum:
- explicit
default: explicit
x-stainless-const: true
description: The breakpoint mode. Always `explicit`.
required:
- mode
additionalProperties: false
title: Prompt cache breakpoint
description: Marks the exact end of a reusable prompt prefix. The breakpoint inherits its TTL from the request's `prompt_cache_options.ttl`; the boundary is not rounded to a token block.
anyOf:
- $ref: '#/components/schemas/DecisionPromptCacheBreakpoint'
- type: 'null'
required:
- type
- text
Expand Down Expand Up @@ -81890,22 +81877,9 @@ components:
description: The image detail level, using the selected model's image profile. Defaults to auto.
default: auto
prompt_cache_breakpoint:
type:
- object
- 'null'
properties:
mode:
type: string
enum:
- explicit
default: explicit
x-stainless-const: true
description: The breakpoint mode. Always `explicit`.
required:
- mode
additionalProperties: false
title: Prompt cache breakpoint
description: Marks the exact end of a reusable prompt prefix. The breakpoint inherits its TTL from the request's `prompt_cache_options.ttl`; the boundary is not rounded to a token block.
anyOf:
- $ref: '#/components/schemas/DecisionPromptCacheBreakpoint'
- type: 'null'
type:
type: string
enum:
Expand Down Expand Up @@ -107370,6 +107344,21 @@ components:
- type
- name
- prompt
DecisionPromptCacheBreakpoint:
type: object
properties:
mode:
type: string
enum:
- explicit
default: explicit
x-stainless-const: true
description: The breakpoint mode. Always `explicit`.
required:
- mode
additionalProperties: false
title: Prompt cache breakpoint
description: Marks the exact end of a reusable prompt prefix. The breakpoint inherits its TTL from the request's `prompt_cache_options.ttl`; the boundary is not rounded to a token block.
OAuthErrorCode:
anyOf:
- enum:
Expand Down
12 changes: 8 additions & 4 deletions scripts/castiron/generated-files.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"api.md": {
"mode": "100644",
"sha256": "f0d379b2373527bc8541d45b4f7297a3cebcf996d73da40cbc2b891f6f9af5eb"
"sha256": "cb21d922f4599e1d2d05cd937ac10072d3b3dbcbac4e73c9903cea2125944cef"
},
"scripts/castiron/CUSTOM_CODE.md": {
"mode": "100644",
Expand Down Expand Up @@ -755,7 +755,7 @@
},
"src/openai/types/__init__.py": {
"mode": "100644",
"sha256": "d9737e5373f40a8eae97a51a3ad158bcbd2cda4bb4d3e6f7b53b4ea21065e43d"
"sha256": "5caaa29a79510a0a3e4a92f7b59d3ccb3f8f6651706f658738cb5e2a22b91481"
},
"src/openai/types/admin/__init__.py": {
"mode": "100644",
Expand Down Expand Up @@ -4067,7 +4067,7 @@
},
"src/openai/types/decision_input_image_param.py": {
"mode": "100644",
"sha256": "2a823bb0b630ac1c1d3572eda41023686b15cb515e990b43a5892119daf55440"
"sha256": "ea10f5cc6ca0126d19b4f5a0b2acd06386d09fe44515ceda473fe920bdc0211d"
},
"src/openai/types/decision_input_message_param.py": {
"mode": "100644",
Expand All @@ -4079,7 +4079,11 @@
},
"src/openai/types/decision_input_text_param.py": {
"mode": "100644",
"sha256": "4555a371d1a82cadc4076b9c08b2d45ec4c31162a112aee319e1912243d6acf2"
"sha256": "96810356758e0082d22d20bc76e9dab61360ca37be3f2f9ad15ae01c473b470f"
},
"src/openai/types/decision_prompt_cache_breakpoint_param.py": {
"mode": "100644",
"sha256": "5317301f25465c321182e02dfe32b7ab5718e3ddf51d4ae5fccf01cbc7380a68"
},
"src/openai/types/deleted_skill.py": {
"mode": "100644",
Expand Down
3 changes: 3 additions & 0 deletions src/openai/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@
from .content_provenance_check_create_params import (
ContentProvenanceCheckCreateParams as ContentProvenanceCheckCreateParams,
)
from .decision_prompt_cache_breakpoint_param import (
DecisionPromptCacheBreakpointParam as DecisionPromptCacheBreakpointParam,
)
from .eval_stored_completions_data_source_config import (
EvalStoredCompletionsDataSourceConfig as EvalStoredCompletionsDataSourceConfig,
)
Expand Down
4 changes: 3 additions & 1 deletion src/openai/types/decision_input_image_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from typing import Optional
from typing_extensions import Literal, Required, TypedDict

from .decision_prompt_cache_breakpoint_param import DecisionPromptCacheBreakpointParam

__all__ = ["DecisionInputImageParam", "PromptCacheBreakpoint"]


Expand Down Expand Up @@ -37,7 +39,7 @@ class DecisionInputImageParam(TypedDict, total=False):
Defaults to auto.
"""

prompt_cache_breakpoint: Optional[PromptCacheBreakpoint]
prompt_cache_breakpoint: Optional[DecisionPromptCacheBreakpointParam]
"""Marks the exact end of a reusable prompt prefix.
The breakpoint inherits its TTL from the request's `prompt_cache_options.ttl`;
Expand Down
4 changes: 3 additions & 1 deletion src/openai/types/decision_input_text_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from typing import Optional
from typing_extensions import Literal, Required, TypedDict

from .decision_prompt_cache_breakpoint_param import DecisionPromptCacheBreakpointParam

__all__ = ["DecisionInputTextParam", "PromptCacheBreakpoint"]


Expand All @@ -23,7 +25,7 @@ class DecisionInputTextParam(TypedDict, total=False):

type: Required[Literal["input_text"]]

prompt_cache_breakpoint: Optional[PromptCacheBreakpoint]
prompt_cache_breakpoint: Optional[DecisionPromptCacheBreakpointParam]
"""Marks the exact end of a reusable prompt prefix.
The breakpoint inherits its TTL from the request's `prompt_cache_options.ttl`;
Expand Down
17 changes: 17 additions & 0 deletions src/openai/types/decision_prompt_cache_breakpoint_param.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# File generated from our OpenAPI spec by Castiron. See CONTRIBUTING.md for details.

from __future__ import annotations

from typing_extensions import Literal, Required, TypedDict

__all__ = ["DecisionPromptCacheBreakpointParam"]


class DecisionPromptCacheBreakpointParam(TypedDict, total=False):
Comment thread
jbeckwith-oai marked this conversation as resolved.
"""Marks the exact end of a reusable prompt prefix.
The breakpoint inherits its TTL from the request's `prompt_cache_options.ttl`; the boundary is not rounded to a token block.
"""

mode: Required[Literal["explicit"]]
"""The breakpoint mode. Always `explicit`."""
102 changes: 102 additions & 0 deletions tests/test_decision_prompt_cache.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
from __future__ import annotations

import json
from typing import TYPE_CHECKING, Any, Optional, get_type_hints
from typing_extensions import Literal, Required

import httpx2
import pytest

from openai import OpenAI, AsyncOpenAI
from openai.types.decision_input_text_param import PromptCacheBreakpoint as TextBreakpoint, DecisionInputTextParam
from openai.types.decision_input_image_param import PromptCacheBreakpoint as ImageBreakpoint, DecisionInputImageParam
from openai.types.decision_prompt_cache_breakpoint_param import DecisionPromptCacheBreakpointParam

if TYPE_CHECKING:
old_text: TextBreakpoint = {"mode": "explicit"}
old_image: ImageBreakpoint = {"mode": "explicit"}
shared_from_text: DecisionPromptCacheBreakpointParam = old_text
shared_from_image: DecisionPromptCacheBreakpointParam = old_image
text: DecisionInputTextParam = {
"type": "input_text",
"text": "synthetic",
"prompt_cache_breakpoint": shared_from_image,
}
image: DecisionInputImageParam = {
"type": "input_image",
"image_url": "https://example.test/image.png",
"prompt_cache_breakpoint": shared_from_text,
}


def test_legacy_breakpoint_exports() -> None:
for cls in (TextBreakpoint, ImageBreakpoint, DecisionPromptCacheBreakpointParam):
assert cls(mode="explicit") == {"mode": "explicit"}
assert get_type_hints(cls, include_extras=True)["mode"] == Required[Literal["explicit"]]
assert TextBreakpoint.__module__ == "openai.types.decision_input_text_param"
assert ImageBreakpoint.__module__ == "openai.types.decision_input_image_param"


def test_shared_breakpoint_annotations() -> None:
for cls in (DecisionInputTextParam, DecisionInputImageParam):
assert get_type_hints(cls)["prompt_cache_breakpoint"] == Optional[DecisionPromptCacheBreakpointParam]


def request_body(mode: str) -> dict[str, Any]:
content: list[dict[str, Any]] = [
{"type": "input_text", "text": "synthetic"},
{"type": "input_image", "image_url": "https://example.test/image.png"},
]
body: dict[str, Any] = {
"model": "synthetic-model",
"input": [{"role": "user", "content": content}],
"questions": [{"instructions": "Synthetic question", "type": "predicate"}],
}
if mode != "omitted":
body["prompt_cache_key"] = None if mode == "nulls" else "synthetic-key"
body["prompt_cache_options"] = None if mode == "nulls" else {"mode": mode, "ttl": "30m"}
for part in content:
part["prompt_cache_breakpoint"] = None if mode == "nulls" else {"mode": "explicit"}
return body


def capture_request(request: httpx2.Request, captured: list[dict[str, Any]]) -> httpx2.Response:
assert request.method == "POST"
assert str(request.url) == "https://example.test/decisions"
captured.append(json.loads(request.content))
return httpx2.Response(
200, json={"id": "decision_synthetic", "answers": [], "model": "synthetic-model", "usage": {}}
)


@pytest.mark.parametrize("mode", ["explicit", "implicit", "nulls", "omitted"])
def test_sync_request(mode: str) -> None:
captured: list[dict[str, Any]] = []
body = request_body(mode)
with OpenAI(
api_key="fake-test-key",
base_url="https://example.test",
max_retries=0,
http_client=httpx2.Client(
transport=httpx2.MockTransport(lambda request: capture_request(request, captured)), trust_env=False
),
) as client:
client.decisions.create(**body)
assert captured == [body]


@pytest.mark.asyncio
@pytest.mark.parametrize("mode", ["explicit", "implicit", "nulls", "omitted"])
async def test_async_request(mode: str) -> None:
captured: list[dict[str, Any]] = []
body = request_body(mode)
async with AsyncOpenAI(
api_key="fake-test-key",
base_url="https://example.test",
max_retries=0,
http_client=httpx2.AsyncClient(
transport=httpx2.MockTransport(lambda request: capture_request(request, captured)), trust_env=False
),
) as client:
await client.decisions.create(**body)
assert captured == [body]
Loading