diff --git a/examples/phoenix/image_classification.exs b/examples/phoenix/image_classification.exs
index d77f0c7c..f0374f42 100644
--- a/examples/phoenix/image_classification.exs
+++ b/examples/phoenix/image_classification.exs
@@ -1,17 +1,5 @@
-Application.put_env(:sample, PhoenixDemo.Endpoint,
- http: [ip: {127, 0, 0, 1}, port: 8080],
- server: true,
- live_view: [signing_salt: "bumblebee"],
- secret_key_base: String.duplicate("b", 64),
- pubsub_server: PhoenixDemo.PubSub
-)
-
Mix.install([
- {:plug_cowboy, "~> 2.6"},
- {:jason, "~> 1.4"},
- {:phoenix, "1.7.10"},
- {:phoenix_live_view, "0.20.1"},
- # Bumblebee and friends
+ {:phoenix_playground, "~> 0.1.7"},
{:bumblebee, "~> 0.6.0"},
{:nx, "~> 0.9.0"},
{:exla, "~> 0.9.0"}
@@ -19,201 +7,178 @@ Mix.install([
Application.put_env(:nx, :default_backend, EXLA.Backend)
-defmodule PhoenixDemo.Layouts do
- use Phoenix.Component
+defmodule DemoLive do
+ use Phoenix.LiveView
+
+ @impl true
+ def mount(_params, _session, socket) do
+ {:ok,
+ socket
+ |> assign(label: nil)
+ |> allow_upload(:image, accept: :any, progress: &handle_progress/3, auto_upload: true)}
+ end
- def render("live.html", assigns) do
+ @impl true
+ def render(assigns) do
~H"""
-
-
-
-
- <%= @inner_content %>
- """
- end
-end
+ canvas.width = scaledWidth;
+ canvas.height = scaledHeight;
-defmodule PhoenixDemo.ErrorView do
- def render(_, _), do: "error"
-end
+ ctx.drawImage(imgEl, 0, 0, width, height, 0, 0, scaledWidth, scaledHeight);
-defmodule PhoenixDemo.SampleLive do
- use Phoenix.LiveView, layout: {PhoenixDemo.Layouts, :live}
+ return canvas;
+ },
- @impl true
- def mount(_params, _session, socket) do
- {:ok,
- socket
- |> assign(label: nil)
- |> allow_upload(:image, accept: :any, progress: &handle_progress/3, auto_upload: true)}
- end
+ canvasToBlob(canvas) {
+ const imageData = canvas
+ .getContext("2d")
+ .getImageData(0, 0, canvas.width, canvas.height);
- @impl true
- def render(assigns) do
- ~H"""
-
-
-
-
- Label:
- <.async_result :let={label} assign={@label} :if={@label}>
- <:loading>
- <.spinner />
-
- <:failed :let={_reason}>
- Oops, something went wrong!
-
- <%= label %>
-
-
-
+ const buffer = this.imageDataToRGBBuffer(imageData);
+
+ const meta = new ArrayBuffer(8);
+ const view = new DataView(meta);
+ view.setUint32(0, canvas.height, false);
+ view.setUint32(4, canvas.width, false);
+
+ return new Blob([meta, buffer], { type: "application/octet-stream" });
+ },
+
+ imageDataToRGBBuffer(imageData) {
+ const pixelCount = imageData.width * imageData.height;
+ const bytes = new Uint8ClampedArray(pixelCount * 3);
+
+ for (let i = 0; i < pixelCount; i++) {
+ bytes[i * 3] = imageData.data[i * 4];
+ bytes[i * 3 + 1] = imageData.data[i * 4 + 1];
+ bytes[i * 3 + 2] = imageData.data[i * 4 + 2];
+ }
+
+ return bytes.buffer;
+ },
+ };
+
"""
end
@@ -276,7 +241,7 @@ defmodule PhoenixDemo.SampleLive do
# Discard previous label so we show the loading state once more
|> assign(:label, nil)
|> assign_async(:label, fn ->
- output = Nx.Serving.batched_run(PhoenixDemo.Serving, image)
+ output = Nx.Serving.batched_run(Demo.Serving, image)
%{predictions: [%{label: label}]} = output
{:ok, %{label: label}}
end)
@@ -299,29 +264,6 @@ defmodule PhoenixDemo.SampleLive do
end
end
-defmodule PhoenixDemo.Router do
- use Phoenix.Router
-
- import Phoenix.LiveView.Router
-
- pipeline :browser do
- plug(:accepts, ["html"])
- end
-
- scope "/", PhoenixDemo do
- pipe_through(:browser)
-
- live("/", SampleLive, :index)
- end
-end
-
-defmodule PhoenixDemo.Endpoint do
- use Phoenix.Endpoint, otp_app: :sample
-
- socket("/live", Phoenix.LiveView.Socket)
- plug(PhoenixDemo.Router)
-end
-
# Application startup
{:ok, model_info} = Bumblebee.load_model({:hf, "microsoft/resnet-50"})
@@ -331,17 +273,12 @@ serving =
Bumblebee.Vision.image_classification(model_info, featurizer,
top_k: 1,
compile: [batch_size: 4],
- defn_options: [compiler: EXLA]
+ defn_options: [
+ compiler: EXLA,
+ cache: Path.join(System.tmp_dir!(), "bumblebee_examples/image_classification")
+ ]
)
-{:ok, _} =
- Supervisor.start_link(
- [
- {Phoenix.PubSub, name: PhoenixDemo.PubSub},
- {Nx.Serving, serving: serving, name: PhoenixDemo.Serving, batch_timeout: 100},
- PhoenixDemo.Endpoint
- ],
- strategy: :one_for_one
- )
+Nx.Serving.start_link(serving: serving, name: Demo.Serving, batch_timeout: 100)
-Process.sleep(:infinity)
+PhoenixPlayground.start(live: DemoLive, port: 8080)
diff --git a/examples/phoenix/speech_to_text.exs b/examples/phoenix/speech_to_text.exs
index 7db93fee..f51bdb30 100644
--- a/examples/phoenix/speech_to_text.exs
+++ b/examples/phoenix/speech_to_text.exs
@@ -1,17 +1,5 @@
-Application.put_env(:sample, PhoenixDemo.Endpoint,
- http: [ip: {127, 0, 0, 1}, port: 8080],
- server: true,
- live_view: [signing_salt: "bumblebee"],
- secret_key_base: String.duplicate("b", 64),
- pubsub_server: PhoenixDemo.PubSub
-)
-
Mix.install([
- {:plug_cowboy, "~> 2.6"},
- {:jason, "~> 1.4"},
- {:phoenix, "1.7.10"},
- {:phoenix_live_view, "0.20.1"},
- # Bumblebee and friends
+ {:phoenix_playground, "~> 0.1.7"},
{:bumblebee, "~> 0.6.0"},
{:nx, "~> 0.9.0"},
{:exla, "~> 0.9.0"}
@@ -19,21 +7,62 @@ Mix.install([
Application.put_env(:nx, :default_backend, EXLA.Backend)
-defmodule PhoenixDemo.Layouts do
- use Phoenix.Component
+defmodule DemoLive do
+ use Phoenix.LiveView
- def render("live.html", assigns) do
+ @impl true
+ def mount(_params, _session, socket) do
+ {:ok,
+ socket
+ |> assign(transcription: nil)
+ |> allow_upload(:audio, accept: :any, progress: &handle_progress/3, auto_upload: true)}
+ end
+
+ @impl true
+ def render(assigns) do
~H"""
-
-
+
+
+
+
+
Press and hold
+
+
+
+
+
+
+
+
Transcription:
+ <.async_result :let={transcription} :if={@transcription} assign={@transcription}>
+ <:loading>
+ <.spinner />
+
+ <:failed :let={_reason}>
+
Oops, something went wrong!
+
+
<%= transcription %>
+
+
+
+
+
-
- <%= @inner_content %>
- """
- end
-end
-
-defmodule PhoenixDemo.ErrorView do
- def render(_, _), do: "error"
-end
-
-defmodule PhoenixDemo.SampleLive do
- use Phoenix.LiveView, layout: {PhoenixDemo.Layouts, :live}
-
- @impl true
- def mount(_params, _session, socket) do
- {:ok,
- socket
- |> assign(transcription: nil)
- |> allow_upload(:audio, accept: :any, progress: &handle_progress/3, auto_upload: true)}
- end
-
- @impl true
- def render(assigns) do
- ~H"""
-
-
-
-
Press and hold
-
-
-
-
-
-
-
-
Transcription:
- <.async_result :let={transcription} assign={@transcription} :if={@transcription}>
- <:loading>
- <.spinner />
-
- <:failed :let={_reason}>
-
Oops, something went wrong!
-
-
<%= transcription %>
-
-
-
-
"""
end
@@ -274,7 +239,7 @@ defmodule PhoenixDemo.SampleLive do
# Discard previous transcription so we show the loading state once more
|> assign(:transcription, nil)
|> assign_async(:transcription, fn ->
- output = Nx.Serving.batched_run(PhoenixDemo.Serving, audio)
+ output = Nx.Serving.batched_run(Demo.Serving, audio)
transcription = output.chunks |> Enum.map_join(& &1.text) |> String.trim()
{:ok, %{transcription: transcription}}
end)
@@ -293,29 +258,6 @@ defmodule PhoenixDemo.SampleLive do
end
end
-defmodule PhoenixDemo.Router do
- use Phoenix.Router
-
- import Phoenix.LiveView.Router
-
- pipeline :browser do
- plug(:accepts, ["html"])
- end
-
- scope "/", PhoenixDemo do
- pipe_through(:browser)
-
- live("/", SampleLive, :index)
- end
-end
-
-defmodule PhoenixDemo.Endpoint do
- use Phoenix.Endpoint, otp_app: :sample
-
- socket("/live", Phoenix.LiveView.Socket)
- plug(PhoenixDemo.Router)
-end
-
# Application startup
{:ok, model_info} = Bumblebee.load_model({:hf, "openai/whisper-tiny"})
@@ -326,17 +268,12 @@ end
serving =
Bumblebee.Audio.speech_to_text_whisper(model_info, featurizer, tokenizer, generation_config,
compile: [batch_size: 4],
- defn_options: [compiler: EXLA]
+ defn_options: [
+ compiler: EXLA,
+ cache: Path.join(System.tmp_dir!(), "bumblebee_examples/speech_to_text")
+ ]
)
-{:ok, _} =
- Supervisor.start_link(
- [
- {Phoenix.PubSub, name: PhoenixDemo.PubSub},
- {Nx.Serving, serving: serving, name: PhoenixDemo.Serving, batch_timeout: 100},
- PhoenixDemo.Endpoint
- ],
- strategy: :one_for_one
- )
+Nx.Serving.start_link(serving: serving, name: Demo.Serving, batch_timeout: 100)
-Process.sleep(:infinity)
+PhoenixPlayground.start(live: DemoLive, port: 8080)
diff --git a/examples/phoenix/text_classification.exs b/examples/phoenix/text_classification.exs
index 63436959..77b2d135 100644
--- a/examples/phoenix/text_classification.exs
+++ b/examples/phoenix/text_classification.exs
@@ -1,16 +1,5 @@
-Application.put_env(:sample, PhoenixDemo.Endpoint,
- http: [ip: {127, 0, 0, 1}, port: 8080],
- server: true,
- live_view: [signing_salt: "bumblebee"],
- secret_key_base: String.duplicate("b", 64)
-)
-
Mix.install([
- {:plug_cowboy, "~> 2.6"},
- {:jason, "~> 1.4"},
- {:phoenix, "1.7.10"},
- {:phoenix_live_view, "0.20.1"},
- # Bumblebee and friends
+ {:phoenix_playground, "~> 0.1.7"},
{:bumblebee, "~> 0.6.0"},
{:nx, "~> 0.9.0"},
{:exla, "~> 0.9.0"}
@@ -18,34 +7,8 @@ Mix.install([
Application.put_env(:nx, :default_backend, EXLA.Backend)
-defmodule PhoenixDemo.Layouts do
- use Phoenix.Component
-
- def render("live.html", assigns) do
- ~H"""
-
-
-
-
- <%= @inner_content %>
- """
- end
-end
-
-defmodule PhoenixDemo.ErrorView do
- def render(_, _), do: "error"
-end
-
-defmodule PhoenixDemo.SampleLive do
- use Phoenix.LiveView, layout: {PhoenixDemo.Layouts, :live}
+defmodule DemoLive do
+ use Phoenix.LiveView
@impl true
def mount(_params, _session, socket) do
@@ -55,6 +18,9 @@ defmodule PhoenixDemo.SampleLive do
@impl true
def render(assigns) do
~H"""
+
+
Emotion:
- <.async_result :let={label} assign={@label} :if={@label}>
+ <.async_result :let={label} :if={@label} assign={@label}>
<:loading>
<.spinner />
@@ -117,7 +83,7 @@ defmodule PhoenixDemo.SampleLive do
# Discard previous label so we show the loading state once more
|> assign(:label, nil)
|> assign_async(:label, fn ->
- output = Nx.Serving.batched_run(PhoenixDemo.Serving, text)
+ output = Nx.Serving.batched_run(Demo.Serving, text)
%{predictions: [%{label: label}]} = output
{:ok, %{label: label}}
end)
@@ -126,29 +92,6 @@ defmodule PhoenixDemo.SampleLive do
end
end
-defmodule PhoenixDemo.Router do
- use Phoenix.Router
-
- import Phoenix.LiveView.Router
-
- pipeline :browser do
- plug(:accepts, ["html"])
- end
-
- scope "/", PhoenixDemo do
- pipe_through(:browser)
-
- live("/", SampleLive, :index)
- end
-end
-
-defmodule PhoenixDemo.Endpoint do
- use Phoenix.Endpoint, otp_app: :sample
-
- socket("/live", Phoenix.LiveView.Socket)
- plug(PhoenixDemo.Router)
-end
-
# Application startup
{:ok, model_info} = Bumblebee.load_model({:hf, "finiteautomata/bertweet-base-emotion-analysis"})
@@ -158,16 +101,12 @@ serving =
Bumblebee.Text.text_classification(model_info, tokenizer,
top_k: 1,
compile: [batch_size: 4, sequence_length: 100],
- defn_options: [compiler: EXLA]
+ defn_options: [
+ compiler: EXLA,
+ cache: Path.join(System.tmp_dir!(), "bumblebee_examples/text_classification")
+ ]
)
-{:ok, _} =
- Supervisor.start_link(
- [
- {Nx.Serving, serving: serving, name: PhoenixDemo.Serving, batch_timeout: 100},
- PhoenixDemo.Endpoint
- ],
- strategy: :one_for_one
- )
+Nx.Serving.start_link(serving: serving, name: Demo.Serving, batch_timeout: 100)
-Process.sleep(:infinity)
+PhoenixPlayground.start(live: DemoLive, port: 8080)