From 15acfdd576e5a41632128bccd32bdc7bd0ed0685 Mon Sep 17 00:00:00 2001 From: Docs Bot Date: Fri, 10 Jul 2026 19:47:27 +0000 Subject: [PATCH 1/2] Document explicit prompt caching support in ChatOpenAI --- src/oss/python/integrations/chat/openai.mdx | 73 +++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/src/oss/python/integrations/chat/openai.mdx b/src/oss/python/integrations/chat/openai.mdx index 6715cee8e0..95609c2e5a 100644 --- a/src/oss/python/integrations/chat/openai.mdx +++ b/src/oss/python/integrations/chat/openai.mdx @@ -1887,6 +1887,79 @@ response1 = llm.invoke(messages) response2 = llm.invoke(messages, prompt_cache_key="override-cache-v1") ``` +### Explicit caching with breakpoints (Responses API) + + +Requires `langchain-openai>=1.3.5` and `openai>=2.45.0`. Only supported when using the [Responses API](/oss/python/integrations/chat/openai#responses-api). + + +OpenAI's Responses API supports [explicit prompt-cache breakpoints](https://developers.openai.com/api/docs/guides/prompt-caching?prompt-cache-api=responses#prompt-cache-breakpoints), which let you designate specific content blocks as cache boundaries. This gives you fine-grained control over which parts of a prompt are cached, rather than relying solely on automatic prefix caching. + +To mark a content block as a cache breakpoint, add `"prompt_cache_breakpoint": True` to the block: + +```python +from langchain_openai import ChatOpenAI + +llm = ChatOpenAI(model="gpt-4.1", use_responses_api=True) + +messages = [ + { + "role": "system", + "content": [ + { + "type": "text", + "text": "You are a helpful assistant with access to a large knowledge base.", + "prompt_cache_breakpoint": True, # [!code highlight] + } + ], + }, + {"role": "user", "content": "Summarize the key points."}, +] + +response = llm.invoke(messages) +``` + +Breakpoints are supported on text, image, and file content blocks. You can also nest `prompt_cache_breakpoint` inside an `extras` dict if you prefer to keep the LangChain content block structure clean: + +```python +content_block = { + "type": "text", + "text": "Long system prompt...", + "extras": {"prompt_cache_breakpoint": True}, +} +``` + +### Request-level cache options + + +Requires `langchain-openai>=1.3.5`. + + +You can pass request-level prompt cache options to the Responses API using the `prompt_cache_options` parameter on the model: + +```python +llm = ChatOpenAI( + model="gpt-4.1", + use_responses_api=True, + prompt_cache_options={"cache_type": "ephemeral"}, +) +``` + +### Cache write tokens + +When OpenAI writes new content to the prompt cache, it reports `cache_write_tokens` in the response. `ChatOpenAI` surfaces this as `cache_creation` in `input_token_details`: + +```python +response = llm.invoke(messages) + +cache_read = response.usage_metadata["input_token_details"].get("cache_read") +cache_creation = response.usage_metadata["input_token_details"].get("cache_creation") +print(f"Cache read tokens: {cache_read}") +print(f"Cache creation tokens: {cache_creation}") +``` + +On the `"priority"` and `"flex"` service tiers, these keys are prefixed with the tier name — for example, `"priority_cache_read"` and `"priority_cache_creation"`. + --- ## Flex processing From d5f71a5db1c0e0c4248ac555241a84e92edc9195 Mon Sep 17 00:00:00 2001 From: Naomi Pentrel <5212232+npentrel@users.noreply.github.com> Date: Sun, 12 Jul 2026 10:01:39 +0100 Subject: [PATCH 2/2] fixup:wq --- pyproject.toml | 2 +- ...rompt-cache-breakpoint-chat-completions.py | 65 ++++++++++++++++ .../openai-prompt-cache-breakpoint-extras.py | 47 +++++++++++ ...penai-prompt-cache-breakpoint-responses.py | 66 ++++++++++++++++ .../langchain/openai-prompt-cache-options.py | 41 ++++++++++ .../openai-prompt-cache-write-tokens.py | 55 +++++++++++++ src/oss/python/integrations/chat/openai.mdx | 77 +++++++------------ ...t-cache-breakpoint-chat-completions-py.mdx | 26 +++++++ ...enai-prompt-cache-breakpoint-extras-py.mdx | 7 ++ ...i-prompt-cache-breakpoint-responses-py.mdx | 27 +++++++ .../openai-prompt-cache-options-py.mdx | 16 ++++ .../openai-prompt-cache-write-tokens-py.mdx | 8 ++ uv.lock | 26 +++---- 13 files changed, 400 insertions(+), 63 deletions(-) create mode 100644 src/code-samples/langchain/openai-prompt-cache-breakpoint-chat-completions.py create mode 100644 src/code-samples/langchain/openai-prompt-cache-breakpoint-extras.py create mode 100644 src/code-samples/langchain/openai-prompt-cache-breakpoint-responses.py create mode 100644 src/code-samples/langchain/openai-prompt-cache-options.py create mode 100644 src/code-samples/langchain/openai-prompt-cache-write-tokens.py create mode 100644 src/snippets/code-samples/openai-prompt-cache-breakpoint-chat-completions-py.mdx create mode 100644 src/snippets/code-samples/openai-prompt-cache-breakpoint-extras-py.mdx create mode 100644 src/snippets/code-samples/openai-prompt-cache-breakpoint-responses-py.mdx create mode 100644 src/snippets/code-samples/openai-prompt-cache-options-py.mdx create mode 100644 src/snippets/code-samples/openai-prompt-cache-write-tokens-py.mdx diff --git a/pyproject.toml b/pyproject.toml index 7d36abc861..c87fcdf2de 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ dependencies = [ "nbconvert>=7.17.1", "langchain>=1.3.9", "langchain-anthropic>=1.0.0", - "langchain-openai>=1.1.14", + "langchain-openai>=1.3.5", "langchain-text-splitters>=0.3.0", "beautifulsoup4>=4.12.0", "requests>=2.31.0", diff --git a/src/code-samples/langchain/openai-prompt-cache-breakpoint-chat-completions.py b/src/code-samples/langchain/openai-prompt-cache-breakpoint-chat-completions.py new file mode 100644 index 0000000000..07e2052eea --- /dev/null +++ b/src/code-samples/langchain/openai-prompt-cache-breakpoint-chat-completions.py @@ -0,0 +1,65 @@ +# :snippet-start: openai-prompt-cache-breakpoint-chat-completions-py +from langchain_openai import ChatOpenAI + +# KEEP MODEL +llm = ChatOpenAI( + model="gpt-5.6-sol", + prompt_cache_options={"mode": "explicit"}, +) + +messages = [ + { + "role": "system", + "content": [ + { + "type": "text", + "text": ( + "You are a helpful assistant with access to a large knowledge base." + ), + "prompt_cache_breakpoint": {"mode": "explicit"}, # [!code highlight] + } + ], + }, + {"role": "user", "content": "Summarize the key points."}, +] + +response = llm.invoke(messages, prompt_cache_key="docs-breakpoint-v1") +# :snippet-end: + +# :remove-start: +if __name__ == "__main__": + # Breakpoints only apply to GPT-5.6+; OpenAI requires a prefix of at least + # 1024 tokens before cache reads/writes appear in usage metadata. + stable_prefix = "Stable, cacheable instructions and reference material. " * 400 + cache_messages = [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": stable_prefix, + "prompt_cache_breakpoint": {"mode": "explicit"}, + }, + {"type": "text", "text": "Say hello."}, + ], + } + ] + cache_key = "docs-breakpoint-cache-test-chat-completions-v1" + + first = llm.invoke(cache_messages, prompt_cache_key=cache_key) + second = llm.invoke(cache_messages, prompt_cache_key=cache_key) + + assert first.usage_metadata is not None + assert second.usage_metadata is not None + first_details = first.usage_metadata["input_token_details"] + second_details = second.usage_metadata["input_token_details"] + cache_read = second_details.get("cache_read") or 0 + + print(f"first invoke input_token_details: {first_details}") + print(f"second invoke input_token_details: {second_details}") + assert cache_read > 0, ( + "expected cache_read > 0 on second invoke with identical " + f"breakpoint prefix, got {second_details}" + ) + print("✓ prompt cache breakpoint (Chat Completions) sample completed") +# :remove-end: diff --git a/src/code-samples/langchain/openai-prompt-cache-breakpoint-extras.py b/src/code-samples/langchain/openai-prompt-cache-breakpoint-extras.py new file mode 100644 index 0000000000..03c4bf770e --- /dev/null +++ b/src/code-samples/langchain/openai-prompt-cache-breakpoint-extras.py @@ -0,0 +1,47 @@ +# :snippet-start: openai-prompt-cache-breakpoint-extras-py +content_block = { + "type": "text", + "text": "Long system prompt...", + "extras": {"prompt_cache_breakpoint": {"mode": "explicit"}}, +} +# :snippet-end: + +# :remove-start: +if __name__ == "__main__": + from langchain_openai import ChatOpenAI + + assert content_block["extras"]["prompt_cache_breakpoint"] == {"mode": "explicit"} + + # Breakpoints only apply to GPT-5.6+; OpenAI requires a prefix of at least + # 1024 tokens before cache reads/writes appear in usage metadata. + stable_prefix = "Stable, cacheable instructions and reference material. " * 400 + # KEEP MODEL + llm = ChatOpenAI( + model="gpt-5.6-sol", + prompt_cache_options={"mode": "explicit"}, + ) + cache_messages = [ + { + "role": "user", + "content": [ + { + **content_block, + "text": stable_prefix, + }, + {"type": "text", "text": "Say hello."}, + ], + } + ] + cache_key = "docs-breakpoint-extras-v1" + first = llm.invoke(cache_messages, prompt_cache_key=cache_key) + second = llm.invoke(cache_messages, prompt_cache_key=cache_key) + + assert first.usage_metadata is not None + assert second.usage_metadata is not None + cache_read = second.usage_metadata["input_token_details"].get("cache_read") or 0 + assert cache_read > 0, ( + "expected cache_read > 0 when breakpoint is nested in extras, " + f"got {second.usage_metadata['input_token_details']}" + ) + print("✓ extras prompt_cache_breakpoint sample completed") +# :remove-end: diff --git a/src/code-samples/langchain/openai-prompt-cache-breakpoint-responses.py b/src/code-samples/langchain/openai-prompt-cache-breakpoint-responses.py new file mode 100644 index 0000000000..3b31828fa4 --- /dev/null +++ b/src/code-samples/langchain/openai-prompt-cache-breakpoint-responses.py @@ -0,0 +1,66 @@ +# :snippet-start: openai-prompt-cache-breakpoint-responses-py +from langchain_openai import ChatOpenAI + +# KEEP MODEL +llm = ChatOpenAI( + model="gpt-5.6-sol", + use_responses_api=True, + prompt_cache_options={"mode": "explicit"}, +) + +messages = [ + { + "role": "system", + "content": [ + { + "type": "text", + "text": ( + "You are a helpful assistant with access to a large knowledge base." + ), + "prompt_cache_breakpoint": {"mode": "explicit"}, # [!code highlight] + } + ], + }, + {"role": "user", "content": "Summarize the key points."}, +] + +response = llm.invoke(messages, prompt_cache_key="docs-breakpoint-v1") +# :snippet-end: + +# :remove-start: +if __name__ == "__main__": + # Breakpoints only apply to GPT-5.6+; OpenAI requires a prefix of at least + # 1024 tokens before cache reads/writes appear in usage metadata. + stable_prefix = "Stable, cacheable instructions and reference material. " * 400 + cache_messages = [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": stable_prefix, + "prompt_cache_breakpoint": {"mode": "explicit"}, + }, + {"type": "text", "text": "Say hello."}, + ], + } + ] + cache_key = "docs-breakpoint-cache-test-responses-v1" + + first = llm.invoke(cache_messages, prompt_cache_key=cache_key) + second = llm.invoke(cache_messages, prompt_cache_key=cache_key) + + assert first.usage_metadata is not None + assert second.usage_metadata is not None + first_details = first.usage_metadata["input_token_details"] + second_details = second.usage_metadata["input_token_details"] + cache_read = second_details.get("cache_read") or 0 + + print(f"first invoke input_token_details: {first_details}") + print(f"second invoke input_token_details: {second_details}") + assert cache_read > 0, ( + "expected cache_read > 0 on second invoke with identical " + f"breakpoint prefix, got {second_details}" + ) + print("✓ prompt cache breakpoint (Responses API) sample completed") +# :remove-end: diff --git a/src/code-samples/langchain/openai-prompt-cache-options.py b/src/code-samples/langchain/openai-prompt-cache-options.py new file mode 100644 index 0000000000..640fe32e54 --- /dev/null +++ b/src/code-samples/langchain/openai-prompt-cache-options.py @@ -0,0 +1,41 @@ +# :snippet-start: openai-prompt-cache-options-py +from langchain_openai import ChatOpenAI + +# KEEP MODEL +llm = ChatOpenAI( + model="gpt-5.6-sol", + prompt_cache_options={"mode": "explicit", "ttl": "30m"}, +) + +messages = [{"role": "user", "content": "Hello"}] + +# Override per request +response = llm.invoke( + messages, + prompt_cache_options={"mode": "implicit"}, +) +# :snippet-end: + +# :remove-start: +if __name__ == "__main__": + assert response is not None + assert response.usage_metadata is not None + + # Confirm model-level options remain available on a follow-up call, and that + # a per-request override is accepted without error. + default_response = llm.invoke(messages) + assert default_response is not None + + # KEEP MODEL + responses_llm = ChatOpenAI( + model="gpt-5.6-sol", + use_responses_api=True, + prompt_cache_options={"mode": "explicit", "ttl": "30m"}, + ) + responses_result = responses_llm.invoke( + messages, + prompt_cache_options={"mode": "implicit"}, + ) + assert responses_result is not None + print("✓ prompt_cache_options model-level and per-request override completed") +# :remove-end: diff --git a/src/code-samples/langchain/openai-prompt-cache-write-tokens.py b/src/code-samples/langchain/openai-prompt-cache-write-tokens.py new file mode 100644 index 0000000000..3813607b8b --- /dev/null +++ b/src/code-samples/langchain/openai-prompt-cache-write-tokens.py @@ -0,0 +1,55 @@ +# :remove-start: +from langchain_openai import ChatOpenAI + +# Breakpoints only apply to GPT-5.6+; OpenAI requires a prefix of at least +# 1024 tokens before cache reads/writes appear in usage metadata. +stable_prefix = "Stable, cacheable instructions and reference material. " * 400 +# KEEP MODEL +llm = ChatOpenAI( + model="gpt-5.6-sol", + prompt_cache_options={"mode": "explicit"}, +) +messages = [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": stable_prefix, + "prompt_cache_breakpoint": {"mode": "explicit"}, + }, + {"type": "text", "text": "Say hello."}, + ], + } +] +# :remove-end: + +# :snippet-start: openai-prompt-cache-write-tokens-py +response = llm.invoke(messages) + +cache_read = response.usage_metadata["input_token_details"].get("cache_read") +cache_creation = response.usage_metadata["input_token_details"].get("cache_creation") +print(f"Cache read tokens: {cache_read}") +print(f"Cache creation tokens: {cache_creation}") +# :snippet-end: + +# :remove-start: +if __name__ == "__main__": + assert response is not None + assert response.usage_metadata is not None + # Exercise the documented accessors; a second call should show a cache read. + cache_key = "docs-prompt-cache-write-tokens-v1" + first = llm.invoke(messages, prompt_cache_key=cache_key) + second = llm.invoke(messages, prompt_cache_key=cache_key) + assert first.usage_metadata is not None + assert second.usage_metadata is not None + first_details = first.usage_metadata["input_token_details"] + second_details = second.usage_metadata["input_token_details"] + print(f"first invoke input_token_details: {first_details}") + print(f"second invoke input_token_details: {second_details}") + cache_read_second = second_details.get("cache_read") or 0 + assert cache_read_second > 0, ( + f"expected cache_read > 0 on second invoke, got {second_details}" + ) + print("✓ cache write/read token reporting sample completed") +# :remove-end: diff --git a/src/oss/python/integrations/chat/openai.mdx b/src/oss/python/integrations/chat/openai.mdx index 95609c2e5a..ddfa54e79a 100644 --- a/src/oss/python/integrations/chat/openai.mdx +++ b/src/oss/python/integrations/chat/openai.mdx @@ -3,6 +3,12 @@ title: "ChatOpenAI integration" description: "Integrate with the ChatOpenAI chat model using LangChain Python." --- +import OpenaiPromptCacheBreakpointChatCompletionsPy from '/snippets/code-samples/openai-prompt-cache-breakpoint-chat-completions-py.mdx'; +import OpenaiPromptCacheBreakpointResponsesPy from '/snippets/code-samples/openai-prompt-cache-breakpoint-responses-py.mdx'; +import OpenaiPromptCacheBreakpointExtrasPy from '/snippets/code-samples/openai-prompt-cache-breakpoint-extras-py.mdx'; +import OpenaiPromptCacheOptionsPy from '/snippets/code-samples/openai-prompt-cache-options-py.mdx'; +import OpenaiPromptCacheWriteTokensPy from '/snippets/code-samples/openai-prompt-cache-write-tokens-py.mdx'; + You can find information about OpenAI's latest models, their costs, context windows, and supported input types in the [OpenAI Platform](https://platform.openai.com) docs. @@ -1887,76 +1893,49 @@ response1 = llm.invoke(messages) response2 = llm.invoke(messages, prompt_cache_key="override-cache-v1") ``` -### Explicit caching with breakpoints (Responses API) +### Explicit caching with breakpoints -Requires `langchain-openai>=1.3.5` and `openai>=2.45.0`. Only supported when using the [Responses API](/oss/python/integrations/chat/openai#responses-api). +Requires `langchain-openai>=1.3.5`. Supported on both the Chat Completions API and the [Responses API](/oss/python/integrations/chat/openai#responses-api). -OpenAI's Responses API supports [explicit prompt-cache breakpoints](https://developers.openai.com/api/docs/guides/prompt-caching?prompt-cache-api=responses#prompt-cache-breakpoints), which let you designate specific content blocks as cache boundaries. This gives you fine-grained control over which parts of a prompt are cached, rather than relying solely on automatic prefix caching. - -To mark a content block as a cache breakpoint, add `"prompt_cache_breakpoint": True` to the block: +OpenAI supports [explicit prompt-cache breakpoints](https://developers.openai.com/api/docs/guides/prompt-caching#prompt-cache-breakpoints), which let you designate specific content blocks as cache boundaries. This gives you fine-grained control over which parts of a prompt are cached, rather than relying solely on automatic prefix caching. -```python -from langchain_openai import ChatOpenAI - -llm = ChatOpenAI(model="gpt-4.1", use_responses_api=True) - -messages = [ - { - "role": "system", - "content": [ - { - "type": "text", - "text": "You are a helpful assistant with access to a large knowledge base.", - "prompt_cache_breakpoint": True, # [!code highlight] - } - ], - }, - {"role": "user", "content": "Summarize the key points."}, -] +To mark a content block as a cache breakpoint, add `"prompt_cache_breakpoint": {"mode": "explicit"}` to the block. Explicit breakpoints require GPT-5.6 or later model families. -response = llm.invoke(messages) -``` + + + + + + + + Breakpoints are supported on text, image, and file content blocks. You can also nest `prompt_cache_breakpoint` inside an `extras` dict if you prefer to keep the LangChain content block structure clean: -```python -content_block = { - "type": "text", - "text": "Long system prompt...", - "extras": {"prompt_cache_breakpoint": True}, -} -``` + ### Request-level cache options -Requires `langchain-openai>=1.3.5`. +Requires `langchain-openai>=1.3.5`. `prompt_cache_options` applies to GPT-5.6 and later model families. -You can pass request-level prompt cache options to the Responses API using the `prompt_cache_options` parameter on the model: +You can pass request-level prompt cache options using the `prompt_cache_options` parameter on the model or per invocation: -```python -llm = ChatOpenAI( - model="gpt-4.1", - use_responses_api=True, - prompt_cache_options={"cache_type": "ephemeral"}, -) -``` +- **`mode`**: `"implicit"` (default) or `"explicit"`. In `"implicit"` mode, OpenAI places a cache breakpoint on the latest message and also uses any explicit breakpoints you provide. In `"explicit"` mode, only your breakpoints are used for cache reads and writes. If the request has no explicit breakpoints, it does not use prompt caching. +- **`ttl`**: Minimum cache lifetime for breakpoints written by the request. The only supported value is `"30m"`, which is also the default. + + + +For models before the GPT-5.6 family, use `prompt_cache_retention` instead (`"in_memory"` or `"24h"`). That field is separate from `prompt_cache_options` and is deprecated on GPT-5.6 and later model families. ### Cache write tokens When OpenAI writes new content to the prompt cache, it reports `cache_write_tokens` in the response. `ChatOpenAI` surfaces this as `cache_creation` in `input_token_details`: -```python -response = llm.invoke(messages) - -cache_read = response.usage_metadata["input_token_details"].get("cache_read") -cache_creation = response.usage_metadata["input_token_details"].get("cache_creation") -print(f"Cache read tokens: {cache_read}") -print(f"Cache creation tokens: {cache_creation}") -``` + On the `"priority"` and `"flex"` service tiers, these keys are prefixed with the tier name — for example, `"priority_cache_read"` and `"priority_cache_creation"`. diff --git a/src/snippets/code-samples/openai-prompt-cache-breakpoint-chat-completions-py.mdx b/src/snippets/code-samples/openai-prompt-cache-breakpoint-chat-completions-py.mdx new file mode 100644 index 0000000000..cb75cd2d79 --- /dev/null +++ b/src/snippets/code-samples/openai-prompt-cache-breakpoint-chat-completions-py.mdx @@ -0,0 +1,26 @@ +```python +from langchain_openai import ChatOpenAI + +llm = ChatOpenAI( + model="gpt-5.6-sol", + prompt_cache_options={"mode": "explicit"}, +) + +messages = [ + { + "role": "system", + "content": [ + { + "type": "text", + "text": ( + "You are a helpful assistant with access to a large knowledge base." + ), + "prompt_cache_breakpoint": {"mode": "explicit"}, # [!code highlight] + } + ], + }, + {"role": "user", "content": "Summarize the key points."}, +] + +response = llm.invoke(messages, prompt_cache_key="docs-breakpoint-v1") +``` diff --git a/src/snippets/code-samples/openai-prompt-cache-breakpoint-extras-py.mdx b/src/snippets/code-samples/openai-prompt-cache-breakpoint-extras-py.mdx new file mode 100644 index 0000000000..41834e2d28 --- /dev/null +++ b/src/snippets/code-samples/openai-prompt-cache-breakpoint-extras-py.mdx @@ -0,0 +1,7 @@ +```python +content_block = { + "type": "text", + "text": "Long system prompt...", + "extras": {"prompt_cache_breakpoint": {"mode": "explicit"}}, +} +``` diff --git a/src/snippets/code-samples/openai-prompt-cache-breakpoint-responses-py.mdx b/src/snippets/code-samples/openai-prompt-cache-breakpoint-responses-py.mdx new file mode 100644 index 0000000000..2ee5b531ae --- /dev/null +++ b/src/snippets/code-samples/openai-prompt-cache-breakpoint-responses-py.mdx @@ -0,0 +1,27 @@ +```python +from langchain_openai import ChatOpenAI + +llm = ChatOpenAI( + model="gpt-5.6-sol", + use_responses_api=True, + prompt_cache_options={"mode": "explicit"}, +) + +messages = [ + { + "role": "system", + "content": [ + { + "type": "text", + "text": ( + "You are a helpful assistant with access to a large knowledge base." + ), + "prompt_cache_breakpoint": {"mode": "explicit"}, # [!code highlight] + } + ], + }, + {"role": "user", "content": "Summarize the key points."}, +] + +response = llm.invoke(messages, prompt_cache_key="docs-breakpoint-v1") +``` diff --git a/src/snippets/code-samples/openai-prompt-cache-options-py.mdx b/src/snippets/code-samples/openai-prompt-cache-options-py.mdx new file mode 100644 index 0000000000..41139d31c2 --- /dev/null +++ b/src/snippets/code-samples/openai-prompt-cache-options-py.mdx @@ -0,0 +1,16 @@ +```python +from langchain_openai import ChatOpenAI + +llm = ChatOpenAI( + model="gpt-5.6-sol", + prompt_cache_options={"mode": "explicit", "ttl": "30m"}, +) + +messages = [{"role": "user", "content": "Hello"}] + +# Override per request +response = llm.invoke( + messages, + prompt_cache_options={"mode": "implicit"}, +) +``` diff --git a/src/snippets/code-samples/openai-prompt-cache-write-tokens-py.mdx b/src/snippets/code-samples/openai-prompt-cache-write-tokens-py.mdx new file mode 100644 index 0000000000..ae7eda943e --- /dev/null +++ b/src/snippets/code-samples/openai-prompt-cache-write-tokens-py.mdx @@ -0,0 +1,8 @@ +```python +response = llm.invoke(messages) + +cache_read = response.usage_metadata["input_token_details"].get("cache_read") +cache_creation = response.usage_metadata["input_token_details"].get("cache_creation") +print(f"Cache read tokens: {cache_read}") +print(f"Cache creation tokens: {cache_creation}") +``` diff --git a/uv.lock b/uv.lock index 91966f74b6..decb29c143 100644 --- a/uv.lock +++ b/uv.lock @@ -730,7 +730,7 @@ requires-dist = [ { name = "langchain-anthropic", specifier = ">=1.0.0" }, { name = "langchain-daytona", specifier = ">=0.0.5" }, { name = "langchain-google-genai", specifier = ">=2.0.0" }, - { name = "langchain-openai", specifier = ">=1.1.14" }, + { name = "langchain-openai", specifier = ">=1.3.5" }, { name = "langchain-quickjs", specifier = ">=0.3.2" }, { name = "langchain-text-splitters", specifier = ">=0.3.0" }, { name = "langgraph", specifier = ">=1.2.5" }, @@ -1217,7 +1217,7 @@ wheels = [ [[package]] name = "langchain-core" -version = "1.4.7" +version = "1.4.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, @@ -1230,9 +1230,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "uuid-utils" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ee/2b/fffaff399d20a56d40b9562fa19701e91abd72d8c9d9bc8c2673077b56b6/langchain_core-1.4.7.tar.gz", hash = "sha256:7a825d77de0a3f39adbd9d09612a75e85527e14a52c1601089bcc062972d9f2b", size = 952522, upload-time = "2026-06-12T19:23:57.588Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2a/b9/e937d0a90b26540bff07e7a7c64349f3b29c2dcc36257cd1cd3fdce17f2a/langchain_core-1.4.9.tar.gz", hash = "sha256:f8078901145bed0466755277500a5a22822a7b628808c4c0a28d4fc88895fcf2", size = 967294, upload-time = "2026-07-08T20:06:54.191Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/de/3e/dcdffa60078ae7b3a00ebb4cbbf1a204a14c3609983c604886523a7d4418/langchain_core-1.4.7-py3-none-any.whl", hash = "sha256:bcadd51951140ecdcba98311dbd931ba5de02a5ba8a2288dad5069c1eea2a13d", size = 554941, upload-time = "2026-06-12T19:23:55.826Z" }, + { url = "https://files.pythonhosted.org/packages/84/70/ade2fada52772798ef815b6352b59e71b116aa0c32c3aef5be3dc2cbed12/langchain_core-1.4.9-py3-none-any.whl", hash = "sha256:28e3909e2a10cc81504952d795ac0a9e014c0018121ef89d48dd396fa09ec624", size = 558293, upload-time = "2026-07-08T20:06:52.382Z" }, ] [[package]] @@ -1265,28 +1265,28 @@ wheels = [ [[package]] name = "langchain-openai" -version = "1.1.14" +version = "1.3.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "openai" }, { name = "tiktoken" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/f5/b1a56f703fb90952b07ff9fb5507123a39df1267d62a7f2bb821c5dbb628/langchain_openai-1.1.14.tar.gz", hash = "sha256:71b4262932fabe506ce79c175dbc956cc48f24d81e20b27662df493147750643", size = 1115195, upload-time = "2026-04-16T14:55:24.696Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d1/7e/43eef3f8fae2668f52e2222fdc26b6de58acf158bcb580e32e88a299260d/langchain_openai-1.3.5.tar.gz", hash = "sha256:c1db2256a42ac46e8e7b0564c5ccb478b9f58dc047a58935da33c82e6e1f9a07", size = 3261548, upload-time = "2026-07-10T18:58:29.576Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0b/fa/8c33befbc0cf81b21371cc1dab4e7bf94a80b8116194f263a5021ec02529/langchain_openai-1.1.14-py3-none-any.whl", hash = "sha256:cb525d2011f9813fc15a7dcfd4bca5b87badcbcb2c113a7fbe45d1b8a1bbb69c", size = 88705, upload-time = "2026-04-16T14:55:23.159Z" }, + { url = "https://files.pythonhosted.org/packages/61/64/4e0918cb96ff2b49e06acd9c11c250297d727d2fcce9e012d62efb73b4d6/langchain_openai-1.3.5-py3-none-any.whl", hash = "sha256:f586263b884bceb3d426ec84d3bfbd27051c3c92ae668da6175629e3f44dcec5", size = 121601, upload-time = "2026-07-10T18:58:28.327Z" }, ] [[package]] name = "langchain-protocol" -version = "0.0.15" +version = "0.0.18" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4f/24/9777489d6fbbee64af0c8f96d4f840239c408cf694f3394672807dafc490/langchain_protocol-0.0.15.tar.gz", hash = "sha256:9ab2d11ee73944754f10e037e717098d3a6796f0e58afa9cadda6154e7655ade", size = 5862, upload-time = "2026-05-01T22:30:04.748Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d2/59/b5959aea96faa9146e2e49a7a22882b3528c62efafe9a6a95beab30c2305/langchain_protocol-0.0.18.tar.gz", hash = "sha256:ec3e11782f1ed0c9db38e5a9ed01b0e7a0d3fba406faa8aef6594b73c56a63e6", size = 6150, upload-time = "2026-06-18T17:08:26.959Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1d/7a/9c97a7b9cbe4c5dc6a44cdb1545450c28f0c8ce89b9c1f0ee7fbad896263/langchain_protocol-0.0.15-py3-none-any.whl", hash = "sha256:461eb794358f83d5e42635a5797799ffec7b4702314e34edf73ac21e75d3ef79", size = 6982, upload-time = "2026-05-01T22:30:03.877Z" }, + { url = "https://files.pythonhosted.org/packages/99/2e/d82db9eec13ad0f72e7aaad5c4bc730ab111934fdc83c85523206eb9b0a0/langchain_protocol-0.0.18-py3-none-any.whl", hash = "sha256:70b53a86fbf9cedc863555effe44da192ab02d556ddbf2cf95b8873adcf41b5a", size = 7221, upload-time = "2026-06-18T17:08:25.996Z" }, ] [[package]] @@ -1728,7 +1728,7 @@ wheels = [ [[package]] name = "openai" -version = "2.30.0" +version = "2.45.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -1740,9 +1740,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/88/15/52580c8fbc16d0675d516e8749806eda679b16de1e4434ea06fb6feaa610/openai-2.30.0.tar.gz", hash = "sha256:92f7661c990bda4b22a941806c83eabe4896c3094465030dd882a71abe80c885", size = 676084, upload-time = "2026-03-25T22:08:59.96Z" } +sdist = { url = "https://files.pythonhosted.org/packages/78/60/d4219875289b11d2c2f7da93c36283da224a2e55865ed865ab64e0ce9217/openai-2.45.0.tar.gz", hash = "sha256:10d34ca9c5643bce775852fddbfc172505cb1d4de1ccd101696c3ecff358765d", size = 1109653, upload-time = "2026-07-09T18:02:44.091Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/9e/5bfa2270f902d5b92ab7d41ce0475b8630572e71e349b2a4996d14bdda93/openai-2.30.0-py3-none-any.whl", hash = "sha256:9a5ae616888eb2748ec5e0c5b955a51592e0b201a11f4262db920f2a78c5231d", size = 1146656, upload-time = "2026-03-25T22:08:58.2Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b0/2291689e3ec4723fbf5bbf3b54afcd7b160f9ddc98ca7aedfd0132af5677/openai-2.45.0-py3-none-any.whl", hash = "sha256:5df105f5f8c9b711fcb9d06d2d3888cebc82506db216484c14a4e53cdf651777", size = 1629470, upload-time = "2026-07-09T18:02:42.21Z" }, ] [[package]]