From be29f6f804e21026afbbcfc5713705ab49444e57 Mon Sep 17 00:00:00 2001 From: Devstopfix Date: Wed, 12 Aug 2026 11:11:18 +0100 Subject: [PATCH 1/9] Model for unit tests --- test/ex_aws/bedrock_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ex_aws/bedrock_test.exs b/test/ex_aws/bedrock_test.exs index 184d929..469aef2 100644 --- a/test/ex_aws/bedrock_test.exs +++ b/test/ex_aws/bedrock_test.exs @@ -5,7 +5,7 @@ defmodule ExAws.BedrockTest do alias ExAws.Bedrock.Titan.TextModel alias ExAws.Operation.JSON - @model_id "amazon.titan-text-lite-v1" + @model_id "amazon.titan-text-express-v1" @prompt "Hello, LLM!" describe "get_custom_model/1" do From 6b3e739a4d1098ce05e38691e6d410d9d7058d86 Mon Sep 17 00:00:00 2001 From: Devstopfix Date: Wed, 12 Aug 2026 11:16:23 +0100 Subject: [PATCH 2/9] Fix fine tuning test --- test/ex_aws/bedrock_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ex_aws/bedrock_test.exs b/test/ex_aws/bedrock_test.exs index 469aef2..f4f0e01 100644 --- a/test/ex_aws/bedrock_test.exs +++ b/test/ex_aws/bedrock_test.exs @@ -147,7 +147,7 @@ defmodule ExAws.BedrockTest do test "allow fine tuning" do request = Bedrock.list_foundation_models(by_customization_type: :FINE_TUNING) - assert %{"modelSummaries" => [%{"customizationsSupported" => ["FINE_TUNING"]} | _]} = + assert %{"modelSummaries" => [%{"customizationsSupported" => ["FINE_TUNING" | _]} | _]} = request!(request) end From 0dc71001c82f2b51f98ed761c9f56fe91d5a0f32 Mon Sep 17 00:00:00 2001 From: Devstopfix Date: Wed, 12 Aug 2026 11:20:00 +0100 Subject: [PATCH 3/9] Fix model test --- test/ex_aws/bedrock_test.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ex_aws/bedrock_test.exs b/test/ex_aws/bedrock_test.exs index f4f0e01..e8e8f06 100644 --- a/test/ex_aws/bedrock_test.exs +++ b/test/ex_aws/bedrock_test.exs @@ -49,7 +49,7 @@ defmodule ExAws.BedrockTest do end test "path", %{request: request} do - assert %JSON{path: "/foundation-models/amazon.titan-text-lite-v1"} = request + assert %JSON{path: "/foundation-models/amazon.titan-text-express-v1"} = request end test "service", %{request: request} do @@ -87,7 +87,7 @@ defmodule ExAws.BedrockTest do end test "path", %{request: request} do - assert %JSON{path: "/model/amazon.titan-text-lite-v1/invoke"} = request + assert %JSON{path: "/model/amazon.titan-text-express-v1/invoke"} = request end test "service", %{request: request} do From b0442030c97a2aff9ec0a1c819b169917cf6bc15 Mon Sep 17 00:00:00 2001 From: Devstopfix Date: Thu, 13 Aug 2026 08:44:26 +0100 Subject: [PATCH 4/9] Image model id --- test/ex_aws/bedrock_image_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ex_aws/bedrock_image_test.exs b/test/ex_aws/bedrock_image_test.exs index 9e30f60..542037f 100644 --- a/test/ex_aws/bedrock_image_test.exs +++ b/test/ex_aws/bedrock_image_test.exs @@ -57,7 +57,7 @@ defmodule ExAws.Bedrock.InvokeModelImageTest do end defp setup_image_model(_) do - [model_id: "amazon.titan-image-generator-v1"] + [model_id: "amazon.titan-image-generator-v2:0"] end defp setup_image_size(_) do From 6fe4d4c6b9e8ef4cbb176b55ebe201cb6fa5a098 Mon Sep 17 00:00:00 2001 From: Devstopfix Date: Thu, 13 Aug 2026 09:08:06 +0100 Subject: [PATCH 5/9] Titan replaced with Nova --- test/ex_aws/bedrock_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ex_aws/bedrock_test.exs b/test/ex_aws/bedrock_test.exs index e8e8f06..6618709 100644 --- a/test/ex_aws/bedrock_test.exs +++ b/test/ex_aws/bedrock_test.exs @@ -5,7 +5,7 @@ defmodule ExAws.BedrockTest do alias ExAws.Bedrock.Titan.TextModel alias ExAws.Operation.JSON - @model_id "amazon.titan-text-express-v1" + @model_id "amazon.nova-micro-v1:0" @prompt "Hello, LLM!" describe "get_custom_model/1" do From e02385534595c4579c2626a98c4178bc71fa7f6f Mon Sep 17 00:00:00 2001 From: Devstopfix Date: Thu, 13 Aug 2026 09:26:56 +0100 Subject: [PATCH 6/9] Nova invoke request (via Gemini) --- lib/ex_aws/bedrock/nova/content.ex | 70 +++++++++++++++++++++ lib/ex_aws/bedrock/nova/inference_config.ex | 53 ++++++++++++++++ lib/ex_aws/bedrock/nova/message.ex | 40 ++++++++++++ lib/ex_aws/bedrock/nova/reasoning_config.ex | 31 +++++++++ lib/ex_aws/bedrock/nova/text_model.ex | 64 +++++++++++++++++++ lib/ex_aws/bedrock/nova/tool_config.ex | 35 +++++++++++ lib/ex_aws/bedrock/nova/tool_spec.ex | 33 ++++++++++ 7 files changed, 326 insertions(+) create mode 100644 lib/ex_aws/bedrock/nova/content.ex create mode 100644 lib/ex_aws/bedrock/nova/inference_config.ex create mode 100644 lib/ex_aws/bedrock/nova/message.ex create mode 100644 lib/ex_aws/bedrock/nova/reasoning_config.ex create mode 100644 lib/ex_aws/bedrock/nova/text_model.ex create mode 100644 lib/ex_aws/bedrock/nova/tool_config.ex create mode 100644 lib/ex_aws/bedrock/nova/tool_spec.ex diff --git a/lib/ex_aws/bedrock/nova/content.ex b/lib/ex_aws/bedrock/nova/content.ex new file mode 100644 index 0000000..59f91dc --- /dev/null +++ b/lib/ex_aws/bedrock/nova/content.ex @@ -0,0 +1,70 @@ +defmodule ExAws.Bedrock.Nova.Content do + @moduledoc """ + Constructor functions for dynamic content items (Text, Image, Video, Audio). + """ + + @doc "Text content item" + def text(string) when is_binary(string), do: %{text: string} + + @doc "Image content item" + def image(format, bytes_or_base64) when format in ~w(jpeg png gif webp) do + %{ + image: %{ + format: format, + source: %{bytes: bytes_or_base64} + } + } + end + + @doc "Video content item via bytes/base64" + def video_bytes(format, bytes_or_base64) + when format in ~w(mkv mov mp4 webm three_gp flv mpeg mpg wmv) do + %{ + video: %{ + format: format, + source: %{bytes: bytes_or_base64} + } + } + end + + @doc "Video content item via S3 Location" + def video_s3(format, uri, bucket_owner \\ nil) + when format in ~w(mkv mov mp4 webm three_gp flv mpeg mpg wmv) do + s3_loc = + %{uri: uri} + |> then(fn map -> if bucket_owner, do: Map.put(map, :bucketOwner, bucket_owner), else: map end) + + %{ + video: %{ + format: format, + source: %{s3Location: s3_loc} + } + } + end + + @doc "Audio content item via bytes/base64" + def audio_bytes(format, bytes_or_base64) + when format in ~w(mp3 opus wav aac flac mp4 ogg mkv) do + %{ + audio: %{ + format: format, + source: %{bytes: bytes_or_base64} + } + } + end + + @doc "Audio content item via S3 Location" + def audio_s3(format, uri, bucket_owner \\ nil) + when format in ~w(mp3 opus wav aac flac mp4 ogg mkv) do + s3_loc = + %{uri: uri} + |> then(fn map -> if bucket_owner, do: Map.put(map, :bucketOwner, bucket_owner), else: map end) + + %{ + audio: %{ + format: format, + source: %{s3Location: s3_loc} + } + } + end +end \ No newline at end of file diff --git a/lib/ex_aws/bedrock/nova/inference_config.ex b/lib/ex_aws/bedrock/nova/inference_config.ex new file mode 100644 index 0000000..b4605d3 --- /dev/null +++ b/lib/ex_aws/bedrock/nova/inference_config.ex @@ -0,0 +1,53 @@ +defmodule ExAws.Bedrock.Nova.InferenceConfig do + @moduledoc """ + Inference options for Nova text models. + """ + + alias ExAws.Bedrock.Nova.ReasoningConfig + + defstruct [ + :maxTokens, + :temperature, + :topP, + :topK, + :stopSequences, + :reasoningConfig + ] + + @type t :: %__MODULE__{ + maxTokens: pos_integer() | nil, + temperature: float() | nil, + topP: float() | nil, + topK: non_neg_integer() | nil, + stopSequences: list(String.t()) | nil, + reasoningConfig: ReasoningConfig.t() | nil + } + + def build(opts \\ []) when is_list(opts) do + reasoning = + case Keyword.get(opts, :reasoning_config) do + %ReasoningConfig{} = config -> config + opts when is_list(opts) -> ReasoningConfig.build(opts) + _ -> nil + end + + %__MODULE__{ + maxTokens: Keyword.get(opts, :max_tokens), + temperature: Keyword.get(opts, :temperature), + topP: Keyword.get(opts, :top_p), + topK: Keyword.get(opts, :top_k), + stopSequences: Keyword.get(opts, :stop_sequences), + reasoningConfig: reasoning + } + end +end + +defimpl Jason.Encoder, for: ExAws.Bedrock.Nova.InferenceConfig do + def encode(struct, opts) do + struct + |> Map.from_struct() + |> Enum.reject(fn {_k, v} -> is_nil(v) end) + |> Map.new() + |> Jason.Encode.map(opts) + end +end \ No newline at end of file diff --git a/lib/ex_aws/bedrock/nova/message.ex b/lib/ex_aws/bedrock/nova/message.ex new file mode 100644 index 0000000..fdf8563 --- /dev/null +++ b/lib/ex_aws/bedrock/nova/message.ex @@ -0,0 +1,40 @@ +defmodule ExAws.Bedrock.Nova.Message do + @moduledoc """ + Encapsulates user and assistant turns in the conversation. + """ + + alias ExAws.Bedrock.Nova.Content + + defstruct [:role, :content] + + @type role :: :user | :assistant + @type t :: %__MODULE__{ + role: String.t(), + content: list(map()) + } + + @doc "Constructs a user turn with text or multimodal content items." + def user(content) when is_binary(content), do: build("user", [Content.text(content)]) + def user(content) when is_list(content), do: build("user", content) + + @doc "Constructs an assistant turn (useful for prompt pre-filling)." + def assistant(content) when is_binary(content), do: build("assistant", [Content.text(content)]) + def assistant(content) when is_list(content), do: build("assistant", content) + + def build(role, content) when role in ["user", "assistant", :user, :assistant] do + %__MODULE__{ + role: to_string(role), + content: content + } + end +end + +defimpl Jason.Encoder, for: ExAws.Bedrock.Nova.Message do + def encode(struct, opts) do + struct + |> Map.from_struct() + |> Enum.reject(fn {_k, v} -> is_nil(v) end) + |> Map.new() + |> Jason.Encode.map(opts) + end +end \ No newline at end of file diff --git a/lib/ex_aws/bedrock/nova/reasoning_config.ex b/lib/ex_aws/bedrock/nova/reasoning_config.ex new file mode 100644 index 0000000..4b80fae --- /dev/null +++ b/lib/ex_aws/bedrock/nova/reasoning_config.ex @@ -0,0 +1,31 @@ +defmodule ExAws.Bedrock.Nova.ReasoningConfig do + @moduledoc """ + Reasoning configuration parameters for Nova reasoning models. + """ + + defstruct [:type, :maxReasoningEffort] + + @type type :: String.t() + @type max_effort :: String.t() + @type t :: %__MODULE__{ + type: type() | nil, + maxReasoningEffort: max_effort() | nil + } + + def build(opts) when is_list(opts) do + %__MODULE__{ + type: Keyword.get(opts, :type, "disabled"), + maxReasoningEffort: Keyword.get(opts, :max_reasoning_effort) + } + end +end + +defimpl Jason.Encoder, for: ExAws.Bedrock.Nova.ReasoningConfig do + def encode(struct, opts) do + struct + |> Map.from_struct() + |> Enum.reject(fn {_k, v} -> is_nil(v) end) + |> Map.new() + |> Jason.Encode.map(opts) + end +end \ No newline at end of file diff --git a/lib/ex_aws/bedrock/nova/text_model.ex b/lib/ex_aws/bedrock/nova/text_model.ex new file mode 100644 index 0000000..20ae014 --- /dev/null +++ b/lib/ex_aws/bedrock/nova/text_model.ex @@ -0,0 +1,64 @@ +defmodule ExAws.Bedrock.Nova.TextModel do + @moduledoc """ + Top-level request payload structure for Amazon Nova models on Bedrock. + """ + + alias ExAws.Bedrock.Nova.{InferenceConfig, Message, ToolConfig} + + defstruct [ + :messages, + :system, + :inferenceConfig, + :toolConfig + ] + + @type t :: %__MODULE__{ + messages: list(Message.t()), + system: list(%{text: String.t()}) | nil, + inferenceConfig: InferenceConfig.t() | nil, + toolConfig: ToolConfig.t() | nil + } + + @doc """ + Build a `TextModel` struct. + + ## Options + * `:system` - String system prompt or list of system prompt maps. + * `:inference_config` - Keyword list or `%InferenceConfig{}`. + * `:tool_config` - Keyword list or `%ToolConfig{}`. + """ + def build(messages, opts \\ []) when is_list(messages) do + system = + case Keyword.get(opts, :system) do + nil -> nil + prompt when is_binary(prompt) -> [%{text: prompt}] + list when is_list(list) -> list + end + + inference_config = + case Keyword.get(opts, :inference_config) do + %InferenceConfig{} = config -> config + opts when is_list(opts) -> InferenceConfig.build(opts) + _ -> nil + end + + tool_config = Keyword.get(opts, :tool_config) + + %__MODULE__{ + messages: messages, + system: system, + inferenceConfig: inference_config, + toolConfig: tool_config + } + end +end + +defimpl Jason.Encoder, for: ExAws.Bedrock.Nova.TextModel do + def encode(struct, opts) do + struct + |> Map.from_struct() + |> Enum.reject(fn {_k, v} -> is_nil(v) end) + |> Map.new() + |> Jason.Encode.map(opts) + end +end \ No newline at end of file diff --git a/lib/ex_aws/bedrock/nova/tool_config.ex b/lib/ex_aws/bedrock/nova/tool_config.ex new file mode 100644 index 0000000..a5b5327 --- /dev/null +++ b/lib/ex_aws/bedrock/nova/tool_config.ex @@ -0,0 +1,35 @@ +defmodule ExAws.Bedrock.Nova.ToolConfig do + @moduledoc """ + Tool specifications and tool choice settings. + """ + + defstruct [:tools, :toolChoice] + + @type tool_choice :: %{auto: %{}} | %{any: %{}} | %{tool: %{name: String.t()}} + @type t :: %__MODULE__{ + tools: list(map()), + toolChoice: tool_choice() | nil + } + + def build(tools, tool_choice \\ :auto) do + %__MODULE__{ + tools: tools, + toolChoice: format_tool_choice(tool_choice) + } + end + + defp format_tool_choice(:auto), do: %{auto: %{}} + defp format_tool_choice(:any), do: %{any: %{}} + defp format_tool_choice({:tool, name}) when is_binary(name), do: %{tool: %{name: name}} + defp format_tool_choice(map) when is_map(map), do: map +end + +defimpl Jason.Encoder, for: ExAws.Bedrock.Nova.ToolConfig do + def encode(struct, opts) do + struct + |> Map.from_struct() + |> Enum.reject(fn {_k, v} -> is_nil(v) end) + |> Map.new() + |> Jason.Encode.map(opts) + end +end \ No newline at end of file diff --git a/lib/ex_aws/bedrock/nova/tool_spec.ex b/lib/ex_aws/bedrock/nova/tool_spec.ex new file mode 100644 index 0000000..8297232 --- /dev/null +++ b/lib/ex_aws/bedrock/nova/tool_spec.ex @@ -0,0 +1,33 @@ +defmodule ExAws.Bedrock.Nova.ToolSpec do + @moduledoc """ + Defines an individual tool schema for tool use/function calling. + """ + + defstruct [:name, :description, :inputSchema] + + @type t :: %__MODULE__{ + name: String.t(), + description: String.t() | nil, + inputSchema: %{json: map()} + } + + def build(name, description, json_schema) do + %{ + toolSpec: %__MODULE__{ + name: name, + description: description, + inputSchema: %{json: json_schema} + } + } + end +end + +defimpl Jason.Encoder, for: ExAws.Bedrock.Nova.ToolSpec do + def encode(struct, opts) do + struct + |> Map.from_struct() + |> Enum.reject(fn {_k, v} -> is_nil(v) end) + |> Map.new() + |> Jason.Encode.map(opts) + end +end \ No newline at end of file From 7c85e83f32d17aeb82164fcb1c8d763b2828f687 Mon Sep 17 00:00:00 2001 From: Devstopfix Date: Fri, 14 Aug 2026 08:42:14 +0100 Subject: [PATCH 7/9] Fix model path tests --- test/ex_aws/bedrock_test.exs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/test/ex_aws/bedrock_test.exs b/test/ex_aws/bedrock_test.exs index 6618709..85e35dd 100644 --- a/test/ex_aws/bedrock_test.exs +++ b/test/ex_aws/bedrock_test.exs @@ -49,7 +49,7 @@ defmodule ExAws.BedrockTest do end test "path", %{request: request} do - assert %JSON{path: "/foundation-models/amazon.titan-text-express-v1"} = request + assert %JSON{path: "/foundation-models/amazon.nova-micro-v1:0"} = request end test "service", %{request: request} do @@ -70,13 +70,6 @@ defmodule ExAws.BedrockTest do assert {:ok, %{"results" => [%{"outputText" => _output} | _]}} = request(request) end - @tag :aws - test "against AWS!" do - inference_parameters = TextModel.build(@prompt, maxTokenCount: 32) - request = Bedrock.invoke_model(@model_id, inference_parameters) - assert %{"results" => [%{"outputText" => _output} | _]} = request!(request) - end - test "content type is JSON", %{request: request} do assert %JSON{headers: headers} = request assert {_, "application/json"} = List.keyfind(headers, "Content-Type", 0) @@ -87,7 +80,7 @@ defmodule ExAws.BedrockTest do end test "path", %{request: request} do - assert %JSON{path: "/model/amazon.titan-text-express-v1/invoke"} = request + assert %JSON{path: "/model/amazon.nova-micro-v1:0/invoke"} = request end test "service", %{request: request} do From ca73bec123752c6a922ee6ff8230c560e89c3e0a Mon Sep 17 00:00:00 2001 From: Devstopfix Date: Fri, 14 Aug 2026 08:52:28 +0100 Subject: [PATCH 8/9] Nova text unit test --- lib/ex_aws/bedrock/nova/content.ex | 10 +++++++--- lib/ex_aws/bedrock/nova/inference_config.ex | 2 +- lib/ex_aws/bedrock/nova/message.ex | 2 +- lib/ex_aws/bedrock/nova/reasoning_config.ex | 2 +- lib/ex_aws/bedrock/nova/text_model.ex | 2 +- lib/ex_aws/bedrock/nova/tool_config.ex | 2 +- lib/ex_aws/bedrock/nova/tool_spec.ex | 2 +- test/ex_aws/bedrock_test.exs | 13 +++++++++++-- 8 files changed, 24 insertions(+), 11 deletions(-) diff --git a/lib/ex_aws/bedrock/nova/content.ex b/lib/ex_aws/bedrock/nova/content.ex index 59f91dc..8431eac 100644 --- a/lib/ex_aws/bedrock/nova/content.ex +++ b/lib/ex_aws/bedrock/nova/content.ex @@ -32,7 +32,9 @@ defmodule ExAws.Bedrock.Nova.Content do when format in ~w(mkv mov mp4 webm three_gp flv mpeg mpg wmv) do s3_loc = %{uri: uri} - |> then(fn map -> if bucket_owner, do: Map.put(map, :bucketOwner, bucket_owner), else: map end) + |> then(fn map -> + if bucket_owner, do: Map.put(map, :bucketOwner, bucket_owner), else: map + end) %{ video: %{ @@ -58,7 +60,9 @@ defmodule ExAws.Bedrock.Nova.Content do when format in ~w(mp3 opus wav aac flac mp4 ogg mkv) do s3_loc = %{uri: uri} - |> then(fn map -> if bucket_owner, do: Map.put(map, :bucketOwner, bucket_owner), else: map end) + |> then(fn map -> + if bucket_owner, do: Map.put(map, :bucketOwner, bucket_owner), else: map + end) %{ audio: %{ @@ -67,4 +71,4 @@ defmodule ExAws.Bedrock.Nova.Content do } } end -end \ No newline at end of file +end diff --git a/lib/ex_aws/bedrock/nova/inference_config.ex b/lib/ex_aws/bedrock/nova/inference_config.ex index b4605d3..d8d69b8 100644 --- a/lib/ex_aws/bedrock/nova/inference_config.ex +++ b/lib/ex_aws/bedrock/nova/inference_config.ex @@ -50,4 +50,4 @@ defimpl Jason.Encoder, for: ExAws.Bedrock.Nova.InferenceConfig do |> Map.new() |> Jason.Encode.map(opts) end -end \ No newline at end of file +end diff --git a/lib/ex_aws/bedrock/nova/message.ex b/lib/ex_aws/bedrock/nova/message.ex index fdf8563..01d9a44 100644 --- a/lib/ex_aws/bedrock/nova/message.ex +++ b/lib/ex_aws/bedrock/nova/message.ex @@ -37,4 +37,4 @@ defimpl Jason.Encoder, for: ExAws.Bedrock.Nova.Message do |> Map.new() |> Jason.Encode.map(opts) end -end \ No newline at end of file +end diff --git a/lib/ex_aws/bedrock/nova/reasoning_config.ex b/lib/ex_aws/bedrock/nova/reasoning_config.ex index 4b80fae..bf6030e 100644 --- a/lib/ex_aws/bedrock/nova/reasoning_config.ex +++ b/lib/ex_aws/bedrock/nova/reasoning_config.ex @@ -28,4 +28,4 @@ defimpl Jason.Encoder, for: ExAws.Bedrock.Nova.ReasoningConfig do |> Map.new() |> Jason.Encode.map(opts) end -end \ No newline at end of file +end diff --git a/lib/ex_aws/bedrock/nova/text_model.ex b/lib/ex_aws/bedrock/nova/text_model.ex index 20ae014..53b492f 100644 --- a/lib/ex_aws/bedrock/nova/text_model.ex +++ b/lib/ex_aws/bedrock/nova/text_model.ex @@ -61,4 +61,4 @@ defimpl Jason.Encoder, for: ExAws.Bedrock.Nova.TextModel do |> Map.new() |> Jason.Encode.map(opts) end -end \ No newline at end of file +end diff --git a/lib/ex_aws/bedrock/nova/tool_config.ex b/lib/ex_aws/bedrock/nova/tool_config.ex index a5b5327..df750b0 100644 --- a/lib/ex_aws/bedrock/nova/tool_config.ex +++ b/lib/ex_aws/bedrock/nova/tool_config.ex @@ -32,4 +32,4 @@ defimpl Jason.Encoder, for: ExAws.Bedrock.Nova.ToolConfig do |> Map.new() |> Jason.Encode.map(opts) end -end \ No newline at end of file +end diff --git a/lib/ex_aws/bedrock/nova/tool_spec.ex b/lib/ex_aws/bedrock/nova/tool_spec.ex index 8297232..676f484 100644 --- a/lib/ex_aws/bedrock/nova/tool_spec.ex +++ b/lib/ex_aws/bedrock/nova/tool_spec.ex @@ -30,4 +30,4 @@ defimpl Jason.Encoder, for: ExAws.Bedrock.Nova.ToolSpec do |> Map.new() |> Jason.Encode.map(opts) end -end \ No newline at end of file +end diff --git a/test/ex_aws/bedrock_test.exs b/test/ex_aws/bedrock_test.exs index 85e35dd..55c9c51 100644 --- a/test/ex_aws/bedrock_test.exs +++ b/test/ex_aws/bedrock_test.exs @@ -2,6 +2,7 @@ defmodule ExAws.BedrockTest do use ExUnit.Case, async: true import ExAws.Bedrock, only: [request: 1, request!: 1] alias ExAws.Bedrock + alias ExAws.Bedrock.Nova.{Message, TextModel} alias ExAws.Bedrock.Titan.TextModel alias ExAws.Operation.JSON @@ -65,9 +66,17 @@ defmodule ExAws.BedrockTest do describe "invoke_model/2 text" do @tag :aws test "against AWS" do - inference_parameters = TextModel.build(@prompt, maxTokenCount: 32) + # inference_parameters = TextModel.build(@prompt, maxTokenCount: 32) + inference_parameters = + TextModel.build( + [Message.user("Hello Amazon Nova!")], + system: "You are a helpful Elixir assistant.", + inference_config: [temperature: 0.5, max_tokens: 32] + ) + request = Bedrock.invoke_model(@model_id, inference_parameters) - assert {:ok, %{"results" => [%{"outputText" => _output} | _]}} = request(request) + + assert {:ok, %{"output" => %{"message" => %{"content" => [%{"text" => _}]}}}} = request(request) end test "content type is JSON", %{request: request} do From 7c8370201e9c3b13bac62863abe67fc657428a72 Mon Sep 17 00:00:00 2001 From: Devstopfix Date: Fri, 14 Aug 2026 09:01:09 +0100 Subject: [PATCH 9/9] Credo pipeline --- lib/ex_aws/bedrock/nova/content.ex | 6 ++---- test/ex_aws/bedrock_test.exs | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/ex_aws/bedrock/nova/content.ex b/lib/ex_aws/bedrock/nova/content.ex index 8431eac..30db0b0 100644 --- a/lib/ex_aws/bedrock/nova/content.ex +++ b/lib/ex_aws/bedrock/nova/content.ex @@ -31,8 +31,7 @@ defmodule ExAws.Bedrock.Nova.Content do def video_s3(format, uri, bucket_owner \\ nil) when format in ~w(mkv mov mp4 webm three_gp flv mpeg mpg wmv) do s3_loc = - %{uri: uri} - |> then(fn map -> + then(%{uri: uri}, fn map -> if bucket_owner, do: Map.put(map, :bucketOwner, bucket_owner), else: map end) @@ -59,8 +58,7 @@ defmodule ExAws.Bedrock.Nova.Content do def audio_s3(format, uri, bucket_owner \\ nil) when format in ~w(mp3 opus wav aac flac mp4 ogg mkv) do s3_loc = - %{uri: uri} - |> then(fn map -> + then(%{uri: uri}, fn map -> if bucket_owner, do: Map.put(map, :bucketOwner, bucket_owner), else: map end) diff --git a/test/ex_aws/bedrock_test.exs b/test/ex_aws/bedrock_test.exs index 55c9c51..d79c3ce 100644 --- a/test/ex_aws/bedrock_test.exs +++ b/test/ex_aws/bedrock_test.exs @@ -76,7 +76,8 @@ defmodule ExAws.BedrockTest do request = Bedrock.invoke_model(@model_id, inference_parameters) - assert {:ok, %{"output" => %{"message" => %{"content" => [%{"text" => _}]}}}} = request(request) + assert {:ok, %{"output" => %{"message" => %{"content" => [%{"text" => _}]}}}} = + request(request) end test "content type is JSON", %{request: request} do