style(core): fix some noqa escapes (#34675)

Co-authored-by: Mason Daugherty <github@mdrxy.com>
Co-authored-by: Mason Daugherty <mason@langchain.dev>
This commit is contained in:
Christophe Bornet
2026-01-09 23:36:08 +01:00
committed by GitHub
parent fd69425439
commit 8e3c6b109f
25 changed files with 286 additions and 149 deletions

View File

@@ -125,7 +125,7 @@ def beta(
_name = _name or obj.__qualname__
old_doc = obj.__doc__
def finalize(wrapper: Callable[..., Any], new_doc: str) -> T: # noqa: ARG001
def finalize(_: Callable[..., Any], new_doc: str, /) -> T:
"""Finalize the annotation of a class."""
# Can't set new_doc on some extension objects.
with contextlib.suppress(AttributeError):
@@ -168,7 +168,7 @@ def beta(
emit_warning()
obj.fdel(instance)
def finalize(_wrapper: Callable[..., Any], new_doc: str) -> Any:
def finalize(_: Callable[..., Any], new_doc: str, /) -> Any:
"""Finalize the property."""
return property(fget=_fget, fset=_fset, fdel=_fdel, doc=new_doc)
@@ -181,7 +181,7 @@ def beta(
wrapped = obj
old_doc = wrapped.__doc__
def finalize(wrapper: Callable[..., Any], new_doc: str) -> T:
def finalize(wrapper: Callable[..., Any], new_doc: str, /) -> T:
"""Wrap the wrapped function using the wrapper and update the docstring.
Args:

View File

@@ -222,7 +222,7 @@ def deprecated(
_name = _name or obj.__qualname__
old_doc = obj.__doc__
def finalize(wrapper: Callable[..., Any], new_doc: str) -> T: # noqa: ARG001
def finalize(_: Callable[..., Any], new_doc: str, /) -> T:
"""Finalize the deprecation of a class."""
# Can't set new_doc on some extension objects.
with contextlib.suppress(AttributeError):
@@ -257,7 +257,7 @@ def deprecated(
raise ValueError(msg)
old_doc = obj.description
def finalize(wrapper: Callable[..., Any], new_doc: str) -> T: # noqa: ARG001
def finalize(_: Callable[..., Any], new_doc: str, /) -> T:
return cast(
"T",
FieldInfoV1(
@@ -278,7 +278,7 @@ def deprecated(
raise ValueError(msg)
old_doc = obj.description
def finalize(wrapper: Callable[..., Any], new_doc: str) -> T: # noqa: ARG001
def finalize(_: Callable[..., Any], new_doc: str, /) -> T:
return cast(
"T",
FieldInfo(
@@ -336,7 +336,7 @@ def deprecated(
if _name == "<lambda>":
_name = set_name
def finalize(wrapper: Callable[..., Any], new_doc: str) -> T: # noqa: ARG001
def finalize(_: Callable[..., Any], new_doc: str, /) -> T:
"""Finalize the property."""
prop = _DeprecatedProperty(
fget=obj.fget, fset=obj.fset, fdel=obj.fdel, doc=new_doc
@@ -357,7 +357,7 @@ def deprecated(
wrapped = obj
old_doc = wrapped.__doc__
def finalize(wrapper: Callable[..., Any], new_doc: str) -> T:
def finalize(wrapper: Callable[..., Any], new_doc: str, /) -> T:
"""Wrap the wrapped function using the wrapper and update the docstring.
Args:

View File

@@ -5,7 +5,6 @@ from __future__ import annotations
import asyncio
import inspect
import json
import typing
from abc import ABC, abstractmethod
from collections.abc import AsyncIterator, Callable, Iterator, Sequence
from functools import cached_property
@@ -74,6 +73,7 @@ from langchain_core.utils.pydantic import TypeBaseModel, is_basemodel_subclass
from langchain_core.utils.utils import LC_ID_PREFIX, from_env
if TYPE_CHECKING:
import builtins
import uuid
from langchain_core.output_parsers.base import OutputParserLike
@@ -1520,9 +1520,7 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
def bind_tools(
self,
tools: Sequence[
typing.Dict[str, Any] | type | Callable | BaseTool # noqa: UP006
],
tools: Sequence[builtins.dict[str, Any] | type | Callable | BaseTool],
*,
tool_choice: str | None = None,
**kwargs: Any,
@@ -1541,11 +1539,11 @@ class BaseChatModel(BaseLanguageModel[AIMessage], ABC):
def with_structured_output(
self,
schema: typing.Dict | type, # noqa: UP006
schema: builtins.dict[str, Any] | type,
*,
include_raw: bool = False,
**kwargs: Any,
) -> Runnable[LanguageModelInput, typing.Dict | BaseModel]: # noqa: UP006
) -> Runnable[LanguageModelInput, builtins.dict[str, Any] | BaseModel]:
"""Model wrapper that returns outputs formatted to match the given schema.
Args:

View File

@@ -20,6 +20,11 @@ NOT instantiated as LC objects.
from typing import Any
from langchain_core.load.serializable import (
Serializable,
to_json_not_implemented,
)
_LC_ESCAPED_KEY = "__lc_escaped__"
"""Sentinel key used to mark escaped user dicts during serialization.
@@ -73,11 +78,6 @@ def _serialize_value(obj: Any) -> Any:
Returns:
The serialized value with user dicts escaped as needed.
"""
from langchain_core.load.serializable import ( # noqa: PLC0415
Serializable,
to_json_not_implemented,
)
if isinstance(obj, Serializable):
# This is an LC object - serialize it properly (not escaped)
return _serialize_lc_object(obj)
@@ -128,8 +128,6 @@ def _serialize_lc_object(obj: Any) -> dict[str, Any]:
metadata) that contains `'lc'` keys. Secret fields (from `lc_secrets`) are
skipped because `to_json()` replaces their values with secret markers.
"""
from langchain_core.load.serializable import Serializable # noqa: PLC0415
if not isinstance(obj, Serializable):
msg = f"Expected Serializable, got {type(obj)}"
raise TypeError(msg)

View File

@@ -133,12 +133,13 @@ class Serializable(BaseModel, ABC):
def get_lc_namespace(cls) -> list[str]:
"""Get the namespace of the LangChain object.
For example, if the class is [`langchain.llms.openai.OpenAI`][langchain_openai.OpenAI],
then the namespace is `["langchain", "llms", "openai"]`
For example, if the class is
[`langchain.llms.openai.OpenAI`][langchain_openai.OpenAI], then the namespace is
`["langchain", "llms", "openai"]`
Returns:
The namespace.
""" # noqa: E501
"""
return cls.__module__.split(".")
@property

View File

@@ -406,8 +406,8 @@ class AIMessageChunk(AIMessage, BaseMessageChunk):
"""
@property
@override
def lc_attributes(self) -> dict:
"""Attributes to be serialized, even if they are derived from other initialization args.""" # noqa: E501
return {
"tool_calls": self.tool_calls,
"invalid_tool_calls": self.invalid_tool_calls,
@@ -564,7 +564,11 @@ class AIMessageChunk(AIMessage, BaseMessageChunk):
@model_validator(mode="after")
def init_server_tool_calls(self) -> Self:
"""Parse `server_tool_call_chunks` from [`ServerToolCallChunk`][langchain.messages.ServerToolCallChunk] objects.""" # noqa: E501
"""Initialize server tool calls.
Parse `server_tool_call_chunks` from
[`ServerToolCallChunk`][langchain.messages.ServerToolCallChunk] objects.
"""
if (
self.chunk_position == "last"
and self.response_metadata.get("output_version") == "v1"

View File

@@ -8,6 +8,7 @@ from pydantic import ConfigDict, Field
from langchain_core._api.deprecation import warn_deprecated
from langchain_core.load.serializable import Serializable
from langchain_core.messages import content as types
from langchain_core.utils import get_bolded_text
from langchain_core.utils._merge import merge_dicts, merge_lists
from langchain_core.utils.interactive_env import is_interactive_env
@@ -17,7 +18,6 @@ if TYPE_CHECKING:
from typing_extensions import Self
from langchain_core.messages import content as types
from langchain_core.prompts.chat import ChatPromptTemplate
@@ -204,7 +204,6 @@ class BaseMessage(Serializable):
"""
# Needed here to avoid circular import, as these classes import BaseMessages
from langchain_core.messages import content as types # noqa: PLC0415
from langchain_core.messages.block_translators.anthropic import ( # noqa: PLC0415
_convert_to_v1_from_anthropic_input,
)

View File

@@ -9,6 +9,13 @@ from langchain_core.messages import AIMessage, AIMessageChunk
from langchain_core.messages import content as types
from langchain_core.messages.content import Citation, create_citation
try:
import filetype # type: ignore[import-not-found]
_HAS_FILETYPE = True
except ImportError:
_HAS_FILETYPE = False
def _bytes_to_b64_str(bytes_: bytes) -> str:
"""Convert bytes to base64 encoded string."""
@@ -391,9 +398,7 @@ def _convert_to_v1_from_genai(message: AIMessage) -> list[types.ContentBlock]:
"base64": url,
}
try:
import filetype # type: ignore[import-not-found] # noqa: PLC0415
if _HAS_FILETYPE:
# Guess MIME type based on file bytes
mime_type = None
kind = filetype.guess(decoded_bytes)
@@ -401,9 +406,6 @@ def _convert_to_v1_from_genai(message: AIMessage) -> list[types.ContentBlock]:
mime_type = kind.mime
if mime_type:
image_url_b64_block["mime_type"] = mime_type
except ImportError:
# filetype library not available, skip type detection
pass
converted_blocks.append(
cast("types.ImageContentBlock", image_url_b64_block)

View File

@@ -105,15 +105,15 @@ def _convert_to_v1_from_groq(message: AIMessage) -> list[types.ContentBlock]:
if isinstance(message.content, str) and message.content:
content_blocks.append({"type": "text", "text": message.content})
for tool_call in message.tool_calls:
content_blocks.append( # noqa: PERF401
{
"type": "tool_call",
"name": tool_call["name"],
"args": tool_call["args"],
"id": tool_call.get("id"),
}
)
content_blocks.extend(
{
"type": "tool_call",
"name": tool_call["name"],
"args": tool_call["args"],
"id": tool_call.get("id"),
}
for tool_call in message.tool_calls
)
return content_blocks

View File

@@ -10,12 +10,13 @@ from langchain_core.language_models._utils import (
_parse_data_uri,
is_openai_data_block,
)
from langchain_core.messages import AIMessageChunk
from langchain_core.messages import content as types
if TYPE_CHECKING:
from collections.abc import Iterable
from langchain_core.messages import AIMessage, AIMessageChunk
from langchain_core.messages import AIMessage
def convert_to_openai_image_block(block: dict[str, Any]) -> dict:
@@ -192,8 +193,6 @@ def _convert_to_v1_from_chat_completions_input(
Returns:
Updated list with OpenAI blocks converted to v1 format.
"""
from langchain_core.messages import content as types # noqa: PLC0415
converted_blocks = []
unpacked_blocks: list[dict[str, Any]] = [
cast("dict[str, Any]", block)
@@ -288,8 +287,6 @@ _FUNCTION_CALL_IDS_MAP_KEY = "__openai_function_call_ids__"
def _convert_from_v03_ai_message(message: AIMessage) -> AIMessage:
"""Convert v0 AIMessage into `output_version="responses/v1"` format."""
from langchain_core.messages import AIMessageChunk # noqa: PLC0415
# Only update ChatOpenAI v0.3 AIMessages
is_chatopenai_v03 = (
isinstance(message.content, list)
@@ -706,8 +703,6 @@ def _convert_to_v1_from_responses(message: AIMessage) -> list[types.ContentBlock
) = None
call_id = block.get("call_id", "")
from langchain_core.messages import AIMessageChunk # noqa: PLC0415
if (
isinstance(message, AIMessageChunk)
and len(message.tool_call_chunks) == 1

View File

@@ -563,6 +563,7 @@ def filter_messages(
):
continue
new_msg = msg
if isinstance(exclude_tool_calls, (list, tuple, set)):
if isinstance(msg, AIMessage) and msg.tool_calls:
tool_calls = [
@@ -586,7 +587,7 @@ def filter_messages(
)
]
msg = msg.model_copy( # noqa: PLW2901
new_msg = msg.model_copy(
update={"tool_calls": tool_calls, "content": content}
)
elif (
@@ -597,11 +598,11 @@ def filter_messages(
# default to inclusion when no inclusion criteria given.
if (
not (include_types or include_ids or include_names)
or (include_names and msg.name in include_names)
or (include_types and _is_message_type(msg, include_types))
or (include_ids and msg.id in include_ids)
or (include_names and new_msg.name in include_names)
or (include_types and _is_message_type(new_msg, include_types))
or (include_ids and new_msg.id in include_ids)
):
filtered.append(msg)
filtered.append(new_msg)
return filtered

View File

@@ -47,7 +47,7 @@ class BaseLLMOutputParser(ABC, Generic[T]):
async def aparse_result(
self, result: list[Generation], *, partial: bool = False
) -> T:
"""Async parse a list of candidate model `Generation` objects into a specific format.
"""Parse a list of candidate model `Generation` objects into a specific format.
Args:
result: A list of `Generation` to be parsed. The Generations are assumed
@@ -57,7 +57,7 @@ class BaseLLMOutputParser(ABC, Generic[T]):
Returns:
Structured output.
""" # noqa: E501
"""
return await run_in_executor(None, self.parse_result, result, partial=partial)
@@ -268,7 +268,7 @@ class BaseOutputParser(
async def aparse_result(
self, result: list[Generation], *, partial: bool = False
) -> T:
"""Async parse a list of candidate model `Generation` objects into a specific format.
"""Parse a list of candidate model `Generation` objects into a specific format.
The return value is parsed from only the first `Generation` in the result, which
is assumed to be the highest-likelihood `Generation`.
@@ -281,7 +281,7 @@ class BaseOutputParser(
Returns:
Structured output.
""" # noqa: E501
"""
return await run_in_executor(None, self.parse_result, result, partial=partial)
async def aparse(self, text: str) -> T:

View File

@@ -2,9 +2,9 @@
from __future__ import annotations
import builtins # noqa: TC003
import contextlib
import json
import typing
from abc import ABC, abstractmethod
from collections.abc import Mapping # noqa: TC003
from functools import cached_property
@@ -51,7 +51,7 @@ class BasePromptTemplate(
These variables are auto inferred from the prompt and user need not provide them.
"""
input_types: typing.Dict[str, Any] = Field(default_factory=dict, exclude=True) # noqa: UP006
input_types: builtins.dict[str, Any] = Field(default_factory=dict, exclude=True)
"""A dictionary of the types of the variables the prompt template expects.
If not provided, all variables are assumed to be strings.
@@ -64,7 +64,7 @@ class BasePromptTemplate(
Partial variables populate the template so that you don't need to pass them in every
time you call the prompt.
"""
metadata: typing.Dict[str, Any] | None = None # noqa: UP006
metadata: builtins.dict[str, Any] | None = None
"""Metadata to be used for tracing."""
tags: list[str] | None = None
"""Tags to be used for tracing."""

View File

@@ -845,9 +845,9 @@ class ChatPromptTemplate(BaseChatPromptTemplate):
!!! note "Single-variable template"
If your prompt has only a single input variable (i.e., 1 instance of "{variable_nams}"),
and you invoke the template with a non-dict object, the prompt template will
inject the provided argument into that variable location.
If your prompt has only a single input variable (i.e., 1 instance of
"{variable_nams}"), and you invoke the template with a non-dict object, the
prompt template will inject the provided argument into that variable location.
```python
from langchain_core.prompts import ChatPromptTemplate
@@ -871,7 +871,7 @@ class ChatPromptTemplate(BaseChatPromptTemplate):
# ]
# )
```
""" # noqa: E501
"""
messages: Annotated[list[MessageLike], SkipValidation()]
"""List of messages consisting of either message prompt templates or messages."""

View File

@@ -369,7 +369,7 @@ class Runnable(ABC, Generic[Input, Output]):
def get_input_schema(
self,
config: RunnableConfig | None = None, # noqa: ARG002
config: RunnableConfig | None = None,
) -> type[BaseModel]:
"""Get a Pydantic model that can be used to validate input to the `Runnable`.
@@ -385,6 +385,7 @@ class Runnable(ABC, Generic[Input, Output]):
Returns:
A Pydantic model that can be used to validate input.
"""
_ = config
root_type = self.InputType
if (
@@ -447,7 +448,7 @@ class Runnable(ABC, Generic[Input, Output]):
def get_output_schema(
self,
config: RunnableConfig | None = None, # noqa: ARG002
config: RunnableConfig | None = None,
) -> type[BaseModel]:
"""Get a Pydantic model that can be used to validate output to the `Runnable`.
@@ -463,6 +464,7 @@ class Runnable(ABC, Generic[Input, Output]):
Returns:
A Pydantic model that can be used to validate output.
"""
_ = config
root_type = self.OutputType
if (

View File

@@ -5,6 +5,7 @@ from __future__ import annotations
import functools
import inspect
import json
import logging
import typing
import warnings
from abc import ABC, abstractmethod
@@ -82,6 +83,8 @@ TOOL_MESSAGE_BLOCK_TYPES = (
"file",
)
_logger = logging.getLogger(__name__)
class SchemaAnnotationError(TypeError):
"""Raised when args_schema is missing or has an incorrect type annotation."""
@@ -815,9 +818,12 @@ class ChildTool(BaseTool):
for field_name, field_type in annotations.items():
if _is_injected_arg_type(field_type):
filtered_keys.add(field_name)
except Exception: # noqa: S110
except Exception:
# If we can't get annotations, just use FILTERED_ARGS
pass
_logger.debug(
"Failed to get args_schema annotations for filtering.",
exc_info=True,
)
# Filter out the injected keys from tool_input
return {k: v for k, v in tool_input.items() if k not in filtered_keys}

View File

@@ -221,9 +221,10 @@ class _TracerCore(ABC):
token: str,
run_id: UUID,
chunk: GenerationChunk | ChatGenerationChunk | None = None,
parent_run_id: UUID | None = None, # noqa: ARG002
parent_run_id: UUID | None = None,
) -> Run:
"""Append token event to LLM run and return the run."""
_ = parent_run_id
llm_run = self._get_run(run_id, run_type={"llm", "chat_model"})
event_kwargs: dict[str, Any] = {"token": token}
if chunk:
@@ -538,43 +539,47 @@ class _TracerCore(ABC):
"""Return self copied."""
return self
def _end_trace(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _end_trace(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""End a trace for a run.
Args:
run: The run.
"""
_ = run
return None
def _on_run_create(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_run_create(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process a run upon creation.
Args:
run: The created run.
"""
_ = run
return None
def _on_run_update(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_run_update(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process a run upon update.
Args:
run: The updated run.
"""
_ = run
return None
def _on_llm_start(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_llm_start(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process the LLM Run upon start.
Args:
run: The LLM run.
"""
_ = run
return None
def _on_llm_new_token(
self,
run: Run, # noqa: ARG002
token: str, # noqa: ARG002
chunk: GenerationChunk | ChatGenerationChunk | None, # noqa: ARG002
run: Run,
token: str,
chunk: GenerationChunk | ChatGenerationChunk | None,
) -> Coroutine[Any, Any, None] | None:
"""Process new LLM token.
@@ -583,100 +588,113 @@ class _TracerCore(ABC):
token: The new token.
chunk: Optional chunk.
"""
_ = (run, token, chunk)
return None
def _on_llm_end(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_llm_end(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process the LLM Run.
Args:
run: The LLM run.
"""
_ = run
return None
def _on_llm_error(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_llm_error(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process the LLM Run upon error.
Args:
run: The LLM run.
"""
_ = run
return None
def _on_chain_start(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_chain_start(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process the Chain Run upon start.
Args:
run: The chain run.
"""
_ = run
return None
def _on_chain_end(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_chain_end(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process the Chain Run.
Args:
run: The chain run.
"""
_ = run
return None
def _on_chain_error(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_chain_error(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process the Chain Run upon error.
Args:
run: The chain run.
"""
_ = run
return None
def _on_tool_start(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_tool_start(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process the Tool Run upon start.
Args:
run: The tool run.
"""
_ = run
return None
def _on_tool_end(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_tool_end(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process the Tool Run.
Args:
run: The tool run.
"""
_ = run
return None
def _on_tool_error(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_tool_error(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process the Tool Run upon error.
Args:
run: The tool run.
"""
_ = run
return None
def _on_chat_model_start(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_chat_model_start(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process the Chat Model Run upon start.
Args:
run: The chat model run.
"""
_ = run
return None
def _on_retriever_start(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_retriever_start(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process the Retriever Run upon start.
Args:
run: The retriever run.
"""
_ = run
return None
def _on_retriever_end(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_retriever_end(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process the Retriever Run.
Args:
run: The retriever run.
"""
_ = run
return None
def _on_retriever_error(self, run: Run) -> Coroutine[Any, Any, None] | None: # noqa: ARG002
def _on_retriever_error(self, run: Run) -> Coroutine[Any, Any, None] | None:
"""Process the Retriever Run upon error.
Args:
run: The retriever run.
"""
_ = run
return None

View File

@@ -72,7 +72,7 @@ def _process_dict_properties(
elif isinstance(value, (dict, list)):
# Recursively process nested objects and arrays
result[key] = _dereference_refs_helper(
value, full_schema, processed_refs, skip_keys, shallow_refs
value, full_schema, processed_refs, skip_keys, shallow_refs=shallow_refs
)
else:
# Copy primitive values directly
@@ -85,7 +85,8 @@ def _dereference_refs_helper(
full_schema: dict[str, Any],
processed_refs: set[str] | None,
skip_keys: Sequence[str],
shallow_refs: bool, # noqa: FBT001
*,
shallow_refs: bool,
) -> Any:
"""Dereference JSON Schema $ref objects, handling both pure and mixed references.
@@ -133,7 +134,11 @@ def _dereference_refs_helper(
# Fetch and recursively resolve the referenced object
referenced_object = deepcopy(_retrieve_ref(ref_path, full_schema))
resolved_reference = _dereference_refs_helper(
referenced_object, full_schema, processed_refs, skip_keys, shallow_refs
referenced_object,
full_schema,
processed_refs,
skip_keys,
shallow_refs=shallow_refs,
)
# Clean up: remove from processing set before returning
@@ -171,7 +176,7 @@ def _dereference_refs_helper(
if isinstance(obj, list):
return [
_dereference_refs_helper(
item, full_schema, processed_refs, skip_keys, shallow_refs
item, full_schema, processed_refs, skip_keys, shallow_refs=shallow_refs
)
for item in obj
]
@@ -260,5 +265,8 @@ def dereference_refs(
keys_to_skip = list(skip_keys) if skip_keys is not None else ["$defs"]
shallow = skip_keys is None
return cast(
"dict", _dereference_refs_helper(schema_obj, full, None, keys_to_skip, shallow)
"dict",
_dereference_refs_helper(
schema_obj, full, None, keys_to_skip, shallow_refs=shallow
),
)

View File

@@ -1,7 +1,5 @@
"""Test in memory indexer."""
from collections.abc import AsyncGenerator, Generator
import pytest
from langchain_tests.integration_tests.indexer import (
AsyncDocumentIndexTestSuite,
@@ -10,7 +8,6 @@ from langchain_tests.integration_tests.indexer import (
from typing_extensions import override
from langchain_core.documents import Document
from langchain_core.indexing.base import DocumentIndex
from langchain_core.indexing.in_memory import (
InMemoryDocumentIndex,
)
@@ -19,16 +16,16 @@ from langchain_core.indexing.in_memory import (
class TestDocumentIndexerTestSuite(DocumentIndexerTestSuite):
@pytest.fixture
@override
def index(self) -> Generator[DocumentIndex, None, None]:
yield InMemoryDocumentIndex() # noqa: PT022
def index(self) -> InMemoryDocumentIndex:
return InMemoryDocumentIndex()
class TestAsyncDocumentIndexerTestSuite(AsyncDocumentIndexTestSuite):
# Something funky is going on with mypy and async pytest fixture
@pytest.fixture
@override
async def index(self) -> AsyncGenerator[DocumentIndex, None]:
yield InMemoryDocumentIndex() # noqa: PT022
async def index(self) -> InMemoryDocumentIndex:
return InMemoryDocumentIndex()
def test_sync_retriever() -> None:

View File

@@ -1564,9 +1564,15 @@ def test_rendering_prompt_with_conditionals_no_empty_text_blocks() -> None:
"kwargs": {
"input_variables": [],
"template_format": "mustache",
"template": "Here is the expected answer or success criteria given by the teacher:", # noqa: E501
"template": (
"Here is the expected answer or success "
"criteria given by the teacher:"
),
"additional_content_fields": {
"text": "Here is the expected answer or success criteria given by the teacher:", # noqa: E501
"text": (
"Here is the expected answer or success "
"criteria given by the teacher:"
),
},
},
},
@@ -1600,9 +1606,17 @@ def test_rendering_prompt_with_conditionals_no_empty_text_blocks() -> None:
"kwargs": {
"input_variables": [],
"template_format": "mustache",
"template": "Note: This may be just one example of many possible correct ways for the student to respond.\n", # noqa: E501
"template": (
"Note: This may be just one example of many "
"possible correct ways for the student to "
"respond.\n"
),
"additional_content_fields": {
"text": "Note: This may be just one example of many possible correct ways for the student to respond.\n", # noqa: E501
"text": (
"Note: This may be just one example of "
"many possible correct ways for the "
"student to respond.\n"
)
},
},
},
@@ -1618,9 +1632,15 @@ def test_rendering_prompt_with_conditionals_no_empty_text_blocks() -> None:
"kwargs": {
"input_variables": [],
"template_format": "mustache",
"template": "For your evaluation of the student's response:\n", # noqa: E501
"template": (
"For your evaluation of the student's "
"response:\n"
),
"additional_content_fields": {
"text": "For your evaluation of the student's response:\n", # noqa: E501
"text": (
"For your evaluation of the student's "
"response:\n"
),
},
},
},
@@ -1636,9 +1656,15 @@ def test_rendering_prompt_with_conditionals_no_empty_text_blocks() -> None:
"kwargs": {
"input_variables": [],
"template_format": "mustache",
"template": "Here is a transcript of the student's explanation:", # noqa: E501
"template": (
"Here is a transcript of the student's "
"explanation:"
),
"additional_content_fields": {
"text": "Here is a transcript of the student's explanation:", # noqa: E501
"text": (
"Here is a transcript of the student's "
"explanation:"
),
},
},
},
@@ -1672,9 +1698,23 @@ def test_rendering_prompt_with_conditionals_no_empty_text_blocks() -> None:
"kwargs": {
"input_variables": ["readingFluencyAnalysis"],
"template_format": "mustache",
"template": "{{#readingFluencyAnalysis}} For this task, the student's reading pronunciation and fluency were important. Here is analysis of the student's oral response: \"{{readingFluencyAnalysis}}\" {{/readingFluencyAnalysis}}", # noqa: E501
"template": (
"{{#readingFluencyAnalysis}} For this task, "
"the student's reading pronunciation and "
"fluency were important. "
"Here is analysis of the student's oral "
'response: "{{readingFluencyAnalysis}}" '
"{{/readingFluencyAnalysis}}"
),
"additional_content_fields": {
"text": "{{#readingFluencyAnalysis}} For this task, the student's reading pronunciation and fluency were important. Here is analysis of the student's oral response: \"{{readingFluencyAnalysis}}\" {{/readingFluencyAnalysis}}", # noqa: E501
"text": (
"{{#readingFluencyAnalysis}} For this "
"task, the student's reading pronunciation "
"and fluency were important. "
"Here is analysis of the student's oral "
'response: "{{readingFluencyAnalysis}}" '
"{{/readingFluencyAnalysis}}"
),
},
},
},
@@ -1690,9 +1730,20 @@ def test_rendering_prompt_with_conditionals_no_empty_text_blocks() -> None:
"kwargs": {
"input_variables": ["readingFluencyAnalysis"],
"template_format": "mustache",
"template": "{{#readingFluencyAnalysis}}Root analysis of the student's response (step 3) in this oral analysis rather than inconsistencies in the transcript.{{/readingFluencyAnalysis}}", # noqa: E501
"template": (
"{{#readingFluencyAnalysis}}Root analysis of "
"the student's response (step 3) in this oral "
"analysis rather than inconsistencies in the "
"transcript.{{/readingFluencyAnalysis}}"
),
"additional_content_fields": {
"text": "{{#readingFluencyAnalysis}}Root analysis of the student's response (step 3) in this oral analysis rather than inconsistencies in the transcript.{{/readingFluencyAnalysis}}", # noqa: E501
"text": (
"{{#readingFluencyAnalysis}}Root analysis "
"of the student's response (step 3) in "
"this oral analysis rather than "
"inconsistencies in the transcript."
"{{/readingFluencyAnalysis}}"
),
},
},
},
@@ -1708,9 +1759,19 @@ def test_rendering_prompt_with_conditionals_no_empty_text_blocks() -> None:
"kwargs": {
"input_variables": ["readingFluencyAnalysis"],
"template_format": "mustache",
"template": "{{#readingFluencyAnalysis}}Remember this is a student, so we care about general fluency - not voice acting. {{/readingFluencyAnalysis}}\n", # noqa: E501
"template": (
"{{#readingFluencyAnalysis}}Remember this is a "
"student, so we care about general fluency - "
"not voice acting. "
"{{/readingFluencyAnalysis}}\n"
),
"additional_content_fields": {
"text": "{{#readingFluencyAnalysis}}Remember this is a student, so we care about general fluency - not voice acting. {{/readingFluencyAnalysis}}\n", # noqa: E501
"text": (
"{{#readingFluencyAnalysis}}Remember this "
"is a student, so we care about general "
"fluency - not voice acting. "
"{{/readingFluencyAnalysis}}\n"
),
},
},
},
@@ -1726,9 +1787,19 @@ def test_rendering_prompt_with_conditionals_no_empty_text_blocks() -> None:
"kwargs": {
"input_variables": ["multipleChoiceAnalysis"],
"template_format": "mustache",
"template": "{{#multipleChoiceAnalysis}}Here is an analysis of the student's multiple choice response: {{multipleChoiceAnalysis}}{{/multipleChoiceAnalysis}}\n", # noqa: E501
"template": (
"{{#multipleChoiceAnalysis}}Here is an "
"analysis of the student's multiple choice "
"response: {{multipleChoiceAnalysis}}"
"{{/multipleChoiceAnalysis}}\n"
),
"additional_content_fields": {
"text": "{{#multipleChoiceAnalysis}}Here is an analysis of the student's multiple choice response: {{multipleChoiceAnalysis}}{{/multipleChoiceAnalysis}}\n", # noqa: E501
"text": (
"{{#multipleChoiceAnalysis}}Here is an "
"analysis of the student's multiple choice "
"response: {{multipleChoiceAnalysis}}"
"{{/multipleChoiceAnalysis}}\n"
),
},
},
},

View File

@@ -43,15 +43,17 @@ class MyRunnable(RunnableSerializable[str, str]):
def my_custom_function_w_config(
self,
config: RunnableConfig | None = None, # noqa: ARG002
config: RunnableConfig | None = None,
) -> str:
_ = config
return self.my_property
def my_custom_function_w_kw_config(
self,
*,
config: RunnableConfig | None = None, # noqa: ARG002
config: RunnableConfig | None = None,
) -> str:
_ = config
return self.my_property
@@ -67,7 +69,8 @@ class MyOtherRunnable(RunnableSerializable[str, str]):
def my_other_custom_function(self) -> str:
return self.my_other_property
def my_other_custom_function_w_config(self, config: RunnableConfig) -> str: # noqa: ARG002
def my_other_custom_function_w_config(self, config: RunnableConfig) -> str:
_ = config
return self.my_other_property

View File

@@ -53,8 +53,10 @@ def _get_get_session_history(
def test_input_messages() -> None:
runnable = RunnableLambda(
lambda messages: "you said: "
+ "\n".join(str(m.content) for m in messages if isinstance(m, HumanMessage))
lambda messages: (
"you said: "
+ "\n".join(str(m.content) for m in messages if isinstance(m, HumanMessage))
)
)
store: dict[str, InMemoryChatMessageHistory] = {}
get_session_history = _get_get_session_history(store=store)
@@ -82,8 +84,10 @@ def test_input_messages() -> None:
async def test_input_messages_async() -> None:
runnable = RunnableLambda(
lambda messages: "you said: "
+ "\n".join(str(m.content) for m in messages if isinstance(m, HumanMessage))
lambda messages: (
"you said: "
+ "\n".join(str(m.content) for m in messages if isinstance(m, HumanMessage))
)
)
store: dict[str, InMemoryChatMessageHistory] = {}
get_session_history = _get_get_session_history(store=store)
@@ -114,9 +118,13 @@ async def test_input_messages_async() -> None:
def test_input_dict() -> None:
runnable = RunnableLambda(
lambda params: "you said: "
+ "\n".join(
str(m.content) for m in params["messages"] if isinstance(m, HumanMessage)
lambda params: (
"you said: "
+ "\n".join(
str(m.content)
for m in params["messages"]
if isinstance(m, HumanMessage)
)
)
)
get_session_history = _get_get_session_history()
@@ -134,9 +142,13 @@ def test_input_dict() -> None:
async def test_input_dict_async() -> None:
runnable = RunnableLambda(
lambda params: "you said: "
+ "\n".join(
str(m.content) for m in params["messages"] if isinstance(m, HumanMessage)
lambda params: (
"you said: "
+ "\n".join(
str(m.content)
for m in params["messages"]
if isinstance(m, HumanMessage)
)
)
)
get_session_history = _get_get_session_history()
@@ -156,10 +168,16 @@ async def test_input_dict_async() -> None:
def test_input_dict_with_history_key() -> None:
runnable = RunnableLambda(
lambda params: "you said: "
+ "\n".join(
[str(m.content) for m in params["history"] if isinstance(m, HumanMessage)]
+ [params["input"]]
lambda params: (
"you said: "
+ "\n".join(
[
str(m.content)
for m in params["history"]
if isinstance(m, HumanMessage)
]
+ [params["input"]]
)
)
)
get_session_history = _get_get_session_history()
@@ -178,10 +196,16 @@ def test_input_dict_with_history_key() -> None:
async def test_input_dict_with_history_key_async() -> None:
runnable = RunnableLambda(
lambda params: "you said: "
+ "\n".join(
[str(m.content) for m in params["history"] if isinstance(m, HumanMessage)]
+ [params["input"]]
lambda params: (
"you said: "
+ "\n".join(
[
str(m.content)
for m in params["history"]
if isinstance(m, HumanMessage)
]
+ [params["input"]]
)
)
)
get_session_history = _get_get_session_history()
@@ -832,8 +856,10 @@ class _RunnableLambdaWithRaiseError(RunnableLambda[Input, Output]):
def test_get_output_messages_no_value_error() -> None:
runnable = _RunnableLambdaWithRaiseError(
lambda messages: "you said: "
+ "\n".join(str(m.content) for m in messages if isinstance(m, HumanMessage))
lambda messages: (
"you said: "
+ "\n".join(str(m.content) for m in messages if isinstance(m, HumanMessage))
)
)
get_session_history = _get_get_session_history()
with_history = RunnableWithMessageHistory(runnable, get_session_history)

View File

@@ -83,8 +83,9 @@ async def test_event_stream_with_simple_function_tool() -> None:
return {"x": 5}
@tool
def get_docs(x: int) -> list[Document]: # noqa: ARG001
def get_docs(x: int) -> list[Document]:
"""Hello Doc."""
_ = x
return [Document(page_content="hello")]
chain = RunnableLambda(foo) | get_docs
@@ -1069,8 +1070,9 @@ async def test_event_streaming_with_tools() -> None:
return "hello"
@tool
def with_callbacks(callbacks: Callbacks) -> str: # noqa: ARG001
def with_callbacks(callbacks: Callbacks) -> str:
"""A tool that does nothing."""
_ = callbacks
return "world"
@tool
@@ -1079,8 +1081,9 @@ async def test_event_streaming_with_tools() -> None:
return {"x": x, "y": y}
@tool
def with_parameters_and_callbacks(x: int, y: str, callbacks: Callbacks) -> dict: # noqa: ARG001
def with_parameters_and_callbacks(x: int, y: str, callbacks: Callbacks) -> dict:
"""A tool that does nothing."""
_ = callbacks
return {"x": x, "y": y}
# type ignores below because the tools don't appear to be runnables to type checkers

View File

@@ -91,13 +91,15 @@ async def _collect_events(
async def test_event_stream_with_simple_function_tool() -> None:
"""Test the event stream with a function and tool."""
def foo(x: int) -> dict: # noqa: ARG001
def foo(x: int) -> dict:
"""Foo."""
_ = x
return {"x": 5}
@tool
def get_docs(x: int) -> list[Document]: # noqa: ARG001
def get_docs(x: int) -> list[Document]:
"""Hello Doc."""
_ = x
return [Document(page_content="hello")]
chain = RunnableLambda(foo) | get_docs
@@ -1087,8 +1089,9 @@ async def test_event_streaming_with_tools() -> None:
return "hello"
@tool
def with_callbacks(callbacks: Callbacks) -> str: # noqa: ARG001
def with_callbacks(callbacks: Callbacks) -> str:
"""A tool that does nothing."""
_ = callbacks
return "world"
@tool
@@ -1097,8 +1100,9 @@ async def test_event_streaming_with_tools() -> None:
return {"x": x, "y": y}
@tool
def with_parameters_and_callbacks(x: int, y: str, callbacks: Callbacks) -> dict: # noqa: ARG001
def with_parameters_and_callbacks(x: int, y: str, callbacks: Callbacks) -> dict:
"""A tool that does nothing."""
_ = callbacks
return {"x": x, "y": y}
# type ignores below because the tools don't appear to be runnables to type checkers

View File

@@ -1047,8 +1047,9 @@ def test__convert_typed_dict_to_openai_function_fail(typed_dict: type) -> None:
def test_convert_union_type() -> None:
@tool
def magic_function(value: int | str) -> str: # noqa: ARG001
def magic_function(value: int | str) -> str:
"""Compute a magic function."""
_ = value
return ""
result = convert_to_openai_function(magic_function)