Closes#38648
`langchain-fireworks` now reports Fireworks cached prompt tokens in
`AIMessage.usage_metadata.input_token_details.cache_read` and no longer
crashes when combining nested token usage from batched `generate()`
calls.
---
Fireworks can return nested token usage details when prompt caching is
involved, including cached prompt token counts. Batched `generate()`
calls were crashing when those nested dictionaries were combined, and
regular chat results did not expose the cached-token breakdown in the
standard LangChain usage metadata shape.
This updates `ChatFireworks` so nested token usage is merged safely and
cached prompt tokens are reported as `input_token_details.cache_read`.
Users and downstream tracing systems can now distinguish cached
Fireworks input tokens from regular input tokens instead of treating the
full prompt as uncached input.
Thanks to @abcgco for the original report and recursive merge fix in
#38646, and to @abhi-0203 for independently identifying the same nested
`token_usage` failure in #38735. This PR builds on that work by using
the recursive merge approach and extending the fix to normalize cached
prompt tokens into standard usage metadata for tracing and cost
reporting.
Co-authored-by: Andrei Boldyrev <abcgco@gmail.com>
Fireworks chat users can pass request-specific headers to the SDK, but
the integration did not have targeted coverage or examples for
session-affinity and multi-turn headers. This adds explicit coverage for
sync, async, and streaming calls, and documents the supported invocation
patterns.
## Changes
- Documented `ChatFireworks` request-level `extra_headers` examples for
session affinity and multi-turn sessions, plus the SDK-level
`prompt_cache_key` alternative.
- Added `TestExtraHeaders` coverage showing `extra_headers` reach
top-level SDK kwargs for sync and streaming calls rather than being
folded into `extra_body`.
- Covered the async `ainvoke` path so request-specific headers are
verified across the main call modes.
Package-version trace metadata now uses the LangChain-owned
`metadata["lc_versions"]` convention instead of the user-owned
`metadata["versions"]` key. Metadata merging is narrowed so only
`lc_versions` accumulates nested package-version entries, while generic
nested metadata keeps normal last-writer-wins behavior.
## Changes
- Renamed `BaseLanguageModel._add_version()` trace metadata from
`versions` to `lc_versions`, including docstrings and the non-dict
replacement warning.
- Scoped `_merge_metadata_dicts()` nested-map accumulation to only
`lc_versions`; duplicate package entries remain last-writer-wins and
`lc_versions` mappings are copied defensively.
- Preserved user-owned `metadata["versions"]` semantics by keeping it
out of package-version tracking and generic nested metadata merging.
- Updated runnable snapshots and partner package metadata assertions
across Anthropic, DeepSeek, Fireworks, Groq, Hugging Face, MistralAI,
Ollama, OpenAI, OpenRouter, Perplexity, and xAI to expect `lc_versions`.
## Testing
- Added/adjusted core tests for `lc_versions` accumulation, duplicate
package overwrite behavior, non-dict `lc_versions` replacement,
defensive copying, and `metadata["versions"]` last-writer-wins behavior.
- Ran focused core and partner metadata tests plus Ruff checks for
changed areas.
Standardizes inline code markup in Python docstrings and comments by
replacing Sphinx-style double backticks with single-backtick Markdown.
The cleanup keeps existing code fences intact while aligning inline
references with the repo's docstring convention.
## Changes
- Converted inline code references in core prompt-loading docs and
LangSmith tracer comments, including `..`, `allow_dangerous_paths`, and
inheritable metadata keys.
- Normalized agent-related docstrings and comments around
`wrap_model_call`, `ExtendedModelResponse`, `Command`,
`create_structured_chat_agent`, and `DockerExecutionPolicy`.
- Updated partner package docstrings for inline references such as
`json_schema`, `ToolCall`, `apply_patch_call_output`, OpenRouter content
block keys, and Perplexity tool-call serialization.
- Cleaned test and helper docstrings that referenced command separators,
fake `resource` modules, stream event names, and xdist rate-limit
environment variables.
Following on the heels of #35293
TODO:
- Packages outside of this repo (e.g. LiteLLM, Nvidia, Google, AWS)
---
## Summary
Surface partner package versions in `metadata.versions` on LangSmith
traces. Mirrors the JS SDK's `_addVersion()` pattern
([langchainjs#10106](https://github.com/langchain-ai/langchainjs/pull/10106)).
Each model constructor records its package version via `_add_version()`
on `BaseLanguageModel`. The version dict accumulates through the class
hierarchy — `langchain-core` is added in
`BaseLanguageModel.model_post_init`, `langchain-openai` in
`BaseChatOpenAI._set_openai_chat_version`, and each leaf partner in its
uniquely-named `model_validator`. Traces end up with:
```json
{
"metadata": {
"versions": {
"langchain-core": "1.4.5",
"langchain-openai": "1.3.0",
"langchain-xai": "1.2.2"
}
}
}
```
### Changes
- `BaseLanguageModel._add_version(pkg, version)` — appends to
`self.metadata["versions"]`; accepts any `Mapping` type; emits a warning
if a non-mapping value is found and replaced
- `BaseLanguageModel.model_post_init` — adds `langchain-core` version;
calls `super()` for MRO safety
- `_merge_metadata_dicts` — one-level-deep (non-recursive) merge for
nested dict metadata keys
- `CallbackManager.add_metadata` — uses `_merge_metadata_dicts` instead
of flat `dict.update()` so nested metadata dicts (like `versions`)
coexist rather than clobber
- `merge_configs` — uses `_merge_metadata_dicts` for config merging
**Partners:**
- Each now calls `self._add_version("langchain-<pkg>", __version__)`
### Design decisions
- **Constructor-based, not `_get_ls_params`-based** — versions flow
through `self.metadata` (local metadata on traces), not through
`LangSmithParams`. This matches JS and makes child-class version
inheritance automatic (no merge/clobber issues).
- **`versions` is local (non-inheritable) metadata** — `self.metadata`
is passed to `CallbackManager.configure` as `local_metadata`
(`add_metadata(..., inherit=False)`), so `versions` is attached **once
per chat-model run** and is **not** propagated to child runs or
duplicated onto every streaming chunk. This is intentionally the
opposite of the inheritable-per-chunk metadata that #36588 was reducing
for performance — `versions` does not regress that path.
- **`add_metadata` deep-merge is a correctness fix, not just for
versions** — previously `add_metadata`/`merge_configs` did a flat
top-level `dict.update`/spread, so any nested metadata dict baked into a
config (e.g. via `.with_config({"metadata": {...}})`) would be wholly
replaced when a caller also passed `metadata`. `_merge_metadata_dicts`
merges one level deep so user-provided `config.metadata.versions` and
model-set `versions` coexist instead of clobbering. The merge runs once
per `configure` (not per chunk), so it is off the streaming hot path.
- **One level deep only** — `_merge_metadata_dicts` is deliberately
*not* a recursive deep merge; values nested more than one level are
last-writer-wins. This covers the `versions` case without the
ambiguity/cost of arbitrary-depth merging.
- **Warn on non-dict `metadata["versions"]`** — if a user sets
`metadata={"versions": "some-string"}`, `_add_version` emits a warning
and replaces the value with the version dict rather than silently
discarding user data or crashing. This is a soft breaking change for
anyone who previously stored non-dict values at this key.
### Follow-ups (tracked separately, out of scope here)
- JS `mergeConfigs` still flat-spreads nested metadata, so
`metadata.versions` can still clobber on the JS side until an equivalent
deep-merge lands.
---
Made by [Open SWE](https://openswe.vercel.app)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
`_sanitize_chat_completions_content` now filters every content-part dict
against an allowlist derived at import time from the `fireworks-ai`
SDK's `ContentUnionMember1` TypedDict, and runs on every message role —
not just `ToolMessage`. Fixes 400s of the form `Extra inputs are not
permitted, field:
'messages[N].content.list[ChatMessageContent][i].<key>'` when
cross-provider history (e.g. an Anthropic-shaped `AIMessage` carrying
the v1 streaming-reassembly `index` marker) is forwarded to a
Fireworks-hosted model.
Fireworks integration tests have been flaky against the live API with
429s. Adds a shared, xdist-aware rate limiter and a global retry policy
so transient rate-limit errors no longer fail the suite. Mirrors the
same fix recently applied to `langchain-mistralai`.
Closes#37172
---
Bumps `langchain-fireworks` to the rewritten `fireworks-ai` 1.x SDK
(currently 1.2.0a*; Stainless-generated, pure-httpx, no
`grpcio`/`protobuf`/`googleapis-common-protos`).
The motivating bug is a startup crash in self-hosted LangGraph
environments that also import `langchain-google-vertexai`. Importing
`fireworks-ai` 0.19.x eagerly loads vendored grpcio protobuf modules
under `fireworks.control_plane.generated.protos_grpcio.*`, which
register `google/rpc/status.proto`, `google/api/*.proto`, and
`google/longrunning/*.proto` in the default protobuf descriptor pool.
When `langchain-google-vertexai` later triggers
`google.api_core.exceptions` → `grpc_status.rpc_status` →
`google.rpc.status_pb2`, the pool already holds a byte-different
descriptor for `google/rpc/status.proto` and startup dies with:
```
TypeError: Couldn't build proto file into descriptor pool:
duplicate file name google/rpc/status.proto
```
Fleet has been pinning around this by routing Fireworks through
`ChatOpenAI` against the OpenAI-compat endpoint, which works for
inference but means Fireworks `ModelProfile` data never loads — so Kimi
K2.6's ~262k context window goes unrecognized and summarization triggers
below limit.
The 1.x SDK does not vendor protobuf at all. The control-plane gRPC code
path is gone; chat inference goes over httpx. Verified locally that
`import langchain_fireworks` and `from langchain_fireworks import
ChatFireworks` load zero `_pb2` / `google.*` modules.
## What changed in `ChatFireworks`
- Imports switch from `fireworks.client` to the top-level `fireworks`
package.
- Async path now `await client.chat.completions.create(...)`; the 0.x
`acreate` shim is no longer used.
- Error classes remapped to the 1.x hierarchy. `InvalidRequestError` →
`BadRequestError`. `BadGatewayError` and `ServiceUnavailableError` no
longer exist (1.x maps all `>=500` to `InternalServerError`) and were
dropped from the retryable set with no loss of coverage.
`FireworksContextOverflowError`'s parent class becomes
`BadRequestError`.
- `stream_options` is moved into the SDK's `extra_body` because the
Stainless-generated `create()` signature does not model it as a typed
kwarg. Top-level `stream_options` is preserved as a caller convenience;
if a caller supplies both `extra_body["stream_options"]` and a top-level
value, `extra_body` wins and the discarded value is logged.
- The 0.x `(connect, read)` tuple form of `request_timeout` is
normalized to an `httpx.Timeout` so existing user code keeps working.
- The SDK's built-in retry layer is suppressed via `max_retries=0` on
client construction so retries remain owned by
`create_base_retry_decorator` and surface through the LangChain
`run_manager`.
## Lifecycle methods
Adds `close()` and `aclose()` on `ChatFireworks`. The 1.x
`AsyncFireworks` client defaults to `httpx_aiohttp.HttpxAiohttpClient`,
whose underlying aiohttp `ClientSession` is created lazily on first
request. Sync-only paths therefore never open a session — which fixes
the "Unclosed client session" warnings from #37172 at the source.
Callers using async paths can now release the connector
deterministically rather than relying on GC after the event loop has
stopped. An autouse fixture in the integration `conftest.py` calls
`aclose()` between tests to silence the corresponding `Unclosed
connector` warning that surfaces under `pytest-asyncio`.
## Relation to #37227
Supersedes #37227. That PR monkey-patched
`fireworks._util.is_running_in_async_context` and
`fireworks.client.api_client.is_running_in_async_context` to suppress
the 0.x SDK's eager `aiohttp.ClientSession` creation in async contexts.
Both module paths are removed in 1.x; the SDK's lazy-session behavior
makes the suppression unnecessary, and the explicit `aclose()` provides
the cleaner long-term lifecycle hook. Thanks to @keenborder786 for
surfacing the failure mode.
## Installation note
`fireworks-ai` 1.x is currently published as an alpha (`1.2.0a*`); a
stable 1.x is not yet out. `pip install langchain-fireworks` / `uv pip
install langchain-fireworks` will need `--pre` (or `--prerelease=allow`)
until Fireworks GAs 1.x. The `pyproject.toml` adds `[tool.uv] prerelease
= "allow"` so the in-repo dev environment resolves cleanly. The package
version is bumped to `1.4.0` — the public surface (`ChatFireworks`,
`Fireworks`, `FireworksEmbeddings`) is unchanged; the breakage is
confined to internal error classes and the transitive SDK.
Fireworks's chat completions endpoint rejects unknown fields on tool
message content blocks — specifically the `id` key that LangChain
auto-generates on `TextContentBlock`. Add
`_sanitize_chat_completions_content` to strip those extra keys before
the payload hits the wire, preventing `Extra inputs are not permitted`
errors on tool message round-trips.
Add a `service_tier` init kwarg to `ChatFireworks`, mirroring the field
on `ChatOpenAI`. Forwards to the Fireworks chat completions API when
set, and echoes the response's tier back onto `response_metadata` and
`llm_output` so callbacks and consumers can read what the server
actually applied.
## Summary
`langchain_fireworks._convert_message_to_dict` ships LangChain canonical
v0/v1 multimodal content blocks (e.g. `{"type": "image", "base64": ...,
"mime_type": ...}`) on the wire unchanged. Fireworks' OpenAI-compatible
chat completions API rejects the unknown `base64`/`mime_type` keys and
the list shape on roles that expect a string, returning HTTP 422 — so
any image upload, including via tools that return image content blocks,
fails for Kimi K2.6 and other Fireworks vision models.
This change mirrors
`langchain_openai.chat_models.base._format_message_content`:
- Walk `content` blocks.
- Drop block types the chat-completions wire doesn't carry (`tool_use`,
`thinking`, `reasoning_content`, `function_call`,
`code_interpreter_call`).
- Detect v0/v1 multimodal data blocks via
`langchain_core.messages.is_data_content_block`, and translate them via
`convert_to_openai_data_block(..., api="chat/completions")`.
- Strings and non-list content pass through unchanged.
Applied in the `ChatMessage`, `HumanMessage`, `SystemMessage`, and
`ToolMessage` paths of `_convert_message_to_dict`. `AIMessage` already
routes through `_convert_from_v1_to_chat_completions` for v1 output and
assistant content is text-only on the way out, so it is left untouched.
## Why this approach
Fireworks is OpenAI-compatible. The canonical → OpenAI translator
already exists in `langchain_core.messages.block_translators.openai` and
is the same one `langchain-openai` uses. Reusing it (rather than
inventing a Fireworks-specific translator) gives:
- v0 (`source_type`-based) and v1 (`base64`/`url`-based) data block
coverage for free.
- Consistent behavior with `langchain-openai` for image, file, and any
future canonical data block.
- A small, focused diff (≈30 lines of new code, plus tests).
## Test plan
- [x] `make test` passes (64/64 unit tests, including 9 new ones for the
new helper and translation paths).
- [x] `make lint` passes (ruff check, ruff format, mypy, lint_imports).
- [ ] End-to-end: image upload to a Kimi K2.6 (Fireworks) agent
translates to `{"type": "image_url", "image_url": {"url":
"data:image/png;base64,..."}}` on the wire and the model returns a
coherent description (validated locally against
`langchain-fireworks==1.0.0` site-packages with the same patch).
---------
Co-authored-by: murugand23 <murugand23@users.noreply.github.com>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
`ChatFireworks.max_retries` silently did nothing. The old code assigned
the value to a `ChatCompletionV2` sub-object rather than the base
client, and the pinned Fireworks SDK (0.13.0–0.19.20) never honors its
own `_max_retries` attribute on the base client either. Since the
Stainless-generated 1.x SDK that does implement retries is still
pre-release (1.0.1a63 at time of writing), retry responsibility is
ported to the LangChain side until the pin can be bumped.
Populate `usage_metadata` on streaming responses. Newer Fireworks models
(e.g. Kimi K2 slugs) require an explicit
`stream_options.include_usage=True` opt-in and return token counts in a
final empty-`choices` chunk; the chunk was previously `continue`-d past,
so streaming usage silently came back as `None`.
Replace `accounts/fireworks/models/kimi-k2-instruct-0905` with
`accounts/fireworks/models/kimi-k2p6` across the Fireworks integration
tests. Fireworks appears to have pulled the 0905 slug from serverless
(returns 404 `NOT_FOUND` despite still appearing "Ready" in their UI);
`kimi-k2p6` is the current deployed successor and supports the same
capabilities used by these tests (tool calls, streaming, structured
output).
Add a `model` property to `ChatFireworks`, `ChatGroq`, and
`ChatOpenRouter` that returns `model_name`. These partners use
Pydantic's `Field(alias="model")` on `model_name`, which means
`instance.model` doesn't work as a read accessor after construction — it
raises an `AttributeError` or returns the field descriptor. `ChatOpenAI`
already has this property; this brings the remaining in-repo partners to
parity.
Extract strict from kwargs and pass it to convert_to_openai_tool when
converting tools. This ensures that when strict is provided, it's
properly used during tool conversion and removed from kwargs before
calling the parent bind method.
Also extract reasoning_content from API responses and store it in
additional_kwargs for AIMessage objects.
Fixes https://github.com/langchain-ai/langchain/issues/34341 and
https://github.com/langchain-ai/langchain/issues/34342
---------
Co-authored-by: Mason Daugherty <mason@langchain.dev>
`mixtral-8x-7b-instruct` was recently retired from Fireworks Serverless.
Here we remove the default model altogether, so that the model must be
explicitly specified on init:
```python
ChatFireworks(model="accounts/fireworks/models/llama-v3p1-70b-instruct") # for example
```
We also set a null default for `temperature`, which previously defaulted
to 0.0. This parameter will no longer be included in request payloads
unless it is explicitly provided.
We are implementing a token-counting callback handler in
`langchain-core` that is intended to work with all chat models
supporting usage metadata. The callback will aggregate usage metadata by
model. This requires responses to include the model name in its
metadata.
To support this, if a model `returns_usage_metadata`, we check that it
includes a string model name in its `response_metadata` in the
`"model_name"` key.
More context: https://github.com/langchain-ai/langchain/pull/30487
Thank you for contributing to LangChain!
**Description**
The current code snippet for `Fireworks` had incorrect parameters. This
PR fixes those parameters.
---------
Co-authored-by: Chester Curme <chester.curme@gmail.com>
Co-authored-by: Bagatur <baskaryan@gmail.com>
- Refactor standard test classes to make them easier to configure
- Update openai to support stop_sequences init param
- Update groq to support stop_sequences init param
- Update fireworks to support max_retries init param
- Update ChatModel.bind_tools to type tool_choice
- Update groq to handle tool_choice="any". **this may be controversial**
---------
Co-authored-by: Chester Curme <chester.curme@gmail.com>
```python
class UsageMetadata(TypedDict):
"""Usage metadata for a message, such as token counts.
Attributes:
input_tokens: (int) count of input (or prompt) tokens
output_tokens: (int) count of output (or completion) tokens
total_tokens: (int) total token count
"""
input_tokens: int
output_tokens: int
total_tokens: int
```
```python
class AIMessage(BaseMessage):
...
usage_metadata: Optional[UsageMetadata] = None
"""If provided, token usage information associated with the message."""
...
```