diff --git a/lib/music_library/records.ex b/lib/music_library/records.ex
index 376a844f..d69261cb 100644
--- a/lib/music_library/records.ex
+++ b/lib/music_library/records.ex
@@ -185,6 +185,27 @@ defmodule MusicLibrary.Records do
end
end
+ def populate_genres(record) do
+ artists =
+ record.artists
+ |> Enum.map(fn a -> a.name end)
+ |> Enum.join(",")
+
+ prompt = """
+ Provide a list of music genres applicable to the album "#{record.title}" by #{artists}.
+
+ Limit the list to 5 genres, ordered by decreasing specificity, all lowercase.
+
+ Return a valid JSON list.
+ """
+
+ {:ok, response} = OpenAI.gpt(prompt)
+
+ record
+ |> Record.add_genres(response["genres"])
+ |> Repo.update()
+ end
+
defp get_cover_art_or_default(musicbrainz_id) do
case music_brainz_config().api.get_cover_art(
{:musicbrainz_id, musicbrainz_id},
diff --git a/lib/music_library/records/record.ex b/lib/music_library/records/record.ex
index c8410c9f..d367554e 100644
--- a/lib/music_library/records/record.ex
+++ b/lib/music_library/records/record.ex
@@ -84,6 +84,10 @@ defmodule MusicLibrary.Records.Record do
|> put_embed(:artists, artists_attrs)
end
+ def add_genres(record, genres) do
+ change(record, genres: genres)
+ end
+
def add_cover_data(record, cover_data) do
record
|> change(cover_data: cover_data)
diff --git a/lib/music_library_web/live/collection_live/show.ex b/lib/music_library_web/live/collection_live/show.ex
index 97913734..471e2156 100644
--- a/lib/music_library_web/live/collection_live/show.ex
+++ b/lib/music_library_web/live/collection_live/show.ex
@@ -63,6 +63,26 @@ defmodule MusicLibraryWeb.CollectionLive.Show do
end
end
+ def handle_event("populate_genres", %{"id" => id}, socket) do
+ record = Records.get_record!(id)
+
+ case Records.populate_genres(record) do
+ {:ok, updated_record} ->
+ {:noreply,
+ socket
+ |> put_flash(:info, gettext("Genres populated successfully"))
+ |> assign(:record, updated_record)}
+
+ {:error, reason} ->
+ {:noreply,
+ socket
+ |> put_flash(
+ :error,
+ gettext("Error populating genres") <> "," <> inspect(reason)
+ )}
+ end
+ end
+
def handle_event("refresh_cover", %{"id" => id}, socket) do
record = Records.get_record!(id)
diff --git a/lib/music_library_web/live/collection_live/show.html.heex b/lib/music_library_web/live/collection_live/show.html.heex
index 26995b61..f7203138 100644
--- a/lib/music_library_web/live/collection_live/show.html.heex
+++ b/lib/music_library_web/live/collection_live/show.html.heex
@@ -56,6 +56,18 @@
{gettext("MB Data")}
+ <.link phx-click={JS.push("populate_genres", value: %{id: @record.id})}>
+ <.button type="button" class="relative -ml-px inline-flex items-center rounded-none">
+ {gettext("Populate")}
+ <.icon
+ name="hero-sparkles"
+ class="h-4 w-4 mr-1 phx-click-loading:animate-shake"
+ aria-hidden="true"
+ data-slot="icon"
+ />
+ {gettext("Genres")}
+
+
<.link
phx-click={JS.push("delete", value: %{id: @record.id})}
data-confirm={gettext("Are you sure?")}
diff --git a/lib/music_library_web/live/wishlist_live/show.ex b/lib/music_library_web/live/wishlist_live/show.ex
index 4d9359ba..a6314d2b 100644
--- a/lib/music_library_web/live/wishlist_live/show.ex
+++ b/lib/music_library_web/live/wishlist_live/show.ex
@@ -83,6 +83,26 @@ defmodule MusicLibraryWeb.WishlistLive.Show do
end
end
+ def handle_event("populate_genres", %{"id" => id}, socket) do
+ record = Records.get_record!(id)
+
+ case Records.populate_genres(record) do
+ {:ok, updated_record} ->
+ {:noreply,
+ socket
+ |> put_flash(:info, gettext("Genres populated successfully"))
+ |> assign(:record, updated_record)}
+
+ {:error, reason} ->
+ {:noreply,
+ socket
+ |> put_flash(
+ :error,
+ gettext("Error populating genres") <> "," <> inspect(reason)
+ )}
+ end
+ end
+
@impl true
def handle_info({MusicLibraryWeb.RecordLive.FormComponent, {:saved, record}}, socket) do
{:noreply, assign(socket, :record, record)}
diff --git a/lib/music_library_web/live/wishlist_live/show.html.heex b/lib/music_library_web/live/wishlist_live/show.html.heex
index e7ab1715..e8a86ee3 100644
--- a/lib/music_library_web/live/wishlist_live/show.html.heex
+++ b/lib/music_library_web/live/wishlist_live/show.html.heex
@@ -56,6 +56,18 @@
{gettext("MB Data")}
+ <.link phx-click={JS.push("populate_genres", value: %{id: @record.id})}>
+ <.button type="button" class="relative -ml-px inline-flex items-center rounded-none">
+ {gettext("Populate")}
+ <.icon
+ name="hero-sparkles"
+ class="h-4 w-4 mr-1 phx-click-loading:animate-shake"
+ aria-hidden="true"
+ data-slot="icon"
+ />
+ {gettext("Genres")}
+
+
<.link
phx-click={JS.push("delete", value: %{id: @record.id})}
data-confirm={gettext("Are you sure?")}
diff --git a/experiment.exs b/lib/open_ai.ex
similarity index 71%
rename from experiment.exs
rename to lib/open_ai.ex
index 37912593..5aac8e2c 100644
--- a/experiment.exs
+++ b/lib/open_ai.ex
@@ -1,5 +1,20 @@
defmodule OpenAI do
- def gpt_stream(prompt, cb) do
+ def gpt(prompt) do
+ {:ok, collector} = Agent.start_link(fn -> "" end)
+
+ gpt_stream(prompt, fn data ->
+ case get_in(data, ["choices", Access.at(0), "delta", "content"]) do
+ nil -> :ok
+ data -> Agent.update(collector, fn current -> current <> data end)
+ end
+ end)
+
+ result = Agent.get(collector, & &1) |> Jason.decode!()
+ Agent.stop(collector)
+ {:ok, result}
+ end
+
+ defp gpt_stream(prompt, cb) do
fun = fn request, finch_request, finch_name, finch_options ->
fun = fn
{:status, status}, response ->
@@ -47,22 +62,3 @@ defmodule OpenAI do
defp decode_body("[DONE]", _), do: :ok
defp decode_body(json, cb), do: cb.(Jason.decode!(json))
end
-
-{:ok, collector} = Agent.start_link(fn -> "" end)
-
-prompt = """
-Provide a list of music genres applicable to the album "Stupid Things that Mean the World" by Tim Bowness.
-
-Limit the list to 5 genres, ordered by decreasing specificity, all lowercase.
-
-Return a valid JSON list.
-"""
-
-OpenAI.gpt_stream(prompt, fn data ->
- case get_in(data, ["choices", Access.at(0), "delta", "content"]) do
- nil -> :ok
- data -> Agent.update(collector, fn current -> current <> data end)
- end
-end)
-
-Agent.get(collector, & &1) |> Jason.decode!() |> IO.inspect()
diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot
index 5b7e5a70..c8029c96 100644
--- a/priv/gettext/default.pot
+++ b/priv/gettext/default.pot
@@ -17,9 +17,9 @@ msgid "Actions"
msgstr ""
#: lib/music_library_web/live/collection_live/index.html.heex:186
-#: lib/music_library_web/live/collection_live/show.html.heex:61
+#: lib/music_library_web/live/collection_live/show.html.heex:73
#: lib/music_library_web/live/wishlist_live/index.html.heex:196
-#: lib/music_library_web/live/wishlist_live/show.html.heex:61
+#: lib/music_library_web/live/wishlist_live/show.html.heex:73
#, elixir-autogen, elixir-format
msgid "Are you sure?"
msgstr ""
@@ -29,12 +29,12 @@ msgstr ""
msgid "Attempting to reconnect"
msgstr ""
-#: lib/music_library_web/live/collection_live/show.html.heex:161
+#: lib/music_library_web/live/collection_live/show.html.heex:173
#, elixir-autogen, elixir-format
msgid "Back to records"
msgstr ""
-#: lib/music_library_web/live/wishlist_live/show.html.heex:154
+#: lib/music_library_web/live/wishlist_live/show.html.heex:166
#, elixir-autogen, elixir-format
msgid "Back to wishlist"
msgstr ""
@@ -53,8 +53,8 @@ msgstr ""
#: lib/music_library_web/components/layouts/app.html.heex:14
#: lib/music_library_web/live/artist_live/show.html.heex:61
#: lib/music_library_web/live/collection_live/index.ex:77
-#: lib/music_library_web/live/collection_live/show.ex:102
-#: lib/music_library_web/live/collection_live/show.ex:119
+#: lib/music_library_web/live/collection_live/show.ex:122
+#: lib/music_library_web/live/collection_live/show.ex:139
#, elixir-autogen, elixir-format
msgid "Collection"
msgstr ""
@@ -65,18 +65,18 @@ msgid "Cover art"
msgstr ""
#: lib/music_library_web/live/collection_live/index.html.heex:188
-#: lib/music_library_web/live/collection_live/show.html.heex:67
+#: lib/music_library_web/live/collection_live/show.html.heex:79
#: lib/music_library_web/live/wishlist_live/index.html.heex:198
-#: lib/music_library_web/live/wishlist_live/show.html.heex:67
+#: lib/music_library_web/live/wishlist_live/show.html.heex:79
#, elixir-autogen, elixir-format
msgid "Delete"
msgstr ""
#: lib/music_library_web/live/collection_live/index.html.heex:177
-#: lib/music_library_web/live/collection_live/show.ex:126
+#: lib/music_library_web/live/collection_live/show.ex:146
#: lib/music_library_web/live/collection_live/show.html.heex:32
#: lib/music_library_web/live/wishlist_live/index.html.heex:177
-#: lib/music_library_web/live/wishlist_live/show.ex:109
+#: lib/music_library_web/live/wishlist_live/show.ex:129
#: lib/music_library_web/live/wishlist_live/show.html.heex:32
#, elixir-autogen, elixir-format
msgid "Edit"
@@ -105,8 +105,10 @@ msgstr ""
msgid "Formats"
msgstr ""
-#: lib/music_library_web/live/collection_live/show.html.heex:77
-#: lib/music_library_web/live/wishlist_live/show.html.heex:78
+#: lib/music_library_web/live/collection_live/show.html.heex:68
+#: lib/music_library_web/live/collection_live/show.html.heex:89
+#: lib/music_library_web/live/wishlist_live/show.html.heex:68
+#: lib/music_library_web/live/wishlist_live/show.html.heex:90
#, elixir-autogen, elixir-format
msgid "Genres"
msgstr ""
@@ -122,8 +124,8 @@ msgstr ""
msgid "Import"
msgstr ""
-#: lib/music_library_web/live/collection_live/show.html.heex:136
-#: lib/music_library_web/live/wishlist_live/show.html.heex:129
+#: lib/music_library_web/live/collection_live/show.html.heex:148
+#: lib/music_library_web/live/wishlist_live/show.html.heex:141
#, elixir-autogen, elixir-format
msgid "Inserted at"
msgstr ""
@@ -149,9 +151,9 @@ msgstr ""
msgid "Logout"
msgstr ""
-#: lib/music_library_web/live/collection_live/show.html.heex:91
+#: lib/music_library_web/live/collection_live/show.html.heex:103
#: lib/music_library_web/live/record_live/form_component.ex:47
-#: lib/music_library_web/live/wishlist_live/show.html.heex:92
+#: lib/music_library_web/live/wishlist_live/show.html.heex:104
#, elixir-autogen, elixir-format
msgid "MusicBrainz ID"
msgstr ""
@@ -199,7 +201,7 @@ msgstr ""
msgid "Purchased at"
msgstr ""
-#: lib/music_library_web/live/collection_live/show.html.heex:113
+#: lib/music_library_web/live/collection_live/show.html.heex:125
#, elixir-autogen, elixir-format
msgid "Purchased on"
msgstr ""
@@ -248,9 +250,9 @@ msgid "Search for records"
msgstr ""
#: lib/music_library_web/live/collection_live/index.html.heex:157
-#: lib/music_library_web/live/collection_live/show.ex:125
+#: lib/music_library_web/live/collection_live/show.ex:145
#: lib/music_library_web/live/wishlist_live/index.html.heex:157
-#: lib/music_library_web/live/wishlist_live/show.ex:108
+#: lib/music_library_web/live/wishlist_live/show.ex:128
#, elixir-autogen, elixir-format
msgid "Show"
msgstr ""
@@ -305,8 +307,8 @@ msgstr ""
msgid "Types"
msgstr ""
-#: lib/music_library_web/live/collection_live/show.html.heex:144
-#: lib/music_library_web/live/wishlist_live/show.html.heex:137
+#: lib/music_library_web/live/collection_live/show.html.heex:156
+#: lib/music_library_web/live/wishlist_live/show.html.heex:149
#, elixir-autogen, elixir-format
msgid "Updated at"
msgstr ""
@@ -330,7 +332,7 @@ msgstr ""
#: lib/music_library_web/components/layouts/app.html.heex:20
#: lib/music_library_web/live/artist_live/show.html.heex:100
#: lib/music_library_web/live/wishlist_live/index.ex:75
-#: lib/music_library_web/live/wishlist_live/show.ex:102
+#: lib/music_library_web/live/wishlist_live/show.ex:122
#, elixir-autogen, elixir-format
msgid "Wishlist"
msgstr ""
@@ -346,14 +348,14 @@ msgstr ""
msgid "close"
msgstr ""
-#: lib/music_library_web/live/collection_live/show.html.heex:101
-#: lib/music_library_web/live/wishlist_live/show.html.heex:102
+#: lib/music_library_web/live/collection_live/show.html.heex:113
+#: lib/music_library_web/live/wishlist_live/show.html.heex:114
#, elixir-autogen, elixir-format
msgid "Copy MusicBrainz ID to clipboard"
msgstr ""
-#: lib/music_library_web/live/collection_live/show.html.heex:155
-#: lib/music_library_web/live/wishlist_live/show.html.heex:148
+#: lib/music_library_web/live/collection_live/show.html.heex:167
+#: lib/music_library_web/live/wishlist_live/show.html.heex:160
#, elixir-autogen, elixir-format
msgid "MusicBrainz data"
msgstr ""
@@ -387,8 +389,8 @@ msgstr ""
msgid "Number of included records"
msgstr ""
-#: lib/music_library_web/live/collection_live/show.html.heex:124
-#: lib/music_library_web/live/wishlist_live/show.html.heex:117
+#: lib/music_library_web/live/collection_live/show.html.heex:136
+#: lib/music_library_web/live/wishlist_live/show.html.heex:129
#, elixir-autogen, elixir-format
msgid "Includes"
msgstr ""
@@ -410,7 +412,7 @@ msgstr ""
msgid "Refresh LastFm Feed"
msgstr ""
-#: lib/music_library_web/live/collection_live/show.ex:73
+#: lib/music_library_web/live/collection_live/show.ex:93
#: lib/music_library_web/live/wishlist_live/show.ex:73
#, elixir-autogen, elixir-format
msgid "Cover refreshed successfully"
@@ -441,7 +443,7 @@ msgstr ""
msgid "Error refreshing Cover"
msgstr ""
-#: lib/music_library_web/live/collection_live/show.ex:81
+#: lib/music_library_web/live/collection_live/show.ex:101
#, elixir-autogen, elixir-format
msgid "Error refreshing cover"
msgstr ""
@@ -452,7 +454,7 @@ msgid "No MB ID"
msgstr ""
#: lib/music_library_web/live/artist_live/show.ex:38
-#: lib/music_library_web/live/collection_live/show.ex:100
+#: lib/music_library_web/live/collection_live/show.ex:120
#, elixir-autogen, elixir-format
msgid "Details"
msgstr ""
@@ -512,3 +514,21 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "There was an error loading the play count"
msgstr ""
+
+#: lib/music_library_web/live/collection_live/show.ex:81
+#: lib/music_library_web/live/wishlist_live/show.ex:101
+#, elixir-autogen, elixir-format
+msgid "Error populating genres"
+msgstr ""
+
+#: lib/music_library_web/live/collection_live/show.ex:73
+#: lib/music_library_web/live/wishlist_live/show.ex:93
+#, elixir-autogen, elixir-format
+msgid "Genres populated successfully"
+msgstr ""
+
+#: lib/music_library_web/live/collection_live/show.html.heex:61
+#: lib/music_library_web/live/wishlist_live/show.html.heex:61
+#, elixir-autogen, elixir-format
+msgid "Populate"
+msgstr ""