Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Pydantic 2 #1858

Merged
merged 60 commits into from
Oct 9, 2024
Merged

Add support for Pydantic 2 #1858

merged 60 commits into from
Oct 9, 2024

Conversation

mattt
Copy link
Contributor

@mattt mattt commented Aug 6, 2024

Rebase of #1687, applied to main instead of async.

Providing context, unhelpfully, in the style of baroque legaleses rehearsals:


THIS PR has been made on this day to bump Cog's supported range of Pydantic to >=1.9,<3

WHEREAS Pydantic is a data validation library that had major API changes from V1 to V2, and mixing of the Pydantic V1 and V2 models is not supported;

WHEREAS FastAPI and other Pydantic dependents use the V2 API when available, thereby precluding use of the v1 compatibility shim;

WITHNESSETH THAT:

  1. A PYDANTIC_V2 constant is defined to support V1 and V2 APIs.
  2. The OpenAPI specification generated by newer versions of Pydantic + FastAPI requires manual intervention to retain the existing content and structure.
  3. Usage of the dict method has been deprecated in V2, in favor of the model_dump method
  4. The API for Field has been altered in V2 such that:
    1. regex has been renamed to pattern
    2. choices has been removed in favor of Literal typing
    3. extras has been renamed to json_schema_extras
  5. The API for BaseModel has been altered in V2 such that:
    1. model_config method determines configuration instead of a nested Config class.
    2. A regime of __get_pydantic_core_schema__ and __get_pydantic_json_schema__ determines serialization instead of the __get_validators__ and __modify_scheme__ methods.
  6. Any no longer have default value of None. So we make it Optional and set a default value of None to get validation / schema to work correctly.
  7. Values of type io.IOBase and serialized by V2 pydantic_core as a generator, thereby wrapping them in a pydantic_core._pydantic_core.SerializationIterator, an object that cannot be pickled and requires unwrapping before being passed between multiprocessing boundaries. 1

NOW THEREFORE, in consideration of the mutual covenants herein contained, it is agreed by and between the parties.

Footnotes

  1. Proper upstream fixes for this have been proposed by @yorickvP with https://github.com/pydantic/pydantic-core/pull/1399 and https://github.com/pydantic/pydantic-core/pull/1401.

Copy link
Contributor

@8W9aG 8W9aG left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some minor comments for my own knowledge but otherwise looks good!

python/cog/command/ast_openapi_schema.py Outdated Show resolved Hide resolved
python/cog/command/ast_openapi_schema.py Outdated Show resolved Hide resolved
python/cog/predictor.py Show resolved Hide resolved
python/cog/server/http.py Outdated Show resolved Hide resolved
python/cog/server/http.py Outdated Show resolved Hide resolved
python/cog/types.py Outdated Show resolved Hide resolved
@mattt mattt force-pushed the mattt/pydantic-v2 branch 5 times, most recently from 837e08f to dcc2f02 Compare August 12, 2024 09:27
pyproject.toml Outdated Show resolved Hide resolved
@mattt mattt requested a review from a team August 12, 2024 09:59
@mattt
Copy link
Contributor Author

mattt commented Aug 12, 2024

Before merging, we should update CI to test against both Pydantic v1 and v2

@mattt mattt force-pushed the mattt/pydantic-v2 branch 2 times, most recently from 2ee83b8 to 56867b1 Compare August 12, 2024 11:13
@yorickvP
Copy link
Contributor

Submitted a PR to pydantic-core to expose .iterator on SerializationIterator: pydantic/pydantic-core#1399

@mattt mattt force-pushed the mattt/pydantic-v2 branch 3 times, most recently from b3713ea to bb064f8 Compare August 12, 2024 12:52
@nickstenning nickstenning force-pushed the mattt/pydantic-v2 branch 7 times, most recently from 0459fe3 to d88cdfe Compare August 19, 2024 14:54
@nickstenning nickstenning force-pushed the mattt/pydantic-v2 branch 2 times, most recently from e89b878 to a99c7d7 Compare September 2, 2024 13:58
Copy the code to {envtmpdir} for pydantic1, since there's no way
to override pyright configuration temporarily.
@yorickvP
Copy link
Contributor

my test with python_dependencies: - pydantic>2 produced a pip install with fastapi==0.98 and pydantic==2.9.2, which wouldn't work. Not sure what to do about that, except re-specifying fastapi constraints.

@yorickvP
Copy link
Contributor

yorickvP commented Sep 20, 2024

We will need to rethink how cog build installs dependencies.

  • Currently, there is a pip install cog step. This installs cog in the image, and picks pydantic2.
  • (base image is built here)
  • Then, user dependencies are installed. If this includes pydantic < 2, pip won't actually downgrade pydantic. It would have to run pip uninstall pydantic first.

Possible solutions:

  1. Depend on pydantic1 in the pip install cog step.

    • This upgrades to pydantic2 as needed during user package installation.
    • Pros: Can work for users using pydantic 1 and 2.
    • Con: This defaults to pydantic 1, while we want to switch to 2.
  2. Make the cog wheel participate in the user's dependency resolution.

    • This means we add /tmp/cog-something.whl to the requirements.txt and run the package installation as a single step.
    • Pro: dependency sets are always valid. Users get clear errors when there's a conflicting dependency.
    • Con: Stops us from including cog in the base images
    • Neutral: Stops users from building packages where dependencies conflict with cog. Not sure if that's desired.
  3. Add a pydantic: specifier to cog.yaml

    • Pro: makes it easy to have multiple base images
    • Con: not obvious for users when this is needed
    • Con: not backwards compatible
  4. Infer pydantic version from dependencies.

    • We already do this with torch.
    • Pro: makes it easy to have multiple base images
    • Con: not backwards compatible
    • Con: pydantic dependencies are often transitive, so this will require extra work for users
  5. Only allow building new images with pydantic2

    • Keep pydantic1 compat for existing images, but remove the functionality from cog go.
    • Pro: easiest to do (current behavior in this PR)
    • Con: Confusing to users (pydantic1 dependencies will break at runtime)
    • Con: not backwards compatible
  6. Switch to something smarter than pip

    • Out of scope for this PR

Installing pydantic>2 won't easily downgrade when the user packages
require it, but upgrading works fine.
@yorickvP
Copy link
Contributor

I went with option 1, which is the easiest for now. We can defer making pydantic2 a default to a later PR.

@technillogue
Copy link
Contributor

IMO that's the correct choice at least for the moment: keep things as they are now, but make it so that vllm doesn't break

@technillogue technillogue merged commit a6219fa into main Oct 9, 2024
20 checks passed
@technillogue technillogue deleted the mattt/pydantic-v2 branch October 9, 2024 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants