Compare commits

...

1 Commits

Author SHA1 Message Date
Eugene Yurtsev
d725a9e3f5 Update pydantic compatibility 2024-08-15 17:30:09 -04:00

View File

@@ -0,0 +1,128 @@
# LangChain Update Announcement
We are excited to announce the 0.3 release of LangChain.
This release was primarily aimed at upgrading LangChain to use Pydantic 2 internally
which resolves a [number of usability issues](
https://python.langchain.com/v0.2/docs/how_to/pydantic_compatibility/
) faced by users that have already migrated to Pydantic 2.
## Context
LangChain has been providing pseudo support for [Pydantic 2 since langchain >= 0.0.267 (August of 2023)](https://github.com/langchain-ai/langchain/discussions/9337)
via the Pydantic v1 namespace.
Since the `0.0.267` release of LangChain, users have been able to install either Pydantic 1 or Pydantic 2 in their environment and interact with LangChain APIs via Pydantic models constructed using v1 functionality.
Given that Pydantic 1 has reached EOL, we have decided to transition to Pydantic 2 officially in this release. This means that users will no longer be able to install Pydantic 1 or use Pydantic.v1 namespace objects when interacting with LangChain APIs. Users will need to update their code to use only Pydantic 2 features when interacting with LangChain.
## Breaking Changes
The breaking changes include:
* Breaking changes arising from the Pydantic 1 to Pydantic 2 transition.
* Deprecated functionality that was to be removed in the 0.3 release.
## Pydantic Migration guidelines
We refer users to Pydantic's [migration guide](https://docs.pydantic.dev/latest/migration/) for more information on how to transition their own code from Pydantic 1 to Pydantic 2.
In addition, we have provided a list of common issues that users may encounter when using LangChain with Pydantic 2:
### 1. Passing Pydantic objects to LangChain APIs
Users using the following APIs:
* `BaseChatModel.bind_tools`
* `BaseChatModel.with_structured_output`
* `Tool.from_function`
* `StructuredTool.from_function`
should ensure that they are passing Pydantic 2 objects to these APIs rather than
Pydantic 1 objects (created via the `pydantic.v1` namespace of pydantic 2).
:::caution
While `v1` objets may be accepted by some of these APIs, users are strongly to
use Pydantic 2 objects to avoid any potential issues.
:::
### 2. Sub-classing LangChain models
Any sub-classing from existing LangChain models (e.g., `BaseTool`, `BaseChatModel`, `LLM`)
should upgrade to use Pydantic 2 features.
For example, any user code that's relying on Pydantic 1 features (e.g., `validator`) should
be updated to the Pydantic 2 equivalent (e.g., `field_validator`), and any references to
`pydantic.v1`, `langchain_core.pydantic_v1`, `langchain.pydantic_v1` should be replaced
with imports from `pydantic`.
```python
from pydantic.v1 import validator, Field # if pydantic 2 is installed
# from pydantic import validator, Field # if pydantic 1 is installed
# from langchain_core.pydantic_v1 import validator, Field
# from langchain.pydantic_v1 import validator, Field
class CustomTool(BaseTool): # BaseTool is v1 code
x: int = Field(default=1)
def _run(*args, **kwargs):
return "hello"
@validator('x') # v1 code
@classmethod
def validate_x(cls, x: int) -> int:
return 1
```
Should change to:
```python
from pydantic import Field, field_validator # pydantic v2
from langchain_core.pydantic_v1 import BaseTool
class CustomTool(BaseTool): # BaseTool is v1 code
x: int = Field(default=1)
def _run(*args, **kwargs):
return "hello"
@field_validator('x') # v2 code
@classmethod
def validate_x(cls, x: int) -> int:
return 1
CustomTool(
name='custom_tool',
description="hello",
x=1,
)
```
### 3. model_rebuild()
When sub-classing from LangChain models, users may need to add relevant imports
to the file and rebuild the model.
```python
from langchain_core.output_parsers import BaseOutputParser
class FooParser(BaseOutputParser):
...
```
New code:
```python
from typing import Optional as Optional
from langchain_core.output_parsers import BaseOutputParser
class FooParser(BaseOutputParser):
...
FooParser.model_rebuild()
```