diff --git a/libs/core/langchain_core/caches.py b/libs/core/langchain_core/caches.py index a2a90eadc6e..86139c5d821 100644 --- a/libs/core/langchain_core/caches.py +++ b/libs/core/langchain_core/caches.py @@ -2,8 +2,8 @@ Distinct from provider-based [prompt caching](https://docs.langchain.com/oss/python/langchain/models#prompt-caching). -!!! warning - This is a beta feature! Please be wary of deploying experimental code to production +!!! warning "Beta feature" + This is a beta feature. Please be wary of deploying experimental code to production unless you've taken appropriate precautions. A cache is useful for two reasons: @@ -49,17 +49,18 @@ class BaseCache(ABC): """Look up based on `prompt` and `llm_string`. A cache implementation is expected to generate a key from the 2-tuple - of prompt and llm_string (e.g., by concatenating them with a delimiter). + of `prompt` and `llm_string` (e.g., by concatenating them with a delimiter). Args: prompt: A string representation of the prompt. In the case of a chat model, the prompt is a non-trivial serialization of the prompt into the language model. llm_string: A string representation of the LLM configuration. + This is used to capture the invocation parameters of the LLM (e.g., model name, temperature, stop tokens, max tokens, etc.). - These invocation parameters are serialized into a string - representation. + + These invocation parameters are serialized into a string representation. Returns: On a cache miss, return `None`. On a cache hit, return the cached value. @@ -78,8 +79,10 @@ class BaseCache(ABC): In the case of a chat model, the prompt is a non-trivial serialization of the prompt into the language model. llm_string: A string representation of the LLM configuration. + This is used to capture the invocation parameters of the LLM (e.g., model name, temperature, stop tokens, max tokens, etc.). + These invocation parameters are serialized into a string representation. return_val: The value to be cached. The value is a list of `Generation` @@ -94,15 +97,17 @@ class BaseCache(ABC): """Async look up based on `prompt` and `llm_string`. A cache implementation is expected to generate a key from the 2-tuple - of prompt and llm_string (e.g., by concatenating them with a delimiter). + of `prompt` and `llm_string` (e.g., by concatenating them with a delimiter). Args: prompt: A string representation of the prompt. In the case of a chat model, the prompt is a non-trivial serialization of the prompt into the language model. llm_string: A string representation of the LLM configuration. + This is used to capture the invocation parameters of the LLM (e.g., model name, temperature, stop tokens, max tokens, etc.). + These invocation parameters are serialized into a string representation. @@ -125,8 +130,10 @@ class BaseCache(ABC): In the case of a chat model, the prompt is a non-trivial serialization of the prompt into the language model. llm_string: A string representation of the LLM configuration. + This is used to capture the invocation parameters of the LLM (e.g., model name, temperature, stop tokens, max tokens, etc.). + These invocation parameters are serialized into a string representation. return_val: The value to be cached. The value is a list of `Generation` diff --git a/libs/core/langchain_core/documents/__init__.py b/libs/core/langchain_core/documents/__init__.py index 2bf3f802197..1969f10935d 100644 --- a/libs/core/langchain_core/documents/__init__.py +++ b/libs/core/langchain_core/documents/__init__.py @@ -1,7 +1,28 @@ -"""Documents module. +"""Documents module for data retrieval and processing workflows. -**Document** module is a collection of classes that handle documents -and their transformations. +This module provides core abstractions for handling data in retrieval-augmented +generation (RAG) pipelines, vector stores, and document processing workflows. + +!!! warning "Documents vs. message content" + This module is distinct from `langchain_core.messages.content`, which provides + multimodal content blocks for **LLM chat I/O** (text, images, audio, etc. within + messages). + + **Key distinction:** + + - **Documents** (this module): For **data retrieval and processing workflows** + - Vector stores, retrievers, RAG pipelines + - Text chunking, embedding, and semantic search + - Example: Chunks of a PDF stored in a vector database + + - **Content Blocks** (`messages.content`): For **LLM conversational I/O** + - Multimodal message content sent to/from models + - Tool calls, reasoning, citations within chat + - Example: An image sent to a vision model in a chat message (via + [`ImageContentBlock`][langchain.messages.ImageContentBlock]) + + While both can represent similar data types (text, files), they serve different + architectural purposes in LangChain applications. """ from typing import TYPE_CHECKING diff --git a/libs/core/langchain_core/documents/base.py b/libs/core/langchain_core/documents/base.py index 68eeca0fd39..f049a9897bc 100644 --- a/libs/core/langchain_core/documents/base.py +++ b/libs/core/langchain_core/documents/base.py @@ -1,4 +1,16 @@ -"""Base classes for media and documents.""" +"""Base classes for media and documents. + +This module contains core abstractions for **data retrieval and processing workflows**: + +- `BaseMedia`: Base class providing `id` and `metadata` fields +- `Blob`: Raw data loading (files, binary data) - used by document loaders +- `Document`: Text content for retrieval (RAG, vector stores, semantic search) + +!!! note "Not for LLM chat messages" + These classes are for data processing pipelines, not LLM I/O. For multimodal + content in chat messages (images, audio in conversations), see + `langchain.messages` content blocks instead. +""" from __future__ import annotations @@ -19,15 +31,13 @@ PathLike = str | PurePath class BaseMedia(Serializable): - """Use to represent media content. + """Base class for content used in retrieval and data processing workflows. - Media objects can be used to represent raw data, such as text or binary data. + Provides common fields for content that needs to be stored, indexed, or searched. - LangChain Media objects allow associating metadata and an optional identifier - with the content. - - The presence of an ID and metadata make it easier to store, index, and search - over the content in a structured way. + !!! note + For multimodal content in **chat messages** (images, audio sent to/from LLMs), + use `langchain.messages` content blocks instead. """ # The ID field is optional at the moment. @@ -45,61 +55,60 @@ class BaseMedia(Serializable): class Blob(BaseMedia): - """Blob represents raw data by either reference or value. + """Raw data abstraction for document loading and file processing. - Provides an interface to materialize the blob in different representations, and - help to decouple the development of data loaders from the downstream parsing of - the raw data. + Represents raw bytes or text, either in-memory or by file reference. Used + primarily by document loaders to decouple data loading from parsing. Inspired by [Mozilla's `Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) - Example: Initialize a blob from in-memory data + ???+ example "Initialize a blob from in-memory data" - ```python - from langchain_core.documents import Blob + ```python + from langchain_core.documents import Blob - blob = Blob.from_data("Hello, world!") + blob = Blob.from_data("Hello, world!") - # Read the blob as a string - print(blob.as_string()) + # Read the blob as a string + print(blob.as_string()) - # Read the blob as bytes - print(blob.as_bytes()) + # Read the blob as bytes + print(blob.as_bytes()) - # Read the blob as a byte stream - with blob.as_bytes_io() as f: - print(f.read()) - ``` + # Read the blob as a byte stream + with blob.as_bytes_io() as f: + print(f.read()) + ``` - Example: Load from memory and specify mime-type and metadata + ??? example "Load from memory and specify MIME type and metadata" - ```python - from langchain_core.documents import Blob + ```python + from langchain_core.documents import Blob - blob = Blob.from_data( - data="Hello, world!", - mime_type="text/plain", - metadata={"source": "https://example.com"}, - ) - ``` + blob = Blob.from_data( + data="Hello, world!", + mime_type="text/plain", + metadata={"source": "https://example.com"}, + ) + ``` - Example: Load the blob from a file + ??? example "Load the blob from a file" - ```python - from langchain_core.documents import Blob + ```python + from langchain_core.documents import Blob - blob = Blob.from_path("path/to/file.txt") + blob = Blob.from_path("path/to/file.txt") - # Read the blob as a string - print(blob.as_string()) + # Read the blob as a string + print(blob.as_string()) - # Read the blob as bytes - print(blob.as_bytes()) + # Read the blob as bytes + print(blob.as_bytes()) - # Read the blob as a byte stream - with blob.as_bytes_io() as f: - print(f.read()) - ``` + # Read the blob as a byte stream + with blob.as_bytes_io() as f: + print(f.read()) + ``` """ data: bytes | str | None = None @@ -213,7 +222,7 @@ class Blob(BaseMedia): encoding: Encoding to use if decoding the bytes into a string mime_type: If provided, will be set as the MIME type of the data guess_type: If `True`, the MIME type will be guessed from the file - extension, if a mime-type was not provided + extension, if a MIME type was not provided metadata: Metadata to associate with the `Blob` Returns: @@ -274,6 +283,10 @@ class Blob(BaseMedia): class Document(BaseMedia): """Class for storing a piece of text and associated metadata. + !!! note + `Document` is for **retrieval workflows**, not chat I/O. For sending text + to an LLM in a conversation, use message types from `langchain.messages`. + Example: ```python from langchain_core.documents import Document diff --git a/libs/core/langchain_core/documents/compressor.py b/libs/core/langchain_core/documents/compressor.py index b18728eb9d3..c765b378bb1 100644 --- a/libs/core/langchain_core/documents/compressor.py +++ b/libs/core/langchain_core/documents/compressor.py @@ -21,14 +21,14 @@ class BaseDocumentCompressor(BaseModel, ABC): This abstraction is primarily used for post-processing of retrieved documents. - Documents matching a given query are first retrieved. + `Document` objects matching a given query are first retrieved. Then the list of documents can be further processed. For example, one could re-rank the retrieved documents using an LLM. !!! note - Users should favor using a RunnableLambda instead of sub-classing from this + Users should favor using a `RunnableLambda` instead of sub-classing from this interface. """ @@ -43,9 +43,9 @@ class BaseDocumentCompressor(BaseModel, ABC): """Compress retrieved documents given the query context. Args: - documents: The retrieved documents. + documents: The retrieved `Document` objects. query: The query context. - callbacks: Optional callbacks to run during compression. + callbacks: Optional `Callbacks` to run during compression. Returns: The compressed documents. @@ -61,9 +61,9 @@ class BaseDocumentCompressor(BaseModel, ABC): """Async compress retrieved documents given the query context. Args: - documents: The retrieved documents. + documents: The retrieved `Document` objects. query: The query context. - callbacks: Optional callbacks to run during compression. + callbacks: Optional `Callbacks` to run during compression. Returns: The compressed documents. diff --git a/libs/core/langchain_core/documents/transformers.py b/libs/core/langchain_core/documents/transformers.py index 4b815464a6d..c05fa29a239 100644 --- a/libs/core/langchain_core/documents/transformers.py +++ b/libs/core/langchain_core/documents/transformers.py @@ -16,8 +16,8 @@ if TYPE_CHECKING: class BaseDocumentTransformer(ABC): """Abstract base class for document transformation. - A document transformation takes a sequence of Documents and returns a - sequence of transformed Documents. + A document transformation takes a sequence of `Document` objects and returns a + sequence of transformed `Document` objects. Example: ```python diff --git a/libs/core/langchain_core/embeddings/fake.py b/libs/core/langchain_core/embeddings/fake.py index 37260ac7113..0a252efc194 100644 --- a/libs/core/langchain_core/embeddings/fake.py +++ b/libs/core/langchain_core/embeddings/fake.py @@ -18,7 +18,7 @@ class FakeEmbeddings(Embeddings, BaseModel): This embedding model creates embeddings by sampling from a normal distribution. - !!! warning + !!! danger "Toy model" Do not use this outside of testing, as it is not a real embedding model. Instantiate: @@ -73,7 +73,7 @@ class DeterministicFakeEmbedding(Embeddings, BaseModel): This embedding model creates embeddings by sampling from a normal distribution with a seed based on the hash of the text. - !!! warning + !!! danger "Toy model" Do not use this outside of testing, as it is not a real embedding model. Instantiate: diff --git a/libs/core/langchain_core/language_models/__init__.py b/libs/core/langchain_core/language_models/__init__.py index 966b42e1220..625543c830f 100644 --- a/libs/core/langchain_core/language_models/__init__.py +++ b/libs/core/langchain_core/language_models/__init__.py @@ -6,12 +6,13 @@ LangChain has two main classes to work with language models: chat models and **Chat models** Language models that use a sequence of messages as inputs and return chat messages -as outputs (as opposed to using plain text). Chat models support the assignment of -distinct roles to conversation messages, helping to distinguish messages from the AI, -users, and instructions such as system messages. +as outputs (as opposed to using plain text). -The key abstraction for chat models is `BaseChatModel`. Implementations -should inherit from this class. +Chat models support the assignment of distinct roles to conversation messages, helping +to distinguish messages from the AI, users, and instructions such as system messages. + +The key abstraction for chat models is `BaseChatModel`. Implementations should inherit +from this class. See existing [chat model integrations](https://docs.langchain.com/oss/python/integrations/chat). diff --git a/libs/core/langchain_core/language_models/fake_chat_models.py b/libs/core/langchain_core/language_models/fake_chat_models.py index b619d3eb920..7ffb5896013 100644 --- a/libs/core/langchain_core/language_models/fake_chat_models.py +++ b/libs/core/langchain_core/language_models/fake_chat_models.py @@ -1,4 +1,4 @@ -"""Fake chat model for testing purposes.""" +"""Fake chat models for testing purposes.""" import asyncio import re diff --git a/libs/core/langchain_core/language_models/llms.py b/libs/core/langchain_core/language_models/llms.py index 645a9ef035c..051c2781e1c 100644 --- a/libs/core/langchain_core/language_models/llms.py +++ b/libs/core/langchain_core/language_models/llms.py @@ -1,4 +1,7 @@ -"""Base interface for large language models to expose.""" +"""Base interface for traditional large language models (LLMs) to expose. + +These are traditionally older models (newer models generally are chat models). +""" from __future__ import annotations diff --git a/libs/core/langchain_core/load/serializable.py b/libs/core/langchain_core/load/serializable.py index 13898d292d5..9c7588c185b 100644 --- a/libs/core/langchain_core/load/serializable.py +++ b/libs/core/langchain_core/load/serializable.py @@ -97,11 +97,14 @@ class Serializable(BaseModel, ABC): by default. This is to prevent accidental serialization of objects that should not be serialized. - `get_lc_namespace`: Get the namespace of the LangChain object. + During deserialization, this namespace is used to identify the correct class to instantiate. + Please see the `Reviver` class in `langchain_core.load.load` for more details. During deserialization an additional mapping is handle classes that have moved or been renamed across package versions. + - `lc_secrets`: A map of constructor argument names to secret ids. - `lc_attributes`: List of additional attribute names that should be included as part of the serialized representation. diff --git a/libs/core/langchain_core/messages/block_translators/google_genai.py b/libs/core/langchain_core/messages/block_translators/google_genai.py index 1f4d297bbc2..2a82f035c23 100644 --- a/libs/core/langchain_core/messages/block_translators/google_genai.py +++ b/libs/core/langchain_core/messages/block_translators/google_genai.py @@ -368,7 +368,7 @@ def _convert_to_v1_from_genai(message: AIMessage) -> list[types.ContentBlock]: else: # Assume it's raw base64 without data URI try: - # Validate base64 and decode for mime type detection + # Validate base64 and decode for MIME type detection decoded_bytes = base64.b64decode(url, validate=True) image_url_b64_block = { @@ -379,7 +379,7 @@ def _convert_to_v1_from_genai(message: AIMessage) -> list[types.ContentBlock]: try: import filetype # type: ignore[import-not-found] # noqa: PLC0415 - # Guess mime type based on file bytes + # Guess MIME type based on file bytes mime_type = None kind = filetype.guess(decoded_bytes) if kind: diff --git a/libs/core/langchain_core/messages/content.py b/libs/core/langchain_core/messages/content.py index 10e17d63738..4b6a63e95f0 100644 --- a/libs/core/langchain_core/messages/content.py +++ b/libs/core/langchain_core/messages/content.py @@ -644,7 +644,7 @@ class AudioContentBlock(TypedDict): class PlainTextContentBlock(TypedDict): - """Plaintext data (e.g., from a document). + """Plaintext data (e.g., from a `.txt` or `.md` document). !!! note A `PlainTextContentBlock` existed in `langchain-core<1.0.0`. Although the @@ -767,7 +767,7 @@ class FileContentBlock(TypedDict): class NonStandardContentBlock(TypedDict): - """Provider-specific data. + """Provider-specific content data. This block contains data for which there is not yet a standard type. @@ -802,7 +802,7 @@ class NonStandardContentBlock(TypedDict): """ value: dict[str, Any] - """Provider-specific data.""" + """Provider-specific content data.""" index: NotRequired[int | str] """Index of block in aggregate response. Used during streaming.""" @@ -1399,7 +1399,7 @@ def create_non_standard_block( """Create a `NonStandardContentBlock`. Args: - value: Provider-specific data. + value: Provider-specific content data. id: Content block identifier. Generated automatically if not provided. index: Index of block in aggregate response. Used during streaming. diff --git a/libs/core/langchain_core/messages/utils.py b/libs/core/langchain_core/messages/utils.py index 5554aa8abf9..16cafce895e 100644 --- a/libs/core/langchain_core/messages/utils.py +++ b/libs/core/langchain_core/messages/utils.py @@ -86,7 +86,7 @@ AnyMessage = Annotated[ | Annotated[ToolMessageChunk, Tag(tag="ToolMessageChunk")], Field(discriminator=Discriminator(_get_type)), ] -""""A type representing any defined `Message` or `MessageChunk` type.""" +"""A type representing any defined `Message` or `MessageChunk` type.""" def get_buffer_string( diff --git a/libs/core/langchain_core/prompt_values.py b/libs/core/langchain_core/prompt_values.py index 99b063bc5bc..731941514fd 100644 --- a/libs/core/langchain_core/prompt_values.py +++ b/libs/core/langchain_core/prompt_values.py @@ -37,8 +37,6 @@ class PromptValue(Serializable, ABC): def get_lc_namespace(cls) -> list[str]: """Get the namespace of the LangChain object. - This is used to determine the namespace of the object when serializing. - Returns: `["langchain", "schema", "prompt"]` """ @@ -64,8 +62,6 @@ class StringPromptValue(PromptValue): def get_lc_namespace(cls) -> list[str]: """Get the namespace of the LangChain object. - This is used to determine the namespace of the object when serializing. - Returns: `["langchain", "prompts", "base"]` """ @@ -101,8 +97,6 @@ class ChatPromptValue(PromptValue): def get_lc_namespace(cls) -> list[str]: """Get the namespace of the LangChain object. - This is used to determine the namespace of the object when serializing. - Returns: `["langchain", "prompts", "chat"]` """ diff --git a/libs/core/langchain_core/prompts/base.py b/libs/core/langchain_core/prompts/base.py index 941c4ec7266..ed322080c93 100644 --- a/libs/core/langchain_core/prompts/base.py +++ b/libs/core/langchain_core/prompts/base.py @@ -48,11 +48,13 @@ class BasePromptTemplate( """A list of the names of the variables whose values are required as inputs to the prompt.""" optional_variables: list[str] = Field(default=[]) - """optional_variables: A list of the names of the variables for placeholder - or MessagePlaceholder that are optional. These variables are auto inferred - from the prompt and user need not provide them.""" + """A list of the names of the variables for placeholder or `MessagePlaceholder` that + are optional. + + 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 """A dictionary of the types of the variables the prompt template expects. + If not provided, all variables are assumed to be strings.""" output_parser: BaseOutputParser | None = None """How to parse the output of calling an LLM on this formatted prompt.""" diff --git a/libs/core/langchain_core/prompts/chat.py b/libs/core/langchain_core/prompts/chat.py index 24cd084817e..7878761f03e 100644 --- a/libs/core/langchain_core/prompts/chat.py +++ b/libs/core/langchain_core/prompts/chat.py @@ -776,11 +776,6 @@ class ChatPromptTemplate(BaseChatPromptTemplate): Use to create flexible templated prompts for chat models. - !!! warning "Behavior changed in 0.2.24" - You can pass any Message-like formats supported by - `ChatPromptTemplate.from_messages()` directly to `ChatPromptTemplate()` - init. - ```python from langchain_core.prompts import ChatPromptTemplate @@ -896,25 +891,35 @@ class ChatPromptTemplate(BaseChatPromptTemplate): """Create a chat prompt template from a variety of message formats. Args: - messages: sequence of message representations. + messages: Sequence of message representations. + A message can be represented using the following formats: - (1) BaseMessagePromptTemplate, (2) BaseMessage, (3) 2-tuple of - (message type, template); e.g., ("human", "{user_input}"), - (4) 2-tuple of (message class, template), (5) a string which is - shorthand for ("human", template); e.g., "{user_input}". - template_format: format of the template. + + 1. `BaseMessagePromptTemplate` + 2. `BaseMessage` + 3. 2-tuple of `(message type, template)`; e.g., + `("human", "{user_input}")` + 4. 2-tuple of `(message class, template)` + 5. A string which is shorthand for `("human", template)`; e.g., + `"{user_input}"` + template_format: Format of the template. input_variables: A list of the names of the variables whose values are required as inputs to the prompt. optional_variables: A list of the names of the variables for placeholder or MessagePlaceholder that are optional. + These variables are auto inferred from the prompt and user need not provide them. partial_variables: A dictionary of the partial variables the prompt - template carries. Partial variables populate the template so that you - don't need to pass them in every time you call the prompt. + template carries. + + Partial variables populate the template so that you don't need to pass + them in every time you call the prompt. validate_template: Whether to validate the template. input_types: A dictionary of the types of the variables the prompt template - expects. If not provided, all variables are assumed to be strings. + expects. + + If not provided, all variables are assumed to be strings. Examples: Instantiation from a list of message templates: @@ -1119,12 +1124,17 @@ class ChatPromptTemplate(BaseChatPromptTemplate): ) ``` Args: - messages: sequence of message representations. + messages: Sequence of message representations. + A message can be represented using the following formats: - (1) BaseMessagePromptTemplate, (2) BaseMessage, (3) 2-tuple of - (message type, template); e.g., ("human", "{user_input}"), - (4) 2-tuple of (message class, template), (5) a string which is - shorthand for ("human", template); e.g., "{user_input}". + + 1. `BaseMessagePromptTemplate` + 2. `BaseMessage` + 3. 2-tuple of `(message type, template)`; e.g., + `("human", "{user_input}")` + 4. 2-tuple of `(message class, template)` + 5. A string which is shorthand for `("human", template)`; e.g., + `"{user_input}"` template_format: format of the template. Returns: @@ -1236,7 +1246,7 @@ class ChatPromptTemplate(BaseChatPromptTemplate): """Extend the chat template with a sequence of messages. Args: - messages: sequence of message representations to append. + messages: Sequence of message representations to append. """ self.messages.extend( [_convert_to_message_template(message) for message in messages] diff --git a/libs/core/langchain_core/prompts/structured.py b/libs/core/langchain_core/prompts/structured.py index 7ae138cf05b..33888691f79 100644 --- a/libs/core/langchain_core/prompts/structured.py +++ b/libs/core/langchain_core/prompts/structured.py @@ -104,19 +104,23 @@ class StructuredPrompt(ChatPromptTemplate): ) ``` Args: - messages: sequence of message representations. + messages: Sequence of message representations. + A message can be represented using the following formats: - (1) BaseMessagePromptTemplate, (2) BaseMessage, (3) 2-tuple of - (message type, template); e.g., ("human", "{user_input}"), - (4) 2-tuple of (message class, template), (5) a string which is - shorthand for ("human", template); e.g., "{user_input}" - schema: a dictionary representation of function call, or a Pydantic model. + + 1. `BaseMessagePromptTemplate` + 2. `BaseMessage` + 3. 2-tuple of `(message type, template)`; e.g., + `("human", "{user_input}")` + 4. 2-tuple of `(message class, template)` + 5. A string which is shorthand for `("human", template)`; e.g., + `"{user_input}"` + schema: A dictionary representation of function call, or a Pydantic model. **kwargs: Any additional kwargs to pass through to `ChatModel.with_structured_output(schema, **kwargs)`. Returns: - a structured prompt template - + A structured prompt template """ return cls(messages, schema, **kwargs) diff --git a/libs/core/langchain_core/retrievers.py b/libs/core/langchain_core/retrievers.py index bb50d2985e0..7be6df9a727 100644 --- a/libs/core/langchain_core/retrievers.py +++ b/libs/core/langchain_core/retrievers.py @@ -50,65 +50,65 @@ class LangSmithRetrieverParams(TypedDict, total=False): class BaseRetriever(RunnableSerializable[RetrieverInput, RetrieverOutput], ABC): - """Abstract base class for a Document retrieval system. + """Abstract base class for a document retrieval system. A retrieval system is defined as something that can take string queries and return - the most 'relevant' Documents from some source. + the most 'relevant' documents from some source. Usage: - A retriever follows the standard Runnable interface, and should be used - via the standard Runnable methods of `invoke`, `ainvoke`, `batch`, `abatch`. + A retriever follows the standard `Runnable` interface, and should be used via the + standard `Runnable` methods of `invoke`, `ainvoke`, `batch`, `abatch`. Implementation: - When implementing a custom retriever, the class should implement - the `_get_relevant_documents` method to define the logic for retrieving documents. + When implementing a custom retriever, the class should implement the + `_get_relevant_documents` method to define the logic for retrieving documents. Optionally, an async native implementations can be provided by overriding the `_aget_relevant_documents` method. - Example: A retriever that returns the first 5 documents from a list of documents + !!! example "Retriever that returns the first 5 documents from a list of documents" - ```python - from langchain_core.documents import Document - from langchain_core.retrievers import BaseRetriever + ```python + from langchain_core.documents import Document + from langchain_core.retrievers import BaseRetriever - class SimpleRetriever(BaseRetriever): - docs: list[Document] - k: int = 5 + class SimpleRetriever(BaseRetriever): + docs: list[Document] + k: int = 5 - def _get_relevant_documents(self, query: str) -> list[Document]: - \"\"\"Return the first k documents from the list of documents\"\"\" - return self.docs[:self.k] + def _get_relevant_documents(self, query: str) -> list[Document]: + \"\"\"Return the first k documents from the list of documents\"\"\" + return self.docs[:self.k] - async def _aget_relevant_documents(self, query: str) -> list[Document]: - \"\"\"(Optional) async native implementation.\"\"\" - return self.docs[:self.k] - ``` + async def _aget_relevant_documents(self, query: str) -> list[Document]: + \"\"\"(Optional) async native implementation.\"\"\" + return self.docs[:self.k] + ``` - Example: A simple retriever based on a scikit-learn vectorizer + !!! example "Simple retriever based on a scikit-learn vectorizer" - ```python - from sklearn.metrics.pairwise import cosine_similarity + ```python + from sklearn.metrics.pairwise import cosine_similarity - class TFIDFRetriever(BaseRetriever, BaseModel): - vectorizer: Any - docs: list[Document] - tfidf_array: Any - k: int = 4 + class TFIDFRetriever(BaseRetriever, BaseModel): + vectorizer: Any + docs: list[Document] + tfidf_array: Any + k: int = 4 - class Config: - arbitrary_types_allowed = True + class Config: + arbitrary_types_allowed = True - def _get_relevant_documents(self, query: str) -> list[Document]: - # Ip -- (n_docs,x), Op -- (n_docs,n_Feats) - query_vec = self.vectorizer.transform([query]) - # Op -- (n_docs,1) -- Cosine Sim with each doc - results = cosine_similarity(self.tfidf_array, query_vec).reshape((-1,)) - return [self.docs[i] for i in results.argsort()[-self.k :][::-1]] - ``` + def _get_relevant_documents(self, query: str) -> list[Document]: + # Ip -- (n_docs,x), Op -- (n_docs,n_Feats) + query_vec = self.vectorizer.transform([query]) + # Op -- (n_docs,1) -- Cosine Sim with each doc + results = cosine_similarity(self.tfidf_array, query_vec).reshape((-1,)) + return [self.docs[i] for i in results.argsort()[-self.k :][::-1]] + ``` """ model_config = ConfigDict( @@ -119,15 +119,19 @@ class BaseRetriever(RunnableSerializable[RetrieverInput, RetrieverOutput], ABC): _expects_other_args: bool = False tags: list[str] | None = None """Optional list of tags associated with the retriever. + These tags will be associated with each call to this retriever, and passed as arguments to the handlers defined in `callbacks`. + You can use these to eg identify a specific instance of a retriever with its use case. """ metadata: dict[str, Any] | None = None """Optional metadata associated with the retriever. + This metadata will be associated with each call to this retriever, and passed as arguments to the handlers defined in `callbacks`. + You can use these to eg identify a specific instance of a retriever with its use case. """ diff --git a/libs/core/langchain_core/tools/convert.py b/libs/core/langchain_core/tools/convert.py index cf16aef45af..ee51e30840f 100644 --- a/libs/core/langchain_core/tools/convert.py +++ b/libs/core/langchain_core/tools/convert.py @@ -89,6 +89,7 @@ def tool( runnable: Optional runnable to convert to a tool. Must be provided as a positional argument. description: Optional description for the tool. + Precedence for the tool description value is as follows: - `description` argument @@ -105,11 +106,13 @@ def tool( infer_schema: Whether to infer the schema of the arguments from the function's signature. This also makes the resultant tool accept a dictionary input to its `run()` function. - response_format: The tool response format. If `"content"` then the output of - the tool is interpreted as the contents of a `ToolMessage`. If - `"content_and_artifact"` then the output is expected to be a two-tuple - corresponding to the `(content, artifact)` of a `ToolMessage`. - parse_docstring: if `infer_schema` and `parse_docstring`, will attempt to + response_format: The tool response format. + + If `"content"` then the output of the tool is interpreted as the contents of + a `ToolMessage`. If `"content_and_artifact"` then the output is expected to + be a two-tuple corresponding to the `(content, artifact)` of a + `ToolMessage`. + parse_docstring: If `infer_schema` and `parse_docstring`, will attempt to parse parameter descriptions from Google Style function docstrings. error_on_invalid_docstring: if `parse_docstring` is provided, configure whether to raise `ValueError` on invalid Google Style docstrings. diff --git a/libs/core/langchain_core/tools/retriever.py b/libs/core/langchain_core/tools/retriever.py index 298ae6dd93d..5677e97bd74 100644 --- a/libs/core/langchain_core/tools/retriever.py +++ b/libs/core/langchain_core/tools/retriever.py @@ -83,11 +83,12 @@ def create_retriever_tool( model, so should be descriptive. document_prompt: The prompt to use for the document. document_separator: The separator to use between documents. - response_format: The tool response format. If `"content"` then the output of - the tool is interpreted as the contents of a `ToolMessage`. If - `"content_and_artifact"` then the output is expected to be a two-tuple - corresponding to the `(content, artifact)` of a `ToolMessage` (artifact - being a list of documents in this case). + response_format: The tool response format. + + If `"content"` then the output of the tool is interpreted as the contents of + a `ToolMessage`. If `"content_and_artifact"` then the output is expected to + be a two-tuple corresponding to the `(content, artifact)` of a `ToolMessage` + (artifact being a list of documents in this case). Returns: Tool class to pass to an agent. diff --git a/libs/core/langchain_core/tools/structured.py b/libs/core/langchain_core/tools/structured.py index 632c450c3b3..43e981570a0 100644 --- a/libs/core/langchain_core/tools/structured.py +++ b/libs/core/langchain_core/tools/structured.py @@ -151,11 +151,13 @@ class StructuredTool(BaseTool): return_direct: Whether to return the result directly or as a callback. args_schema: The schema of the tool's input arguments. infer_schema: Whether to infer the schema from the function's signature. - response_format: The tool response format. If `"content"` then the output of - the tool is interpreted as the contents of a `ToolMessage`. If - `"content_and_artifact"` then the output is expected to be a two-tuple - corresponding to the `(content, artifact)` of a `ToolMessage`. - parse_docstring: if `infer_schema` and `parse_docstring`, will attempt + response_format: The tool response format. + + If `"content"` then the output of the tool is interpreted as the + contents of a `ToolMessage`. If `"content_and_artifact"` then the output + is expected to be a two-tuple corresponding to the `(content, artifact)` + of a `ToolMessage`. + parse_docstring: If `infer_schema` and `parse_docstring`, will attempt to parse parameter descriptions from Google Style function docstrings. error_on_invalid_docstring: if `parse_docstring` is provided, configure whether to raise `ValueError` on invalid Google Style docstrings. diff --git a/libs/core/tests/unit_tests/runnables/test_runnable.py b/libs/core/tests/unit_tests/runnables/test_runnable.py index e04bf4e75b8..22300f4188f 100644 --- a/libs/core/tests/unit_tests/runnables/test_runnable.py +++ b/libs/core/tests/unit_tests/runnables/test_runnable.py @@ -313,6 +313,12 @@ def test_schemas(snapshot: SnapshotAssertion) -> None: "description": "Class for storing a piece of text and " "associated metadata.\n" "\n" + "!!! note\n" + " `Document` is for **retrieval workflows**, not chat I/O. For " + "sending text\n" + " to an LLM in a conversation, use message types from " + "`langchain.messages`.\n" + "\n" "Example:\n" " ```python\n" " from langchain_core.documents import Document\n" diff --git a/libs/langchain/langchain_classic/chat_models/base.py b/libs/langchain/langchain_classic/chat_models/base.py index 248e0dd0b0c..1ac5d4bdc06 100644 --- a/libs/langchain/langchain_classic/chat_models/base.py +++ b/libs/langchain/langchain_classic/chat_models/base.py @@ -76,26 +76,35 @@ def init_chat_model( config_prefix: str | None = None, **kwargs: Any, ) -> BaseChatModel | _ConfigurableModel: - """Initialize a chat model in a single line using the model's name and provider. + """Initialize a chat model from any supported provider using a unified interface. + + **Two main use cases:** + + 1. **Fixed model** – specify the model upfront and get back a ready-to-use chat + model. + 2. **Configurable model** – choose to specify parameters (including model name) at + runtime via `config`. Makes it easy to switch between models/providers without + changing your code !!! note - Requires the integration package for your model provider to be installed. + Requires the integration package for the chosen model provider to be installed. See the `model_provider` parameter below for specific package names (e.g., `pip install langchain-openai`). Refer to the [provider integration's API reference](https://docs.langchain.com/oss/python/integrations/providers) - for supported model parameters. + for supported model parameters to use as `**kwargs`. Args: model: The name of the model, e.g. `'o3-mini'`, `'claude-sonnet-4-5'`. - You can also specify model and model provider in a single argument using: - + You can also specify model and model provider in a single argument using `'{model_provider}:{model}'` format, e.g. `'openai:o1'`. model_provider: The model provider if not specified as part of the model arg - (see above). Supported `model_provider` values and the corresponding - integration package are: + (see above). + + Supported `model_provider` values and the corresponding integration package + are: - `openai` -> [`langchain-openai`](https://docs.langchain.com/oss/python/integrations/providers/openai) - `anthropic` -> [`langchain-anthropic`](https://docs.langchain.com/oss/python/integrations/providers/anthropic) @@ -132,80 +141,95 @@ def init_chat_model( - `deepseek...` -> `deepseek` - `grok...` -> `xai` - `sonar...` -> `perplexity` - configurable_fields: Which model parameters are configurable: + configurable_fields: Which model parameters are configurable at runtime: - - `None`: No configurable fields. + - `None`: No configurable fields (i.e., a fixed model). - `'any'`: All fields are configurable. **See security note below.** - `list[str] | Tuple[str, ...]`: Specified fields are configurable. - Fields are assumed to have `config_prefix` stripped if there is a - `config_prefix`. If model is specified, then defaults to `None`. If model is - not specified, then defaults to `("model", "model_provider")`. + Fields are assumed to have `config_prefix` stripped if a `config_prefix` is + specified. + + If `model` is specified, then defaults to `None`. + + If `model` is not specified, then defaults to `("model", "model_provider")`. !!! warning "Security note" Setting `configurable_fields="any"` means fields like `api_key`, - `base_url`, etc. can be altered at runtime, potentially redirecting - model requests to a different service/user. Make sure that if you're - accepting untrusted configurations that you enumerate the - `configurable_fields=(...)` explicitly. + `base_url`, etc., can be altered at runtime, potentially redirecting + model requests to a different service/user. - config_prefix: If `'config_prefix'` is a non-empty string then model will be - configurable at runtime via the - `config["configurable"]["{config_prefix}_{param}"]` keys. If - `'config_prefix'` is an empty string then model will be configurable via + Make sure that if you're accepting untrusted configurations that you + enumerate the `configurable_fields=(...)` explicitly. + + config_prefix: Optional prefix for configuration keys. + + Useful when you have multiple configurable models in the same application. + + If `'config_prefix'` is a non-empty string then `model` will be configurable + at runtime via the `config["configurable"]["{config_prefix}_{param}"]` keys. + See examples below. + + If `'config_prefix'` is an empty string then model will be configurable via `config["configurable"]["{param}"]`. - temperature: Model temperature. - max_tokens: Max output tokens. - timeout: The maximum time (in seconds) to wait for a response from the model - before canceling the request. - max_retries: The maximum number of attempts the system will make to resend a - request if it fails due to issues like network timeouts or rate limits. - base_url: The URL of the API endpoint where requests are sent. - rate_limiter: A `BaseRateLimiter` to space out requests to avoid exceeding - rate limits. - kwargs: Additional model-specific keyword args to pass to - `<>.__init__(model=model_name, **kwargs)`. + **kwargs: Additional model-specific keyword args to pass to the underlying + chat model's `__init__` method. Common parameters include: + + - `temperature`: Model temperature for controlling randomness. + - `max_tokens`: Maximum number of output tokens. + - `timeout`: Maximum time (in seconds) to wait for a response. + - `max_retries`: Maximum number of retry attempts for failed requests. + - `base_url`: Custom API endpoint URL. + - `rate_limiter`: A + [`BaseRateLimiter`][langchain_core.rate_limiters.BaseRateLimiter] + instance to control request rate. + + Refer to the specific model provider's + [integration reference](https://reference.langchain.com/python/integrations/) + for all available parameters. Returns: - A `BaseChatModel` corresponding to the `model_name` and `model_provider` - specified if configurability is inferred to be `False`. If configurable, a - chat model emulator that initializes the underlying model at runtime once a - config is passed in. + A [`BaseChatModel`][langchain_core.language_models.BaseChatModel] corresponding + to the `model_name` and `model_provider` specified if configurability is + inferred to be `False`. If configurable, a chat model emulator that + initializes the underlying model at runtime once a config is passed in. Raises: ValueError: If `model_provider` cannot be inferred or isn't supported. ImportError: If the model provider integration package is not installed. - ???+ note "Initialize a non-configurable model" + ???+ example "Initialize a non-configurable model" ```python # pip install langchain langchain-openai langchain-anthropic langchain-google-vertexai + from langchain_classic.chat_models import init_chat_model o3_mini = init_chat_model("openai:o3-mini", temperature=0) claude_sonnet = init_chat_model("anthropic:claude-sonnet-4-5", temperature=0) - gemini_2_flash = init_chat_model( + gemini_2-5_flash = init_chat_model( "google_vertexai:gemini-2.5-flash", temperature=0 ) o3_mini.invoke("what's your name") claude_sonnet.invoke("what's your name") - gemini_2_flash.invoke("what's your name") + gemini_2-5_flash.invoke("what's your name") ``` - ??? note "Partially configurable model with no default" + ??? example "Partially configurable model with no default" ```python # pip install langchain langchain-openai langchain-anthropic + from langchain_classic.chat_models import init_chat_model - # We don't need to specify configurable=True if a model isn't specified. + # (We don't need to specify configurable=True if a model isn't specified.) configurable_model = init_chat_model(temperature=0) configurable_model.invoke( "what's your name", config={"configurable": {"model": "gpt-4o"}} ) - # GPT-4o response + # Use GPT-4o to generate the response configurable_model.invoke( "what's your name", @@ -213,10 +237,11 @@ def init_chat_model( ) ``` - ??? note "Fully configurable model with a default" + ??? example "Fully configurable model with a default" ```python # pip install langchain langchain-openai langchain-anthropic + from langchain_classic.chat_models import init_chat_model configurable_model_with_default = init_chat_model( @@ -227,7 +252,7 @@ def init_chat_model( ) configurable_model_with_default.invoke("what's your name") - # GPT-4o response with temperature 0 + # GPT-4o response with temperature 0 (as set in default) configurable_model_with_default.invoke( "what's your name", @@ -238,15 +263,17 @@ def init_chat_model( } }, ) + # Override default to use Sonnet 4.5 with temperature 0.6 to generate response ``` - ??? note "Bind tools to a configurable model" + ??? example "Bind tools to a configurable model" You can call any chat model declarative methods on a configurable model in the same way that you would with a normal model: ```python # pip install langchain langchain-openai langchain-anthropic + from langchain_classic.chat_models import init_chat_model from pydantic import BaseModel, Field @@ -280,11 +307,13 @@ def init_chat_model( configurable_model_with_tools.invoke( "Which city is hotter today and which is bigger: LA or NY?" ) + # Use GPT-4o configurable_model_with_tools.invoke( "Which city is hotter today and which is bigger: LA or NY?", config={"configurable": {"model": "claude-sonnet-4-5"}}, ) + # Use Sonnet 4.5 ``` !!! warning "Behavior changed in 0.2.8" diff --git a/libs/langchain/langchain_classic/evaluation/embedding_distance/base.py b/libs/langchain/langchain_classic/evaluation/embedding_distance/base.py index e2af7665ea2..c7c0e320dbe 100644 --- a/libs/langchain/langchain_classic/evaluation/embedding_distance/base.py +++ b/libs/langchain/langchain_classic/evaluation/embedding_distance/base.py @@ -48,7 +48,7 @@ def _check_numpy() -> bool: def _embedding_factory() -> Embeddings: - """Create an Embeddings object. + """Create an `Embeddings` object. Returns: The created `Embeddings` object. diff --git a/libs/langchain/pyproject.toml b/libs/langchain/pyproject.toml index 1a791d4481a..6316b97ab18 100644 --- a/libs/langchain/pyproject.toml +++ b/libs/langchain/pyproject.toml @@ -153,6 +153,7 @@ ignore = [ "TC003", # Doesn't play well with Pydantic "TD002", # Missing author in TODO "TD003", # Missing issue link in TODO + "RUF002", # Em-dash in docstring # TODO rules "ANN401", # No type Any diff --git a/libs/langchain_v1/langchain/agents/factory.py b/libs/langchain_v1/langchain/agents/factory.py index e22f851bd84..3094261bd2b 100644 --- a/libs/langchain_v1/langchain/agents/factory.py +++ b/libs/langchain_v1/langchain/agents/factory.py @@ -530,44 +530,65 @@ def create_agent( # noqa: PLR0915 Args: model: The language model for the agent. Can be a string identifier - (e.g., `"openai:gpt-4"`) or a chat model instance (e.g., `ChatOpenAI()`). + (e.g., `"openai:gpt-4"`) or a direct chat model instance (e.g., + [`ChatOpenAI`][langchain_openai.ChatOpenAI] or other another + [chat model](https://docs.langchain.com/oss/python/integrations/chat)). + For a full list of supported model strings, see [`init_chat_model`][langchain.chat_models.init_chat_model(model_provider)]. - tools: A list of tools, `dicts`, or `Callable`. If `None` or an empty list, - the agent will consist of a model node without a tool calling loop. - system_prompt: An optional system prompt for the LLM. Prompts are converted to a - `SystemMessage` and added to the beginning of the message list. + tools: A list of tools, `dicts`, or `Callable`. + + If `None` or an empty list, the agent will consist of a model node without a + tool calling loop. + system_prompt: An optional system prompt for the LLM. + + Prompts are converted to a + [`SystemMessage`][langchain.messages.SystemMessage] and added to the + beginning of the message list. middleware: A sequence of middleware instances to apply to the agent. - Middleware can intercept and modify agent behavior at various stages. + + Middleware can intercept and modify agent behavior at various stages. See + the [full guide](https://docs.langchain.com/oss/python/langchain/middleware). response_format: An optional configuration for structured responses. + Can be a `ToolStrategy`, `ProviderStrategy`, or a Pydantic model class. + If provided, the agent will handle structured output during the conversation flow. Raw schemas will be wrapped in an appropriate strategy based on model capabilities. state_schema: An optional `TypedDict` schema that extends `AgentState`. + When provided, this schema is used instead of `AgentState` as the base schema for merging with middleware state schemas. This allows users to add custom state fields without needing to create custom middleware. - Generally, it's recommended to use state_schema extensions via middleware + Generally, it's recommended to use `state_schema` extensions via middleware to keep relevant extensions scoped to corresponding hooks / tools. + The schema must be a subclass of `AgentState[ResponseT]`. context_schema: An optional schema for runtime context. - checkpointer: An optional checkpoint saver object. This is used for persisting - the state of the graph (e.g., as chat memory) for a single thread - (e.g., a single conversation). - store: An optional store object. This is used for persisting data - across multiple threads (e.g., multiple conversations / users). + checkpointer: An optional checkpoint saver object. + + Used for persisting the state of the graph (e.g., as chat memory) for a + single thread (e.g., a single conversation). + store: An optional store object. + + Used for persisting data across multiple threads (e.g., multiple + conversations / users). interrupt_before: An optional list of node names to interrupt before. + Useful if you want to add a user confirmation or other interrupt before taking an action. interrupt_after: An optional list of node names to interrupt after. + Useful if you want to return directly or run additional processing on an output. - debug: Whether to enable verbose logging for graph execution. When enabled, - prints detailed information about each node execution, state updates, - and transitions during agent runtime. Useful for debugging middleware - behavior and understanding agent execution flow. + debug: Whether to enable verbose logging for graph execution. + + When enabled, prints detailed information about each node execution, state + updates, and transitions during agent runtime. Useful for debugging + middleware behavior and understanding agent execution flow. name: An optional name for the `CompiledStateGraph`. + This name will be automatically used when adding the agent graph to another graph as a subgraph node - particularly useful for building multi-agent systems. @@ -577,11 +598,12 @@ def create_agent( # noqa: PLR0915 A compiled `StateGraph` that can be used for chat interactions. The agent node calls the language model with the messages list (after applying - the system prompt). If the resulting `AIMessage` contains `tool_calls`, the graph - will then call the tools. The tools node executes the tools and adds the responses - to the messages list as `ToolMessage` objects. The agent node then calls the - language model again. The process repeats until no more `tool_calls` are - present in the response. The agent then returns the full list of messages. + the system prompt). If the resulting [`AIMessage`][langchain.messages.AIMessage] + contains `tool_calls`, the graph will then call the tools. The tools node executes + the tools and adds the responses to the messages list as + [`ToolMessage`][langchain.messages.ToolMessage] objects. The agent node then calls + the language model again. The process repeats until no more `tool_calls` are present + in the response. The agent then returns the full list of messages. Example: ```python diff --git a/libs/langchain_v1/langchain/agents/middleware/context_editing.py b/libs/langchain_v1/langchain/agents/middleware/context_editing.py index 1f0978ed77f..3623d1872ce 100644 --- a/libs/langchain_v1/langchain/agents/middleware/context_editing.py +++ b/libs/langchain_v1/langchain/agents/middleware/context_editing.py @@ -182,7 +182,7 @@ class ClearToolUsesEdit(ContextEdit): class ContextEditingMiddleware(AgentMiddleware): - """Middleware that automatically prunes tool results to manage context size. + """Automatically prunes tool results to manage context size. The middleware applies a sequence of edits when the total input token count exceeds configured thresholds. Currently the `ClearToolUsesEdit` strategy is diff --git a/libs/langchain_v1/langchain/agents/middleware/model_call_limit.py b/libs/langchain_v1/langchain/agents/middleware/model_call_limit.py index 412cd16b8e3..90dba99dfa3 100644 --- a/libs/langchain_v1/langchain/agents/middleware/model_call_limit.py +++ b/libs/langchain_v1/langchain/agents/middleware/model_call_limit.py @@ -87,7 +87,7 @@ class ModelCallLimitExceededError(Exception): class ModelCallLimitMiddleware(AgentMiddleware[ModelCallLimitState, Any]): - """Middleware that tracks model call counts and enforces limits. + """Tracks model call counts and enforces limits. This middleware monitors the number of model calls made during agent execution and can terminate the agent when specified limits are reached. It supports diff --git a/libs/langchain_v1/langchain/agents/middleware/summarization.py b/libs/langchain_v1/langchain/agents/middleware/summarization.py index de59095be1c..6ba6221206c 100644 --- a/libs/langchain_v1/langchain/agents/middleware/summarization.py +++ b/libs/langchain_v1/langchain/agents/middleware/summarization.py @@ -60,7 +60,7 @@ _SEARCH_RANGE_FOR_TOOL_PAIRS = 5 class SummarizationMiddleware(AgentMiddleware): - """Middleware that summarizes conversation history when token limits are approached. + """Summarizes conversation history when token limits are approached. This middleware monitors message token counts and automatically summarizes older messages when a threshold is reached, preserving recent messages and maintaining diff --git a/libs/langchain_v1/langchain/agents/middleware/tool_call_limit.py b/libs/langchain_v1/langchain/agents/middleware/tool_call_limit.py index df97f5da233..dca66e96824 100644 --- a/libs/langchain_v1/langchain/agents/middleware/tool_call_limit.py +++ b/libs/langchain_v1/langchain/agents/middleware/tool_call_limit.py @@ -146,7 +146,7 @@ class ToolCallLimitExceededError(Exception): class ToolCallLimitMiddleware(AgentMiddleware[ToolCallLimitState, Any]): - """Middleware that tracks tool call counts and enforces limits. + """Tracks tool call counts and enforces limits. This middleware monitors the number of tool calls made during agent execution and can terminate the agent when specified limits are reached. It supports diff --git a/libs/langchain_v1/langchain/agents/middleware/tool_emulator.py b/libs/langchain_v1/langchain/agents/middleware/tool_emulator.py index 019045c577a..74e814ed1fd 100644 --- a/libs/langchain_v1/langchain/agents/middleware/tool_emulator.py +++ b/libs/langchain_v1/langchain/agents/middleware/tool_emulator.py @@ -20,7 +20,7 @@ if TYPE_CHECKING: class LLMToolEmulator(AgentMiddleware): - """Middleware that emulates specified tools using an LLM instead of executing them. + """Emulates specified tools using an LLM instead of executing them. This middleware allows selective emulation of tools for testing purposes. By default (when tools=None), all tools are emulated. You can specify which diff --git a/libs/langchain_v1/langchain/chat_models/base.py b/libs/langchain_v1/langchain/chat_models/base.py index e546c3ad84c..43a6d386193 100644 --- a/libs/langchain_v1/langchain/chat_models/base.py +++ b/libs/langchain_v1/langchain/chat_models/base.py @@ -64,26 +64,34 @@ def init_chat_model( config_prefix: str | None = None, **kwargs: Any, ) -> BaseChatModel | _ConfigurableModel: - """Initialize a chat model in a single line using the model's name and provider. + """Initialize a chat model from any supported provider using a unified interface. + + **Two main use cases:** + + 1. **Fixed model** – specify the model upfront and get a ready-to-use chat model. + 2. **Configurable model** – choose to specify parameters (including model name) at + runtime via `config`. Makes it easy to switch between models/providers without + changing your code !!! note - Requires the integration package for your model provider to be installed. + Requires the integration package for the chosen model provider to be installed. See the `model_provider` parameter below for specific package names (e.g., `pip install langchain-openai`). Refer to the [provider integration's API reference](https://docs.langchain.com/oss/python/integrations/providers) - for supported model parameters. + for supported model parameters to use as `**kwargs`. Args: model: The name of the model, e.g. `'o3-mini'`, `'claude-sonnet-4-5'`. - You can also specify model and model provider in a single argument using: - + You can also specify model and model provider in a single argument using `'{model_provider}:{model}'` format, e.g. `'openai:o1'`. model_provider: The model provider if not specified as part of the model arg - (see above). Supported `model_provider` values and the corresponding - integration package are: + (see above). + + Supported `model_provider` values and the corresponding integration package + are: - `openai` -> [`langchain-openai`](https://docs.langchain.com/oss/python/integrations/providers/openai) - `anthropic` -> [`langchain-anthropic`](https://docs.langchain.com/oss/python/integrations/providers/anthropic) @@ -120,27 +128,36 @@ def init_chat_model( - `deepseek...` -> `deepseek` - `grok...` -> `xai` - `sonar...` -> `perplexity` - configurable_fields: Which model parameters are configurable: + configurable_fields: Which model parameters are configurable at runtime: - - `None`: No configurable fields. + - `None`: No configurable fields (i.e., a fixed model). - `'any'`: All fields are configurable. **See security note below.** - `list[str] | Tuple[str, ...]`: Specified fields are configurable. - Fields are assumed to have `config_prefix` stripped if there is a - `config_prefix`. If model is specified, then defaults to `None`. If model is - not specified, then defaults to `("model", "model_provider")`. + Fields are assumed to have `config_prefix` stripped if a `config_prefix` is + specified. + + If `model` is specified, then defaults to `None`. + + If `model` is not specified, then defaults to `("model", "model_provider")`. !!! warning "Security note" Setting `configurable_fields="any"` means fields like `api_key`, - `base_url`, etc. can be altered at runtime, potentially redirecting - model requests to a different service/user. Make sure that if you're - accepting untrusted configurations that you enumerate the - `configurable_fields=(...)` explicitly. + `base_url`, etc., can be altered at runtime, potentially redirecting + model requests to a different service/user. - config_prefix: If `'config_prefix'` is a non-empty string then model will be - configurable at runtime via the - `config["configurable"]["{config_prefix}_{param}"]` keys. If - `'config_prefix'` is an empty string then model will be configurable via + Make sure that if you're accepting untrusted configurations that you + enumerate the `configurable_fields=(...)` explicitly. + + config_prefix: Optional prefix for configuration keys. + + Useful when you have multiple configurable models in the same application. + + If `'config_prefix'` is a non-empty string then `model` will be configurable + at runtime via the `config["configurable"]["{config_prefix}_{param}"]` keys. + See examples below. + + If `'config_prefix'` is an empty string then model will be configurable via `config["configurable"]["{param}"]`. **kwargs: Additional model-specific keyword args to pass to the underlying chat model's `__init__` method. Common parameters include: @@ -150,10 +167,13 @@ def init_chat_model( - `timeout`: Maximum time (in seconds) to wait for a response. - `max_retries`: Maximum number of retry attempts for failed requests. - `base_url`: Custom API endpoint URL. - - `rate_limiter`: A `BaseRateLimiter` instance to control request rate. + - `rate_limiter`: A + [`BaseRateLimiter`][langchain_core.rate_limiters.BaseRateLimiter] + instance to control request rate. - Refer to the specific model provider's documentation for all available - parameters. + Refer to the specific model provider's + [integration reference](https://reference.langchain.com/python/integrations/) + for all available parameters. Returns: A `BaseChatModel` corresponding to the `model_name` and `model_provider` @@ -165,32 +185,34 @@ def init_chat_model( ValueError: If `model_provider` cannot be inferred or isn't supported. ImportError: If the model provider integration package is not installed. - ???+ note "Initialize a non-configurable model" + ???+ example "Initialize a non-configurable model" ```python # pip install langchain langchain-openai langchain-anthropic langchain-google-vertexai + from langchain.chat_models import init_chat_model o3_mini = init_chat_model("openai:o3-mini", temperature=0) claude_sonnet = init_chat_model("anthropic:claude-sonnet-4-5", temperature=0) - gemini_2_flash = init_chat_model("google_vertexai:gemini-2.5-flash", temperature=0) + gemini_2-5_flash = init_chat_model("google_vertexai:gemini-2.5-flash", temperature=0) o3_mini.invoke("what's your name") claude_sonnet.invoke("what's your name") - gemini_2_flash.invoke("what's your name") + gemini_2-5_flash.invoke("what's your name") ``` - ??? note "Partially configurable model with no default" + ??? example "Partially configurable model with no default" ```python # pip install langchain langchain-openai langchain-anthropic + from langchain.chat_models import init_chat_model - # We don't need to specify configurable=True if a model isn't specified. + # (We don't need to specify configurable=True if a model isn't specified.) configurable_model = init_chat_model(temperature=0) configurable_model.invoke("what's your name", config={"configurable": {"model": "gpt-4o"}}) - # GPT-4o response + # Use GPT-4o to generate the response configurable_model.invoke( "what's your name", @@ -198,10 +220,11 @@ def init_chat_model( ) ``` - ??? note "Fully configurable model with a default" + ??? example "Fully configurable model with a default" ```python # pip install langchain langchain-openai langchain-anthropic + from langchain.chat_models import init_chat_model configurable_model_with_default = init_chat_model( @@ -212,7 +235,7 @@ def init_chat_model( ) configurable_model_with_default.invoke("what's your name") - # GPT-4o response with temperature 0 + # GPT-4o response with temperature 0 (as set in default) configurable_model_with_default.invoke( "what's your name", @@ -223,15 +246,17 @@ def init_chat_model( } }, ) + # Override default to use Sonnet 4.5 with temperature 0.6 to generate response ``` - ??? note "Bind tools to a configurable model" + ??? example "Bind tools to a configurable model" You can call any chat model declarative methods on a configurable model in the same way that you would with a normal model: ```python # pip install langchain langchain-openai langchain-anthropic + from langchain.chat_models import init_chat_model from pydantic import BaseModel, Field @@ -261,11 +286,13 @@ def init_chat_model( configurable_model_with_tools.invoke( "Which city is hotter today and which is bigger: LA or NY?" ) + # Use GPT-4o configurable_model_with_tools.invoke( "Which city is hotter today and which is bigger: LA or NY?", config={"configurable": {"model": "claude-sonnet-4-5"}}, ) + # Use Sonnet 4.5 ``` """ # noqa: E501 diff --git a/libs/langchain_v1/langchain/embeddings/__init__.py b/libs/langchain_v1/langchain/embeddings/__init__.py index 90a7644e0d0..6943b1cd7cc 100644 --- a/libs/langchain_v1/langchain/embeddings/__init__.py +++ b/libs/langchain_v1/langchain/embeddings/__init__.py @@ -1,4 +1,4 @@ -"""Embeddings. +"""Embeddings models. !!! warning "Reference docs" This page contains **reference documentation** for Embeddings. See diff --git a/libs/langchain_v1/langchain/embeddings/base.py b/libs/langchain_v1/langchain/embeddings/base.py index 2793c02df75..708ac6a41a1 100644 --- a/libs/langchain_v1/langchain/embeddings/base.py +++ b/libs/langchain_v1/langchain/embeddings/base.py @@ -126,26 +126,27 @@ def init_embeddings( provider: str | None = None, **kwargs: Any, ) -> Embeddings: - """Initialize an embeddings model from a model name and optional provider. + """Initialize an embedding model from a model name and optional provider. !!! note - Must have the integration package corresponding to the model provider - installed. + Requires the integration package for the chosen model provider to be installed. + + See the `model_provider` parameter below for specific package names + (e.g., `pip install langchain-openai`). + + Refer to the [provider integration's API reference](https://docs.langchain.com/oss/python/integrations/providers) + for supported model parameters to use as `**kwargs`. Args: - model: Name of the model to use. + model: The name of the model, e.g. `'openai:text-embedding-3-small'`. - Can be either: + You can also specify model and model provider in a single argument using + `'{model_provider}:{model}'` format, e.g. `'openai:text-embedding-3-small'`. + provider: The model provider if not specified as part of the model arg + (see above). - - A model string like `"openai:text-embedding-3-small"` - - Just the model name if the provider is specified separately or can be - inferred. - - See supported providers under the `provider` arg description. - provider: Optional explicit provider name. If not specified, will attempt to - parse from the model string in the `model` arg. - - Supported providers: + Supported `provider` values and the corresponding integration package + are: - `openai` -> [`langchain-openai`](https://docs.langchain.com/oss/python/integrations/providers/openai) - `azure_openai` -> [`langchain-openai`](https://docs.langchain.com/oss/python/integrations/providers/openai) @@ -157,7 +158,10 @@ def init_embeddings( - `ollama` -> [`langchain-ollama`](https://docs.langchain.com/oss/python/integrations/providers/ollama) **kwargs: Additional model-specific parameters passed to the embedding model. - These vary by provider, see the provider-specific documentation for details. + + These vary by provider. Refer to the specific model provider's + [integration reference](https://reference.langchain.com/python/integrations/) + for all available parameters. Returns: An `Embeddings` instance that can generate embeddings for text. @@ -166,9 +170,11 @@ def init_embeddings( ValueError: If the model provider is not supported or cannot be determined ImportError: If the required provider package is not installed - ???+ note "Example Usage" + ???+ example ```python + # pip install langchain langchain-openai + # Using a model string model = init_embeddings("openai:text-embedding-3-small") model.embed_query("Hello, world!") diff --git a/libs/langchain_v1/langchain/messages/__init__.py b/libs/langchain_v1/langchain/messages/__init__.py index 9ebe98c81f2..b757afd1f47 100644 --- a/libs/langchain_v1/langchain/messages/__init__.py +++ b/libs/langchain_v1/langchain/messages/__init__.py @@ -1,4 +1,4 @@ -"""Message types. +"""Message and message content types. Includes message types for different roles (e.g., human, AI, system), as well as types for message content blocks (e.g., text, image, audio) and tool calls. diff --git a/libs/langchain_v1/pyproject.toml b/libs/langchain_v1/pyproject.toml index 7c76e4e4176..9289bec806f 100644 --- a/libs/langchain_v1/pyproject.toml +++ b/libs/langchain_v1/pyproject.toml @@ -115,6 +115,7 @@ ignore = [ "PLC0415", # Imports should be at the top. Not always desirable "PLR0913", # Too many arguments in function definition "PLC0414", # Inconsistent with how type checkers expect to be notified of intentional re-exports + "RUF002", # Em-dash in docstring ] unfixable = ["B028"] # People should intentionally tune the stacklevel diff --git a/libs/partners/anthropic/langchain_anthropic/chat_models.py b/libs/partners/anthropic/langchain_anthropic/chat_models.py index 6d55ce3faf5..f25bdccfe29 100644 --- a/libs/partners/anthropic/langchain_anthropic/chat_models.py +++ b/libs/partners/anthropic/langchain_anthropic/chat_models.py @@ -1535,7 +1535,11 @@ class ChatAnthropic(BaseChatModel): @classmethod def get_lc_namespace(cls) -> list[str]: - """Get the namespace of the LangChain object.""" + """Get the namespace of the LangChain object. + + Returns: + `["langchain", "chat_models", "anthropic"]` + """ return ["langchain", "chat_models", "anthropic"] @property diff --git a/libs/partners/fireworks/langchain_fireworks/chat_models.py b/libs/partners/fireworks/langchain_fireworks/chat_models.py index 38343c188ed..53af609a42a 100644 --- a/libs/partners/fireworks/langchain_fireworks/chat_models.py +++ b/libs/partners/fireworks/langchain_fireworks/chat_models.py @@ -286,7 +286,11 @@ class ChatFireworks(BaseChatModel): @classmethod def get_lc_namespace(cls) -> list[str]: - """Get the namespace of the LangChain object.""" + """Get the namespace of the LangChain object. + + Returns: + `["langchain", "chat_models", "fireworks"]` + """ return ["langchain", "chat_models", "fireworks"] @property diff --git a/libs/partners/huggingface/langchain_huggingface/embeddings/huggingface.py b/libs/partners/huggingface/langchain_huggingface/embeddings/huggingface.py index 6d8dbd73e53..8c55348cee1 100644 --- a/libs/partners/huggingface/langchain_huggingface/embeddings/huggingface.py +++ b/libs/partners/huggingface/langchain_huggingface/embeddings/huggingface.py @@ -12,8 +12,6 @@ from langchain_huggingface.utils.import_utils import ( is_optimum_intel_version, ) -DEFAULT_MODEL_NAME = "sentence-transformers/all-mpnet-base-v2" - _MIN_OPTIMUM_VERSION = "1.22" @@ -37,7 +35,9 @@ class HuggingFaceEmbeddings(BaseModel, Embeddings): ``` """ - model_name: str = Field(default=DEFAULT_MODEL_NAME, alias="model") + model_name: str = Field( + default="sentence-transformers/all-mpnet-base-v2", alias="model" + ) """Model name to use.""" cache_folder: str | None = None """Path to store models. diff --git a/libs/partners/mistralai/langchain_mistralai/chat_models.py b/libs/partners/mistralai/langchain_mistralai/chat_models.py index d36f0511b33..39c7c80d910 100644 --- a/libs/partners/mistralai/langchain_mistralai/chat_models.py +++ b/libs/partners/mistralai/langchain_mistralai/chat_models.py @@ -1138,7 +1138,11 @@ class ChatMistralAI(BaseChatModel): @classmethod def get_lc_namespace(cls) -> list[str]: - """Get the namespace of the LangChain object.""" + """Get the namespace of the LangChain object. + + Returns: + `["langchain", "chat_models", "mistralai"]` + """ return ["langchain", "chat_models", "mistralai"] diff --git a/libs/partners/openai/langchain_openai/chat_models/azure.py b/libs/partners/openai/langchain_openai/chat_models/azure.py index 429d599af91..ce4440b3e18 100644 --- a/libs/partners/openai/langchain_openai/chat_models/azure.py +++ b/libs/partners/openai/langchain_openai/chat_models/azure.py @@ -572,7 +572,11 @@ class AzureChatOpenAI(BaseChatOpenAI): @classmethod def get_lc_namespace(cls) -> list[str]: - """Get the namespace of the LangChain object.""" + """Get the namespace of the LangChain object. + + Returns: + `["langchain", "chat_models", "azure_openai"]` + """ return ["langchain", "chat_models", "azure_openai"] @property diff --git a/libs/partners/openai/langchain_openai/chat_models/base.py b/libs/partners/openai/langchain_openai/chat_models/base.py index 35beb08ec5f..7b11cd29219 100644 --- a/libs/partners/openai/langchain_openai/chat_models/base.py +++ b/libs/partners/openai/langchain_openai/chat_models/base.py @@ -2839,7 +2839,11 @@ class ChatOpenAI(BaseChatOpenAI): # type: ignore[override] @classmethod def get_lc_namespace(cls) -> list[str]: - """Get the namespace of the LangChain object.""" + """Get the namespace of the LangChain object. + + Returns: + `["langchain", "chat_models", "openai"]` + """ return ["langchain", "chat_models", "openai"] @property diff --git a/libs/partners/openai/langchain_openai/llms/azure.py b/libs/partners/openai/langchain_openai/llms/azure.py index cad149c506f..e86e9113867 100644 --- a/libs/partners/openai/langchain_openai/llms/azure.py +++ b/libs/partners/openai/langchain_openai/llms/azure.py @@ -97,7 +97,11 @@ class AzureOpenAI(BaseOpenAI): @classmethod def get_lc_namespace(cls) -> list[str]: - """Get the namespace of the LangChain object.""" + """Get the namespace of the LangChain object. + + Returns: + `["langchain", "llms", "openai"]` + """ return ["langchain", "llms", "openai"] @property diff --git a/libs/partners/openai/langchain_openai/llms/base.py b/libs/partners/openai/langchain_openai/llms/base.py index f983f398239..08f4dc458f1 100644 --- a/libs/partners/openai/langchain_openai/llms/base.py +++ b/libs/partners/openai/langchain_openai/llms/base.py @@ -799,7 +799,11 @@ class OpenAI(BaseOpenAI): @classmethod def get_lc_namespace(cls) -> list[str]: - """Get the namespace of the LangChain object.""" + """Get the namespace of the LangChain object. + + Returns: + `["langchain", "llms", "openai"]` + """ return ["langchain", "llms", "openai"] @classmethod diff --git a/libs/partners/openai/uv.lock b/libs/partners/openai/uv.lock index 16616fa8bfb..352ff9f6e2f 100644 --- a/libs/partners/openai/uv.lock +++ b/libs/partners/openai/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.10.0, <4.0.0" resolution-markers = [ "python_full_version >= '3.13' and platform_python_implementation == 'PyPy'", @@ -544,7 +544,7 @@ wheels = [ [[package]] name = "langchain" -version = "1.0.1" +version = "1.0.2" source = { editable = "../../langchain_v1" } dependencies = [ { name = "langchain-core" }, @@ -570,7 +570,7 @@ requires-dist = [ { name = "langchain-perplexity", marker = "extra == 'perplexity'" }, { name = "langchain-together", marker = "extra == 'together'" }, { name = "langchain-xai", marker = "extra == 'xai'" }, - { name = "langgraph", specifier = ">=1.0.0,<1.1.0" }, + { name = "langgraph", specifier = ">=1.0.2,<1.1.0" }, { name = "pydantic", specifier = ">=2.7.4,<3.0.0" }, ] provides-extras = ["community", "anthropic", "openai", "google-vertexai", "google-genai", "fireworks", "ollama", "together", "mistralai", "huggingface", "groq", "aws", "deepseek", "xai", "perplexity"] @@ -606,7 +606,7 @@ typing = [ [[package]] name = "langchain-core" -version = "1.0.0" +version = "1.0.1" source = { editable = "../../core" } dependencies = [ { name = "jsonpatch" }, @@ -796,7 +796,7 @@ typing = [ [[package]] name = "langgraph" -version = "1.0.1" +version = "1.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, @@ -806,9 +806,9 @@ dependencies = [ { name = "pydantic" }, { name = "xxhash" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/20/7c/a0f4211f751b8b37aae2d88c6243ceb14027ca9ebf00ac8f3b210657af6a/langgraph-1.0.1.tar.gz", hash = "sha256:4985b32ceabb046a802621660836355dfcf2402c5876675dc353db684aa8f563", size = 480245, upload-time = "2025-10-20T18:51:59.839Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0e/25/18e6e056ee1a8af64fcab441b4a3f2e158399935b08f148c7718fc42ecdb/langgraph-1.0.2.tar.gz", hash = "sha256:dae1af08d6025cb1fcaed68f502c01af7d634d9044787c853a46c791cfc52f67", size = 482660, upload-time = "2025-10-29T18:38:28.374Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/3c/acc0956a0da96b25a2c5c1a85168eacf1253639a04ed391d7a7bcaae5d6c/langgraph-1.0.1-py3-none-any.whl", hash = "sha256:892f04f64f4889abc80140265cc6bd57823dd8e327a5eef4968875f2cd9013bd", size = 155415, upload-time = "2025-10-20T18:51:58.321Z" }, + { url = "https://files.pythonhosted.org/packages/d7/b1/9f4912e13d4ed691f2685c8a4b764b5a9237a30cca0c5782bc213d9f0a9a/langgraph-1.0.2-py3-none-any.whl", hash = "sha256:b3d56b8c01de857b5fb1da107e8eab6e30512a377685eeedb4f76456724c9729", size = 156751, upload-time = "2025-10-29T18:38:26.577Z" }, ] [[package]] @@ -826,15 +826,15 @@ wheels = [ [[package]] name = "langgraph-prebuilt" -version = "1.0.1" +version = "1.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core" }, { name = "langgraph-checkpoint" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b2/b6/2bcb992acf67713a3557e51c1955854672ec6c1abe6ba51173a87eb8d825/langgraph_prebuilt-1.0.1.tar.gz", hash = "sha256:ecbfb9024d9d7ed9652dde24eef894650aaab96bf79228e862c503e2a060b469", size = 119918, upload-time = "2025-10-20T18:49:55.991Z" } +sdist = { url = "https://files.pythonhosted.org/packages/33/2f/b940590436e07b3450fe6d791aad5e581363ad536c4f1771e3ba46530268/langgraph_prebuilt-1.0.2.tar.gz", hash = "sha256:9896dbabf04f086eb59df4294f54ab5bdb21cd78e27e0a10e695dffd1cc6097d", size = 142075, upload-time = "2025-10-29T18:29:00.401Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/47/9ffd10882403020ea866e381de7f8e504a78f606a914af7f8244456c7783/langgraph_prebuilt-1.0.1-py3-none-any.whl", hash = "sha256:8c02e023538f7ef6ad5ed76219ba1ab4f6de0e31b749e4d278f57a8a95eec9f7", size = 28458, upload-time = "2025-10-20T18:49:54.723Z" }, + { url = "https://files.pythonhosted.org/packages/27/2f/9a7d00d4afa036e65294059c7c912002fb72ba5dbbd5c2a871ca06360278/langgraph_prebuilt-1.0.2-py3-none-any.whl", hash = "sha256:d9499f7c449fb637ee7b87e3f6a3b74095f4202053c74d33894bd839ea4c57c7", size = 34286, upload-time = "2025-10-29T18:28:59.26Z" }, ] [[package]] diff --git a/libs/partners/xai/langchain_xai/chat_models.py b/libs/partners/xai/langchain_xai/chat_models.py index d2de07c20ff..d717e7bf459 100644 --- a/libs/partners/xai/langchain_xai/chat_models.py +++ b/libs/partners/xai/langchain_xai/chat_models.py @@ -428,7 +428,11 @@ class ChatXAI(BaseChatOpenAI): # type: ignore[override] @classmethod def get_lc_namespace(cls) -> list[str]: - """Get the namespace of the LangChain object.""" + """Get the namespace of the LangChain object. + + Returns: + `["langchain_xai", "chat_models"]` + """ return ["langchain_xai", "chat_models"] @property diff --git a/libs/standard-tests/langchain_tests/integration_tests/chat_models.py b/libs/standard-tests/langchain_tests/integration_tests/chat_models.py index 6b1131fad5b..6f80704d1a1 100644 --- a/libs/standard-tests/langchain_tests/integration_tests/chat_models.py +++ b/libs/standard-tests/langchain_tests/integration_tests/chat_models.py @@ -202,7 +202,7 @@ class ChatModelIntegrationTests(ChatModelTests): calling or multi-modality) by selectively overriding the following properties. Expand to see details: - ??? note "`has_tool_calling`" + ??? info "`has_tool_calling`" Boolean property indicating whether the chat model supports tool calling. @@ -217,7 +217,7 @@ class ChatModelIntegrationTests(ChatModelTests): return True ``` - ??? note "`tool_choice_value`" + ??? info "`tool_choice_value`" Value to use for tool choice when used in tests. @@ -235,7 +235,7 @@ class ChatModelIntegrationTests(ChatModelTests): return "any" ``` - ??? note "`has_tool_choice`" + ??? info "`has_tool_choice`" Boolean property indicating whether the chat model supports forcing tool calling via a `tool_choice` parameter. @@ -255,7 +255,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "`has_structured_output`" + ??? info "`has_structured_output`" Boolean property indicating whether the chat model supports structured output. @@ -272,7 +272,7 @@ class ChatModelIntegrationTests(ChatModelTests): return True ``` - ??? note "`structured_output_kwargs`" + ??? info "`structured_output_kwargs`" Dict property that can be used to specify additional kwargs for `with_structured_output`. Useful for testing different models. @@ -283,7 +283,7 @@ class ChatModelIntegrationTests(ChatModelTests): return {"method": "function_calling"} ``` - ??? note "`supports_json_mode`" + ??? info "`supports_json_mode`" Boolean property indicating whether the chat model supports JSON mode in `with_structured_output`. @@ -296,7 +296,7 @@ class ChatModelIntegrationTests(ChatModelTests): return True ``` - ??? note "`supports_image_inputs`" + ??? info "`supports_image_inputs`" Boolean property indicating whether the chat model supports image inputs. @@ -309,7 +309,7 @@ class ChatModelIntegrationTests(ChatModelTests): { "type": "image", "base64": "", - "mime_type": "image/jpeg", # or appropriate mime-type + "mime_type": "image/jpeg", # or appropriate MIME type } ``` @@ -330,7 +330,7 @@ class ChatModelIntegrationTests(ChatModelTests): return True ``` - ??? note "`supports_image_urls`" + ??? info "`supports_image_urls`" Boolean property indicating whether the chat model supports image inputs from URLs. @@ -355,7 +355,7 @@ class ChatModelIntegrationTests(ChatModelTests): return True ``` - ??? note "`supports_pdf_inputs`" + ??? info "`supports_pdf_inputs`" Boolean property indicating whether the chat model supports PDF inputs. @@ -380,7 +380,7 @@ class ChatModelIntegrationTests(ChatModelTests): return True ``` - ??? note "`supports_audio_inputs`" + ??? info "`supports_audio_inputs`" Boolean property indicating whether the chat model supports audio inputs. @@ -393,7 +393,7 @@ class ChatModelIntegrationTests(ChatModelTests): { "type": "audio", "base64": "", - "mime_type": "audio/wav", # or appropriate mime-type + "mime_type": "audio/wav", # or appropriate MIME type } ``` @@ -405,13 +405,13 @@ class ChatModelIntegrationTests(ChatModelTests): return True ``` - ??? note "`supports_video_inputs`" + ??? info "`supports_video_inputs`" Boolean property indicating whether the chat model supports image inputs. Defaults to `False`. No current tests are written for this feature. - ??? note "`returns_usage_metadata`" + ??? info "`returns_usage_metadata`" Boolean property indicating whether the chat model returns usage metadata on invoke and streaming responses. @@ -431,7 +431,7 @@ class ChatModelIntegrationTests(ChatModelTests): Models supporting `usage_metadata` should also return the name of the underlying model in the `response_metadata` of the `AIMessage`. - ??? note "`supports_anthropic_inputs`" + ??? info "`supports_anthropic_inputs`" Boolean property indicating whether the chat model supports Anthropic-style inputs. @@ -459,7 +459,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "`supports_image_tool_message`" + ??? info "`supports_image_tool_message`" Boolean property indicating whether the chat model supports a `ToolMessage` that includes image content, e.g. in the OpenAI Chat Completions format: @@ -502,7 +502,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "`supports_pdf_tool_message`" + ??? info "`supports_pdf_tool_message`" Boolean property indicating whether the chat model supports a `ToolMessage that include PDF content using the LangChain `FileContentBlock` format: @@ -530,7 +530,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "`supported_usage_metadata_details`" + ??? info "`supported_usage_metadata_details`" Property controlling what usage metadata details are emitted in both invoke and stream. @@ -545,7 +545,7 @@ class ChatModelIntegrationTests(ChatModelTests): Only needs to be overridden if these details are supplied. - ??? note "`enable_vcr_tests`" + ??? info "`enable_vcr_tests`" Property controlling whether to enable select tests that rely on [VCR](https://vcrpy.readthedocs.io/en/latest/) caching of HTTP calls, such @@ -706,7 +706,7 @@ class ChatModelIntegrationTests(ChatModelTests): This should pass for all integrations. - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, you should make sure your `_generate` method does not raise any exceptions, and that it returns a valid @@ -732,7 +732,7 @@ class ChatModelIntegrationTests(ChatModelTests): a "natively async" implementation, but rather that the model can be used in an async context. - ??? note "Troubleshooting" + ??? question "Troubleshooting" First, debug `langchain_tests.integration_tests.chat_models.ChatModelIntegrationTests.test_invoke`. @@ -763,7 +763,7 @@ class ChatModelIntegrationTests(ChatModelTests): a "streaming" implementation, but rather that the model can be used in a streaming context. - ??? note "Troubleshooting" + ??? question "Troubleshooting" First, debug `langchain_tests.integration_tests.chat_models.ChatModelIntegrationTests.test_invoke`. @@ -801,7 +801,7 @@ class ChatModelIntegrationTests(ChatModelTests): a "natively async" or "streaming" implementation, but rather that the model can be used in an async streaming context. - ??? note "Troubleshooting" + ??? question "Troubleshooting" First, debug `langchain_tests.integration_tests.chat_models.ChatModelIntegrationTests.test_stream`. @@ -840,7 +840,7 @@ class ChatModelIntegrationTests(ChatModelTests): This should pass for all integrations. Tests the model's ability to process multiple prompts in a single batch. - ??? note "Troubleshooting" + ??? question "Troubleshooting" First, debug `langchain_tests.integration_tests.chat_models.ChatModelIntegrationTests.test_invoke` @@ -868,7 +868,7 @@ class ChatModelIntegrationTests(ChatModelTests): This should pass for all integrations. Tests the model's ability to process multiple prompts in a single batch asynchronously. - ??? note "Troubleshooting" + ??? question "Troubleshooting" First, debug `langchain_tests.integration_tests.chat_models.ChatModelIntegrationTests.test_batch` @@ -899,7 +899,7 @@ class ChatModelIntegrationTests(ChatModelTests): a sequence of alternating human and AI messages as context for generating the next response. - ??? note "Troubleshooting" + ??? question "Troubleshooting" First, debug `langchain_tests.integration_tests.chat_models.ChatModelIntegrationTests.test_invoke` @@ -930,7 +930,7 @@ class ChatModelIntegrationTests(ChatModelTests): a sequence of double-system, double-human, and double-ai messages as context for generating the next response. - ??? note "Troubleshooting" + ??? question "Troubleshooting" First, debug `langchain_tests.integration_tests.chat_models.ChatModelIntegrationTests.test_invoke` @@ -1013,11 +1013,11 @@ class ChatModelIntegrationTests(ChatModelTests): } ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, first verify that your model returns `langchain_core.messages.ai.UsageMetadata` dicts - attached to the returned AIMessage object in `_generate`: + attached to the returned `AIMessage` object in `_generate`: ```python return ChatResult( @@ -1185,11 +1185,11 @@ class ChatModelIntegrationTests(ChatModelTests): } ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, first verify that your model yields `langchain_core.messages.ai.UsageMetadata` dicts - attached to the returned AIMessage object in `_stream` + attached to the returned `AIMessage` object in `_stream` that sum up to the total usage metadata. Note that `input_tokens` should only be included on one of the chunks @@ -1307,7 +1307,7 @@ class ChatModelIntegrationTests(ChatModelTests): This should pass for all integrations. - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that the function signature for `_generate` (as well as `_stream` and async variants) accepts the `stop` parameter: @@ -1357,7 +1357,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that `bind_tools` is implemented to correctly translate LangChain tool objects into the appropriate schema for your @@ -1419,7 +1419,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that `bind_tools` is implemented to correctly translate LangChain tool objects into the appropriate schema for your @@ -1482,7 +1482,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that `bind_tools` is implemented to correctly translate LangChain tool objects into the appropriate schema for your @@ -1552,7 +1552,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that: @@ -1641,7 +1641,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that: @@ -1721,7 +1721,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check whether the `test_tool_calling` test is passing. If it is not, refer to the troubleshooting steps in that test first. @@ -1773,7 +1773,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that `bind_tools` is implemented to correctly translate LangChain tool objects into the appropriate schema for your @@ -1846,7 +1846,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that the `status` field on `ToolMessage` objects is either ignored or passed to the model appropriately. @@ -1907,7 +1907,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" This test uses [a utility function](https://python.langchain.com/api_reference/core/utils/langchain_core.utils.function_calling.tool_example_to_messages.html). in `langchain_core` to generate a sequence of messages representing @@ -1971,7 +1971,7 @@ class ChatModelIntegrationTests(ChatModelTests): By default, `has_structured_output` is True if a model overrides the `with_structured_output` or `bind_tools` methods. - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, ensure that the model's `bind_tools` method properly handles both JSON Schema and Pydantic V2 models. @@ -2054,7 +2054,7 @@ class ChatModelIntegrationTests(ChatModelTests): By default, `has_structured_output` is True if a model overrides the `with_structured_output` or `bind_tools` methods. - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, ensure that the model's `bind_tools` method properly handles both JSON Schema and Pydantic V2 models. @@ -2136,7 +2136,7 @@ class ChatModelIntegrationTests(ChatModelTests): By default, `has_structured_output` is True if a model overrides the `with_structured_output` or `bind_tools` methods. - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, ensure that the model's `bind_tools` method properly handles both JSON Schema and Pydantic V1 models. @@ -2202,7 +2202,7 @@ class ChatModelIntegrationTests(ChatModelTests): By default, `has_structured_output` is True if a model overrides the `with_structured_output` or `bind_tools` methods. - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, ensure that the model's `bind_tools` method properly handles Pydantic V2 models with optional parameters. @@ -2271,7 +2271,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" See example implementation of `with_structured_output` here: https://python.langchain.com/api_reference/_modules/langchain_openai/chat_models/base.html#BaseChatOpenAI.with_structured_output @@ -2355,7 +2355,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that the model can correctly handle messages with pdf content blocks, including base64-encoded files. Otherwise, set @@ -2412,7 +2412,7 @@ class ChatModelIntegrationTests(ChatModelTests): { "type": "audio", "base64": "", - "mime_type": "audio/wav", # or appropriate mime-type + "mime_type": "audio/wav", # or appropriate MIME type } ``` @@ -2441,7 +2441,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that the model can correctly handle messages with audio content blocks, specifically base64-encoded files. Otherwise, @@ -2495,7 +2495,7 @@ class ChatModelIntegrationTests(ChatModelTests): { "type": "image", "base64": "", - "mime_type": "image/jpeg", # or appropriate mime-type + "mime_type": "image/jpeg", # or appropriate MIME type } ``` @@ -2541,7 +2541,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that the model can correctly handle messages with image content blocks, including base64-encoded images. Otherwise, set @@ -2643,7 +2643,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that the model can correctly handle messages with image content blocks in `ToolMessage` objects, including base64-encoded @@ -2742,7 +2742,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that the model can correctly handle messages with PDF content blocks in `ToolMessage` objects, specifically @@ -2848,7 +2848,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that: @@ -2984,7 +2984,7 @@ class ChatModelIntegrationTests(ChatModelTests): If possible, the `name` field should be parsed and passed appropriately to the model. Otherwise, it should be ignored. - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that the `name` field on `HumanMessage` objects is either ignored or passed to the model appropriately. @@ -3018,7 +3018,7 @@ class ChatModelIntegrationTests(ChatModelTests): return False ``` - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that `bind_tools` is implemented to correctly translate LangChain tool objects into the appropriate schema for your diff --git a/libs/standard-tests/langchain_tests/unit_tests/chat_models.py b/libs/standard-tests/langchain_tests/unit_tests/chat_models.py index ff536f5d96c..e54c70ccac2 100644 --- a/libs/standard-tests/langchain_tests/unit_tests/chat_models.py +++ b/libs/standard-tests/langchain_tests/unit_tests/chat_models.py @@ -310,7 +310,7 @@ class ChatModelUnitTests(ChatModelTests): calling or multi-modality) by selectively overriding the following properties. Expand to see details: - ??? note "`has_tool_calling`" + ??? info "`has_tool_calling`" Boolean property indicating whether the chat model supports tool calling. @@ -325,7 +325,7 @@ class ChatModelUnitTests(ChatModelTests): return True ``` - ??? note "`tool_choice_value`" + ??? info "`tool_choice_value`" Value to use for tool choice when used in tests. @@ -342,7 +342,7 @@ class ChatModelUnitTests(ChatModelTests): return "any" ``` - ??? note "`has_tool_choice`" + ??? info "`has_tool_choice`" Boolean property indicating whether the chat model supports forcing tool calling via a `tool_choice` parameter. @@ -362,7 +362,7 @@ class ChatModelUnitTests(ChatModelTests): return False ``` - ??? note "`has_structured_output`" + ??? info "`has_structured_output`" Boolean property indicating whether the chat model supports structured output. @@ -379,7 +379,7 @@ class ChatModelUnitTests(ChatModelTests): return True ``` - ??? note "`structured_output_kwargs`" + ??? info "`structured_output_kwargs`" Dict property that can be used to specify additional kwargs for `with_structured_output`. Useful for testing different models. @@ -390,7 +390,7 @@ class ChatModelUnitTests(ChatModelTests): return {"method": "function_calling"} ``` - ??? note "`supports_json_mode`" + ??? info "`supports_json_mode`" Boolean property indicating whether the chat model supports JSON mode in `with_structured_output`. @@ -403,7 +403,7 @@ class ChatModelUnitTests(ChatModelTests): return True ``` - ??? note "`supports_image_inputs`" + ??? info "`supports_image_inputs`" Boolean property indicating whether the chat model supports image inputs. @@ -416,7 +416,7 @@ class ChatModelUnitTests(ChatModelTests): { "type": "image", "base64": "", - "mime_type": "image/jpeg", # or appropriate mime-type + "mime_type": "image/jpeg", # or appropriate MIME type } ``` @@ -438,7 +438,7 @@ class ChatModelUnitTests(ChatModelTests): return True ``` - ??? note "`supports_image_urls`" + ??? info "`supports_image_urls`" Boolean property indicating whether the chat model supports image inputs from URLs. @@ -464,7 +464,7 @@ class ChatModelUnitTests(ChatModelTests): return True ``` - ??? note "`supports_pdf_inputs`" + ??? info "`supports_pdf_inputs`" Boolean property indicating whether the chat model supports PDF inputs. @@ -490,7 +490,7 @@ class ChatModelUnitTests(ChatModelTests): return True ``` - ??? note "`supports_audio_inputs`" + ??? info "`supports_audio_inputs`" Boolean property indicating whether the chat model supports audio inputs. @@ -503,7 +503,7 @@ class ChatModelUnitTests(ChatModelTests): { "type": "audio", "base64": "", - "mime_type": "audio/wav", # or appropriate mime-type + "mime_type": "audio/wav", # or appropriate MIME type } ``` @@ -515,13 +515,13 @@ class ChatModelUnitTests(ChatModelTests): return True ``` - ??? note "`supports_video_inputs`" + ??? info "`supports_video_inputs`" Boolean property indicating whether the chat model supports image inputs. Defaults to `False`. No current tests are written for this feature. - ??? note "`returns_usage_metadata`" + ??? info "`returns_usage_metadata`" Boolean property indicating whether the chat model returns usage metadata on invoke and streaming responses. @@ -541,7 +541,7 @@ class ChatModelUnitTests(ChatModelTests): Models supporting `usage_metadata` should also return the name of the underlying model in the `response_metadata` of the `AIMessage`. - ??? note "`supports_anthropic_inputs`" + ??? info "`supports_anthropic_inputs`" Boolean property indicating whether the chat model supports Anthropic-style inputs. @@ -569,7 +569,7 @@ class ChatModelUnitTests(ChatModelTests): return False ``` - ??? note "`supports_image_tool_message`" + ??? info "`supports_image_tool_message`" Boolean property indicating whether the chat model supports `ToolMessage` objects that include image content, e.g., @@ -615,7 +615,7 @@ class ChatModelUnitTests(ChatModelTests): return False ``` - ??? note "`supports_pdf_tool_message`" + ??? info "`supports_pdf_tool_message`" Boolean property indicating whether the chat model supports `ToolMessage` objects that include PDF content, i.e., @@ -645,7 +645,7 @@ class ChatModelUnitTests(ChatModelTests): return False ``` - ??? note "`supported_usage_metadata_details`" + ??? info "`supported_usage_metadata_details`" Property controlling what usage metadata details are emitted in both `invoke` and `stream`. @@ -660,7 +660,7 @@ class ChatModelUnitTests(ChatModelTests): Only needs to be overridden if these details are supplied. - ??? note "`enable_vcr_tests`" + ??? info "`enable_vcr_tests`" Property controlling whether to enable select tests that rely on [VCR](https://vcrpy.readthedocs.io/en/latest/) caching of HTTP calls, such @@ -815,7 +815,7 @@ class ChatModelUnitTests(ChatModelTests): These tests can be enabled by overriding the `init_from_env_params` property (see below). - ??? note "`init_from_env_params`" + ??? info "`init_from_env_params`" This property is used in unit tests to test initialization from environment variables. It should return a tuple of three dictionaries @@ -862,7 +862,7 @@ class ChatModelUnitTests(ChatModelTests): def test_init(self) -> None: """Test model initialization. This should pass for all integrations. - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, ensure that: @@ -886,7 +886,7 @@ class ChatModelUnitTests(ChatModelTests): Relies on the `init_from_env_params` property. Test is skipped if that property is not set. - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, ensure that `init_from_env_params` is specified correctly and that model parameters are properly set from environment @@ -913,7 +913,7 @@ class ChatModelUnitTests(ChatModelTests): This is for backward-compatibility purposes. - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, ensure that the model can be initialized with a boolean `streaming` parameter. @@ -939,7 +939,7 @@ class ChatModelUnitTests(ChatModelTests): into `bind_tools`. Test is skipped if the `has_tool_calling` property on the test class is False. - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, ensure that the model's `bind_tools` method properly handles Pydantic V2 models. `langchain_core` implements @@ -981,7 +981,7 @@ class ChatModelUnitTests(ChatModelTests): Test is skipped if the `has_structured_output` property on the test class is False. - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, ensure that the model's `bind_tools` method properly handles Pydantic V2 models. `langchain_core` implements @@ -1006,7 +1006,7 @@ class ChatModelUnitTests(ChatModelTests): These are used for tracing purposes. - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that the model accommodates [standard parameters](https://python.langchain.com/docs/concepts/chat_models/#standard-parameters). @@ -1046,7 +1046,7 @@ class ChatModelUnitTests(ChatModelTests): Test is skipped if the `is_lc_serializable` property on the chat model class is not overwritten to return `True`. - ??? note "Troubleshooting" + ??? question "Troubleshooting" If this test fails, check that the `init_from_env_params` property is correctly set on the test class. diff --git a/libs/text-splitters/langchain_text_splitters/__init__.py b/libs/text-splitters/langchain_text_splitters/__init__.py index e6c88699bae..623582f8d91 100644 --- a/libs/text-splitters/langchain_text_splitters/__init__.py +++ b/libs/text-splitters/langchain_text_splitters/__init__.py @@ -1,4 +1,4 @@ -"""**Text Splitters** are classes for splitting text. +"""Text Splitters are classes for splitting text. !!! note `MarkdownHeaderTextSplitter` and `HTMLHeaderTextSplitter` do not derive from