Avatar for the langchain-ai user
langchain-ai
langchain
BlogDocsChangelog

Performance History

Latest Results

fix(core): inspect class constructors when detecting injected args `_get_type_hints_source` returned a class as its own annotation owner, so `get_type_hints` yielded class-attribute annotations while the parameter names came from `signature(cls)` -- i.e. the constructor. Matching two different namespaces by name dropped injected args whose name collided with a class attribute, and marked model-facing params injected when the collision ran the other way. Resolve a class to its constructor instead, mirroring `signature` precedence (metaclass `__call__`, then own `__new__`/`__init__`, then an inherited one). Fold the wholesale and per-annotation hint paths into a single loop so a parameter left uncovered by `get_type_hints` -- rather than only a wholesale failure -- also falls back to resolving its own annotation; an empty hints `dict` no longer counts as full coverage. Also add the parameter name and owning callable to the annotation resolution debug logs, which previously named neither.
mdrxy/core/structured-tool-postponed-annotations
8 hours ago
fix(core): resolve explicit signature annotations
mdrxy/core/structured-tool-postponed-annotations
9 hours ago
fix(core): dedupe per-annotation forward ref resolution in injected-arg fallback
mdrxy/core/structured-tool-postponed-annotations
10 hours ago
Merge branch 'master' into Yigtwxx/langchain/propagate-non-retryable-model-exceptions
Yigtwxx:Yigtwxx/langchain/propagate-non-retryable-model-exceptions
10 hours ago
revert extraneous change
Jacopos311:fix-windows-tests
11 hours ago
fix(core): fail fast when tool schemas can't resolve forward refs during serialization (#39570) fixes #39099 We currently allow forward refs in pydantic v2 schemas upon creation: ```python class Container(BaseModel): rows: list["Row"] = [] # "Row" is declared below, after the tool is decorated @tool def my_tool(container: Container): """A tool whose schema depends on a forward reference that is not resolvable yet.""" return "ok" class Row(BaseModel): name: str ``` When it comes time to introspect the tool schema (notably in `count_tokens_approximately` and `convert_to_openai_tool`), we rely on [signature introspection](https://github.com/langchain-ai/langchain/blob/943dd700ef7c33e3f1f21d3e280c9c249b88259c/libs/core/langchain_core/tools/base.py#L1654-L1661) to extract the tool's input schema. If that contains invalid forward references, there's no schema fields to extract which results in an empty dict: <details> <summary>Invalid forward reference MRE</summary> ```python from __future__ import annotations import inspect from pydantic import BaseModel, Field from pydantic.errors import PydanticUndefinedAnnotation from langchain_core.tools.base import get_all_basemodel_annotations from langchain_core.utils.pydantic import _create_subset_model, model_json_schema class Container(BaseModel): """A model with a nested forward reference that can never resolve.""" rows: list["UndefinedRow"] = Field(default_factory=list) def main() -> None: """Print the field-selection inputs and their zero-field subset result.""" selected_annotations = get_all_basemodel_annotations(Container) subset_schema = _create_subset_model( "ContainerSubset", Container, list(selected_annotations), fn_description=Container.__doc__, ) print(f"Pydantic complete: {Container.__pydantic_complete__}") print(f"Pydantic fields: {list(Container.model_fields)}") print(f"inspect.signature: {inspect.signature(Container)}") print(f"Fields selected by get_all_basemodel_annotations: {selected_annotations}") print(f"Subset properties: {model_json_schema(subset_schema)['properties']}") if __name__ == "__main__": main() ``` ```output Pydantic complete: False Pydantic fields: ['rows'] inspect.signature: (**data: 'Any') -> 'None' Fields selected by get_all_basemodel_annotations: {} Subset properties: {} ``` </details> <details> <summary>Valid forward reference MRE</summary> ```python from __future__ import annotations import inspect from pydantic import BaseModel, Field from pydantic.errors import PydanticUndefinedAnnotation from langchain_core.tools.base import get_all_basemodel_annotations from langchain_core.utils.pydantic import _create_subset_model, model_json_schema class Container(BaseModel): """A model with a nested forward reference that can never resolve.""" rows: list["UndefinedRow"] = Field(default_factory=list) class UndefinedRow(BaseModel): name: str = Field() def main() -> None: """Print the field-selection inputs and their zero-field subset result.""" Container.model_rebuild() selected_annotations = get_all_basemodel_annotations(Container) subset_schema = _create_subset_model( "ContainerSubset", Container, list(selected_annotations), fn_description=Container.__doc__, ) print(f"Pydantic complete: {Container.__pydantic_complete__}") print(f"Pydantic fields: {list(Container.model_fields)}") print(f"inspect.signature: {inspect.signature(Container)}") print(f"Fields selected by get_all_basemodel_annotations: {selected_annotations}") print(f"Subset properties: {model_json_schema(subset_schema)['properties']}") if __name__ == "__main__": main() ``` ```output Pydantic complete: True Pydantic fields: ['rows'] inspect.signature: (*, rows: list[__main__.UndefinedRow] = <factory>) -> None Fields selected by get_all_basemodel_annotations: {'rows': list[__main__.UndefinedRow]} Subset properties: {'rows': {'items': {'$ref': '#/$defs/UndefinedRow'}, 'title': 'Rows', 'type': 'array'}} ``` </details> --- The fix is to * at introspection time, resolve forward references using `.model_rebuild()` that raises a pydantic exception if forward references cant be resolved * i'm also widening a pydantic utility to use a type guard instead of having to use bool + cast I'm intentionally not rebuilding pydantic v1 schemas in the same way since * forward references are specified by explicitly passing names into `update_forward_refs` * pydantic v1 is old news
master
11 hours ago

Latest Branches

CodSpeed Performance Gauge
0%
fix(core): resolve postponed annotations in `StructuredTool._injected_args_keys`#39602
8 hours ago
27f3264
mdrxy/core/structured-tool-postponed-annotations
CodSpeed Performance Gauge
0%
fix(langchain): re-raise non-retryable exceptions in `ModelRetryMiddleware`#38960
10 hours ago
8df042f
Yigtwxx:Yigtwxx/langchain/propagate-non-retryable-model-exceptions
CodSpeed Performance Gauge
0%
11 hours ago
9db6d14
Jacopos311:fix-windows-tests
© 2026 CodSpeed Technology
Home Terms Privacy Docs