Refactor DefaultPrompt into Chats.Prompt with build/2

This commit is contained in:
Claudio Ortolina
2026-04-05 08:32:03 +01:00
parent f9155f8c52
commit 4be9db6417
5 changed files with 57 additions and 41 deletions
+1 -1
View File
@@ -129,7 +129,7 @@ Last.fm schemas (separate, not Ecto-persisted to main DB):
| `Chats.StreamProvider` | Behaviour for streaming AI chat (`stream_response/3` callback) | | `Chats.StreamProvider` | Behaviour for streaming AI chat (`stream_response/3` callback) |
| `Chats.RecordChat` | Chat implementation for records (OpenAI streaming, web search enabled) | | `Chats.RecordChat` | Chat implementation for records (OpenAI streaming, web search enabled) |
| `Chats.ArtistChat` | Chat implementation for artists (OpenAI streaming, uses Wikipedia/artist context) | | `Chats.ArtistChat` | Chat implementation for artists (OpenAI streaming, uses Wikipedia/artist context) |
| `Chats.DefaultPrompt` | Shared default prompt fragments (identity, approach) for chat implementations | | `Chats.Prompt` | Builds complete chat prompts by interpolating identity, content, and approach guidelines |
| `Country` | Country code (alpha-2, alpha-3, subdivision, IETF) to flag emoji conversion | | `Country` | Country code (alpha-2, alpha-3, subdivision, IETF) to flag emoji conversion |
| `ErrorTracker.ErrorNotifier` | GenServer: attaches to ErrorTracker telemetry, skips muted errors, throttles repeated errors, dispatches email notifications | | `ErrorTracker.ErrorNotifier` | GenServer: attaches to ErrorTracker telemetry, skips muted errors, throttles repeated errors, dispatches email notifications |
| `ErrorTracker.ErrorNotifier.Email` | Builds and sends Swoosh error notification emails with stack trace formatting | | `ErrorTracker.ErrorNotifier.Email` | Builds and sends Swoosh error notification emails with stack trace formatting |
+6 -9
View File
@@ -6,7 +6,7 @@ defmodule MusicLibrary.Chats.ArtistChat do
@behaviour MusicLibrary.Chats.StreamProvider @behaviour MusicLibrary.Chats.StreamProvider
alias MusicLibrary.Artists.ArtistInfo alias MusicLibrary.Artists.ArtistInfo
alias MusicLibrary.Chats.DefaultPrompt alias MusicLibrary.Chats.Prompt
@impl true @impl true
@spec stream_response([map()], {map(), ArtistInfo.t()}, (String.t() -> any())) :: @spec stream_response([map()], {map(), ArtistInfo.t()}, (String.t() -> any())) ::
@@ -20,16 +20,13 @@ defmodule MusicLibrary.Chats.ArtistChat do
defp build_instructions(artist, artist_info) do defp build_instructions(artist, artist_info) do
context = build_context(artist, artist_info) context = build_context(artist, artist_info)
""" Prompt.build("""
#{DefaultPrompt.identity()}
Answer questions about the artist the user is currently viewing. \ Answer questions about the artist the user is currently viewing. \
Use the provided artist information as your primary reference, \ Use the provided artist information as your primary reference.
#{DefaultPrompt.approach()} Artist information:
#{context}\
Album information: """)
#{context}
"""
end end
defp build_context(artist, artist_info) do defp build_context(artist, artist_info) do
-23
View File
@@ -1,23 +0,0 @@
defmodule MusicLibrary.Chats.DefaultPrompt do
@moduledoc false
def identity do
"""
You are a knowledgeable music assistant.
"""
end
def approach do
"""
Use web search to find additional up-to-date \
information when helpful. Be concise and accurate. When unsure, say so. \
Include links when they add genuine value, and at least one per response \
(but not one per paragraph).
Vary your response style and structure. Don't repeat information already \
discussed in the conversation. Refer back to earlier points naturally \
instead of restating them. DO NOT INCLUDE A SUMMARY AT THE END OF YOUR MESSAGE. \
DO NOT PROVIDE SUGGESTIONS OR ASK QUESTIONS AS A MEAN TO CONTINUE THE CONVERSATION.
"""
end
end
+45
View File
@@ -0,0 +1,45 @@
defmodule MusicLibrary.Chats.Prompt do
@moduledoc """
Builds complete chat prompts by interpolating identity, content, and approach.
"""
@doc """
Builds a complete prompt from the given `text` and options.
Options:
* `:identity` - the identity preamble (defaults to a music assistant identity)
* `:approach` - the approach guidance (defaults to standard response guidelines)
"""
@spec build(String.t(), keyword()) :: String.t()
def build(text, opts \\ []) do
identity = Keyword.get(opts, :identity, default_identity())
approach = Keyword.get(opts, :approach, default_approach())
"""
#{identity}
#{text}
#{approach}\
"""
end
defp default_identity do
"""
You are a knowledgeable music assistant.\
"""
end
defp default_approach do
"""
Use web search to find additional up-to-date \
information when helpful. Be concise and accurate. When unsure, say so. \
Include links when they add genuine value, and at least one per response \
(but not one per paragraph).
Vary your response style and structure. Don't repeat information already \
discussed in the conversation. Refer back to earlier points naturally \
instead of restating them. DO NOT INCLUDE A SUMMARY AT THE END OF YOUR MESSAGE. \
DO NOT PROVIDE SUGGESTIONS OR ASK QUESTIONS AS A MEAN TO CONTINUE THE CONVERSATION.\
"""
end
end
+5 -8
View File
@@ -5,7 +5,7 @@ defmodule MusicLibrary.Chats.RecordChat do
@behaviour MusicLibrary.Chats.StreamProvider @behaviour MusicLibrary.Chats.StreamProvider
alias MusicLibrary.Chats.DefaultPrompt alias MusicLibrary.Chats.Prompt
alias MusicLibrary.Records.Record alias MusicLibrary.Records.Record
@impl true @impl true
@@ -25,16 +25,13 @@ defmodule MusicLibrary.Chats.RecordChat do
text -> text text -> text
end end
""" Prompt.build("""
#{DefaultPrompt.identity()}
Answer questions about the album the user is currently viewing. \ Answer questions about the album the user is currently viewing. \
Use the provided album information as your primary reference, \ Use the provided album information as your primary reference.
#{DefaultPrompt.approach()}
Album information: Album information:
#{context} #{context}\
""" """)
end end
defp basic_context(%Record{} = record) do defp basic_context(%Record{} = record) do