From 553deca6f64fbd9f33bcb8517c0fb3f3493d5153 Mon Sep 17 00:00:00 2001 From: Daniel Kukula Date: Fri, 2 Oct 2026 22:19:06 +0200 Subject: [PATCH 1/2] Add YaRN RoPE scaling and correct dynamic scaling --- lib/bumblebee/layers.ex | 239 +++++++++++++++++++++++++++++++-- lib/bumblebee/shared.ex | 183 ++++++++++++++++++++++--- test/bumblebee/layers_test.exs | 156 +++++++++++++++++++++ test/bumblebee/shared_test.exs | 93 +++++++++++++ 4 files changed, 645 insertions(+), 26 deletions(-) create mode 100644 test/bumblebee/layers_test.exs diff --git a/lib/bumblebee/layers.ex b/lib/bumblebee/layers.ex index 27d81990..3bd830ae 100644 --- a/lib/bumblebee/layers.ex +++ b/lib/bumblebee/layers.ex @@ -1239,18 +1239,206 @@ defmodule Bumblebee.Layers do def rotary_embedding(query, key, position_ids, attention_mask, size, opts \\ []) do opts = Keyword.validate!(opts, [:name, :scaling_strategy, max_positions: 2048, base: 10_000]) + scaling_strategy = + normalize_rotary_embedding_scaling_strategy(opts[:scaling_strategy], size, opts) + output = Axon.layer( &apply_rotary_embedding/5, [query, key, position_ids, Axon.optional(attention_mask)], - [size: size] ++ opts + [size: size, scaling_strategy: scaling_strategy] ++ + Keyword.drop(opts, [:scaling_strategy]) ) unwrap_tuple(output, 2) end + defp normalize_rotary_embedding_scaling_strategy(nil, _size, _opts), do: nil + + defp normalize_rotary_embedding_scaling_strategy( + %{type: :yarn} = strategy, + size, + opts + ) do + required_keys = [ + :factor, + :original_max_positions, + :beta_fast, + :beta_slow + ] + + case Enum.find(required_keys, &(not Map.has_key?(strategy, &1))) do + nil -> + validate_factor!(strategy.factor, :yarn) + + strategy = + strategy + |> Map.put_new_lazy(:attention_factor, fn -> 0.1 * :math.log(strategy.factor) + 1.0 end) + |> Map.put_new(:truncate, true) + + validate_yarn_strategy!(strategy) + + low = + yarn_correction_dim( + strategy.beta_fast, + size, + opts[:base], + strategy.original_max_positions + ) + + high = + yarn_correction_dim( + strategy.beta_slow, + size, + opts[:base], + strategy.original_max_positions + ) + + {low, high} = + if strategy.truncate do + {:math.floor(low), :math.ceil(high)} + else + {low, high} + end + + low = max(low, 0) + high = min(high, size - 1) + high = if low == high, do: high + 0.001, else: high + + Map.merge(strategy, %{ + correction_low: low, + correction_high: high + }) + + key -> + raise ArgumentError, "YaRN rotary embedding scaling strategy is missing #{inspect(key)}" + end + end + + defp normalize_rotary_embedding_scaling_strategy( + %{type: :longrope, short_factor: short_factor, long_factor: long_factor} = strategy, + size, + _opts + ) do + expected_size = div(size, 2) + + if longrope_factors?(short_factor, expected_size) and + longrope_factors?(long_factor, expected_size) do + strategy + else + raise ArgumentError, + "LongRoPE factors must each have #{expected_size} entries for a rotary size of #{size}" + end + end + + defp normalize_rotary_embedding_scaling_strategy( + %{type: :dynamic, factor: factor} = strategy, + size, + _opts + ) do + validate_factor!(factor, :dynamic) + + if size <= 2 do + raise ArgumentError, "dynamic RoPE requires a rotary size greater than 2" + end + + strategy + end + + defp normalize_rotary_embedding_scaling_strategy( + %{type: :linear, factor: factor} = strategy, + _size, + _opts + ) do + validate_factor!(factor, :linear) + strategy + end + + defp normalize_rotary_embedding_scaling_strategy(%{type: type}, _size, _opts) + when type in [:linear, :dynamic] do + raise ArgumentError, "#{type} RoPE requires :factor to be a number >= 1" + end + + defp normalize_rotary_embedding_scaling_strategy( + %{ + type: :llama3, + factor: factor, + low_frequency_factor: low, + high_frequency_factor: high, + original_max_positions: original_max_positions + } = strategy, + _size, + _opts + ) do + validate_factor!(factor, :llama3) + validate_positive_number!(low, :low_frequency_factor, :llama3) + validate_positive_number!(high, :high_frequency_factor, :llama3) + validate_positive_integer!(original_max_positions, :original_max_positions, :llama3) + + if high <= low do + raise ArgumentError, "llama3 RoPE requires :high_frequency_factor > :low_frequency_factor" + end + + strategy + end + + defp normalize_rotary_embedding_scaling_strategy(strategy, _size, _opts) do + raise ArgumentError, "unsupported rotary embedding scaling strategy: #{inspect(strategy)}" + end + + defp yarn_correction_dim(num_rotations, size, base, original_max_positions) do + size * :math.log(original_max_positions / (num_rotations * 2 * :math.pi())) / + (2 * :math.log(base)) + end + + defp validate_yarn_strategy!(strategy) do + validate_factor!(strategy.factor, :yarn) + validate_positive_integer!(strategy.original_max_positions, :original_max_positions, :yarn) + validate_positive_number!(strategy.beta_fast, :beta_fast, :yarn) + validate_positive_number!(strategy.beta_slow, :beta_slow, :yarn) + validate_positive_number!(strategy.attention_factor, :attention_factor, :yarn) + + unless is_boolean(strategy.truncate) do + raise ArgumentError, "YaRN RoPE requires :truncate to be a boolean" + end + + if strategy.beta_fast < strategy.beta_slow do + raise ArgumentError, "YaRN RoPE requires :beta_fast >= :beta_slow" + end + end + + defp longrope_factors?(factors, expected_size) do + is_list(factors) and length(factors) == expected_size and + Enum.all?(factors, &(is_number(&1) and &1 > 0)) + end + + defp validate_factor!(factor, type) do + if is_number(factor) and factor >= 1.0 do + :ok + else + raise ArgumentError, "#{type} RoPE requires :factor to be a number >= 1" + end + end + + defp validate_positive_number!(value, key, type) do + if is_number(value) and value > 0 do + :ok + else + raise ArgumentError, "#{type} RoPE requires #{inspect(key)} to be a positive number" + end + end + + defp validate_positive_integer!(value, key, type) do + if is_integer(value) and value > 0 do + :ok + else + raise ArgumentError, "#{type} RoPE requires #{inspect(key)} to be a positive integer" + end + end + deftransformp create_sinusoidal_positions( sequence_length, + context_length, max_positions, size, base, @@ -1266,15 +1454,48 @@ defmodule Bumblebee.Layers do position = Nx.divide(position, factor) positions_cos_sin(position, inv_frequency) - %{type: :dynamic, factor: factor} when sequence_length > max_positions -> - base = - base - |> Nx.multiply(factor * sequence_length / max_positions - (factor - 1)) - |> Nx.pow(size / (size - 2)) + %{type: :dynamic, factor: factor} -> + context_length = Nx.max(context_length, max_positions) + + scale = + context_length + |> Nx.multiply(factor) + |> Nx.divide(max_positions) + |> Nx.subtract(factor - 1) + + base = Nx.multiply(base, Nx.pow(scale, size / (size - 2))) inv_frequency = inv_frequency(base, range) positions_cos_sin(position, inv_frequency) + %{ + type: :yarn, + factor: factor, + attention_factor: attention_factor, + correction_low: low, + correction_high: high + } -> + inv_frequency_extrapolation = inv_frequency(base, range) + inv_frequency_interpolation = Nx.divide(inv_frequency_extrapolation, factor) + + ramp = + Nx.iota({div(size, 2)}) + |> Nx.subtract(low) + |> Nx.divide(high - low) + |> Nx.clip(0.0, 1.0) + + inv_frequency_extrapolation_factor = Nx.subtract(1.0, ramp) + + inv_frequency = + Nx.multiply( + inv_frequency_interpolation, + Nx.subtract(1.0, inv_frequency_extrapolation_factor) + ) + |> Nx.add(Nx.multiply(inv_frequency_extrapolation, inv_frequency_extrapolation_factor)) + + {cos, sin} = positions_cos_sin(position, inv_frequency) + {Nx.multiply(cos, attention_factor), Nx.multiply(sin, attention_factor)} + %{ type: :longrope, short_factor: short_factor, @@ -1394,17 +1615,19 @@ defmodule Bumblebee.Layers do _other -> Nx.axis_size(attention_mask, 1) end + position_ids = Nx.as_type(position_ids, :s64) + context_length = Nx.add(Nx.reduce_max(position_ids), 1) + {cos, sin} = create_sinusoidal_positions( sequence_length, + context_length, opts[:max_positions], opts[:size], opts[:base], opts[:scaling_strategy] ) - position_ids = Nx.as_type(position_ids, :s64) - cos = cos |> Nx.take(position_ids) |> Nx.new_axis(2) |> Nx.as_type(Nx.type(query)) sin = sin |> Nx.take(position_ids) |> Nx.new_axis(2) |> Nx.as_type(Nx.type(query)) diff --git a/lib/bumblebee/shared.ex b/lib/bumblebee/shared.ex index e4ff6c55..06fb66ff 100644 --- a/lib/bumblebee/shared.ex +++ b/lib/bumblebee/shared.ex @@ -38,10 +38,15 @@ defmodule Bumblebee.Shared do * `%{type: :dynamic, factor: number()}` + * `%{type: :yarn, factor: number(), original_max_positions: pos_integer(), beta_fast: number(), beta_slow: number()}` + * `%{type: :llama3, factor: number(), low_frequency_factor: number(), high_frequency_factor: number(), original_max_positions: pos_integer()}` * `%{type: :longrope, short_factor: list(number()), long_factor: list(number()), original_max_positions: pos_integer()}` + YaRN also accepts `:attention_factor` (defaults to `0.1 * log(factor) + 1.0`) + and `:truncate` (defaults to `true`). + For more details see https://www.reddit.com/r/LocalLLaMA/comments/14mrgpr/dynamically_scaled_rope_further_increases """ ] @@ -168,8 +173,14 @@ defmodule Bumblebee.Shared do end defp rotary_embedding_options(params, data) do + base = params["rope_theta"] + + if base != nil and (not is_number(base) or base <= 0) do + raise "conversion failed, \"rope_theta\" must be a positive number" + end + [ - rotary_embedding_base: params["rope_theta"], + rotary_embedding_base: base, rotary_embedding_percentage: params["partial_rotary_factor"], rotary_embedding_scaling_strategy: rotary_embedding_scaling_strategy(params, data) ] @@ -182,40 +193,176 @@ defmodule Bumblebee.Shared do data["original_max_position_embeddings"] || params["original_max_position_embeddings"] || data["max_position_embeddings"] - case {params["rope_type"] || params["type"] || "default", params} do + type = rope_type!(params) + + if type == "default" and scaling_fields?(params) do + if Map.has_key?(params, "type") or Map.has_key?(params, "rope_type") do + raise "conversion failed, default rotary embedding does not accept scaling parameters" + else + raise "conversion failed, rotary embedding scaling parameters require \"type\" or \"rope_type\"" + end + end + + case {type, params} do {"default", _params} -> nil {"linear", %{"factor" => factor}} -> - %{type: :linear, factor: factor} + %{type: :linear, factor: validate_factor!(factor, "linear")} {"dynamic", %{"factor" => factor}} -> - %{type: :dynamic, factor: factor} + %{type: :dynamic, factor: validate_factor!(factor, type)} {"llama3", %{"factor" => factor, "low_freq_factor" => low, "high_freq_factor" => high}} -> - %{ - type: :llama3, - factor: factor, - low_frequency_factor: low, - high_frequency_factor: high, - original_max_positions: original_max_positions - } + llama3_scaling_strategy(factor, low, high, original_max_positions) # Old Phi-3 checkpoints use "su" and "yarn" for LongRoPE - {type, %{"short_factor" => short_factor, "long_factor" => long_factor}} + {type, %{"short_factor" => _short_factor, "long_factor" => _long_factor} = params} when type in ["longrope", "su", "yarn"] -> - %{ - type: :longrope, - short_factor: short_factor, - long_factor: long_factor, - original_max_positions: original_max_positions - } + longrope_scaling_strategy(params, original_max_positions) + + {"yarn", %{"factor" => _factor}} = config -> + yarn_scaling_strategy(config, original_max_positions) _other -> raise "conversion failed, unsupported rotary embedding parameters: #{inspect(params)}" end end + defp yarn_scaling_strategy({"yarn", params}, original_max_positions) do + factor = validate_factor!(params["factor"], "yarn") + original_max_positions = validate_original_max_positions!(original_max_positions, "yarn") + beta_fast = validate_positive_number!(params["beta_fast"] || 32.0, "beta_fast", "yarn") + beta_slow = validate_positive_number!(params["beta_slow"] || 1.0, "beta_slow", "yarn") + + unless is_boolean(Map.get(params, "truncate", true)) do + raise "conversion failed, yarn requires \"truncate\" to be a boolean" + end + + if beta_fast < beta_slow do + raise "conversion failed, YaRN requires \"beta_fast\" >= \"beta_slow\"" + end + + %{ + type: :yarn, + factor: factor, + original_max_positions: original_max_positions, + beta_fast: beta_fast, + beta_slow: beta_slow, + attention_factor: yarn_attention_factor(params, factor), + truncate: Map.get(params, "truncate", true) + } + end + + defp llama3_scaling_strategy(factor, low, high, original_max_positions) do + factor = validate_factor!(factor, "llama3") + low = validate_positive_number!(low, "low_freq_factor", "llama3") + high = validate_positive_number!(high, "high_freq_factor", "llama3") + + if high <= low do + raise "conversion failed, llama3 requires \"high_freq_factor\" > \"low_freq_factor\"" + end + + %{ + type: :llama3, + factor: factor, + low_frequency_factor: low, + high_frequency_factor: high, + original_max_positions: validate_original_max_positions!(original_max_positions, "llama3") + } + end + + defp rope_type!(%{"rope_type" => rope_type, "type" => type}) when rope_type != type do + raise "conversion failed, conflicting \"rope_type\" and \"type\" values" + end + + defp rope_type!(%{"rope_type" => rope_type}), do: rope_type + defp rope_type!(%{"type" => type}), do: type + defp rope_type!(_params), do: "default" + + defp scaling_fields?(params) do + Enum.any?( + [ + "factor", + "short_factor", + "long_factor", + "low_freq_factor", + "high_freq_factor", + "beta_fast", + "beta_slow", + "attention_factor", + "mscale", + "mscale_all_dim", + "truncate" + ], + &Map.has_key?(params, &1) + ) + end + + defp longrope_scaling_strategy(params, original_max_positions) do + %{ + type: :longrope, + short_factor: validate_number_list!(params["short_factor"], "short_factor", "longrope"), + long_factor: validate_number_list!(params["long_factor"], "long_factor", "longrope"), + original_max_positions: validate_original_max_positions!(original_max_positions, "longrope") + } + end + + defp yarn_attention_factor(params, factor) do + case params["attention_factor"] do + nil -> + case {params["mscale"], params["mscale_all_dim"]} do + {nil, nil} -> + yarn_mscale(factor) + + {mscale, mscale_all_dim} when is_number(mscale) and is_number(mscale_all_dim) -> + yarn_mscale(factor, mscale) / yarn_mscale(factor, mscale_all_dim) + + _other -> + raise "conversion failed, yarn requires numeric \"mscale\" and \"mscale_all_dim\" together" + end + + attention_factor -> + validate_positive_number!(attention_factor, "attention_factor", "yarn") + end + end + + defp yarn_mscale(factor, mscale \\ 1.0) + defp yarn_mscale(factor, _mscale) when factor <= 1.0, do: 1.0 + defp yarn_mscale(factor, mscale), do: 0.1 * mscale * :math.log(factor) + 1.0 + + defp validate_factor!(factor, type) do + if is_number(factor) and factor >= 1.0 do + factor + else + raise "conversion failed, #{type} requires a numeric \"factor\" >= 1" + end + end + + defp validate_original_max_positions!(value, type) do + if is_integer(value) and value > 0 do + value + else + raise "conversion failed, #{type} requires a positive integer \"original_max_position_embeddings\"" + end + end + + defp validate_positive_number!(value, key, type) do + if is_number(value) and value > 0 do + value + else + raise "conversion failed, #{type} requires a positive numeric #{inspect(key)}" + end + end + + defp validate_number_list!(value, key, type) do + if is_list(value) and value != [] and Enum.all?(value, &(is_number(&1) and &1 > 0)) do + value + else + raise "conversion failed, #{type} requires a non-empty list of positive numbers for #{inspect(key)}" + end + end + @doc """ Merges the given list of attributes into a configuration struct. diff --git a/test/bumblebee/layers_test.exs b/test/bumblebee/layers_test.exs new file mode 100644 index 00000000..688ee7bd --- /dev/null +++ b/test/bumblebee/layers_test.exs @@ -0,0 +1,156 @@ +defmodule Bumblebee.LayersTest do + use ExUnit.Case, async: true + + import Bumblebee.TestHelpers + + alias Bumblebee.Layers + + test "documented YaRN configuration uses the default attention factor and truncation" do + strategy = %{ + type: :yarn, + factor: 4.0, + original_max_positions: 2, + beta_fast: 32.0, + beta_slow: 1.0 + } + + {query, _key} = apply_rotary_embedding(strategy) + {init, predict} = Axon.build(query) + + inputs = %{ + "query" => Nx.broadcast(1.0, {1, 4, 1, 4}), + "key" => Nx.broadcast(1.0, {1, 4, 1, 4}), + "position_ids" => Nx.tensor([[0, 1, 2, 3]]), + "attention_mask" => Nx.tensor([[1, 1, 1, 1]]) + } + + params = init.(inputs, Axon.ModelState.empty()) + output = predict.(params, inputs) + + assert_all_close( + output[[0, 1..3, 0, 0..1]], + Nx.tensor([[-0.3012, 0.9975], [-1.3254, 0.9950], [-1.1311, 0.9925]]) + |> Nx.multiply(0.1 * :math.log(4.0) + 1.0) + ) + end + + test "rejects an explicit unknown rotary scaling strategy" do + assert_raise ArgumentError, ~r/unsupported rotary embedding scaling strategy/, fn -> + apply_rotary_embedding(%{type: :unsupported}) + end + end + + test "rejects an explicit malformed linear scaling strategy" do + assert_raise ArgumentError, ~r/linear RoPE requires :factor to be a number >= 1/, fn -> + apply_rotary_embedding(%{type: :linear}) + end + end + + test "rejects non-positive LongRoPE factors" do + assert_raise ArgumentError, ~r/LongRoPE factors must each have 2 entries/, fn -> + apply_rotary_embedding(%{ + type: :longrope, + short_factor: [1.0, 0.0], + long_factor: [1.0, 1.0], + original_max_positions: 2 + }) + end + end + + test "dynamic RoPE exponent applies to the multiplier, using position IDs" do + query = Axon.input("query", shape: {1, 4, 1, 4}) + key = Axon.input("key", shape: {1, 4, 1, 4}) + position_ids = Axon.input("position_ids", shape: {1, 4}) + attention_mask = Axon.input("attention_mask", shape: {1, 8}) + + {query, _key} = + Layers.rotary_embedding(query, key, position_ids, attention_mask, 4, + max_positions: 2, + base: 10_000, + scaling_strategy: %{type: :dynamic, factor: 2.0} + ) + + model = Axon.container(%{query: query}) + + inputs = %{ + "query" => Nx.broadcast(1.0, {1, 4, 1, 4}), + "key" => Nx.broadcast(1.0, {1, 4, 1, 4}), + "position_ids" => Nx.tensor([[0, 1, 2, 3]]), + "attention_mask" => Nx.tensor([[1, 1, 1, 1, 0, 0, 0, 0]]) + } + + {init, predict} = Axon.build(model) + params = init.(inputs, Axon.ModelState.empty()) + outputs = predict.(params, inputs) + + scale = 2.0 * 4 / 2 - (2.0 - 1.0) + base = 10_000 * :math.pow(scale, 4 / (4 - 2)) + angle = 1 / :math.sqrt(base) + + assert_all_close(outputs.query[[0, 1, 0, 1]], Nx.tensor(:math.cos(angle) - :math.sin(angle))) + end + + test "rejects dynamic RoPE with a rotary size of two" do + assert_raise ArgumentError, ~r/requires a rotary size greater than 2/, fn -> + query = Axon.input("query", shape: {1, 4, 1, 2}) + key = Axon.input("key", shape: {1, 4, 1, 2}) + position_ids = Axon.input("position_ids", shape: {1, 4}) + attention_mask = Axon.input("attention_mask", shape: {1, 4}) + + Layers.rotary_embedding(query, key, position_ids, attention_mask, 2, + scaling_strategy: %{type: :dynamic, factor: 2.0} + ) + end + end + + test "YaRN scales rotary frequencies at positions beyond the original context" do + query = Axon.input("query", shape: {1, 4, 1, 4}) + key = Axon.input("key", shape: {1, 4, 1, 4}) + position_ids = Axon.input("position_ids", shape: {1, 4}) + attention_mask = Axon.input("attention_mask", shape: {1, 4}) + + strategy = %{ + type: :yarn, + factor: 4.0, + original_max_positions: 2, + beta_fast: 32.0, + beta_slow: 1.0, + attention_factor: 1.0, + truncate: true + } + + {query, _key} = + Layers.rotary_embedding(query, key, position_ids, attention_mask, 4, + scaling_strategy: strategy + ) + + model = Axon.container(%{query: query}) + + inputs = %{ + "query" => Nx.broadcast(1.0, {1, 4, 1, 4}), + "key" => Nx.broadcast(1.0, {1, 4, 1, 4}), + "position_ids" => Nx.tensor([[0, 1, 2, 3]]), + "attention_mask" => Nx.tensor([[1, 1, 1, 1]]) + } + + {init, predict} = Axon.build(model) + params = init.(inputs, Axon.ModelState.empty()) + outputs = predict.(params, inputs) + + assert_all_close( + outputs.query[[0, 1..3, 0, 0..1]], + Nx.tensor([[-0.3012, 0.9975], [-1.3254, 0.9950], [-1.1311, 0.9925]]) + ) + end + + defp apply_rotary_embedding(strategy) do + query = Axon.input("query", shape: {1, 4, 1, 4}) + key = Axon.input("key", shape: {1, 4, 1, 4}) + position_ids = Axon.input("position_ids", shape: {1, 4}) + attention_mask = Axon.input("attention_mask", shape: {1, 4}) + + Layers.rotary_embedding(query, key, position_ids, attention_mask, 4, + scaling_strategy: strategy + ) + end +end diff --git a/test/bumblebee/shared_test.exs b/test/bumblebee/shared_test.exs index 3467286c..6d54ff0b 100644 --- a/test/bumblebee/shared_test.exs +++ b/test/bumblebee/shared_test.exs @@ -3,6 +3,99 @@ defmodule Bumblebee.SharedTest do alias Bumblebee.Shared + describe "rotary_embedding_options_from_transformers/1" do + test "accepts the legacy type key" do + assert [rotary_embedding_scaling_strategy: %{type: :linear, factor: 2.0}] = + Shared.rotary_embedding_options_from_transformers(%{ + "rope_scaling" => %{"type" => "linear", "factor" => 2.0} + }) + end + + test "accepts the rope_type key for YaRN" do + assert [ + rotary_embedding_scaling_strategy: %{ + type: :yarn, + factor: 4.0, + original_max_positions: 128, + beta_fast: 32.0, + beta_slow: 1.0 + } + ] = + Shared.rotary_embedding_options_from_transformers(%{ + "max_position_embeddings" => 512, + "rope_parameters" => %{ + "rope_type" => "yarn", + "factor" => 4.0, + "original_max_position_embeddings" => 128, + "beta_fast" => 32.0, + "beta_slow" => 1.0 + } + }) + end + + test "raises for an unsupported RoPE type" do + assert_raise RuntimeError, ~r/unsupported rotary embedding parameters/, fn -> + Shared.rotary_embedding_options_from_transformers(%{ + "rope_scaling" => %{"type" => "unsupported", "factor" => 2.0} + }) + end + end + + test "raises for conflicting type aliases" do + assert_raise RuntimeError, ~r/conflicting "rope_type" and "type" values/, fn -> + Shared.rotary_embedding_options_from_transformers(%{ + "rope_scaling" => %{"rope_type" => "linear", "type" => "dynamic", "factor" => 2.0} + }) + end + end + + test "raises for invalid YaRN parameters" do + assert_raise RuntimeError, ~r/requires a numeric "factor" >= 1/, fn -> + Shared.rotary_embedding_options_from_transformers(%{ + "rope_scaling" => %{ + "type" => "yarn", + "factor" => 0.5, + "original_max_position_embeddings" => 128 + } + }) + end + end + + test "rejects scaling parameters without a type" do + assert_raise RuntimeError, ~r/scaling parameters require "type" or "rope_type"/, fn -> + Shared.rotary_embedding_options_from_transformers(%{ + "rope_scaling" => %{"factor" => 2.0} + }) + end + end + + test "rejects a non-positive rope theta" do + assert_raise RuntimeError, ~r/"rope_theta" must be a positive number/, fn -> + Shared.rotary_embedding_options_from_transformers(%{"rope_theta" => 0}) + end + end + + test "preserves legacy Phi-3 YaRN LongRoPE without a factor" do + assert [ + rotary_embedding_scaling_strategy: %{ + type: :longrope, + short_factor: [1.0, 1.0], + long_factor: [2.0, 2.0], + original_max_positions: 128 + } + ] = + Shared.rotary_embedding_options_from_transformers(%{ + "max_position_embeddings" => 512, + "rope_scaling" => %{ + "type" => "yarn", + "short_factor" => [1.0, 1.0], + "long_factor" => [2.0, 2.0], + "original_max_position_embeddings" => 128 + } + }) + end + end + describe "validate_label_options/1" do test "passes when :id_to_label is empty" do spec = %{__struct__: TestConfig, num_labels: 3, id_to_label: %{}} From 11d68635802575a3bd6817f93a6d7d405b1eb481 Mon Sep 17 00:00:00 2001 From: Daniel Kukula Date: Fri, 2 Oct 2026 22:20:50 +0200 Subject: [PATCH 2/2] Support bidirectional decoder backbones for text embeddings --- lib/bumblebee/layers/decoder.ex | 18 + lib/bumblebee/shared.ex | 41 ++ lib/bumblebee/text/gemma3_text.ex | 37 +- lib/bumblebee/text/llama.ex | 23 +- lib/bumblebee/text/mistral.ex | 28 +- lib/bumblebee/text/qwen3.ex | 110 +++- notebooks/llms_rag.livemd | 60 ++ test/bumblebee/shared_test.exs | 23 + .../text/embedding_attention_test.exs | 173 ++++++ test/bumblebee/text/embedding_config_test.exs | 150 +++++ .../text/embedding_gemma_integration_test.exs | 40 ++ test/bumblebee/text/embedding_parity_test.exs | 94 +++ test/fixtures/embedding_models/generate.py | 197 ++++++ .../config.json | 50 ++ .../model.safetensors | Bin 0 -> 19224 bytes .../reference.json | 585 ++++++++++++++++++ .../config.json | 50 ++ .../model.safetensors | Bin 0 -> 19224 bytes .../reference.json | 585 ++++++++++++++++++ .../config.json | 33 + .../model.safetensors | Bin 0 -> 18072 bytes .../reference.json | 585 ++++++++++++++++++ .../tiny-random-llama-causal/config.json | 33 + .../model.safetensors | Bin 0 -> 18072 bytes .../tiny-random-llama-causal/reference.json | 585 ++++++++++++++++++ .../config.json | 31 + .../model.safetensors | Bin 0 -> 18072 bytes .../reference.json | 585 ++++++++++++++++++ .../tiny-random-mistral-causal/config.json | 31 + .../model.safetensors | Bin 0 -> 18072 bytes .../tiny-random-mistral-causal/reference.json | 585 ++++++++++++++++++ .../config.json | 42 ++ .../model.safetensors | Bin 0 -> 18560 bytes .../reference.json | 585 ++++++++++++++++++ .../tiny-random-qwen3-causal/config.json | 42 ++ .../model.safetensors | Bin 0 -> 18560 bytes .../tiny-random-qwen3-causal/reference.json | 585 ++++++++++++++++++ .../config.json | 39 ++ .../model.safetensors | Bin 0 -> 18560 bytes .../reference.json | 585 ++++++++++++++++++ .../config.json | 39 ++ .../model.safetensors | Bin 0 -> 18560 bytes .../reference.json | 585 ++++++++++++++++++ .../config.json | 40 ++ .../model.safetensors | Bin 0 -> 18560 bytes .../reference.json | 585 ++++++++++++++++++ .../config.json | 40 ++ .../model.safetensors | Bin 0 -> 18560 bytes .../reference.json | 585 ++++++++++++++++++ 49 files changed, 8469 insertions(+), 15 deletions(-) create mode 100644 test/bumblebee/text/embedding_attention_test.exs create mode 100644 test/bumblebee/text/embedding_config_test.exs create mode 100644 test/bumblebee/text/embedding_gemma_integration_test.exs create mode 100644 test/bumblebee/text/embedding_parity_test.exs create mode 100644 test/fixtures/embedding_models/generate.py create mode 100644 test/fixtures/embedding_models/tiny-random-gemma3_text-bidirectional/config.json create mode 100644 test/fixtures/embedding_models/tiny-random-gemma3_text-bidirectional/model.safetensors create mode 100644 test/fixtures/embedding_models/tiny-random-gemma3_text-bidirectional/reference.json create mode 100644 test/fixtures/embedding_models/tiny-random-gemma3_text-causal/config.json create mode 100644 test/fixtures/embedding_models/tiny-random-gemma3_text-causal/model.safetensors create mode 100644 test/fixtures/embedding_models/tiny-random-gemma3_text-causal/reference.json create mode 100644 test/fixtures/embedding_models/tiny-random-llama-bidirectional/config.json create mode 100644 test/fixtures/embedding_models/tiny-random-llama-bidirectional/model.safetensors create mode 100644 test/fixtures/embedding_models/tiny-random-llama-bidirectional/reference.json create mode 100644 test/fixtures/embedding_models/tiny-random-llama-causal/config.json create mode 100644 test/fixtures/embedding_models/tiny-random-llama-causal/model.safetensors create mode 100644 test/fixtures/embedding_models/tiny-random-llama-causal/reference.json create mode 100644 test/fixtures/embedding_models/tiny-random-mistral-bidirectional/config.json create mode 100644 test/fixtures/embedding_models/tiny-random-mistral-bidirectional/model.safetensors create mode 100644 test/fixtures/embedding_models/tiny-random-mistral-bidirectional/reference.json create mode 100644 test/fixtures/embedding_models/tiny-random-mistral-causal/config.json create mode 100644 test/fixtures/embedding_models/tiny-random-mistral-causal/model.safetensors create mode 100644 test/fixtures/embedding_models/tiny-random-mistral-causal/reference.json create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3-bidirectional/config.json create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3-bidirectional/model.safetensors create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3-bidirectional/reference.json create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3-causal/config.json create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3-causal/model.safetensors create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3-causal/reference.json create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3_dynamic-bidirectional/config.json create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3_dynamic-bidirectional/model.safetensors create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3_dynamic-bidirectional/reference.json create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3_dynamic-causal/config.json create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3_dynamic-causal/model.safetensors create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3_dynamic-causal/reference.json create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3_linear-bidirectional/config.json create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3_linear-bidirectional/model.safetensors create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3_linear-bidirectional/reference.json create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3_linear-causal/config.json create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3_linear-causal/model.safetensors create mode 100644 test/fixtures/embedding_models/tiny-random-qwen3_linear-causal/reference.json diff --git a/lib/bumblebee/layers/decoder.ex b/lib/bumblebee/layers/decoder.ex index fc56b7f2..36cdc50d 100644 --- a/lib/bumblebee/layers/decoder.ex +++ b/lib/bumblebee/layers/decoder.ex @@ -5,6 +5,24 @@ defmodule Bumblebee.Layers.Decoder do alias Bumblebee.Layers + @doc """ + Rejects cached inference with bidirectional self-attention, since adding + tokens changes the hidden states of previously processed tokens. + """ + def validate_attention_cache(cache, false), do: cache + + def validate_attention_cache(cache, true) do + Axon.layer( + fn cache, _opts -> + case cache do + %Axon.None{} -> cache + _ -> raise ArgumentError, "decoding cache is not supported with bidirectional attention" + end + end, + [Axon.optional(cache)] + ) + end + defmodule Cache do @moduledoc false diff --git a/lib/bumblebee/shared.ex b/lib/bumblebee/shared.ex index 06fb66ff..cc9e33c8 100644 --- a/lib/bumblebee/shared.ex +++ b/lib/bumblebee/shared.ex @@ -146,6 +146,47 @@ defmodule Bumblebee.Shared do end end + @doc """ + Converts the causal-attention setting from Hugging Face config data. + + Hugging Face models use `"is_causal"`, while some embedding checkpoints + serialize `"use_bidirectional_attention"`. `"is_causal"` takes precedence + when both are present. + """ + @spec bidirectional_attention_options_from_transformers(map()) :: keyword() + def bidirectional_attention_options_from_transformers(data) do + case Map.fetch(data, "is_causal") do + {:ok, is_causal} when is_boolean(is_causal) -> + [use_bidirectional_attention: not is_causal] + + {:ok, _value} -> + raise "conversion failed, expected \"is_causal\" to be a boolean" + + :error -> + case Map.fetch(data, "use_bidirectional_attention") do + {:ok, use_bidirectional_attention} when is_boolean(use_bidirectional_attention) -> + [use_bidirectional_attention: use_bidirectional_attention] + + {:ok, _value} -> + raise "conversion failed, expected \"use_bidirectional_attention\" to be a boolean" + + :error -> + [] + end + end + end + + @doc false + @spec validate_bidirectional_attention(Bumblebee.ModelSpec.t()) :: Bumblebee.ModelSpec.t() + def validate_bidirectional_attention(%{use_bidirectional_attention: value} = spec) + when is_boolean(value), + do: spec + + def validate_bidirectional_attention(%{use_bidirectional_attention: value}) do + raise ArgumentError, + ":use_bidirectional_attention must be a boolean, got: #{inspect(value)}" + end + @doc """ Converts rotary embedding options from Hugging Face config data. diff --git a/lib/bumblebee/text/gemma3_text.ex b/lib/bumblebee/text/gemma3_text.ex index 19301315..b379c8e2 100644 --- a/lib/bumblebee/text/gemma3_text.ex +++ b/lib/bumblebee/text/gemma3_text.ex @@ -80,7 +80,7 @@ defmodule Bumblebee.Text.Gemma3Text do attention_window_size: [ default: 4096, doc: - "the number of tokens each token can attend to in the sliding attention window, including itself. Only used for `:sliding_attention` layers" + "causal window width including the token itself. Bidirectional layers use half this width as the distance on either side, matching Transformers. Only used for `:sliding_attention` layers" ], layer_types: [ default: nil, @@ -95,7 +95,12 @@ defmodule Bumblebee.Text.Gemma3Text do ], use_bidirectional_attention: [ default: false, - doc: "whether to use bidirectional attention instead of causal attention" + doc: """ + whether to use bidirectional attention. Loaded from checkpoint `is_causal` + (inverted), or `use_bidirectional_attention`. The default is causal, including + the `:base` architecture. Bidirectional inference requires the full sequence + on each pass and does not support decoding cache or generation + """ ] ] ++ Shared.common_options([:rotary_embedding_scaling_strategy, :num_labels, :id_to_label]) ++ @@ -194,6 +199,7 @@ defmodule Bumblebee.Text.Gemma3Text do spec |> Shared.put_config_attrs(opts) |> Shared.validate_label_options() + |> Shared.validate_bidirectional_attention() end @impl true @@ -204,6 +210,11 @@ defmodule Bumblebee.Text.Gemma3Text do end @impl true + def init_cache(%{use_bidirectional_attention: true}, _batch_size, _max_length, _inputs) do + raise ArgumentError, + "decoding cache and generation are not supported with bidirectional attention" + end + def init_cache(spec, batch_size, max_length, _inputs) do Layers.Decoder.init_cache(batch_size, max_length, hidden_size: spec.hidden_size, @@ -312,7 +323,10 @@ defmodule Bumblebee.Text.Gemma3Text do position_ids, inputs["attention_mask"], inputs["attention_head_mask"], - inputs["cache"], + Layers.Decoder.validate_attention_cache( + inputs["cache"], + spec.use_bidirectional_attention + ), spec, name: "decoder" ) @@ -395,8 +409,12 @@ defmodule Bumblebee.Text.Gemma3Text do {nil, spec.rotary_embedding_base, spec.rotary_embedding_scaling_strategy} :sliding_attention -> - {{spec.attention_window_size - 1, spec.attention_window_size - 1}, - spec.rotary_embedding_base_local, nil} + radius = + if spec.use_bidirectional_attention, + do: div(spec.attention_window_size, 2), + else: spec.attention_window_size - 1 + + {{radius, radius}, spec.rotary_embedding_base_local, nil} end shortcut = hidden_state @@ -539,9 +557,14 @@ defmodule Bumblebee.Text.Gemma3Text do "full_attention" => :full_attention }) )}, - tie_word_embeddings: {"tie_word_embeddings", boolean()}, - use_bidirectional_attention: {"use_bidirectional_attention", boolean()} + tie_word_embeddings: {"tie_word_embeddings", boolean()} ) ++ + Shared.bidirectional_attention_options_from_transformers( + if(Map.has_key?(data, "use_bidirectional_attention"), + do: Map.delete(data, "is_causal"), + else: data + ) + ) ++ Shared.rotary_embedding_options_from_transformers(data) ++ Shared.common_options_from_transformers(data, spec) diff --git a/lib/bumblebee/text/llama.ex b/lib/bumblebee/text/llama.ex index 6a6d28f8..afa063a1 100644 --- a/lib/bumblebee/text/llama.ex +++ b/lib/bumblebee/text/llama.ex @@ -3,6 +3,15 @@ defmodule Bumblebee.Text.Llama do options = [ + use_bidirectional_attention: [ + default: false, + doc: """ + whether to use bidirectional attention. Loaded from checkpoint `is_causal` + (inverted), or `use_bidirectional_attention`. The default is causal, including + the `:base` architecture. Bidirectional inference requires the full sequence + on each pass and does not support decoding cache or generation + """ + ], vocab_size: [ default: 32000, doc: """ @@ -154,6 +163,7 @@ defmodule Bumblebee.Text.Llama do spec |> Shared.put_config_attrs(opts) |> Shared.validate_label_options() + |> Shared.validate_bidirectional_attention() end @impl true @@ -164,6 +174,11 @@ defmodule Bumblebee.Text.Llama do end @impl true + def init_cache(%{use_bidirectional_attention: true}, _batch_size, _max_length, _inputs) do + raise ArgumentError, + "decoding cache and generation are not supported with bidirectional attention" + end + def init_cache(spec, batch_size, max_length, _inputs) do Layers.Decoder.init_cache(batch_size, max_length, hidden_size: spec.hidden_size, @@ -272,7 +287,10 @@ defmodule Bumblebee.Text.Llama do position_ids, inputs["attention_mask"], inputs["attention_head_mask"], - inputs["cache"], + Layers.Decoder.validate_attention_cache( + inputs["cache"], + spec.use_bidirectional_attention + ), spec, name: "decoder" ) @@ -338,7 +356,7 @@ defmodule Bumblebee.Text.Llama do num_key_value_heads: spec.num_key_value_heads, hidden_size: spec.hidden_size, attention_head_size: spec.attention_head_size, - causal: true, + causal: not spec.use_bidirectional_attention, rotary_embedding: [ position_ids: position_ids, max_positions: spec.max_positions, @@ -409,6 +427,7 @@ defmodule Bumblebee.Text.Llama do layer_norm_epsilon: {"rms_norm_eps", number()}, tie_word_embeddings: {"tie_word_embeddings", boolean()} ) ++ + Shared.bidirectional_attention_options_from_transformers(data) ++ Shared.rotary_embedding_options_from_transformers(data) ++ Shared.common_options_from_transformers(data, spec) diff --git a/lib/bumblebee/text/mistral.ex b/lib/bumblebee/text/mistral.ex index 51324cf2..be08b313 100644 --- a/lib/bumblebee/text/mistral.ex +++ b/lib/bumblebee/text/mistral.ex @@ -3,6 +3,15 @@ defmodule Bumblebee.Text.Mistral do options = [ + use_bidirectional_attention: [ + default: false, + doc: """ + whether to use bidirectional attention. Loaded from checkpoint `is_causal` + (inverted), or `use_bidirectional_attention`. The default is causal, including + the `:base` architecture. Bidirectional inference requires the full sequence + on each pass and does not support decoding cache or generation + """ + ], vocab_size: [ default: 32000, doc: """ @@ -46,7 +55,7 @@ defmodule Bumblebee.Text.Mistral do attention_window_size: [ default: 4096, doc: - "the number of tokens each token can attend to in the sliding attention window, including itself" + "causal window width including the token itself; in bidirectional mode, the maximum distance on either side" ], activation: [ default: :silu, @@ -153,6 +162,7 @@ defmodule Bumblebee.Text.Mistral do spec |> Shared.put_config_attrs(opts) |> Shared.validate_label_options() + |> Shared.validate_bidirectional_attention() end @impl true @@ -163,6 +173,11 @@ defmodule Bumblebee.Text.Mistral do end @impl true + def init_cache(%{use_bidirectional_attention: true}, _batch_size, _max_length, _inputs) do + raise ArgumentError, + "decoding cache and generation are not supported with bidirectional attention" + end + def init_cache(spec, batch_size, max_length, _inputs) do Layers.Decoder.init_cache(batch_size, max_length, hidden_size: spec.hidden_size, @@ -270,7 +285,10 @@ defmodule Bumblebee.Text.Mistral do position_ids, inputs["attention_mask"], inputs["attention_head_mask"], - inputs["cache"], + Layers.Decoder.validate_attention_cache( + inputs["cache"], + spec.use_bidirectional_attention + ), spec, name: "decoder" ) @@ -337,10 +355,11 @@ defmodule Bumblebee.Text.Mistral do num_heads: spec.num_attention_heads, num_key_value_heads: spec.num_key_value_heads, hidden_size: spec.hidden_size, - causal: true, + causal: not spec.use_bidirectional_attention, attention_window_size: spec.attention_window_size && - {spec.attention_window_size - 1, spec.attention_window_size - 1}, + {spec.attention_window_size - if(spec.use_bidirectional_attention, do: 0, else: 1), + spec.attention_window_size}, rotary_embedding: [ position_ids: position_ids, max_positions: spec.max_positions, @@ -409,6 +428,7 @@ defmodule Bumblebee.Text.Mistral do initializer_scale: {"initializer_range", number()}, layer_norm_epsilon: {"rms_norm_eps", number()} ) ++ + Shared.bidirectional_attention_options_from_transformers(data) ++ Shared.rotary_embedding_options_from_transformers(data) ++ Shared.common_options_from_transformers(data, spec) diff --git a/lib/bumblebee/text/qwen3.ex b/lib/bumblebee/text/qwen3.ex index a959e9d0..63d907ea 100644 --- a/lib/bumblebee/text/qwen3.ex +++ b/lib/bumblebee/text/qwen3.ex @@ -3,6 +3,15 @@ defmodule Bumblebee.Text.Qwen3 do options = [ + use_bidirectional_attention: [ + default: false, + doc: """ + whether to use bidirectional attention. Loaded from checkpoint `is_causal` + (inverted), or `use_bidirectional_attention`. The default is causal, including + the `:base` architecture. Bidirectional inference requires the full sequence + on each pass and does not support decoding cache or generation + """ + ], vocab_size: [ default: 151_936, doc: """ @@ -44,6 +53,22 @@ defmodule Bumblebee.Text.Qwen3 do default: 8, doc: "the number of key value heads for each attention layer in the model" ], + attention_window_size: [ + default: nil, + doc: """ + sliding window width, or nil for full attention. Causal layers attend to + this many tokens including themselves; bidirectional layers attend to + tokens within this distance on either side + """ + ], + max_window_layers: [ + default: 28, + doc: "number of initial full-attention layers when :layer_types is not specified" + ], + layer_types: [ + default: nil, + doc: "per-layer :full_attention or :sliding_attention overrides" + ], activation: [ default: :silu, doc: "the activation function" @@ -157,6 +182,33 @@ defmodule Bumblebee.Text.Qwen3 do spec |> Shared.put_config_attrs(opts) |> Shared.validate_label_options() + |> Shared.validate_bidirectional_attention() + |> validate_attention_options() + end + + defp validate_attention_options(spec) do + unless is_nil(spec.attention_window_size) or + (is_integer(spec.attention_window_size) and spec.attention_window_size > 0) do + raise ArgumentError, ":attention_window_size must be nil or a positive integer" + end + + unless is_integer(spec.max_window_layers) and spec.max_window_layers >= 0 do + raise ArgumentError, ":max_window_layers must be a non-negative integer" + end + + if spec.layer_types do + unless is_list(spec.layer_types) and length(spec.layer_types) == spec.num_blocks and + Enum.all?(spec.layer_types, &(&1 in [:full_attention, :sliding_attention])) do + raise ArgumentError, + ":layer_types must specify :full_attention or :sliding_attention for each block" + end + + if :sliding_attention in spec.layer_types and is_nil(spec.attention_window_size) do + raise ArgumentError, "sliding attention layers require :attention_window_size" + end + end + + spec end @impl true @@ -167,6 +219,11 @@ defmodule Bumblebee.Text.Qwen3 do end @impl true + def init_cache(%{use_bidirectional_attention: true}, _batch_size, _max_length, _inputs) do + raise ArgumentError, + "decoding cache and generation are not supported with bidirectional attention" + end + def init_cache(spec, batch_size, max_length, _inputs) do Layers.Decoder.init_cache(batch_size, max_length, hidden_size: spec.hidden_size, @@ -275,7 +332,10 @@ defmodule Bumblebee.Text.Qwen3 do position_ids, inputs["attention_mask"], inputs["attention_head_mask"], - inputs["cache"], + Layers.Decoder.validate_attention_cache( + inputs["cache"], + spec.use_bidirectional_attention + ), spec, name: "decoder" ) @@ -334,6 +394,25 @@ defmodule Bumblebee.Text.Qwen3 do fn hidden_state, block -> name = block.name + layer_type = + if spec.layer_types do + Enum.fetch!(spec.layer_types, block.index) + else + if spec.attention_window_size && block.index >= spec.max_window_layers, + do: :sliding_attention, + else: :full_attention + end + + attention_window_size = + if layer_type == :sliding_attention do + radius = + if spec.use_bidirectional_attention, + do: spec.attention_window_size, + else: spec.attention_window_size - 1 + + {radius, radius} + end + shortcut = hidden_state {hidden_state, attention, self_attention_cache} = @@ -347,7 +426,8 @@ defmodule Bumblebee.Text.Qwen3 do num_key_value_heads: spec.num_key_value_heads, hidden_size: spec.hidden_size, attention_head_size: spec.attention_head_size, - causal: true, + causal: not spec.use_bidirectional_attention, + attention_window_size: attention_window_size, query_norm: qk_norm, key_norm: qk_norm, rotary_embedding: [ @@ -403,8 +483,33 @@ defmodule Bumblebee.Text.Qwen3 do def load(spec, data) do import Shared.Converters + data = + case Map.get(data, "use_sliding_window", false) do + false -> + Map.put(data, "sliding_window", nil) + + true -> + Map.put_new(data, "sliding_window", 4096) + + value -> + raise ArgumentError, + "expected use_sliding_window to be a boolean, got: #{inspect(value)}" + end + opts = convert!(data, + attention_window_size: {"sliding_window", optional(number())}, + max_window_layers: {"max_window_layers", number()}, + layer_types: + {"layer_types", + optional( + list( + mapping(%{ + "full_attention" => :full_attention, + "sliding_attention" => :sliding_attention + }) + ) + )}, vocab_size: {"vocab_size", number()}, tie_word_embeddings: {"tie_word_embeddings", boolean()}, max_positions: {"max_position_embeddings", number()}, @@ -418,6 +523,7 @@ defmodule Bumblebee.Text.Qwen3 do initializer_scale: {"initializer_range", number()}, layer_norm_epsilon: {"rms_norm_eps", number()} ) ++ + Shared.bidirectional_attention_options_from_transformers(data) ++ Shared.rotary_embedding_options_from_transformers(data) ++ Shared.common_options_from_transformers(data, spec) diff --git a/notebooks/llms_rag.livemd b/notebooks/llms_rag.livemd index 1d3bfc18..d69f7982 100644 --- a/notebooks/llms_rag.livemd +++ b/notebooks/llms_rag.livemd @@ -358,3 +358,63 @@ And here we have our answer! For additional context you can also visit the [Mistral docs](https://docs.mistral.ai/guides/rag/) that go through a similar example. + +## Embeddings from decoder models + +Gemma3Text, Llama, Mistral and Qwen3 support `use_bidirectional_attention: true`. +Loading a checkpoint reads `is_causal` (inverted) for Llama, Mistral and Qwen3, +and `use_bidirectional_attention` for Gemma3Text. The other spelling is also +accepted as a fallback. Gemma's native field takes precedence when both are +present; the other models prefer `is_causal`. All four default to causal +attention, including the `:base` architecture. + +When a checkpoint does not declare its embedding attention mode, pass it +explicitly when loading: + +```elixir +# Replace with the repository of your embedding checkpoint. +{:ok, model_info} = + Bumblebee.load_model({:hf, "organization/embedding-model"}, + architecture: :base, + spec_overrides: [use_bidirectional_attention: true] + ) +``` + +The same option works through `Bumblebee.configure/2` when constructing a spec. +Consumers that delegate checkpoint loading and inference to Bumblebee, such as +Sting, automatically use the checkpoint's declared attention mode after updating +Bumblebee. Consumers supplying their own spec must preserve this option or pass +the override above. Selecting `architecture: :base` alone does not enable it. + +Padding masks are combined with causal or bidirectional attention. Gemma's local +bidirectional layers use half the configured sliding window as their radius; +Mistral and Qwen3 use the full configured window as their bidirectional radius. +Causal windows include the current token in their width. Qwen3 also loads the +checkpoint's `use_sliding_window`, `max_window_layers` and `layer_types` settings. +Bidirectional inference requires recomputing the whole sequence. Cache inputs, +cache initialization and generation are rejected in this mode. + +RoPE configurations accept both `type` and `rope_type`, including linear, +dynamic and YaRN scaling. Unsupported variants, conflicting type keys and +invalid scaling parameters raise an error. YaRN uses the configured factor and +the current Transformers frequency blending and attention scaling formula. +Dynamic RoPE chooses its scale from the highest `position_ids` value, matching +Transformers. For padding-independent dynamic scaling, supply positions derived +from the attention mask, for example `Nx.max(Nx.cumulative_sum(mask, axis: 1) - 1, 0)`. +The default positions include padding slots, just as in Transformers; padding +that crosses the original context boundary can therefore change the scale. + +[EmbeddingGemma](https://huggingface.co/google/embeddinggemma-300m) uses a Gemma3Text +backbone, but its complete embedding pipeline additionally requires prompt +formatting, masked mean pooling, two trained Dense projections and L2 +normalization. Loading the backbone alone does not apply those projections. +Use float32 or bfloat16 for EmbeddingGemma. Its gated checkpoint integration test +can be run against an authorized local copy: + +```shell +BUMBLEBEE_EMBEDDING_GEMMA=/path/to/checkpoint mix test \ + test/bumblebee/text/embedding_gemma_integration_test.exs --include slow +``` + +That test exercises the backbone, tokenizer and pooled serving; deterministic +small-model comparisons with Python Transformers run without Hub access. diff --git a/test/bumblebee/shared_test.exs b/test/bumblebee/shared_test.exs index 6d54ff0b..7b93f633 100644 --- a/test/bumblebee/shared_test.exs +++ b/test/bumblebee/shared_test.exs @@ -96,6 +96,29 @@ defmodule Bumblebee.SharedTest do end end + describe "bidirectional_attention_options_from_transformers/1" do + test "uses is_causal when present" do + assert [use_bidirectional_attention: true] = + Shared.bidirectional_attention_options_from_transformers(%{ + "is_causal" => false, + "use_bidirectional_attention" => false + }) + end + + test "falls back to use_bidirectional_attention" do + assert [use_bidirectional_attention: true] = + Shared.bidirectional_attention_options_from_transformers(%{ + "use_bidirectional_attention" => true + }) + end + + test "rejects a non-boolean is_causal value" do + assert_raise RuntimeError, ~r/expected "is_causal" to be a boolean/, fn -> + Shared.bidirectional_attention_options_from_transformers(%{"is_causal" => "false"}) + end + end + end + describe "validate_label_options/1" do test "passes when :id_to_label is empty" do spec = %{__struct__: TestConfig, num_labels: 3, id_to_label: %{}} diff --git a/test/bumblebee/text/embedding_attention_test.exs b/test/bumblebee/text/embedding_attention_test.exs new file mode 100644 index 00000000..e80a159d --- /dev/null +++ b/test/bumblebee/text/embedding_attention_test.exs @@ -0,0 +1,173 @@ +defmodule Bumblebee.Text.EmbeddingAttentionTest do + use ExUnit.Case, async: false + + import Bumblebee.TestHelpers + + alias Bumblebee.HuggingFace.Transformers.Config + + for module <- [ + Bumblebee.Text.Gemma3Text, + Bumblebee.Text.Llama, + Bumblebee.Text.Mistral, + Bumblebee.Text.Qwen3 + ], + bidirectional <- [false, true] do + @module module + @bidirectional bidirectional + + test "#{inspect(module)} attention boundaries and padding, bidirectional=#{bidirectional}" do + spec = spec(@module, @bidirectional) + inputs = %{"input_ids" => Nx.tensor([[1, 2, 3, 4, 5, 6, 7]])} + + {init, predict} = + Axon.build(Bumblebee.build_model(spec), + compiler: EXLA, + global_layer_options: [output_attentions: true] + ) + + params = init.(inputs, Axon.ModelState.empty()) + output = predict.(params, inputs) + + radius = radius(@module, @bidirectional) + weights = elem(output.attentions, 0) |> Nx.to_flat_list() + + expected = + for _head <- 1..2, query <- 0..6, key <- 0..6 do + allowed?(query, key, radius, @bidirectional) + end + + assert Enum.map(weights, &(&1 > 0)) == expected + + if @module in [Bumblebee.Text.Gemma3Text, Bumblebee.Text.Qwen3] do + global = elem(output.attentions, 1) |> Nx.to_flat_list() + + expected_global = + for _head <- 1..2, query <- 0..6, key <- 0..6, do: @bidirectional or key <= query + + assert Enum.map(global, &(&1 > 0)) == expected_global + end + + padded = Map.put(inputs, "attention_mask", Nx.tensor([[1, 1, 1, 1, 0, 0, 0]])) + changed_padding = Map.put(padded, "input_ids", Nx.tensor([[1, 2, 3, 4, 10, 11, 12]])) + + assert_all_close( + predict.(params, padded).hidden_state[[.., 0..3, ..]], + predict.(params, changed_padding).hidden_state[[.., 0..3, ..]] + ) + + changed_future = Map.put(inputs, "input_ids", Nx.tensor([[1, 2, 3, 4, 5, 6, 8]])) + before = output.hidden_state[[.., 5, ..]] + after_change = predict.(params, changed_future).hidden_state[[.., 5, ..]] + + if @bidirectional do + refute Nx.to_number(Nx.all_close(before, after_change, atol: 1.0e-6, rtol: 1.0e-6)) == 1 + else + assert_all_close(before, after_change, atol: 1.0e-6, rtol: 1.0e-6) + end + end + end + + for module <- [ + Bumblebee.Text.Gemma3Text, + Bumblebee.Text.Llama, + Bumblebee.Text.Mistral, + Bumblebee.Text.Qwen3 + ] do + @module module + + test "#{inspect(module)} causal cache matches full inference" do + spec = spec(@module, false) + model = Bumblebee.build_model(spec) + + inputs = %{ + "input_ids" => Nx.tensor([[1, 2, 3, 4, 5, 6, 7]]), + "attention_mask" => Nx.tensor([[1, 1, 1, 1, 1, 1, 1]]) + } + + {init, predict} = Axon.build(model, compiler: EXLA) + params = init.(inputs, Axon.ModelState.empty()) + full = predict.(params, inputs) + cache = @module.init_cache(spec, 1, 7, %{}) + + prefix = + predict.(params, %{ + "input_ids" => Nx.tensor([[1, 2, 3, 4, 5, 6]]), + "attention_mask" => Nx.tensor([[1, 1, 1, 1, 1, 1]]), + "cache" => cache + }) + + last = + predict.(params, %{ + "input_ids" => Nx.tensor([[7]]), + "attention_mask" => Nx.tensor([[1]]), + "position_ids" => Nx.tensor([[6]]), + "cache" => prefix.cache + }) + + assert_all_close(last.hidden_state, full.hidden_state[[.., 6..6, ..]], + atol: 1.0e-5, + rtol: 1.0e-5 + ) + end + + test "#{inspect(module)} cached generation matches uncached greedy decoding" do + spec = + Bumblebee.configure(spec(@module, false), architecture: :for_causal_language_modeling) + + model = Bumblebee.build_model(spec) + inputs = %{"input_ids" => Nx.tensor([[1, 2]])} + {init, predict} = Axon.build(model, compiler: EXLA) + params = init.(inputs, Axon.ModelState.empty()) + + {expected, _ids} = + Enum.map_reduce(1..2, inputs["input_ids"], fn _, ids -> + logits = predict.(params, %{"input_ids" => ids}).logits + token = logits[[0, -1, ..]] |> Nx.argmax() |> Nx.to_number() + {token, Nx.concatenate([ids, Nx.tensor([[token]])], axis: 1)} + end) + + config = + Bumblebee.configure(Bumblebee.Text.GenerationConfig, max_new_tokens: 2, pad_token_id: 0) + + generate = Bumblebee.Text.Generation.build_generate(model, spec, config) + output = generate.(params, Map.put(inputs, "seed", Nx.tensor([0]))) + assert_equal(output.token_ids, Nx.tensor([expected])) + end + end + + defp allowed?(_query, _key, nil, true), do: true + defp allowed?(query, key, nil, false), do: key <= query + defp allowed?(query, key, radius, true), do: abs(query - key) <= radius + defp allowed?(query, key, radius, false), do: key <= query and query - key <= radius + + defp radius(Bumblebee.Text.Llama, _), do: nil + defp radius(Bumblebee.Text.Gemma3Text, true), do: 2 + defp radius(_, true), do: 4 + defp radius(_, false), do: 3 + + defp spec(module, bidirectional) do + data = %{ + "vocab_size" => 32, + "hidden_size" => 16, + "intermediate_size" => 20, + "num_hidden_layers" => 2, + "num_attention_heads" => 2, + "num_key_value_heads" => 1, + "head_dim" => 8, + "query_pre_attn_scalar" => 8, + "max_position_embeddings" => 16, + "sliding_window" => 4, + "use_sliding_window" => true, + "max_window_layers" => 0, + "is_causal" => not bidirectional, + "use_bidirectional_attention" => bidirectional + } + + data = + if module in [Bumblebee.Text.Gemma3Text, Bumblebee.Text.Qwen3], + do: Map.put(data, "layer_types", ["sliding_attention", "full_attention"]), + else: data + + Config.load(Bumblebee.configure(module), data) + end +end diff --git a/test/bumblebee/text/embedding_config_test.exs b/test/bumblebee/text/embedding_config_test.exs new file mode 100644 index 00000000..ac24c8ed --- /dev/null +++ b/test/bumblebee/text/embedding_config_test.exs @@ -0,0 +1,150 @@ +defmodule Bumblebee.Text.EmbeddingConfigTest do + use ExUnit.Case, async: true + + alias Bumblebee.HuggingFace.Transformers.Config + + test "Gemma prefers its native bidirectional field" do + spec = Bumblebee.configure(Bumblebee.Text.Gemma3Text) + + assert Config.load(spec, %{"is_causal" => true, "use_bidirectional_attention" => true}).use_bidirectional_attention + end + + test "Qwen3 loads sliding layers and respects the upstream enable flag" do + data = %{ + "num_hidden_layers" => 3, + "use_sliding_window" => true, + "sliding_window" => 2, + "max_window_layers" => 1 + } + + spec = Config.load(Bumblebee.configure(Bumblebee.Text.Qwen3), data) + assert spec.attention_window_size == 2 + assert spec.max_window_layers == 1 + disabled = Config.load(spec, Map.put(data, "use_sliding_window", false)) + assert disabled.attention_window_size == nil + assert Config.load(spec, Map.delete(data, "use_sliding_window")).attention_window_size == nil + assert Config.load(spec, Map.delete(data, "sliding_window")).attention_window_size == 4096 + + assert_raise ArgumentError, ~r/use_sliding_window/, fn -> + Config.load(spec, Map.put(data, "use_sliding_window", "false")) + end + + explicit = + Config.load( + spec, + Map.put(data, "layer_types", ["full_attention", "sliding_attention", "full_attention"]) + ) + + assert explicit.layer_types == [:full_attention, :sliding_attention, :full_attention] + end + + for module <- [ + Bumblebee.Text.Gemma3Text, + Bumblebee.Text.Llama, + Bumblebee.Text.Mistral, + Bumblebee.Text.Qwen3 + ] do + @module module + + test "#{inspect(module)} loads is_causal without changing the base default" do + spec = Bumblebee.configure(@module, architecture: :base) + refute Map.get(spec, :use_bidirectional_attention) + assert Config.load(spec, %{"is_causal" => false}).use_bidirectional_attention + refute Config.load(spec, %{"is_causal" => true}).use_bidirectional_attention + + assert Bumblebee.configure(spec, use_bidirectional_attention: true).use_bidirectional_attention + end + + test "#{inspect(module)} rejects bidirectional generation cache" do + spec = Config.load(Bumblebee.configure(@module), %{"is_causal" => false}) + + assert_raise ArgumentError, ~r/bidirectional/, fn -> + @module.init_cache(spec, 1, 8, %{}) + end + end + + test "#{inspect(module)} rejects a directly supplied bidirectional cache" do + spec = + @module + |> Bumblebee.configure(tiny_options(@module)) + |> Config.load(%{"is_causal" => false}) + + model = Bumblebee.build_model(spec) + + cache = + Bumblebee.Layers.Decoder.init_cache(1, 8, + hidden_size: spec.hidden_size, + attention_head_size: Map.get(spec, :attention_head_size), + decoder_num_attention_heads: spec.num_attention_heads, + decoder_num_key_value_heads: spec.num_key_value_heads, + decoder_num_blocks: spec.num_blocks + ) + + input_template = %{"input_ids" => Nx.template({1, 1}, :s64)} + {init_fun, predict_fun} = Axon.build(model, compiler: EXLA) + params = init_fun.(input_template, Axon.ModelState.empty()) + + assert_raise Axon.CompileError, ~r/bidirectional/, fn -> + predict_fun.(params, %{ + "input_ids" => Nx.tensor([[1]]), + "cache" => cache + }) + end + end + end + + defp tiny_options(Bumblebee.Text.Gemma3Text) do + [ + vocab_size: 32, + max_positions: 8, + hidden_size: 16, + intermediate_size: 20, + attention_head_size: 8, + attention_scale_base: 8, + num_blocks: 1, + num_attention_heads: 2, + num_key_value_heads: 1, + attention_window_size: 4, + layer_types: [:full_attention] + ] + end + + defp tiny_options(Bumblebee.Text.Llama) do + [ + vocab_size: 32, + max_positions: 8, + hidden_size: 16, + intermediate_size: 20, + attention_head_size: 8, + num_blocks: 1, + num_attention_heads: 2, + num_key_value_heads: 1 + ] + end + + defp tiny_options(Bumblebee.Text.Mistral) do + [ + vocab_size: 32, + max_positions: 8, + hidden_size: 16, + intermediate_size: 20, + num_blocks: 1, + num_attention_heads: 2, + num_key_value_heads: 1, + attention_window_size: 4 + ] + end + + defp tiny_options(Bumblebee.Text.Qwen3) do + [ + vocab_size: 32, + max_positions: 8, + hidden_size: 16, + intermediate_size: 20, + attention_head_size: 8, + num_blocks: 1, + num_attention_heads: 2, + num_key_value_heads: 1 + ] + end +end diff --git a/test/bumblebee/text/embedding_gemma_integration_test.exs b/test/bumblebee/text/embedding_gemma_integration_test.exs new file mode 100644 index 00000000..7c3a46e8 --- /dev/null +++ b/test/bumblebee/text/embedding_gemma_integration_test.exs @@ -0,0 +1,40 @@ +defmodule Bumblebee.Text.EmbeddingGemmaIntegrationTest do + use ExUnit.Case, async: false + + @moduletag :slow + @moduletag timeout: 600_000 + + # Opt in with BUMBLEBEE_EMBEDDING_GEMMA=/path/to/checkpoint and --include slow. + # The gated Google checkpoint must already be available locally. + if path = System.get_env("BUMBLEBEE_EMBEDDING_GEMMA") do + import Bumblebee.TestHelpers + + @path path + + test "EmbeddingGemma transformer, tokenizer and embedding serving" do + repository = {:local, @path} + assert {:ok, model_info} = Bumblebee.load_model(repository, architecture: :base) + assert model_info.spec.use_bidirectional_attention + assert {:ok, tokenizer} = Bumblebee.load_tokenizer(repository) + + serving = + Bumblebee.Text.text_embedding(model_info, tokenizer, + output_attribute: :hidden_state, + output_pool: :mean_pooling, + embedding_processor: :l2_norm + ) + + short = "task: search result | title: Example | text: A bee visits a flower." + long = "task: search result | title: Example | text: Bees collect pollen and make honey." + %{embedding: single} = Nx.Serving.run(serving, short) + [first, second] = Nx.Serving.run(serving, [short, long]) + + assert Nx.shape(single) == {model_info.spec.hidden_size} + assert_all_close(first.embedding, single, atol: 1.0e-4, rtol: 1.0e-4) + + for embedding <- [first.embedding, second.embedding] do + assert_all_close(Nx.sum(Nx.pow(embedding, 2)), Nx.tensor(1.0)) + end + end + end +end diff --git a/test/bumblebee/text/embedding_parity_test.exs b/test/bumblebee/text/embedding_parity_test.exs new file mode 100644 index 00000000..61f7a052 --- /dev/null +++ b/test/bumblebee/text/embedding_parity_test.exs @@ -0,0 +1,94 @@ +defmodule Bumblebee.Text.EmbeddingParityTest do + use ExUnit.Case, async: true + + import Bumblebee.TestHelpers + + @fixtures Path.expand("../../fixtures/embedding_models", __DIR__) + # Float32 CPU reductions differ slightly between PyTorch and XLA. 1e-4 + # leaves room for rounding while detecting mask and RoPE formula errors. + @models ~w(gemma3_text llama mistral qwen3 qwen3_linear qwen3_dynamic) + + for name <- @models, mode <- ~w(causal bidirectional) do + @name name + @mode mode + + test "#{name} #{@mode} matches Transformers hidden states" do + {model, params, reference} = load_fixture(@name, @mode) + + outputs = + Axon.predict(model, params, %{ + "input_ids" => Nx.tensor(reference["input_ids"]), + "attention_mask" => Nx.tensor(reference["attention_mask"]) + }) + + assert_all_close(outputs.hidden_state, Nx.tensor(reference["hidden_state"]), atol: 1.0e-4) + + changed_outputs = + Axon.predict(model, params, %{ + "input_ids" => Nx.tensor([[1, 2, 3, 4, 5, 6, 7, 9]]), + "attention_mask" => Nx.tensor(reference["attention_mask"]) + }) + + assert_all_close( + changed_outputs.hidden_state, + Nx.tensor(reference["changed_future_hidden_state"]), + atol: 1.0e-4 + ) + + padded_outputs = + Axon.predict(model, params, %{ + "input_ids" => Nx.tensor(reference["padded_input_ids"]), + "attention_mask" => Nx.tensor(reference["padded_attention_mask"]), + "position_ids" => Nx.tensor(reference["padded_position_ids"]) + }) + + assert_all_close( + padded_outputs.hidden_state, + Nx.tensor(reference["padded_hidden_state"]), + atol: 1.0e-4 + ) + + compact_outputs = + Axon.predict(model, params, %{ + "input_ids" => Nx.tensor([[1, 2, 3, 4]]), + "attention_mask" => Nx.tensor([[1, 1, 1, 1]]) + }) + + assert_all_close(compact_outputs.hidden_state, Nx.tensor(reference["compact_hidden_state"]), + atol: 1.0e-4, + rtol: 1.0e-4 + ) + + assert_all_close( + padded_outputs.hidden_state[[.., 0..3, ..]], + compact_outputs.hidden_state, + atol: 1.0e-4 + ) + + first_token_changed? = + outputs.hidden_state[[.., 0, ..]] + |> Nx.all_close( + changed_outputs.hidden_state[[.., 0, ..]], + atol: 1.0e-6, + rtol: 1.0e-6 + ) + |> Nx.to_number() == 0 + + assert first_token_changed? == (@mode == "bidirectional") + end + end + + defp load_fixture(name, mode) do + path = Path.join(@fixtures, "tiny-random-#{name}-#{mode}") + reference = path |> Path.join("reference.json") |> File.read!() |> Jason.decode!() + + assert {:ok, %{model: model, params: params, spec: spec}} = + Bumblebee.load_model({:local, path}) + + assert reference["transformers_version"] == "5.19.0.dev0" + assert reference["transformers_commit"] == "3693f8d26311305e914735a6373fb03468d6aaa0" + assert spec.use_bidirectional_attention == (mode == "bidirectional") + + {model, params, reference} + end +end diff --git a/test/fixtures/embedding_models/generate.py b/test/fixtures/embedding_models/generate.py new file mode 100644 index 00000000..03151063 --- /dev/null +++ b/test/fixtures/embedding_models/generate.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python3 +"""Generate deterministic embedding-model parity fixtures. + +Requires Python 3.10+, torch 2.7.1 and Transformers commit +3693f8d26311305e914735a6373fb03468d6aaa0. Install it with: + + pip install torch==2.7.1 \ + git+https://github.com/huggingface/transformers.git@3693f8d26311305e914735a6373fb03468d6aaa0 + +The generated directories are ordinary local Hugging Face repositories, so +they can be loaded by Bumblebee with {:local, path}. `reference.json` contains +float32 hidden states from the same checkpoint and is intentionally kept +separate from the checkpoint to make an update to either reviewable. +""" + +import argparse +import copy +import json +from pathlib import Path + +import torch +import transformers +from transformers import ( + Gemma3TextConfig, + Gemma3TextModel, + LlamaConfig, + LlamaModel, + MistralConfig, + MistralModel, + Qwen3Config, + Qwen3Model, +) + + +torch.manual_seed(0) +torch.set_printoptions(precision=9) + +INPUT_IDS = torch.tensor([[1, 2, 3, 4, 5, 6, 7, 8]]) +CHANGED_FUTURE_IDS = torch.tensor([[1, 2, 3, 4, 5, 6, 7, 9]]) +PADDED_IDS = torch.tensor([[1, 2, 3, 4, 0, 0, 0, 0]]) +FULL_MASK = torch.ones_like(INPUT_IDS) +PADDED_MASK = torch.tensor([[1, 1, 1, 1, 0, 0, 0, 0]]) + + +def common_kwargs(): + return { + "vocab_size": 32, + "hidden_size": 16, + "intermediate_size": 20, + "num_hidden_layers": 2, + "num_attention_heads": 2, + "num_key_value_heads": 1, + "head_dim": 8, + "max_position_embeddings": 4, + "rms_norm_eps": 1.0e-6, + "pad_token_id": 0, + "tie_word_embeddings": False, + } + + +def model_definitions(): + common = common_kwargs() + + return { + "gemma3_text": ( + Gemma3TextConfig, + Gemma3TextModel, + { + **common, + "hidden_activation": "gelu_pytorch_tanh", + "query_pre_attn_scalar": 8, + "sliding_window": 4, + "layer_types": ["sliding_attention", "full_attention"], + "rope_parameters": { + "full_attention": { + "rope_type": "yarn", + "factor": 2.0, + "original_max_position_embeddings": 4, + "beta_fast": 32.0, + "beta_slow": 1.0, + }, + "sliding_attention": {"rope_theta": 10_000.0}, + }, + }, + ), + "llama": (LlamaConfig, LlamaModel, {**common, "rope_theta": 10_000.0}), + "mistral": ( + MistralConfig, + MistralModel, + {**common, "rope_theta": 10_000.0, "sliding_window": 4}, + ), + "qwen3": ( + Qwen3Config, + Qwen3Model, + { + **common, + "rope_theta": 10_000.0, + "use_sliding_window": True, + "sliding_window": 4, + "max_window_layers": 1, + "rope_scaling": { + "rope_type": "yarn", + "factor": 2.0, + "original_max_position_embeddings": 4, + "beta_fast": 32.0, + "beta_slow": 1.0, + }, + }, + ), + # Exercise both accepted serialized spellings. These inputs are longer + # than max_position_embeddings, so changing the scaling cannot be a + # no-op in the generated reference. + "qwen3_linear": ( + Qwen3Config, + Qwen3Model, + { + **common, + "rope_theta": 10_000.0, + "rope_scaling": {"type": "linear", "factor": 2.0}, + }, + ), + "qwen3_dynamic": ( + Qwen3Config, + Qwen3Model, + { + **common, + "rope_theta": 10_000.0, + "rope_scaling": {"rope_type": "dynamic", "factor": 2.0}, + }, + ), + } + + +def tensor(value): + return value.detach().to(torch.float32).cpu().tolist() + + +def evaluate(model, input_ids, attention_mask, position_ids=None): + # Dynamic RoPE caches its frequency state. Each reference represents an + # independent inference so prior long inputs must not affect short ones. + model = copy.deepcopy(model) + with torch.no_grad(): + return tensor(model(input_ids=input_ids, attention_mask=attention_mask, + position_ids=position_ids).last_hidden_state) + + +def write_fixture(output_dir, name, config_class, model_class, kwargs, is_causal): + directory = output_dir / f"tiny-random-{name}-{'causal' if is_causal else 'bidirectional'}" + # Gemma normalizes its local window in __post_init__, so these flags must + # be present during construction rather than assigned afterward. + attention_mode = ( + {"use_bidirectional_attention": not is_causal} + if name == "gemma3_text" + else {"is_causal": is_causal} + ) + config = config_class(**kwargs, **attention_mode, _attn_implementation="eager") + + model = model_class(config).eval() + model.save_pretrained(directory, safe_serialization=True) + + # Compare against exactly the serialized checkpoint configuration. This + # catches model-specific config normalization (notably Gemma's window). + config = config_class.from_pretrained(directory) + model = model_class.from_pretrained(directory, attn_implementation="eager").eval() + + reference = { + "transformers_version": transformers.__version__, + "transformers_commit": "3693f8d26311305e914735a6373fb03468d6aaa0", + "is_causal": is_causal, + "input_ids": INPUT_IDS.tolist(), + "attention_mask": FULL_MASK.tolist(), + "hidden_state": evaluate(model, INPUT_IDS, FULL_MASK), + "changed_future_hidden_state": evaluate(model, CHANGED_FUTURE_IDS, FULL_MASK), + "padded_input_ids": PADDED_IDS.tolist(), + "padded_attention_mask": PADDED_MASK.tolist(), + "padded_position_ids": [[0, 1, 2, 3, 0, 0, 0, 0]], + "padded_hidden_state": evaluate(model, PADDED_IDS, PADDED_MASK, + torch.tensor([[0, 1, 2, 3, 0, 0, 0, 0]])), + "compact_hidden_state": evaluate(model, INPUT_IDS[:, :4], FULL_MASK[:, :4]), + } + + (directory / "reference.json").write_text(json.dumps(reference, indent=2) + "\n") + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--output", type=Path, default=Path(__file__).parent) + args = parser.parse_args() + args.output.mkdir(parents=True, exist_ok=True) + + for name, (config_class, model_class, kwargs) in model_definitions().items(): + for is_causal in (True, False): + write_fixture(args.output, name, config_class, model_class, kwargs, is_causal) + + +if __name__ == "__main__": + main() diff --git a/test/fixtures/embedding_models/tiny-random-gemma3_text-bidirectional/config.json b/test/fixtures/embedding_models/tiny-random-gemma3_text-bidirectional/config.json new file mode 100644 index 00000000..d55cd358 --- /dev/null +++ b/test/fixtures/embedding_models/tiny-random-gemma3_text-bidirectional/config.json @@ -0,0 +1,50 @@ +{ + "_sliding_window_pattern": 6, + "architectures": [ + "Gemma3TextModel" + ], + "attention_bias": false, + "attention_dropout": 0.0, + "attn_logit_softcapping": null, + "bos_token_id": 2, + "dtype": "float32", + "eos_token_id": 1, + "final_logit_softcapping": null, + "head_dim": 8, + "hidden_activation": "gelu_pytorch_tanh", + "hidden_size": 16, + "initializer_range": 0.02, + "intermediate_size": 20, + "layer_types": [ + "sliding_attention", + "full_attention" + ], + "max_position_embeddings": 4, + "model_type": "gemma3_text", + "num_attention_heads": 2, + "num_hidden_layers": 2, + "num_key_value_heads": 1, + "pad_token_id": 0, + "query_pre_attn_scalar": 8, + "rms_norm_eps": 1e-06, + "rope_parameters": { + "full_attention": { + "beta_fast": 32.0, + "beta_slow": 1.0, + "factor": 2.0, + "original_max_position_embeddings": 4, + "rope_theta": 1000000.0, + "rope_type": "yarn" + }, + "sliding_attention": { + "rope_theta": 10000.0, + "rope_type": "default" + } + }, + "sliding_window": 4, + "tie_word_embeddings": false, + "transformers_version": "5.19.0.dev0", + "use_bidirectional_attention": true, + "use_cache": true, + "vocab_size": 32 +} diff --git a/test/fixtures/embedding_models/tiny-random-gemma3_text-bidirectional/model.safetensors b/test/fixtures/embedding_models/tiny-random-gemma3_text-bidirectional/model.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..2d0eea3f39beb727cfcdd57cd8b9ca66984d039c GIT binary patch literal 19224 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 aCn*`&Rp!WO*3SbgQN)^TeezHBxBmrL+PM7y literal 0 HcmV?d00001 diff --git a/test/fixtures/embedding_models/tiny-random-llama-causal/reference.json b/test/fixtures/embedding_models/tiny-random-llama-causal/reference.json new file mode 100644 index 00000000..0d7cb8a8 --- /dev/null +++ b/test/fixtures/embedding_models/tiny-random-llama-causal/reference.json @@ -0,0 +1,585 @@ +{ + "transformers_version": "5.19.0.dev0", + "transformers_commit": "3693f8d26311305e914735a6373fb03468d6aaa0", + "is_causal": true, + "input_ids": [ + [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 + ] + ], + "attention_mask": [ + [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ] + ], + "hidden_state": [ + [ + [ + -1.5929151773452759, + -0.6003653407096863, + -0.5094078779220581, + -0.962164044380188, + -0.31567907333374023, + 0.630582869052887, + -1.6334172487258911, + 1.6027878522872925, + 0.23477952182292938, + -0.8364869952201843, + 0.15759843587875366, + 0.7943824529647827, + -0.2593148350715637, + 0.10758619755506516, + -0.7669921517372131, + 2.0198476314544678 + ], + [ + 0.6898882985115051, + -1.389062523841858, + -1.0428372621536255, + -0.7545837759971619, + -0.6884869933128357, + 1.1694477796554565, + -0.8826923370361328, + -0.11817003786563873, + 1.098335862159729, + 0.7683865427970886, + -0.7247151732444763, + 0.6575729846954346, + 1.129040002822876, + 1.5497493743896484, + 0.1274891495704651, + 1.681316614151001 + ], + [ + 0.3429621756076813, + 1.7419458627700806, + -0.753235936164856, + -0.4981689453125, + -0.9175847172737122, + 0.5624348521232605, + -1.3638721704483032, + 0.9257065653800964, + 1.6528384685516357, + -0.3569645881652832, + -1.5816876888275146, + 0.03878334164619446, + -0.8804912567138672, + 1.0846880674362183, + -0.3427111506462097, + 0.8187417387962341 + ], + [ + -0.44830402731895447, + -0.21460671722888947, + 0.12261118739843369, + -0.43910181522369385, + -1.4307810068130493, + -0.08696458488702774, + 0.27569085359573364, + 0.3632393479347229, + 0.33360517024993896, + -1.5959644317626953, + 0.3499789834022522, + 2.512471914291382, + 1.274120569229126, + 1.333441972732544, + 0.22759853303432465, + 0.8352688550949097 + ], + [ + -0.37356293201446533, + 0.16278886795043945, + -0.9381667375564575, + 0.32777032256126404, + -1.333550214767456, + 0.5953577756881714, + 0.29960277676582336, + -1.2891823053359985, + -0.004067094996571541, + 1.309119701385498, + -0.9793269038200378, + 0.5088264346122742, + -1.743228554725647, + 0.5554646253585815, + -0.9512976408004761, + 1.937324047088623 + ], + [ + 0.9740347266197205, + -0.020724942907691002, + 0.0052393702790141106, + 1.4428623914718628, + -0.9838392734527588, + -1.3757606744766235, + -1.9937610626220703, + -1.9541552066802979, + 0.011807242408394814, + -0.8277478218078613, + -0.2320166528224945, + 0.4832310974597931, + -0.8893502354621887, + -0.1255970150232315, + 0.5280473828315735, + -0.48376184701919556 + ], + [ + -0.5678181052207947, + 2.4606494903564453, + -0.29888927936553955, + -0.05167769640684128, + -0.929226279258728, + -0.966411828994751, + -0.23025651276111603, + 0.8395761847496033, + 0.4954826533794403, + 0.385222464799881, + -0.8163310885429382, + 0.3191235363483429, + 0.9865652918815613, + 1.9905973672866821, + -0.7614292502403259, + 0.5184648633003235 + ], + [ + -1.1133098602294922, + 0.7935789227485657, + -0.24836866557598114, + -0.7486827373504639, + 0.8966212272644043, + 1.3970950841903687, + 0.5570847988128662, + -1.355514407157898, + -0.037265222519636154, + 1.4263502359390259, + -1.3563772439956665, + -0.13238456845283508, + -0.6878980398178101, + -0.2922036051750183, + -1.9965641498565674, + -0.36700403690338135 + ] + ] + ], + "changed_future_hidden_state": [ + [ + [ + -1.5929151773452759, + -0.6003653407096863, + -0.5094078779220581, + -0.962164044380188, + -0.31567907333374023, + 0.630582869052887, + -1.6334172487258911, + 1.6027878522872925, + 0.23477952182292938, + -0.8364869952201843, + 0.15759843587875366, + 0.7943824529647827, + -0.2593148350715637, + 0.10758619755506516, + -0.7669921517372131, + 2.0198476314544678 + ], + [ + 0.6898882985115051, + -1.389062523841858, + -1.0428372621536255, + -0.7545837759971619, + -0.6884869933128357, + 1.1694477796554565, + -0.8826923370361328, + -0.11817003786563873, + 1.098335862159729, + 0.7683865427970886, + -0.7247151732444763, + 0.6575729846954346, + 1.129040002822876, + 1.5497493743896484, + 0.1274891495704651, + 1.681316614151001 + ], + [ + 0.3429621756076813, + 1.7419458627700806, + -0.753235936164856, + -0.4981689453125, + -0.9175847172737122, + 0.5624348521232605, + -1.3638721704483032, + 0.9257065653800964, + 1.6528384685516357, + -0.3569645881652832, + -1.5816876888275146, + 0.03878334164619446, + -0.8804912567138672, + 1.0846880674362183, + -0.3427111506462097, + 0.8187417387962341 + ], + [ + -0.44830402731895447, + -0.21460671722888947, + 0.12261118739843369, + -0.43910181522369385, + -1.4307810068130493, + -0.08696458488702774, + 0.27569085359573364, + 0.3632393479347229, + 0.33360517024993896, + -1.5959644317626953, + 0.3499789834022522, + 2.512471914291382, + 1.274120569229126, + 1.333441972732544, + 0.22759853303432465, + 0.8352688550949097 + ], + [ + -0.37356293201446533, + 0.16278886795043945, + -0.9381667375564575, + 0.32777032256126404, + -1.333550214767456, + 0.5953577756881714, + 0.29960277676582336, + -1.2891823053359985, + -0.004067094996571541, + 1.309119701385498, + -0.9793269038200378, + 0.5088264346122742, + -1.743228554725647, + 0.5554646253585815, + -0.9512976408004761, + 1.937324047088623 + ], + [ + 0.9740347266197205, + -0.020724942907691002, + 0.0052393702790141106, + 1.4428623914718628, + -0.9838392734527588, + -1.3757606744766235, + -1.9937610626220703, + -1.9541552066802979, + 0.011807242408394814, + -0.8277478218078613, + -0.2320166528224945, + 0.4832310974597931, + -0.8893502354621887, + -0.1255970150232315, + 0.5280473828315735, + -0.48376184701919556 + ], + [ + -0.5678181052207947, + 2.4606494903564453, + -0.29888927936553955, + -0.05167769640684128, + -0.929226279258728, + -0.966411828994751, + -0.23025651276111603, + 0.8395761847496033, + 0.4954826533794403, + 0.385222464799881, + -0.8163310885429382, + 0.3191235363483429, + 0.9865652918815613, + 1.9905973672866821, + -0.7614292502403259, + 0.5184648633003235 + ], + [ + -0.1458314061164856, + 2.203958034515381, + 0.3634493947029114, + -0.3175545632839203, + 0.4547146260738373, + -0.8177770376205444, + -0.8347190618515015, + 0.25345662236213684, + -0.259469598531723, + -1.5115933418273926, + 0.21156080067157745, + 1.0331226587295532, + 0.6968410611152649, + 1.5568182468414307, + 1.6687116622924805, + -0.2433205097913742 + ] + ] + ], + "padded_input_ids": [ + [ + 1, + 2, + 3, + 4, + 0, + 0, + 0, + 0 + ] + ], + "padded_attention_mask": [ + [ + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0 + ] + ], + "padded_position_ids": [ + [ + 0, + 1, + 2, + 3, + 0, + 0, + 0, + 0 + ] + ], + "padded_hidden_state": [ + [ + [ + -1.5929151773452759, + -0.6003653407096863, + -0.5094078779220581, + -0.962164044380188, + -0.31567907333374023, + 0.630582869052887, + -1.6334172487258911, + 1.6027878522872925, + 0.23477952182292938, + -0.8364869952201843, + 0.15759843587875366, + 0.7943824529647827, + -0.2593148350715637, + 0.10758619755506516, + -0.7669921517372131, + 2.0198476314544678 + ], + [ + 0.6898882985115051, + -1.389062523841858, + -1.0428372621536255, + -0.7545837759971619, + -0.6884869933128357, + 1.1694477796554565, + -0.8826923370361328, + -0.11817003786563873, + 1.098335862159729, + 0.7683865427970886, + -0.7247151732444763, + 0.6575729846954346, + 1.129040002822876, + 1.5497493743896484, + 0.1274891495704651, + 1.681316614151001 + ], + [ + 0.3429621756076813, + 1.7419458627700806, + -0.753235936164856, + -0.4981689453125, + -0.9175847172737122, + 0.5624348521232605, + -1.3638721704483032, + 0.9257065653800964, + 1.6528384685516357, + -0.3569645881652832, + -1.5816876888275146, + 0.03878334164619446, + -0.8804912567138672, + 1.0846880674362183, + -0.3427111506462097, + 0.8187417387962341 + ], + [ + -0.44830402731895447, + -0.21460671722888947, + 0.12261118739843369, + -0.43910181522369385, + -1.4307810068130493, + -0.08696458488702774, + 0.27569085359573364, + 0.3632393479347229, + 0.33360517024993896, + -1.5959644317626953, + 0.3499789834022522, + 2.512471914291382, + 1.274120569229126, + 1.333441972732544, + 0.22759853303432465, + 0.8352688550949097 + ], + [ + 0.44188886880874634, + 0.5267016887664795, + 0.7889223098754883, + -1.126582145690918, + -0.9818824529647827, + 0.6240435838699341, + -1.705146074295044, + -0.6350654363632202, + 2.041469097137451, + -0.3892385959625244, + -0.29268360137939453, + 0.5754352807998657, + 0.6632300019264221, + 0.5014443397521973, + -1.6303359270095825, + 0.7556922435760498 + ], + [ + 0.44188886880874634, + 0.5267016887664795, + 0.7889223098754883, + -1.126582145690918, + -0.9818824529647827, + 0.6240435838699341, + -1.705146074295044, + -0.6350654363632202, + 2.041469097137451, + -0.3892385959625244, + -0.29268360137939453, + 0.5754352807998657, + 0.6632300019264221, + 0.5014443397521973, + -1.6303359270095825, + 0.7556922435760498 + ], + [ + 0.44188886880874634, + 0.5267016887664795, + 0.7889223098754883, + -1.126582145690918, + -0.9818824529647827, + 0.6240435838699341, + -1.705146074295044, + -0.6350654363632202, + 2.041469097137451, + -0.3892385959625244, + -0.29268360137939453, + 0.5754352807998657, + 0.6632300019264221, + 0.5014443397521973, + -1.6303359270095825, + 0.7556922435760498 + ], + [ + 0.44188886880874634, + 0.5267016887664795, + 0.7889223098754883, + -1.126582145690918, + -0.9818824529647827, + 0.6240435838699341, + -1.705146074295044, + -0.6350654363632202, + 2.041469097137451, + -0.3892385959625244, + -0.29268360137939453, + 0.5754352807998657, + 0.6632300019264221, + 0.5014443397521973, + -1.6303359270095825, + 0.7556922435760498 + ] + ] + ], + "compact_hidden_state": [ + [ + [ + -1.5929151773452759, + -0.6003653407096863, + -0.5094078779220581, + -0.962164044380188, + -0.31567907333374023, + 0.630582869052887, + -1.6334172487258911, + 1.6027878522872925, + 0.23477952182292938, + -0.8364869952201843, + 0.15759843587875366, + 0.7943824529647827, + -0.2593148350715637, + 0.10758619755506516, + -0.7669921517372131, + 2.0198476314544678 + ], + [ + 0.6898882985115051, + -1.389062523841858, + -1.0428372621536255, + -0.7545837759971619, + -0.6884869933128357, + 1.1694477796554565, + -0.8826923370361328, + -0.11817003786563873, + 1.098335862159729, + 0.7683865427970886, + -0.7247151732444763, + 0.6575729846954346, + 1.129040002822876, + 1.5497493743896484, + 0.1274891495704651, + 1.681316614151001 + ], + [ + 0.3429621756076813, + 1.7419458627700806, + -0.753235936164856, + -0.4981689453125, + -0.9175847172737122, + 0.5624348521232605, + -1.3638721704483032, + 0.9257065653800964, + 1.6528384685516357, + -0.3569645881652832, + -1.5816876888275146, + 0.03878334164619446, + -0.8804912567138672, + 1.0846880674362183, + -0.3427111506462097, + 0.8187417387962341 + ], + [ + -0.44830402731895447, + -0.21460671722888947, + 0.12261118739843369, + -0.43910181522369385, + -1.4307810068130493, + -0.08696458488702774, + 0.27569085359573364, + 0.3632393479347229, + 0.33360517024993896, + -1.5959644317626953, + 0.3499789834022522, + 2.512471914291382, + 1.274120569229126, + 1.333441972732544, + 0.22759853303432465, + 0.8352688550949097 + ] + ] + ] +} diff --git a/test/fixtures/embedding_models/tiny-random-mistral-bidirectional/config.json b/test/fixtures/embedding_models/tiny-random-mistral-bidirectional/config.json new file mode 100644 index 00000000..a5325087 --- /dev/null +++ b/test/fixtures/embedding_models/tiny-random-mistral-bidirectional/config.json @@ -0,0 +1,31 @@ +{ + "architectures": [ + "MistralModel" + ], + "attention_dropout": 0.0, + "bos_token_id": 1, + "dtype": "float32", + "eos_token_id": 2, + "head_dim": 8, + "hidden_act": "silu", + "hidden_size": 16, + "initializer_range": 0.02, + "intermediate_size": 20, + "is_causal": false, + "max_position_embeddings": 4, + "model_type": "mistral", + "num_attention_heads": 2, + "num_hidden_layers": 2, + "num_key_value_heads": 1, + "pad_token_id": 0, + "rms_norm_eps": 1e-06, + "rope_parameters": { + "rope_theta": 10000.0, + "rope_type": "default" + }, + "sliding_window": 4, + "tie_word_embeddings": false, + "transformers_version": "5.19.0.dev0", + "use_cache": true, + "vocab_size": 32 +} diff --git a/test/fixtures/embedding_models/tiny-random-mistral-bidirectional/model.safetensors b/test/fixtures/embedding_models/tiny-random-mistral-bidirectional/model.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..b503051b37faac85b9cdab93267b54e1468273fb GIT binary patch literal 18072 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 O;3TZ(WB+OV@V@}u%Kv2m literal 0 HcmV?d00001 diff --git a/test/fixtures/embedding_models/tiny-random-mistral-bidirectional/reference.json b/test/fixtures/embedding_models/tiny-random-mistral-bidirectional/reference.json new file mode 100644 index 00000000..1b8ade08 --- /dev/null +++ b/test/fixtures/embedding_models/tiny-random-mistral-bidirectional/reference.json @@ -0,0 +1,585 @@ +{ + "transformers_version": "5.19.0.dev0", + "transformers_commit": "3693f8d26311305e914735a6373fb03468d6aaa0", + "is_causal": false, + "input_ids": [ + [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 + ] + ], + "attention_mask": [ + [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ] + ], + "hidden_state": [ + [ + [ + -2.0247020721435547, + -0.012201372534036636, + 1.7035696506500244, + 0.7370375990867615, + -0.5783039927482605, + 0.1447124183177948, + 0.8927332758903503, + -1.554565668106079, + -0.6524656414985657, + 1.125311017036438, + 1.5565158128738403, + -0.07736732810735703, + 0.17577055096626282, + -0.4254700839519501, + 0.1328285038471222, + 0.7147100567817688 + ], + [ + -1.5079776048660278, + -2.021573066711426, + 0.7333519458770752, + -0.6778014898300171, + 1.222817301750183, + -0.4644806683063507, + 0.8939060568809509, + -1.1685874462127686, + 0.6928260922431946, + -0.6972037553787231, + 0.6837774515151978, + -0.6337920427322388, + 1.283979058265686, + 0.8037490248680115, + 0.4375670850276947, + 0.6400811672210693 + ], + [ + 0.7522222995758057, + -2.4407713413238525, + -0.6910439133644104, + 0.06596823781728745, + -0.4407411813735962, + -1.1143351793289185, + 0.40500980615615845, + 1.4900282621383667, + -1.0456336736679077, + 0.1007714569568634, + -0.9451706409454346, + -1.172706127166748, + 0.7552176713943481, + 0.8097615838050842, + -0.22225351631641388, + 0.6885299682617188 + ], + [ + 0.6646749377250671, + -0.6112914085388184, + 0.5806158185005188, + 0.2580931782722473, + -1.8095028400421143, + -0.8893306851387024, + 0.02545849420130253, + -0.02969667688012123, + 1.3413195610046387, + 0.2543677091598511, + 0.19161836802959442, + 0.28271499276161194, + 2.297266960144043, + 1.3095048666000366, + -1.2959986925125122, + -0.1208648830652237 + ], + [ + 0.7496078014373779, + -2.2097177505493164, + -0.7815321683883667, + 0.4869077801704407, + -0.10121357440948486, + 0.2663804590702057, + -1.069189190864563, + -0.5793210864067078, + 0.8195260167121887, + -0.9879010915756226, + 1.2082843780517578, + -1.1771281957626343, + -0.6697749495506287, + 1.5572588443756104, + -0.7321873903274536, + 0.45191946625709534 + ], + [ + -0.15355224907398224, + -1.1929396390914917, + 0.20983542501926422, + -0.8824790716171265, + 1.554892659187317, + -0.728230893611908, + 1.9105623960494995, + -0.5609907507896423, + -1.7941912412643433, + 1.1221245527267456, + -0.6664549708366394, + -0.9410739541053772, + -0.6750085353851318, + 0.22097043693065643, + -0.6755238175392151, + 0.12003744393587112 + ], + [ + -0.8482521772384644, + -0.062093254178762436, + 0.727107048034668, + 2.3487868309020996, + -1.2736424207687378, + -0.32234397530555725, + -0.1389290988445282, + -0.22715575993061066, + 0.7971732020378113, + -0.8311808705329895, + -0.6845999360084534, + 1.0399690866470337, + 1.7368683815002441, + -0.7837607860565186, + 0.5346148610115051, + 0.7268665432929993 + ], + [ + 0.267392635345459, + 0.0448216013610363, + 0.07543287426233292, + 1.5457935333251953, + 0.4062495529651642, + -0.1640452891588211, + -0.8455737829208374, + -1.2664391994476318, + 0.9405146241188049, + -0.524522066116333, + -0.1804894506931305, + -2.6236255168914795, + -0.05992063879966736, + -1.1540672779083252, + 1.1948506832122803, + 0.36509034037590027 + ] + ] + ], + "changed_future_hidden_state": [ + [ + [ + -2.0353455543518066, + -0.009777919389307499, + 1.7037909030914307, + 0.7331627011299133, + -0.5816856026649475, + 0.1446327120065689, + 0.8884427547454834, + -1.5551533699035645, + -0.6485012769699097, + 1.1244816780090332, + 1.5519068241119385, + -0.07203176617622375, + 0.17506134510040283, + -0.4227631986141205, + 0.1347687989473343, + 0.706200897693634 + ], + [ + -1.5273430347442627, + -2.0181384086608887, + 0.7364054322242737, + -0.6806715130805969, + 1.216414213180542, + -0.4635556936264038, + 0.886526346206665, + -1.170629620552063, + 0.6995099186897278, + -0.6974316835403442, + 0.6749190092086792, + -0.6280335187911987, + 1.2805250883102417, + 0.8086708784103394, + 0.4403485357761383, + 0.6240567564964294 + ], + [ + 0.7175267934799194, + -2.4465043544769287, + -0.6843821406364441, + 0.06272272020578384, + -0.45572224259376526, + -1.1230920553207397, + 0.3993740975856781, + 1.4922150373458862, + -1.0365406274795532, + 0.10133982449769974, + -0.968696653842926, + -1.1672077178955078, + 0.7489297389984131, + 0.825299084186554, + -0.21780666708946228, + 0.6662425398826599 + ], + [ + 0.628162682056427, + -0.6684461236000061, + 0.5838244557380676, + 0.21614059805870056, + -1.7899967432022095, + -0.8198503851890564, + -0.21753622591495514, + -0.021028436720371246, + 1.5345687866210938, + 0.1504795253276825, + 0.20272524654865265, + 0.3116346597671509, + 2.219223737716675, + 1.364264726638794, + -1.2181761264801025, + -0.1361822932958603 + ], + [ + 0.7046382427215576, + -2.1784708499908447, + -0.7131818532943726, + 0.4324449896812439, + -0.16237497329711914, + 0.27515873312950134, + -1.2362092733383179, + -0.5422430038452148, + 1.0155054330825806, + -1.0187900066375732, + 1.1623311042785645, + -1.0775691270828247, + -0.6002969741821289, + 1.590712308883667, + -0.6781668066978455, + 0.4117414951324463 + ], + [ + -0.17539867758750916, + -1.370245337486267, + 0.2588801085948944, + -0.9761856198310852, + 1.5842220783233643, + -0.753889262676239, + 1.7800787687301636, + -0.5911240577697754, + -1.6404273509979248, + 1.1025878190994263, + -0.6935837864875793, + -0.9677101373672485, + -0.6832735538482666, + 0.37043076753616333, + -0.7044968605041504, + 0.10762422531843185 + ], + [ + -0.7835953831672668, + -0.2401110827922821, + 0.7416219115257263, + 2.136293888092041, + -1.3266798257827759, + -0.23845501244068146, + -0.6135538816452026, + -0.199204221367836, + 1.2656277418136597, + -0.9655046463012695, + -0.6081408262252808, + 1.0705150365829468, + 1.7072529792785645, + -0.48098939657211304, + 0.5165702700614929, + 0.6487212181091309 + ], + [ + -1.8421461582183838, + 1.15996515750885, + 0.6344616413116455, + -0.8227241635322571, + 0.9418267607688904, + -1.3762634992599487, + 0.13901816308498383, + -0.8082731366157532, + 0.34216225147247314, + -0.1821904480457306, + -0.3073679208755493, + -0.027936596423387527, + 1.023556113243103, + 2.2654120922088623, + 0.4819644093513489, + 0.1678839474916458 + ] + ] + ], + "padded_input_ids": [ + [ + 1, + 2, + 3, + 4, + 0, + 0, + 0, + 0 + ] + ], + "padded_attention_mask": [ + [ + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0 + ] + ], + "padded_position_ids": [ + [ + 0, + 1, + 2, + 3, + 0, + 0, + 0, + 0 + ] + ], + "padded_hidden_state": [ + [ + [ + -2.024979591369629, + 0.00422435300424695, + 1.6957898139953613, + 0.7697137594223022, + -0.6883586645126343, + 0.11442556977272034, + 0.7328180074691772, + -1.5748454332351685, + -0.5792887806892395, + 1.0610051155090332, + 1.6441532373428345, + -0.06880106776952744, + 0.17206580936908722, + -0.3806779682636261, + 0.17469821870326996, + 0.7253968119621277 + ], + [ + -1.574650526046753, + -1.9975262880325317, + 0.6534299254417419, + -0.642878532409668, + 1.156783938407898, + -0.6467214822769165, + 0.7542971968650818, + -1.1479636430740356, + 0.8172124028205872, + -0.7986409068107605, + 0.671444296836853, + -0.5100952982902527, + 1.3076112270355225, + 0.8520255088806152, + 0.43006426095962524, + 0.6130269765853882 + ], + [ + 0.5974754691123962, + -2.4806430339813232, + -0.6777498722076416, + 0.07211479544639587, + -0.5010150074958801, + -1.263437032699585, + 0.21863402426242828, + 1.4749866724014282, + -0.8187174797058105, + -0.030426712706685066, + -0.9761536121368408, + -1.1424365043640137, + 0.7796595096588135, + 0.9137669801712036, + -0.23002482950687408, + 0.6912825703620911 + ], + [ + 0.5695361495018005, + -0.7074604630470276, + 0.5785335302352905, + 0.26793089509010315, + -1.741084098815918, + -0.9064237475395203, + -0.27818211913108826, + -0.06530818343162537, + 1.5608278512954712, + 0.10034053027629852, + 0.18459738790988922, + 0.2896520495414734, + 2.228212833404541, + 1.3797621726989746, + -1.1619044542312622, + -0.10607702285051346 + ], + [ + -1.473647117614746, + -1.2038339376449585, + 1.2881907224655151, + 0.3939710557460785, + -0.05986154079437256, + -0.6614582538604736, + -0.9326079487800598, + -0.9152061343193054, + 2.1059892177581787, + -0.34020259976387024, + -0.6582565307617188, + 0.17788299918174744, + 1.24713134765625, + 1.0128247737884521, + -0.3762119710445404, + -0.35254669189453125 + ], + [ + -1.9578449726104736, + -0.8402428030967712, + 1.8692209720611572, + 0.32894837856292725, + -0.3004555404186249, + -0.5150565505027771, + 0.7866722345352173, + -0.4721951484680176, + 1.8520021438598633, + 0.07333793491125107, + -1.147714376449585, + 0.06321533769369125, + 0.5042028427124023, + 0.9146731495857239, + -0.2515338659286499, + -0.6100011467933655 + ], + [ + -1.3096731901168823, + -0.5322571396827698, + 2.1369197368621826, + 0.6385367512702942, + 0.29661819338798523, + -0.2601790130138397, + 1.7370480298995972, + -0.9429073333740234, + 1.0160404443740845, + 0.765198826789856, + -1.10575532913208, + -0.28133368492126465, + 0.6474294066429138, + 0.47843703627586365, + 0.4757455587387085, + -0.9193580150604248 + ], + [ + -2.9883406162261963, + -1.278907299041748, + 1.2906922101974487, + 0.4815269410610199, + 0.27497509121894836, + -0.8659355044364929, + 0.6521288156509399, + -0.3194761872291565, + 0.40679335594177246, + 0.20416444540023804, + -1.134086012840271, + -0.2472257912158966, + 0.004673673305660486, + 0.3670925199985504, + 0.03405305743217468, + -0.5286491513252258 + ] + ] + ], + "compact_hidden_state": [ + [ + [ + -2.024979591369629, + 0.00422435300424695, + 1.6957898139953613, + 0.7697137594223022, + -0.6883586645126343, + 0.11442556977272034, + 0.7328180074691772, + -1.5748454332351685, + -0.5792887806892395, + 1.0610051155090332, + 1.6441532373428345, + -0.06880106776952744, + 0.17206580936908722, + -0.3806779682636261, + 0.17469821870326996, + 0.7253968119621277 + ], + [ + -1.574650526046753, + -1.9975262880325317, + 0.6534299254417419, + -0.642878532409668, + 1.156783938407898, + -0.6467214822769165, + 0.7542971968650818, + -1.1479636430740356, + 0.8172124028205872, + -0.7986409068107605, + 0.671444296836853, + -0.5100952982902527, + 1.3076112270355225, + 0.8520255088806152, + 0.43006426095962524, + 0.6130269765853882 + ], + [ + 0.5974754691123962, + -2.4806430339813232, + -0.6777498722076416, + 0.07211479544639587, + -0.5010150074958801, + -1.263437032699585, + 0.21863402426242828, + 1.4749866724014282, + -0.8187174797058105, + -0.030426712706685066, + -0.9761536121368408, + -1.1424365043640137, + 0.7796595096588135, + 0.9137669801712036, + -0.23002482950687408, + 0.6912825703620911 + ], + [ + 0.5695361495018005, + -0.7074604630470276, + 0.5785335302352905, + 0.26793089509010315, + -1.741084098815918, + -0.9064237475395203, + -0.27818211913108826, + -0.06530818343162537, + 1.5608278512954712, + 0.10034053027629852, + 0.18459738790988922, + 0.2896520495414734, + 2.228212833404541, + 1.3797621726989746, + -1.1619044542312622, + -0.10607702285051346 + ] + ] + ] +} diff --git a/test/fixtures/embedding_models/tiny-random-mistral-causal/config.json b/test/fixtures/embedding_models/tiny-random-mistral-causal/config.json new file mode 100644 index 00000000..c8a6d7a0 --- /dev/null +++ b/test/fixtures/embedding_models/tiny-random-mistral-causal/config.json @@ -0,0 +1,31 @@ +{ + "architectures": [ + "MistralModel" + ], + "attention_dropout": 0.0, + "bos_token_id": 1, + "dtype": "float32", + "eos_token_id": 2, + "head_dim": 8, + "hidden_act": "silu", + "hidden_size": 16, + "initializer_range": 0.02, + "intermediate_size": 20, + "is_causal": true, + "max_position_embeddings": 4, + "model_type": "mistral", + "num_attention_heads": 2, + "num_hidden_layers": 2, + "num_key_value_heads": 1, + "pad_token_id": 0, + "rms_norm_eps": 1e-06, + "rope_parameters": { + "rope_theta": 10000.0, + "rope_type": "default" + }, + "sliding_window": 4, + "tie_word_embeddings": false, + "transformers_version": "5.19.0.dev0", + "use_cache": true, + "vocab_size": 32 +} diff --git a/test/fixtures/embedding_models/tiny-random-mistral-causal/model.safetensors b/test/fixtures/embedding_models/tiny-random-mistral-causal/model.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..ba8fccc1f4f6a21eaed688c57dc96e9346abbdae GIT binary patch literal 18072 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 c}MbB3fug%BzUk&q!n8W1vsNXT#<`xF|4 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 aei1^?4;i>TehmnXJN0k%9sjQX`2PUl=08vX literal 0 HcmV?d00001 diff --git a/test/fixtures/embedding_models/tiny-random-qwen3_dynamic-causal/reference.json b/test/fixtures/embedding_models/tiny-random-qwen3_dynamic-causal/reference.json new file mode 100644 index 00000000..aadf713c --- /dev/null +++ b/test/fixtures/embedding_models/tiny-random-qwen3_dynamic-causal/reference.json @@ -0,0 +1,585 @@ +{ + "transformers_version": "5.19.0.dev0", + "transformers_commit": "3693f8d26311305e914735a6373fb03468d6aaa0", + "is_causal": true, + "input_ids": [ + [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 + ] + ], + "attention_mask": [ + [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ] + ], + "hidden_state": [ + [ + [ + -0.4182742238044739, + 1.5112836360931396, + -0.025699011981487274, + -0.7797371745109558, + -0.13699187338352203, + 0.2942725121974945, + -1.487064003944397, + 0.6858462691307068, + 0.8765056729316711, + -1.8516476154327393, + -1.5692821741104126, + -1.0727769136428833, + -1.050380825996399, + -0.8316739201545715, + 0.3493972420692444, + 0.6111904978752136 + ], + [ + 1.4220627546310425, + 0.27736592292785645, + 0.7255986928939819, + 0.04643205553293228, + -0.33639198541641235, + 1.1324095726013184, + 0.501779317855835, + 1.8326257467269897, + 0.09026020020246506, + 0.8267349004745483, + 0.9334233999252319, + -1.8538038730621338, + -0.015311451628804207, + 0.5632038712501526, + 1.3654264211654663, + -1.071913480758667 + ], + [ + 0.12224620580673218, + -1.7805639505386353, + 0.5182938575744629, + 0.3151543438434601, + -1.02891206741333, + 1.7755043506622314, + -1.3350296020507812, + -0.394748330116272, + -1.928560495376587, + -0.802724301815033, + 0.030400831252336502, + -0.25020918250083923, + -0.12602803111076355, + -0.11729856580495834, + 1.304673671722412, + -0.32380563020706177 + ], + [ + -1.5125590562820435, + 0.3046088218688965, + -0.6275227069854736, + 2.155548334121704, + 1.1568942070007324, + -0.306565523147583, + -0.3077033460140228, + -0.7024491429328918, + 0.09575822949409485, + 0.11629553139209747, + 1.132570743560791, + 0.9242783188819885, + -0.11231645941734314, + 1.3881763219833374, + 1.1013861894607544, + 1.0966095924377441 + ], + [ + 1.9884411096572876, + 0.361234575510025, + 0.23765923082828522, + 0.2582189440727234, + 0.8649953603744507, + -0.49694254994392395, + -0.5676278471946716, + 0.02620985172688961, + 0.08442974835634232, + -1.1107805967330933, + 1.8562204837799072, + -0.5003494620323181, + 0.6689697504043579, + 0.08006023615598679, + -2.2170612812042236, + -0.35246214270591736 + ], + [ + -1.1601098775863647, + -0.5565108060836792, + 1.7388681173324585, + -0.8363213539123535, + 0.9898486733436584, + 2.444310188293457, + -0.5241672396659851, + 0.30723533034324646, + -0.45568767189979553, + -0.4653460383415222, + 0.4462859630584717, + 0.6351938843727112, + 0.48426809906959534, + -0.04627907648682594, + 1.2444204092025757, + -0.6541460752487183 + ], + [ + -0.7450334429740906, + -0.36560744047164917, + -1.348331332206726, + 0.03933992609381676, + 0.599586546421051, + 1.3102186918258667, + -0.6898004412651062, + -2.680666208267212, + -0.3923966586589813, + 1.0113565921783447, + 0.3248187005519867, + -1.0695972442626953, + 0.788663387298584, + -0.2565804719924927, + 0.1526925414800644, + 0.7670185565948486 + ], + [ + 0.7545332312583923, + -1.5008366107940674, + 0.6859128475189209, + -1.7492886781692505, + -0.8584056496620178, + 0.11235889792442322, + 0.8676731586456299, + 0.21482735872268677, + 0.15913145244121552, + -1.1214385032653809, + 1.2091416120529175, + 0.8795013427734375, + 0.012556985020637512, + 0.8023542761802673, + 0.1268131285905838, + -1.967818260192871 + ] + ] + ], + "changed_future_hidden_state": [ + [ + [ + -0.4182742238044739, + 1.5112836360931396, + -0.025699011981487274, + -0.7797371745109558, + -0.13699187338352203, + 0.2942725121974945, + -1.487064003944397, + 0.6858462691307068, + 0.8765056729316711, + -1.8516476154327393, + -1.5692821741104126, + -1.0727769136428833, + -1.050380825996399, + -0.8316739201545715, + 0.3493972420692444, + 0.6111904978752136 + ], + [ + 1.4220627546310425, + 0.27736592292785645, + 0.7255986928939819, + 0.04643205553293228, + -0.33639198541641235, + 1.1324095726013184, + 0.501779317855835, + 1.8326257467269897, + 0.09026020020246506, + 0.8267349004745483, + 0.9334233999252319, + -1.8538038730621338, + -0.015311451628804207, + 0.5632038712501526, + 1.3654264211654663, + -1.071913480758667 + ], + [ + 0.12224620580673218, + -1.7805639505386353, + 0.5182938575744629, + 0.3151543438434601, + -1.02891206741333, + 1.7755043506622314, + -1.3350296020507812, + -0.394748330116272, + -1.928560495376587, + -0.802724301815033, + 0.030400831252336502, + -0.25020918250083923, + -0.12602803111076355, + -0.11729856580495834, + 1.304673671722412, + -0.32380563020706177 + ], + [ + -1.5125590562820435, + 0.3046088218688965, + -0.6275227069854736, + 2.155548334121704, + 1.1568942070007324, + -0.306565523147583, + -0.3077033460140228, + -0.7024491429328918, + 0.09575822949409485, + 0.11629553139209747, + 1.132570743560791, + 0.9242783188819885, + -0.11231645941734314, + 1.3881763219833374, + 1.1013861894607544, + 1.0966095924377441 + ], + [ + 1.9884411096572876, + 0.361234575510025, + 0.23765923082828522, + 0.2582189440727234, + 0.8649953603744507, + -0.49694254994392395, + -0.5676278471946716, + 0.02620985172688961, + 0.08442974835634232, + -1.1107805967330933, + 1.8562204837799072, + -0.5003494620323181, + 0.6689697504043579, + 0.08006023615598679, + -2.2170612812042236, + -0.35246214270591736 + ], + [ + -1.1601098775863647, + -0.5565108060836792, + 1.7388681173324585, + -0.8363213539123535, + 0.9898486733436584, + 2.444310188293457, + -0.5241672396659851, + 0.30723533034324646, + -0.45568767189979553, + -0.4653460383415222, + 0.4462859630584717, + 0.6351938843727112, + 0.48426809906959534, + -0.04627907648682594, + 1.2444204092025757, + -0.6541460752487183 + ], + [ + -0.7450334429740906, + -0.36560744047164917, + -1.348331332206726, + 0.03933992609381676, + 0.599586546421051, + 1.3102186918258667, + -0.6898004412651062, + -2.680666208267212, + -0.3923966586589813, + 1.0113565921783447, + 0.3248187005519867, + -1.0695972442626953, + 0.788663387298584, + -0.2565804719924927, + 0.1526925414800644, + 0.7670185565948486 + ], + [ + 0.8485293388366699, + 0.21174556016921997, + -0.7083292603492737, + -0.3837893009185791, + 0.4921610653400421, + 0.17720545828342438, + -1.3712587356567383, + -1.4570472240447998, + 0.27693814039230347, + 1.2866679430007935, + 2.038839101791382, + -1.0481922626495361, + -0.33188512921333313, + -0.6351959705352783, + -1.55901300907135, + -0.5915477275848389 + ] + ] + ], + "padded_input_ids": [ + [ + 1, + 2, + 3, + 4, + 0, + 0, + 0, + 0 + ] + ], + "padded_attention_mask": [ + [ + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0 + ] + ], + "padded_position_ids": [ + [ + 0, + 1, + 2, + 3, + 0, + 0, + 0, + 0 + ] + ], + "padded_hidden_state": [ + [ + [ + -0.4182742238044739, + 1.5112836360931396, + -0.025699011981487274, + -0.7797371745109558, + -0.13699187338352203, + 0.2942725121974945, + -1.487064003944397, + 0.6858462691307068, + 0.8765056729316711, + -1.8516476154327393, + -1.5692821741104126, + -1.0727769136428833, + -1.050380825996399, + -0.8316739201545715, + 0.3493972420692444, + 0.6111904978752136 + ], + [ + 1.4226020574569702, + 0.2768370509147644, + 0.7244383692741394, + 0.044443804770708084, + -0.3361719846725464, + 1.1311790943145752, + 0.5026962757110596, + 1.8327158689498901, + 0.09035629034042358, + 0.8271207213401794, + 0.9325364828109741, + -1.854024052619934, + -0.015438954345881939, + 0.5642936825752258, + 1.3660928010940552, + -1.0716432332992554 + ], + [ + 0.12117406725883484, + -1.7803711891174316, + 0.5216084718704224, + 0.3140164315700531, + -1.029453158378601, + 1.776227593421936, + -1.3324857950210571, + -0.3984460234642029, + -1.9280109405517578, + -0.806088387966156, + 0.02698143944144249, + -0.24862496554851532, + -0.12284760177135468, + -0.11554059386253357, + 1.303626537322998, + -0.3237568140029907 + ], + [ + -1.5048562288284302, + 0.30200761556625366, + -0.6270103454589844, + 2.1612040996551514, + 1.1521599292755127, + -0.30691203474998474, + -0.30504342913627625, + -0.7017474174499512, + 0.0974915623664856, + 0.11040645837783813, + 1.1320863962173462, + 0.9267258644104004, + -0.115012526512146, + 1.3851051330566406, + 1.1032369136810303, + 1.1038659811019897 + ], + [ + 1.0181776285171509, + 0.7616355419158936, + -0.6478985548019409, + -1.41938316822052, + 1.4242634773254395, + 0.4871251583099365, + -0.8162285685539246, + -1.328191876411438, + -0.28537213802337646, + 1.353971242904663, + 1.0180273056030273, + -1.5634214878082275, + -0.03228190541267395, + -0.08149232715368271, + -1.0069823265075684, + 0.16483289003372192 + ], + [ + 1.0181776285171509, + 0.7616355419158936, + -0.6478985548019409, + -1.41938316822052, + 1.4242634773254395, + 0.4871251583099365, + -0.8162285685539246, + -1.328191876411438, + -0.28537213802337646, + 1.353971242904663, + 1.0180273056030273, + -1.5634214878082275, + -0.03228190541267395, + -0.08149232715368271, + -1.0069823265075684, + 0.16483289003372192 + ], + [ + 1.0181776285171509, + 0.7616355419158936, + -0.6478985548019409, + -1.41938316822052, + 1.4242634773254395, + 0.4871251583099365, + -0.8162285685539246, + -1.328191876411438, + -0.28537213802337646, + 1.353971242904663, + 1.0180273056030273, + -1.5634214878082275, + -0.03228190541267395, + -0.08149232715368271, + -1.0069823265075684, + 0.16483289003372192 + ], + [ + 1.0181776285171509, + 0.7616355419158936, + -0.6478985548019409, + -1.41938316822052, + 1.4242634773254395, + 0.4871251583099365, + -0.8162285685539246, + -1.328191876411438, + -0.28537213802337646, + 1.353971242904663, + 1.0180273056030273, + -1.5634214878082275, + -0.03228190541267395, + -0.08149232715368271, + -1.0069823265075684, + 0.16483289003372192 + ] + ] + ], + "compact_hidden_state": [ + [ + [ + -0.4182742238044739, + 1.5112836360931396, + -0.025699011981487274, + -0.7797371745109558, + -0.13699187338352203, + 0.2942725121974945, + -1.487064003944397, + 0.6858462691307068, + 0.8765056729316711, + -1.8516476154327393, + -1.5692821741104126, + -1.0727769136428833, + -1.050380825996399, + -0.8316739201545715, + 0.3493972420692444, + 0.6111904978752136 + ], + [ + 1.4226020574569702, + 0.276837021112442, + 0.7244383692741394, + 0.044443804770708084, + -0.336171954870224, + 1.1311790943145752, + 0.5026962757110596, + 1.8327161073684692, + 0.09035629034042358, + 0.8271207213401794, + 0.9325364828109741, + -1.8540241718292236, + -0.015438982285559177, + 0.5642938017845154, + 1.3660928010940552, + -1.071643352508545 + ], + [ + 0.12117404490709305, + -1.7803711891174316, + 0.5216084718704224, + 0.3140164315700531, + -1.029453158378601, + 1.776227593421936, + -1.3324857950210571, + -0.39844605326652527, + -1.9280109405517578, + -0.806088387966156, + 0.026981450617313385, + -0.24862496554851532, + -0.12284760922193527, + -0.11554061621427536, + 1.303626537322998, + -0.3237568140029907 + ], + [ + -1.5048561096191406, + 0.3020075559616089, + -0.6270102858543396, + 2.1612040996551514, + 1.1521598100662231, + -0.30691200494766235, + -0.30504336953163147, + -0.7017473578453064, + 0.0974915474653244, + 0.11040650308132172, + 1.1320862770080566, + 0.9267258048057556, + -0.1150125041604042, + 1.385105013847351, + 1.1032369136810303, + 1.1038659811019897 + ] + ] + ] +} diff --git a/test/fixtures/embedding_models/tiny-random-qwen3_linear-bidirectional/config.json b/test/fixtures/embedding_models/tiny-random-qwen3_linear-bidirectional/config.json new file mode 100644 index 00000000..af73b29a --- /dev/null +++ b/test/fixtures/embedding_models/tiny-random-qwen3_linear-bidirectional/config.json @@ -0,0 +1,40 @@ +{ + "architectures": [ + "Qwen3Model" + ], + "attention_bias": false, + "attention_dropout": 0.0, + "bos_token_id": null, + "dtype": "float32", + "eos_token_id": null, + "head_dim": 8, + "hidden_act": "silu", + "hidden_size": 16, + "initializer_range": 0.02, + "intermediate_size": 20, + "is_causal": false, + "layer_types": [ + "full_attention", + "full_attention" + ], + "max_position_embeddings": 4, + "max_window_layers": 28, + "model_type": "qwen3", + "num_attention_heads": 2, + "num_hidden_layers": 2, + "num_key_value_heads": 1, + "pad_token_id": 0, + "rms_norm_eps": 1e-06, + "rope_parameters": { + "factor": 2.0, + "rope_theta": 10000.0, + "rope_type": "linear", + "type": "linear" + }, + "sliding_window": null, + "tie_word_embeddings": false, + "transformers_version": "5.19.0.dev0", + "use_cache": true, + "use_sliding_window": false, + "vocab_size": 32 +} diff --git a/test/fixtures/embedding_models/tiny-random-qwen3_linear-bidirectional/model.safetensors b/test/fixtures/embedding_models/tiny-random-qwen3_linear-bidirectional/model.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..3d773f48e4cb0f73463a7ee86337c600e3890ab2 GIT binary patch literal 18560 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 literal 0 HcmV?d00001 diff --git a/test/fixtures/embedding_models/tiny-random-qwen3_linear-bidirectional/reference.json b/test/fixtures/embedding_models/tiny-random-qwen3_linear-bidirectional/reference.json new file mode 100644 index 00000000..5b78907f --- /dev/null +++ b/test/fixtures/embedding_models/tiny-random-qwen3_linear-bidirectional/reference.json @@ -0,0 +1,585 @@ +{ + "transformers_version": "5.19.0.dev0", + "transformers_commit": "3693f8d26311305e914735a6373fb03468d6aaa0", + "is_causal": false, + "input_ids": [ + [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 + ] + ], + "attention_mask": [ + [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ] + ], + "hidden_state": [ + [ + [ + 2.3804707527160645, + -0.47000035643577576, + 0.4663759768009186, + 0.21189892292022705, + 0.9254993796348572, + 0.13283444941043854, + -0.5416399836540222, + -0.5064319372177124, + 0.402098685503006, + -0.627611517906189, + -0.021320605650544167, + -0.8468173146247864, + -1.7060489654541016, + 0.8879084587097168, + 0.21694938838481903, + -1.829768419265747 + ], + [ + 0.17248137295246124, + -1.4456835985183716, + 1.3732117414474487, + -0.639765202999115, + 0.5857303142547607, + 1.8158798217773438, + -0.13544635474681854, + 0.9852367639541626, + 1.3312965631484985, + -1.7727092504501343, + -0.3874310851097107, + 0.878923237323761, + -0.16760191321372986, + 0.8765888810157776, + -0.290028840303421, + -0.4286009669303894 + ], + [ + 0.5260079503059387, + 1.255531668663025, + 0.1318393349647522, + 0.4174288511276245, + -1.7375743389129639, + 0.09830798953771591, + 1.8797768354415894, + -1.2352778911590576, + 0.9927306175231934, + 1.2362178564071655, + 1.3285902738571167, + -0.07969822734594345, + 0.015381804667413235, + 0.6812264919281006, + -1.0378978252410889, + 0.04090458154678345 + ], + [ + 0.5007434487342834, + 2.0936684608459473, + -0.30570748448371887, + 0.2589314579963684, + 1.0930927991867065, + 0.7757241725921631, + -0.14021842181682587, + -1.6860812902450562, + -0.957875669002533, + 0.1710398644208908, + 1.7559993267059326, + 1.056137204170227, + 0.34663906693458557, + 0.1105915978550911, + 0.3989846110343933, + 1.0401036739349365 + ], + [ + -1.3355661630630493, + -0.872868537902832, + -0.8113995790481567, + 1.9513561725616455, + -0.2533009946346283, + -1.1128652095794678, + 0.7558857202529907, + -1.0569686889648438, + -0.29127490520477295, + -0.5515467524528503, + -1.5773495435714722, + 1.2873198986053467, + -0.36441829800605774, + -0.22161449491977692, + -0.1613665074110031, + -1.09657621383667 + ], + [ + 2.7258474826812744, + 0.09528335183858871, + -0.2645092308521271, + 0.15224775671958923, + 0.37966176867485046, + -1.266640067100525, + -1.3302533626556396, + 0.2352428138256073, + -1.3847336769104004, + -0.9199259281158447, + 0.49911290407180786, + 0.512569785118103, + -0.2932400107383728, + -0.15695318579673767, + 0.24800381064414978, + -1.1958178281784058 + ], + [ + -2.437811851501465, + 1.3706233501434326, + -0.6130828857421875, + 0.04555630311369896, + 1.3398782014846802, + 0.5457714200019836, + 1.275175929069519, + -0.5850625038146973, + 0.169952854514122, + -0.33303090929985046, + -0.9604375958442688, + -0.4522644281387329, + 0.9667981266975403, + 0.15534047782421112, + -1.2079795598983765, + -0.16259858012199402 + ], + [ + 0.04562314599752426, + 0.3919294774532318, + 0.410649836063385, + 0.6469319462776184, + 0.5774237513542175, + 2.2630908489227295, + -0.712445080280304, + -1.1138416528701782, + -0.7111727595329285, + -0.23091602325439453, + 1.602993130683899, + 1.1184111833572388, + 0.023472322151064873, + -0.9061961770057678, + 0.5119935274124146, + -1.6013227701187134 + ] + ] + ], + "changed_future_hidden_state": [ + [ + [ + 2.475024700164795, + -0.6283769011497498, + 0.29217568039894104, + 0.2642004191875458, + 0.8736686706542969, + 0.2726992070674896, + -0.6569352746009827, + -0.3821741044521332, + 0.29276666045188904, + -0.5534896850585938, + 0.042307864874601364, + -0.8595573306083679, + -1.6633203029632568, + 0.8529935479164124, + 0.2194073349237442, + -1.7804899215698242 + ], + [ + 0.15898320078849792, + -1.4966493844985962, + 1.3001396656036377, + -0.6201580166816711, + 0.530611515045166, + 1.8932693004608154, + -0.2186431735754013, + 1.0169291496276855, + 1.337486982345581, + -1.7301602363586426, + -0.36457934975624084, + 0.9295175671577454, + -0.11727128177881241, + 0.8034771084785461, + -0.2423841655254364, + -0.39675071835517883 + ], + [ + 0.4805983901023865, + 1.233636498451233, + 0.10775107890367508, + 0.4749114215373993, + -1.7554174661636353, + 0.18694931268692017, + 1.918078064918518, + -1.1883585453033447, + 0.9721998572349548, + 1.2768914699554443, + 1.3323050737380981, + -0.10972718149423599, + 0.01270999200642109, + 0.5845822095870972, + -1.0266444683074951, + 0.07985126227140427 + ], + [ + 0.5115131735801697, + 2.0750560760498047, + -0.36482152342796326, + 0.36730054020881653, + 1.0504040718078613, + 0.812953531742096, + -0.08275329321622849, + -1.6894105672836304, + -0.9945475459098816, + 0.27095890045166016, + 1.745376706123352, + 1.0257768630981445, + 0.3360763192176819, + 0.08110307157039642, + 0.36621585488319397, + 1.0482699871063232 + ], + [ + -1.4828557968139648, + -1.0546871423721313, + -0.9412181973457336, + 1.9966119527816772, + -0.38986608386039734, + -0.889629065990448, + 0.8169992566108704, + -0.804073691368103, + -0.3093498647212982, + -0.6190943717956543, + -1.5029290914535522, + 1.2116988897323608, + -0.2647683024406433, + -0.44166991114616394, + -0.270818829536438, + -0.9805724620819092 + ], + [ + 2.741715431213379, + 0.028661800548434258, + -0.39848828315734863, + 0.2750968039035797, + 0.34070122241973877, + -1.1863961219787598, + -1.319670557975769, + 0.3108786344528198, + -1.470852255821228, + -0.8779962658882141, + 0.5133561491966248, + 0.4926741123199463, + -0.25539135932922363, + -0.22750741243362427, + 0.1821253001689911, + -1.1306731700897217 + ], + [ + -2.441521406173706, + 1.3566219806671143, + -0.6639652848243713, + 0.09307017922401428, + 1.3075882196426392, + 0.6092075705528259, + 1.3082771301269531, + -0.5488526821136475, + 0.13429860770702362, + -0.31727075576782227, + -0.9035346508026123, + -0.45030564069747925, + 0.9753814935684204, + 0.12409159541130066, + -1.2260557413101196, + -0.14233292639255524 + ], + [ + -1.3802008628845215, + 1.8135160207748413, + 0.6494446992874146, + 0.08106948435306549, + -0.7716838121414185, + -0.500453531742096, + -1.1942366361618042, + 1.1733472347259521, + -0.9451490044593811, + -0.6638289093971252, + 0.38905319571495056, + 0.3025127053260803, + 1.7114239931106567, + 0.5295724272727966, + 0.970282256603241, + -0.986286997795105 + ] + ] + ], + "padded_input_ids": [ + [ + 1, + 2, + 3, + 4, + 0, + 0, + 0, + 0 + ] + ], + "padded_attention_mask": [ + [ + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0 + ] + ], + "padded_position_ids": [ + [ + 0, + 1, + 2, + 3, + 0, + 0, + 0, + 0 + ] + ], + "padded_hidden_state": [ + [ + [ + 2.348954200744629, + -0.09527663886547089, + 0.19545263051986694, + 0.464946448802948, + 0.6779965162277222, + 0.45914191007614136, + -1.3672893047332764, + -0.7023479342460632, + 0.09788250923156738, + 0.06207561865448952, + 0.07718004286289215, + -0.7484263777732849, + -1.9141855239868164, + 0.9653149843215942, + 0.7345874309539795, + -1.1919121742248535 + ], + [ + 0.43318870663642883, + -1.0824134349822998, + 1.328692078590393, + -0.6072807908058167, + 0.5671329498291016, + 2.3261961936950684, + -0.8367037177085876, + 0.6042765974998474, + 1.2848491668701172, + -1.3204411268234253, + -0.3695427477359772, + 1.067093014717102, + -0.2501853108406067, + 0.9268195629119873, + 0.03786185756325722, + -0.22839462757110596 + ], + [ + 0.710109293460846, + 1.3063181638717651, + 0.05125481262803078, + 0.05416928604245186, + -1.816381812095642, + 0.155558779835701, + 1.4213935136795044, + -1.4467324018478394, + 1.0432040691375732, + 1.3452603816986084, + 1.4665547609329224, + -0.12673895061016083, + 0.04358247295022011, + 0.708381712436676, + -0.8235551714897156, + 0.24225881695747375 + ], + [ + 0.726507842540741, + 2.035364866256714, + -0.10553140193223953, + -0.1327599436044693, + 1.0338947772979736, + 0.7242819666862488, + -0.39529672265052795, + -1.8069162368774414, + -0.8547156453132629, + 0.2672673463821411, + 1.7453638315200806, + 0.9569552540779114, + 0.14532488584518433, + 0.29543718695640564, + 0.4912334084510803, + 1.070923089981079 + ], + [ + 1.0984631776809692, + 0.6658608317375183, + 0.4536934494972229, + -1.111095905303955, + -0.07813029736280441, + -0.3534058630466461, + -2.846869468688965, + -0.3757239282131195, + 0.330267995595932, + -0.2717861235141754, + -0.46070024371147156, + 0.9907264113426208, + -0.41101986169815063, + 0.8149014711380005, + 1.0126690864562988, + -0.7273316979408264 + ], + [ + 1.0984631776809692, + 0.6658608317375183, + 0.4536934494972229, + -1.111095905303955, + -0.07813029736280441, + -0.3534058630466461, + -2.846869468688965, + -0.3757239282131195, + 0.330267995595932, + -0.2717861235141754, + -0.46070024371147156, + 0.9907264113426208, + -0.41101986169815063, + 0.8149014711380005, + 1.0126690864562988, + -0.7273316979408264 + ], + [ + 1.0984631776809692, + 0.6658608317375183, + 0.4536934494972229, + -1.111095905303955, + -0.07813029736280441, + -0.3534058630466461, + -2.846869468688965, + -0.3757239282131195, + 0.330267995595932, + -0.2717861235141754, + -0.46070024371147156, + 0.9907264113426208, + -0.41101986169815063, + 0.8149014711380005, + 1.0126690864562988, + -0.7273316979408264 + ], + [ + 1.0984631776809692, + 0.6658608317375183, + 0.4536934494972229, + -1.111095905303955, + -0.07813029736280441, + -0.3534058630466461, + -2.846869468688965, + -0.3757239282131195, + 0.330267995595932, + -0.2717861235141754, + -0.46070024371147156, + 0.9907264113426208, + -0.41101986169815063, + 0.8149014711380005, + 1.0126690864562988, + -0.7273316979408264 + ] + ] + ], + "compact_hidden_state": [ + [ + [ + 2.348954200744629, + -0.09527663886547089, + 0.19545261561870575, + 0.464946448802948, + 0.6779964566230774, + 0.4591417908668518, + -1.367289423942566, + -0.702347993850708, + 0.0978824570775032, + 0.06207560747861862, + 0.07718005031347275, + -0.7484262585639954, + -1.9141855239868164, + 0.9653149843215942, + 0.7345874309539795, + -1.1919121742248535 + ], + [ + 0.4331887662410736, + -1.0824134349822998, + 1.328692078590393, + -0.6072808504104614, + 0.5671330094337463, + 2.3261961936950684, + -0.8367034792900085, + 0.6042764782905579, + 1.2848492860794067, + -1.3204411268234253, + -0.3695427179336548, + 1.067093014717102, + -0.2501853406429291, + 0.9268195629119873, + 0.03786187991499901, + -0.22839465737342834 + ], + [ + 0.7101092338562012, + 1.3063180446624756, + 0.05125480890274048, + 0.05416933074593544, + -1.8163816928863525, + 0.155558779835701, + 1.4213933944702148, + -1.4467324018478394, + 1.0432039499282837, + 1.3452602624893188, + 1.4665546417236328, + -0.12673893570899963, + 0.04358244687318802, + 0.7083816528320312, + -0.8235551118850708, + 0.24225875735282898 + ], + [ + 0.726507842540741, + 2.035364866256714, + -0.10553137212991714, + -0.1327599436044693, + 1.0338947772979736, + 0.7242819666862488, + -0.39529675245285034, + -1.8069162368774414, + -0.8547155857086182, + 0.2672673761844635, + 1.7453638315200806, + 0.9569552540779114, + 0.14532488584518433, + 0.29543718695640564, + 0.4912334084510803, + 1.0709229707717896 + ] + ] + ] +} diff --git a/test/fixtures/embedding_models/tiny-random-qwen3_linear-causal/config.json b/test/fixtures/embedding_models/tiny-random-qwen3_linear-causal/config.json new file mode 100644 index 00000000..afd5053b --- /dev/null +++ b/test/fixtures/embedding_models/tiny-random-qwen3_linear-causal/config.json @@ -0,0 +1,40 @@ +{ + "architectures": [ + "Qwen3Model" + ], + "attention_bias": false, + "attention_dropout": 0.0, + "bos_token_id": null, + "dtype": "float32", + "eos_token_id": null, + "head_dim": 8, + "hidden_act": "silu", + "hidden_size": 16, + "initializer_range": 0.02, + "intermediate_size": 20, + "is_causal": true, + "layer_types": [ + "full_attention", + "full_attention" + ], + "max_position_embeddings": 4, + "max_window_layers": 28, + "model_type": "qwen3", + "num_attention_heads": 2, + "num_hidden_layers": 2, + "num_key_value_heads": 1, + "pad_token_id": 0, + "rms_norm_eps": 1e-06, + "rope_parameters": { + "factor": 2.0, + "rope_theta": 10000.0, + "rope_type": "linear", + "type": "linear" + }, + "sliding_window": null, + "tie_word_embeddings": false, + "transformers_version": "5.19.0.dev0", + "use_cache": true, + "use_sliding_window": false, + "vocab_size": 32 +} diff --git a/test/fixtures/embedding_models/tiny-random-qwen3_linear-causal/model.safetensors b/test/fixtures/embedding_models/tiny-random-qwen3_linear-causal/model.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..43c4937442da0963c1f2d6b1dcf9a647f5fff922 GIT binary patch literal 18560 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 I_;;WGf2id*e*gdg literal 0 HcmV?d00001 diff --git a/test/fixtures/embedding_models/tiny-random-qwen3_linear-causal/reference.json b/test/fixtures/embedding_models/tiny-random-qwen3_linear-causal/reference.json new file mode 100644 index 00000000..794e92f8 --- /dev/null +++ b/test/fixtures/embedding_models/tiny-random-qwen3_linear-causal/reference.json @@ -0,0 +1,585 @@ +{ + "transformers_version": "5.19.0.dev0", + "transformers_commit": "3693f8d26311305e914735a6373fb03468d6aaa0", + "is_causal": true, + "input_ids": [ + [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 + ] + ], + "attention_mask": [ + [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ] + ], + "hidden_state": [ + [ + [ + -1.332697868347168, + 0.7285035252571106, + 0.2462701052427292, + 0.9126808643341064, + 0.49572375416755676, + -0.055270370095968246, + 0.5712628960609436, + -0.10520800203084946, + -0.4197082221508026, + 0.16006706655025482, + 2.513075828552246, + 0.5101444125175476, + -0.8519627451896667, + 2.007155418395996, + -0.777197539806366, + 0.19769108295440674 + ], + [ + -1.1066310405731201, + 0.2999636232852936, + 0.1991424709558487, + 0.3156890273094177, + -0.5695977210998535, + 0.2666531205177307, + 0.717149555683136, + -0.29553404450416565, + 1.3534818887710571, + -1.0769379138946533, + 1.1365094184875488, + 1.9484788179397583, + -0.9598391056060791, + -0.040897298604249954, + -0.707036018371582, + 1.9969927072525024 + ], + [ + 0.39589110016822815, + -1.3712940216064453, + 0.988987922668457, + 0.5564053654670715, + -0.9279597997665405, + 0.989714503288269, + 0.7368783354759216, + -0.4904135763645172, + -0.4365149438381195, + -0.20802313089370728, + 1.819280982017517, + -2.12956166267395, + 0.9164615869522095, + -0.7529182434082031, + -0.5852075815200806, + 0.4306463599205017 + ], + [ + 0.20449954271316528, + 0.0890413224697113, + -0.773203432559967, + 0.752077579498291, + -0.1044410914182663, + 1.0855385065078735, + -0.28461599349975586, + -1.2774797677993774, + -0.7137797474861145, + -1.2971302270889282, + 0.9671080708503723, + 0.5762349963188171, + 0.7520018815994263, + -1.6377841234207153, + 0.5740512609481812, + -2.189971685409546 + ], + [ + 0.559679388999939, + -1.5600589513778687, + -0.616054356098175, + -0.8498685359954834, + 0.846074640750885, + -1.996099829673767, + 0.03344755619764328, + -0.8699432015419006, + 0.8233052492141724, + 0.9942224025726318, + 1.3975518941879272, + -0.2718188762664795, + 1.1883363723754883, + -0.9908868670463562, + 0.6362152695655823, + 0.42185166478157043 + ], + [ + 2.350285768508911, + -0.3711071312427521, + -0.7534564733505249, + 0.5843968391418457, + -1.5700724124908447, + 1.3491671085357666, + 0.34152090549468994, + -1.5185502767562866, + 0.684260904788971, + 0.12176615744829178, + 0.1520400047302246, + 0.21613669395446777, + 0.8942729830741882, + -0.6035752296447754, + -0.9133085012435913, + -0.3742775321006775 + ], + [ + 0.5736373662948608, + -0.6041820645332336, + -0.8257227540016174, + 0.102457694709301, + 0.13089315593242645, + -0.5561263561248779, + 0.7387528419494629, + -0.3921845555305481, + -2.482466697692871, + 0.4435667097568512, + -1.0529035329818726, + -0.880914568901062, + -1.6230337619781494, + -0.9740861058235168, + 1.2443904876708984, + 0.4275036156177521 + ], + [ + -0.4798935055732727, + 1.137915849685669, + 0.14236591756343842, + -1.7746542692184448, + -0.02988196164369583, + 0.15443821251392365, + 0.46419161558151245, + -1.2310506105422974, + 1.1666206121444702, + 0.551112949848175, + 1.4211466312408447, + 0.4597647190093994, + 2.011002540588379, + -1.1744412183761597, + 0.3702611029148102, + 0.24859091639518738 + ] + ] + ], + "changed_future_hidden_state": [ + [ + [ + -1.332697868347168, + 0.7285035252571106, + 0.2462701052427292, + 0.9126808643341064, + 0.49572375416755676, + -0.055270370095968246, + 0.5712628960609436, + -0.10520800203084946, + -0.4197082221508026, + 0.16006706655025482, + 2.513075828552246, + 0.5101444125175476, + -0.8519627451896667, + 2.007155418395996, + -0.777197539806366, + 0.19769108295440674 + ], + [ + -1.1066310405731201, + 0.2999636232852936, + 0.1991424709558487, + 0.3156890273094177, + -0.5695977210998535, + 0.2666531205177307, + 0.717149555683136, + -0.29553404450416565, + 1.3534818887710571, + -1.0769379138946533, + 1.1365094184875488, + 1.9484788179397583, + -0.9598391056060791, + -0.040897298604249954, + -0.707036018371582, + 1.9969927072525024 + ], + [ + 0.39589110016822815, + -1.3712940216064453, + 0.988987922668457, + 0.5564053654670715, + -0.9279597997665405, + 0.989714503288269, + 0.7368783354759216, + -0.4904135763645172, + -0.4365149438381195, + -0.20802313089370728, + 1.819280982017517, + -2.12956166267395, + 0.9164615869522095, + -0.7529182434082031, + -0.5852075815200806, + 0.4306463599205017 + ], + [ + 0.20449954271316528, + 0.0890413224697113, + -0.773203432559967, + 0.752077579498291, + -0.1044410914182663, + 1.0855385065078735, + -0.28461599349975586, + -1.2774797677993774, + -0.7137797474861145, + -1.2971302270889282, + 0.9671080708503723, + 0.5762349963188171, + 0.7520018815994263, + -1.6377841234207153, + 0.5740512609481812, + -2.189971685409546 + ], + [ + 0.559679388999939, + -1.5600589513778687, + -0.616054356098175, + -0.8498685359954834, + 0.846074640750885, + -1.996099829673767, + 0.03344755619764328, + -0.8699432015419006, + 0.8233052492141724, + 0.9942224025726318, + 1.3975518941879272, + -0.2718188762664795, + 1.1883363723754883, + -0.9908868670463562, + 0.6362152695655823, + 0.42185166478157043 + ], + [ + 2.350285768508911, + -0.3711071312427521, + -0.7534564733505249, + 0.5843968391418457, + -1.5700724124908447, + 1.3491671085357666, + 0.34152090549468994, + -1.5185502767562866, + 0.684260904788971, + 0.12176615744829178, + 0.1520400047302246, + 0.21613669395446777, + 0.8942729830741882, + -0.6035752296447754, + -0.9133085012435913, + -0.3742775321006775 + ], + [ + 0.5736373662948608, + -0.6041820645332336, + -0.8257227540016174, + 0.102457694709301, + 0.13089315593242645, + -0.5561263561248779, + 0.7387528419494629, + -0.3921845555305481, + -2.482466697692871, + 0.4435667097568512, + -1.0529035329818726, + -0.880914568901062, + -1.6230337619781494, + -0.9740861058235168, + 1.2443904876708984, + 0.4275036156177521 + ], + [ + 0.20173311233520508, + -0.9515380263328552, + 0.004179876763373613, + 1.1135282516479492, + 0.5165417790412903, + 1.2093756198883057, + 0.28589048981666565, + 0.4498256742954254, + -0.8937991857528687, + -1.5571949481964111, + 1.2252867221832275, + -0.8017433285713196, + 0.490538090467453, + -0.44763776659965515, + -1.0989993810653687, + 2.1681644916534424 + ] + ] + ], + "padded_input_ids": [ + [ + 1, + 2, + 3, + 4, + 0, + 0, + 0, + 0 + ] + ], + "padded_attention_mask": [ + [ + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0 + ] + ], + "padded_position_ids": [ + [ + 0, + 1, + 2, + 3, + 0, + 0, + 0, + 0 + ] + ], + "padded_hidden_state": [ + [ + [ + -1.332697868347168, + 0.7285035252571106, + 0.2462701052427292, + 0.9126808643341064, + 0.49572375416755676, + -0.055270370095968246, + 0.5712628960609436, + -0.10520800203084946, + -0.4197082221508026, + 0.16006706655025482, + 2.513075828552246, + 0.5101444125175476, + -0.8519627451896667, + 2.007155418395996, + -0.777197539806366, + 0.19769108295440674 + ], + [ + -1.1066310405731201, + 0.2999636232852936, + 0.1991424709558487, + 0.3156890273094177, + -0.5695977210998535, + 0.2666531205177307, + 0.717149555683136, + -0.29553404450416565, + 1.3534818887710571, + -1.0769379138946533, + 1.1365094184875488, + 1.9484788179397583, + -0.9598391056060791, + -0.040897298604249954, + -0.707036018371582, + 1.9969927072525024 + ], + [ + 0.39589110016822815, + -1.3712940216064453, + 0.988987922668457, + 0.5564053654670715, + -0.9279597997665405, + 0.989714503288269, + 0.7368783354759216, + -0.4904135763645172, + -0.4365149438381195, + -0.20802313089370728, + 1.819280982017517, + -2.12956166267395, + 0.9164615869522095, + -0.7529182434082031, + -0.5852075815200806, + 0.4306463599205017 + ], + [ + 0.20449954271316528, + 0.0890413224697113, + -0.773203432559967, + 0.752077579498291, + -0.1044410914182663, + 1.0855385065078735, + -0.28461599349975586, + -1.2774797677993774, + -0.7137797474861145, + -1.2971302270889282, + 0.9671080708503723, + 0.5762349963188171, + 0.7520018815994263, + -1.6377841234207153, + 0.5740512609481812, + -2.189971685409546 + ], + [ + -0.8472859263420105, + -0.5972305536270142, + -0.8438308835029602, + 1.7743812799453735, + 0.7173834443092346, + -1.123368501663208, + 0.6549981236457825, + -0.7230342626571655, + 0.09419386088848114, + -0.4039069712162018, + 1.8323605060577393, + -0.30406713485717773, + -1.653549075126648, + -0.8194564580917358, + 0.6959991455078125, + -0.2258853167295456 + ], + [ + -0.8472859263420105, + -0.5972305536270142, + -0.8438308835029602, + 1.7743812799453735, + 0.7173834443092346, + -1.123368501663208, + 0.6549981236457825, + -0.7230342626571655, + 0.09419386088848114, + -0.4039069712162018, + 1.8323605060577393, + -0.30406713485717773, + -1.653549075126648, + -0.8194564580917358, + 0.6959991455078125, + -0.2258853167295456 + ], + [ + -0.8472859263420105, + -0.5972305536270142, + -0.8438308835029602, + 1.7743812799453735, + 0.7173834443092346, + -1.123368501663208, + 0.6549981236457825, + -0.7230342626571655, + 0.09419386088848114, + -0.4039069712162018, + 1.8323605060577393, + -0.30406713485717773, + -1.653549075126648, + -0.8194564580917358, + 0.6959991455078125, + -0.2258853167295456 + ], + [ + -0.8472859263420105, + -0.5972305536270142, + -0.8438308835029602, + 1.7743812799453735, + 0.7173834443092346, + -1.123368501663208, + 0.6549981236457825, + -0.7230342626571655, + 0.09419386088848114, + -0.4039069712162018, + 1.8323605060577393, + -0.30406713485717773, + -1.653549075126648, + -0.8194564580917358, + 0.6959991455078125, + -0.2258853167295456 + ] + ] + ], + "compact_hidden_state": [ + [ + [ + -1.332697868347168, + 0.7285035252571106, + 0.2462701052427292, + 0.9126808643341064, + 0.49572375416755676, + -0.055270370095968246, + 0.5712628960609436, + -0.10520800203084946, + -0.4197082221508026, + 0.16006706655025482, + 2.513075828552246, + 0.5101444125175476, + -0.8519627451896667, + 2.007155418395996, + -0.777197539806366, + 0.19769108295440674 + ], + [ + -1.1066310405731201, + 0.2999635934829712, + 0.19914251565933228, + 0.3156890273094177, + -0.569597601890564, + 0.2666531503200531, + 0.717149555683136, + -0.29553407430648804, + 1.3534820079803467, + -1.0769380331039429, + 1.1365094184875488, + 1.9484788179397583, + -0.9598391056060791, + -0.040897272527217865, + -0.7070360779762268, + 1.9969927072525024 + ], + [ + 0.3958910405635834, + -1.3712940216064453, + 0.9889881014823914, + 0.5564053654670715, + -0.9279597997665405, + 0.9897145628929138, + 0.7368783950805664, + -0.4904135763645172, + -0.4365150034427643, + -0.20802317559719086, + 1.819280982017517, + -2.12956166267395, + 0.9164614677429199, + -0.7529183030128479, + -0.5852077007293701, + 0.4306463897228241 + ], + [ + 0.2044994831085205, + 0.08904127776622772, + -0.773203432559967, + 0.752077579498291, + -0.10444121062755585, + 1.0855385065078735, + -0.2846159338951111, + -1.2774797677993774, + -0.7137797474861145, + -1.2971302270889282, + 0.9671080708503723, + 0.5762349367141724, + 0.7520018219947815, + -1.6377841234207153, + 0.5740513205528259, + -2.189971685409546 + ] + ] + ] +}