From cc83c96f6fee8fe38210b0467db61fbb8211bfcb Mon Sep 17 00:00:00 2001 From: Alex Martsinovich Date: Mon, 9 Sep 2024 17:49:18 -0700 Subject: [PATCH] Support Ecto 3.12 parameterized type new internal representation (#71) --- lib/instructor.ex | 9 +++------ lib/instructor/json_schema.ex | 12 ++++++------ mix.exs | 2 +- mix.lock | 6 +++--- test/gbnf_test.exs | 12 ++++-------- test/json_schema_test.exs | 24 +++++++++++------------- 6 files changed, 28 insertions(+), 37 deletions(-) diff --git a/lib/instructor.ex b/lib/instructor.ex index 48d6d3d..cc9579b 100644 --- a/lib/instructor.ex +++ b/lib/instructor.ex @@ -263,8 +263,7 @@ defmodule Instructor do defp do_streaming_partial_array_chat_completion(response_model, params, config) do wrapped_model = %{ value: - {:parameterized, Ecto.Embedded, - %Ecto.Embedded{cardinality: :many, related: response_model}} + Ecto.ParameterizedType.init(Ecto.Embedded, cardinality: :many, related: response_model) } params = Keyword.put(params, :response_model, wrapped_model) @@ -334,8 +333,7 @@ defmodule Instructor do defp do_streaming_partial_chat_completion(response_model, params, config) do wrapped_model = %{ value: - {:parameterized, Ecto.Embedded, - %Ecto.Embedded{cardinality: :one, related: response_model}} + Ecto.ParameterizedType.init(Ecto.Embedded, cardinality: :one, related: response_model) } params = Keyword.put(params, :response_model, wrapped_model) @@ -382,8 +380,7 @@ defmodule Instructor do defp do_streaming_array_chat_completion(response_model, params, config) do wrapped_model = %{ value: - {:parameterized, Ecto.Embedded, - %Ecto.Embedded{cardinality: :many, related: response_model}} + Ecto.ParameterizedType.init(Ecto.Embedded, cardinality: :many, related: response_model) } params = Keyword.put(params, :response_model, wrapped_model) diff --git a/lib/instructor/json_schema.ex b/lib/instructor/json_schema.ex index 32de736..afdc6ae 100644 --- a/lib/instructor/json_schema.ex +++ b/lib/instructor/json_schema.ex @@ -148,7 +148,7 @@ defmodule Instructor.JSONSchema do required = Map.keys(properties) |> Enum.sort() embedded_schemas = - for {_field, {:parameterized, Ecto.Embedded, %Ecto.Embedded{related: related}}} <- + for {_field, {:parameterized, {Ecto.Embedded, %Ecto.Embedded{related: related}}}} <- ecto_types, is_ecto_schema(related) do related @@ -226,7 +226,7 @@ defmodule Instructor.JSONSchema do defp for_type(:utc_datetime_usec), do: %{type: "string", format: "date-time"} defp for_type( - {:parameterized, Ecto.Embedded, %Ecto.Embedded{cardinality: :many, related: related}} + {:parameterized, {Ecto.Embedded, %Ecto.Embedded{cardinality: :many, related: related}}} ) when is_ecto_schema(related) do title = title_for(related) @@ -239,7 +239,7 @@ defmodule Instructor.JSONSchema do end defp for_type( - {:parameterized, Ecto.Embedded, %Ecto.Embedded{cardinality: :many, related: related}} + {:parameterized, {Ecto.Embedded, %Ecto.Embedded{cardinality: :many, related: related}}} ) when is_ecto_types(related) do properties = @@ -260,14 +260,14 @@ defmodule Instructor.JSONSchema do end defp for_type( - {:parameterized, Ecto.Embedded, %Ecto.Embedded{cardinality: :one, related: related}} + {:parameterized, {Ecto.Embedded, %Ecto.Embedded{cardinality: :one, related: related}}} ) when is_ecto_schema(related) do %{"$ref": "#/$defs/#{title_for(related)}"} end defp for_type( - {:parameterized, Ecto.Embedded, %Ecto.Embedded{cardinality: :one, related: related}} + {:parameterized, {Ecto.Embedded, %Ecto.Embedded{cardinality: :one, related: related}}} ) when is_ecto_types(related) do properties = @@ -284,7 +284,7 @@ defmodule Instructor.JSONSchema do } end - defp for_type({:parameterized, Ecto.Enum, %{mappings: mappings}}) do + defp for_type({:parameterized, {Ecto.Enum, %{mappings: mappings}}}) do %{ type: "string", enum: Keyword.keys(mappings) diff --git a/mix.exs b/mix.exs index b7b584c..28aa85f 100644 --- a/mix.exs +++ b/mix.exs @@ -111,7 +111,7 @@ defmodule Instructor.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ - {:ecto, "~> 3.11"}, + {:ecto, "~> 3.12"}, {:jason, "~> 1.4.0"}, {:req, "~> 0.5 or ~> 1.0"}, {:jaxon, "~> 2.0"}, diff --git a/mix.lock b/mix.lock index 9c1b235..2f1b5f6 100644 --- a/mix.lock +++ b/mix.lock @@ -2,12 +2,12 @@ "castore": {:hex, :castore, "1.0.7", "b651241514e5f6956028147fe6637f7ac13802537e895a724f90bf3e36ddd1dd", [:mix], [], "hexpm", "da7785a4b0d2a021cd1292a60875a784b6caef71e76bf4917bdee1f390455cf5"}, "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, - "ecto": {:hex, :ecto, "3.11.1", "4b4972b717e7ca83d30121b12998f5fcdc62ba0ed4f20fd390f16f3270d85c3e", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ebd3d3772cd0dfcd8d772659e41ed527c28b2a8bde4b00fe03e0463da0f1983b"}, + "ecto": {:hex, :ecto, "3.12.1", "626765f7066589de6fa09e0876a253ff60c3d00870dd3a1cd696e2ba67bfceea", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "df0045ab9d87be947228e05a8d153f3e06e0d05ab10c3b3cc557d2f7243d1940"}, "elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"}, "ex_doc": {:hex, :ex_doc, "0.31.0", "06eb1dfd787445d9cab9a45088405593dd3bb7fe99e097eaa71f37ba80c7a676", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "5350cafa6b7f77bdd107aa2199fe277acf29d739aba5aee7e865fc680c62a110"}, "finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"}, "hpax": {:hex, :hpax, "0.2.0", "5a58219adcb75977b2edce5eb22051de9362f08236220c9e859a47111c194ff5", [:mix], [], "hexpm", "bea06558cdae85bed075e6c036993d43cd54d447f76d8190a8db0dc5893fa2f1"}, - "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, + "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "jaxon": {:hex, :jaxon, "2.0.8", "00951a79d354260e28d7e36f956c3de94818124768a4b22e0fc55559d1b3bfe7", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "74532853b1126609615ea98f0ceb5009e70465ca98027afbbd8ed314d887e82d"}, "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, @@ -19,5 +19,5 @@ "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, "req": {:hex, :req, "0.5.0", "6d8a77c25cfc03e06a439fb12ffb51beade53e3fe0e2c5e362899a18b50298b3", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "dda04878c1396eebbfdec6db6f3d4ca609e5c8846b7ee88cc56eb9891406f7a3"}, - "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, + "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, } diff --git a/test/gbnf_test.exs b/test/gbnf_test.exs index e6b0086..8c7a2e2 100644 --- a/test/gbnf_test.exs +++ b/test/gbnf_test.exs @@ -123,14 +123,10 @@ defmodule GBNFTest do test "nested inline objects" do ecto_schema = %{ value: - {:parameterized, Ecto.Embedded, - %Ecto.Embedded{ - cardinality: :one, - related: %{ - name: :string, - birth_date: :date - } - }} + Ecto.ParameterizedType.init(Ecto.Embedded, + cardinality: :one, + related: %{name: :string, birth_date: :date} + ) } gbnf = diff --git a/test/json_schema_test.exs b/test/json_schema_test.exs index 3668b00..3ee4e6e 100644 --- a/test/json_schema_test.exs +++ b/test/json_schema_test.exs @@ -328,19 +328,17 @@ defmodule JSONSchemaTest do test "handles ecto types with embeds recursively" do schema = %{ value: - {:parameterized, Ecto.Embedded, - %Ecto.Embedded{ - cardinality: :one, - related: %{ - name: :string, - children: - {:parameterized, Ecto.Embedded, - %Ecto.Embedded{ - cardinality: :many, - related: %{name: :string} - }} - } - }} + Ecto.ParameterizedType.init(Ecto.Embedded, + cardinality: :one, + related: %{ + name: :string, + children: + Ecto.ParameterizedType.init(Ecto.Embedded, + cardinality: :many, + related: %{name: :string} + ) + } + ) } json_schema =