Files
music_library/lib/music_library/artist_chat.ex
T
Claudio Ortolina 7cf9b4e7f8 First pass at uniformed types, specs and docs
- spec public functions (skipping controllers, views, live views and
components)
- use types instead of explanations in docs
- remove redundant docs
- fix typos
2026-03-06 08:33:11 +00:00

47 lines
1.4 KiB
Elixir

defmodule MusicLibrary.ArtistChat do
@behaviour MusicLibrary.Chat
alias MusicLibrary.Artists.ArtistInfo
@impl true
@spec stream_response([map()], {map(), ArtistInfo.t()}, (String.t() -> any())) ::
:ok | {:error, term()}
def stream_response(messages, {artist, artist_info}, callback) do
instructions = build_instructions(artist, artist_info)
OpenAI.chat_stream(messages, on_chunk: callback, instructions: instructions)
end
defp build_instructions(artist, artist_info) do
context = build_context(artist, artist_info)
"""
You are a knowledgeable music assistant. Answer questions about the artist \
the user is currently viewing. Use the provided artist information as your \
primary reference, and use web search to find additional up-to-date \
information when helpful. Be concise and accurate. When unsure, say so.
Artist information:
#{context}
"""
end
defp build_context(artist, artist_info) do
country = ArtistInfo.country(artist_info)
description = ArtistInfo.wikipedia_description(artist_info)
summary = ArtistInfo.wikipedia_summary(artist_info)
parts =
[
{"Name", artist.name},
{"Country", country.name},
{"Description", description},
{"Biography", summary}
]
|> Enum.reject(fn {_label, value} -> value in [nil, ""] end)
|> Enum.map_join("\n", fn {label, value} -> "#{label}: #{value}" end)
parts
end
end