ajayarora1235 commited on
Commit
5cfd8a9
1 Parent(s): a2dd4a4

start repo

Browse files
.env ADDED
@@ -0,0 +1 @@
 
 
1
+ OPEN_AI_KEY="sk-proj-p2YYidwgo0sTLWWz6OthT3BlbkFJGaXrkrR0aEcyUdafUJJF"
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ .env
2
+ __pycache__
README.md CHANGED
@@ -1 +1,11 @@
1
- # auto-songchat
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Auto SONG CHAT
3
+ emoji: 🏢
4
+ colorFrom: blue
5
+ colorTo: purple
6
+ sdk: gradio
7
+ sdk_version: 4.24.0
8
+ app_file: app.py
9
+ pinned: false
10
+ license: apache-2.0
11
+ ---
__pycache__/app.cpython-310.pyc ADDED
Binary file (18.1 kB). View file
 
__pycache__/app.cpython-312.pyc ADDED
Binary file (32.2 kB). View file
 
__pycache__/assistant.cpython-312.pyc ADDED
Binary file (3.85 kB). View file
 
__pycache__/gpt_calls.cpython-310.pyc ADDED
Binary file (2.83 kB). View file
 
__pycache__/gpt_calls.cpython-312.pyc ADDED
Binary file (7.69 kB). View file
 
__pycache__/suno.cpython-310.pyc ADDED
Binary file (1.69 kB). View file
 
__pycache__/suno.cpython-312.pyc ADDED
Binary file (4.74 kB). View file
 
ai_tools.json ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "type": "function",
4
+ "function": {
5
+ "name": "write_section",
6
+ "description": "Write a section of a song based on given ideas. Anytime you would like to suggest lyrics for a new section or the user has provided enough ideas for a new section, you must call this function.",
7
+ "parameters": {
8
+ "type": "object",
9
+ "properties": {
10
+ "section_name": {
11
+ "type": "string",
12
+ "description": "Name of new section being written."
13
+ },
14
+ "section_description": {
15
+ "type": "string",
16
+ "description": "Description of section as stated in first message of the conversation"
17
+ },
18
+ "relevant_ideas": {
19
+ "type": "array",
20
+ "items": {
21
+ "type": "string"
22
+ },
23
+ "description": "Ideas that should be included in the section that is being written. Obtained by paraphrasing the key details from the user's responses about their story into short sentences that each start with 'I ...', 'I ...', etc."
24
+ },
25
+ "section_length": {
26
+ "type": "number",
27
+ "description": "Number of lines in the section. This is also the number of bars, retrieved from first message of the conversation."
28
+ },
29
+ "snippet_instrumental_tags": {
30
+ "type": "string",
31
+ "description": "Instrumental tags to be used for this section. Deduce from most recent list of suggested instrumental tags in conversation. Should be comma separated string of one-word tags that describe genre as stated in intro message, instruments, moods. Specify gender."
32
+ },
33
+ "snippet_clip_to_continue_from": {
34
+ "type": "string",
35
+ "description": "The last approved clip of the song to continue the requested section from. Deduce from most recent approved clip of prior section in conversation. If user did not receive a snippet for the prior section or ever before, this should not be passed."
36
+ },
37
+ "sections_written": {
38
+ "type": "array",
39
+ "items": {
40
+ "type": "string"
41
+ },
42
+ "description": "Sections that have been written so far. This is to ensure that the song is coherent and that the sections flow well together. Include section headers (ie [verse 1]) in the lyrics."
43
+ },
44
+ "overall_song_description": {
45
+ "type": "string",
46
+ "description": "Description of the overall song. As stated in first message of conversation."
47
+ }
48
+ },
49
+ "required": ["section_name", "section_description", "relevant_ideas", "section_length", "snippet_instrumental_tags"]
50
+ }
51
+ }
52
+ },
53
+ {
54
+ "type": "function",
55
+ "function": {
56
+ "name": "revise_section_lyrics",
57
+ "description": "Revise a consecutive set of lines from a section of a song based on given ideas",
58
+ "parameters": {
59
+ "type": "object",
60
+ "properties": {
61
+ "section_name": {
62
+ "type": "string",
63
+ "description": "Name of section we are revising"
64
+ },
65
+ "current_section": {
66
+ "type": "string",
67
+ "description": "Current version of lyrics in section of the song. The last outputted version of the section before user suggested changes that we are now implementing."
68
+ },
69
+ "lines_to_revise": {
70
+ "type": "array",
71
+ "items": {
72
+ "type": "number"
73
+ },
74
+ "description": "Lines to revise, as a list of numbers. The first line is labelled 1, second 2, and so on. Lines to change should be assessed based on feedback user provides and where they suggest changes."
75
+ },
76
+ "snippet_instrumental_tags": {
77
+ "type": "string",
78
+ "description": "Instrumental tags to be used for this section revision. This should be the exact same as what was used for the snippet being revised. The instrumental tags are listed under the recent audio clip html."
79
+ },
80
+ "snippet_clip_to_continue_from": {
81
+ "type": "string",
82
+ "description": "The 'continued from clip:' clip id that was used in the original snippet we are now revising. This should be the exact same as 'continued from clip' for the snippet being revised, listed under the original snippet's audioplayer; if it is None, this should not be passed."
83
+ },
84
+ "relevant_ideas": {
85
+ "type": "array",
86
+ "items": {
87
+ "type": "string"
88
+ },
89
+ "description": "Ideas that should be included in the lines that are being changed. Should be directly derived from suggested user changes."
90
+ },
91
+ "relevant_words": {
92
+ "type": "array",
93
+ "items": {
94
+ "type": "string"
95
+ },
96
+ "description": "Words that are requested to be included in revised lines. Unless specific words are requested, this should be empty"
97
+ }
98
+ },
99
+ "required": ["section_name", "current_section", "lines_to_revise", "snippet_instrumental_tags"]
100
+ }
101
+ }
102
+ },
103
+ {
104
+ "type": "function",
105
+ "function": {
106
+ "name": "revise_instrumental_tags",
107
+ "description": "Revise instrumental tags passed to instrumental generator based on user feedback. Only call when user explicitly comments on instrumental. This will re-generate all the lyrics with this new instrumental. Confirm with the user that this is okay before running.",
108
+ "parameters": {
109
+ "type": "object",
110
+ "properties": {
111
+ "current_instrumental_tags": {
112
+ "type": "array",
113
+ "items": {
114
+ "type": "string"
115
+ },
116
+ "description": "Current instrumental tags passed to instrumental generator. Deduce from most recent list of instrumental tags in conversation."
117
+ },
118
+ "user_instrumental_feedback": {
119
+ "type": "string",
120
+ "description": "A single sentence summary of the user's feedback on instrumental. Can include suggested moods, genres, or instruments."
121
+ },
122
+ "sections_written": {
123
+ "type": "array",
124
+ "items": {
125
+ "type": "string"
126
+ },
127
+ "description": "All the sections that have been written so far for us to regenerate with the new instrumental. Include the lyrics from the current section that we are revising. Include section headers (ie [verse 1]) in the lyrics."
128
+ }
129
+ },
130
+ "required": ["current_instrumental_tags", "user_instrumental_feedback", "sections_written"]
131
+ }
132
+ }
133
+ },
134
+ {
135
+ "type": "function",
136
+ "function": {
137
+ "name": "get_audio_snippet",
138
+ "description": "Call this function when the user explicitly asks 'Can I have an audio snippet'. Return a clip of all the parts of the song we've written that they have not heard.",
139
+ "parameters": {
140
+ "type": "object",
141
+ "properties": {
142
+ "snippet_lyrics": {
143
+ "type": "string",
144
+ "description": "The lyrics of the section that the user wants to hear. If there are lyrics that the user approved but did not hear a snippet of, those must be included in this snippet as well before the current section. Include section headers (ie [verse 1]) in the lyrics."
145
+ },
146
+ "snippet_instrumental_tags": {
147
+ "type": "string",
148
+ "description": "Instrumental tags to be used to generate the snippet. Deduce from most recent list of suggested instrumental tags in conversation. Should be comma separated string of one-word tags. Specify gender."
149
+ },
150
+ "snippet_clip_to_continue_from": {
151
+ "type": "string",
152
+ "description": "The last approved song clip to continue from. Almost always the most recent clip id outputted in the conversation. If user did not receive a snippet for the prior section or ever before, this should not be passed."
153
+ }
154
+ },
155
+ "required": ["snippet_lyrics", "snippet_instrumental_tags"]
156
+ }
157
+ }
158
+ },
159
+ {
160
+ "type": "function",
161
+ "function": {
162
+ "name": "merge_all_snippets",
163
+ "description": "Merge all existing snippets of the song together. Should only be called when explicitly requested by the user.",
164
+ "parameters": {
165
+ "type": "object",
166
+ "properties": {
167
+ "last_snippet_id": {
168
+ "type": "string",
169
+ "description": "The ID of the last approved/generated snippet of the song. The path of snippets to merge is contained in this snippet, so only pass the id of the last one generated."
170
+ }
171
+ },
172
+ "required": ["last_snippet_id"]
173
+ }
174
+ }
175
+ },
176
+ {
177
+ "type": "function",
178
+ "function": {
179
+ "name": "finish_full_song",
180
+ "description": "Write the full song based on the snippets that have been generated. Should only be called when explicitly requested by the user.",
181
+ "parameters": {
182
+ "type": "object",
183
+ "properties": {
184
+ "sections_to_be_written": {
185
+ "type": "array",
186
+ "items": {
187
+ "type": "object",
188
+ "properties": {
189
+ "section_name": {
190
+ "type": "string",
191
+ "description": "Name of the section that have yet to be written or suggested. Exactly quoted as stated in first message of the conversation"
192
+ },
193
+ "section_description": {
194
+ "type": "string",
195
+ "description": "The description of the section that have yet to be written or suggested. Exactly quoted as stated in first message of the conversation"
196
+ },
197
+ "section_length": {
198
+ "type": "number",
199
+ "description": "Number of lines in the section. This is also the number of bars, retrieved from first message of the conversation."
200
+ }
201
+ }
202
+ },
203
+ "description": "The sections that have yet to be written or suggested. Should be in chronological order of the sections as positioned in the song, retrieved from the first message of the conversation."
204
+ },
205
+ "snippet_instrumental_tags": {
206
+ "type": "string",
207
+ "description": "Instrumental tags to be used for the remaining sections. Deduce from most recent list of suggested instrumental tags in conversation. Should be comma separated string of one-word tags. Specify gender."
208
+ },
209
+ "snippet_clip_to_continue_from": {
210
+ "type": "string",
211
+ "description": "The last approved clip ID of the song to continue the remaining sections from. Almost always the most recent clip id outputted in the conversation. If user did not receive a snippet for the prior section or ever before, this should not be passed."
212
+ },
213
+ "sections_written": {
214
+ "type": "array",
215
+ "items": {
216
+ "type": "string"
217
+ },
218
+ "description": "Sections that have been written so far. This is to ensure that the song is coherent and that the sections flow well together. Include section headers (ie [verse 1]) in the lyrics. If no sections have been suggested yet, this should be an empty list."
219
+ },
220
+ "overall_song_description": {
221
+ "type": "string",
222
+ "description": "Description of the overall song. As stated in first message of conversation."
223
+ }
224
+ },
225
+ "required": ["sections_to_be_written", "snippet_instrumental_tags", "snippet_clip_to_continue", "sections_written", "overall_song_description"]
226
+ }
227
+ }
228
+ }
229
+ ]
app.py ADDED
@@ -0,0 +1,696 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ from typing import List, Optional, Tuple, Dict
4
+ import time
5
+ import datetime
6
+
7
+ def get_current_time() -> str:
8
+ """
9
+ Returns the current time as a formatted string.
10
+ """
11
+ now = datetime.datetime.now()
12
+ return now.strftime("%Y-%m-%d %H:%M:%S")
13
+
14
+
15
+ from gpt_calls import AI_Songwriter
16
+
17
+ from openai import OpenAI
18
+ oai_client = OpenAI(
19
+ api_key=os.getenv("OPEN_AI_KEY"),
20
+ )
21
+ client_key = os.getenv("OPEN_AI_KEY")
22
+ client = OpenAI(
23
+ api_key=os.getenv("OPEN_AI_KEY"),
24
+ )
25
+
26
+ import time
27
+ import os
28
+ import json
29
+ import random
30
+
31
+ from suno import generate_song, concat_snippets
32
+
33
+
34
+ History = List[Tuple[str, str]] # pairs of (query, response), where query is user input and response is system output
35
+ Messages = List[Dict[str, str]] # list of messages with role and content
36
+
37
+ '''
38
+ Genre list
39
+ Preset dropdown: Missing Home, Heartbroken, Getting Turnt, Childhood Nostalgia, (Custom) How are you?
40
+ - tags based on preset
41
+ Artist identity dropdown: A 15-year old boy who dreams of being a broadway actor, A 23-year old soft but bombastic woman who loves to rap, dance, and take over the streets, A 30-year old man who has plans to take over the world as a villain
42
+
43
+ male tenor, dramatic, emotional, strings
44
+
45
+ pass artist identity in starting prompt to gpt-4 conversation.
46
+ pass preset dropdown to gpt-4 conversation to inspire the questions that Lupe asks the user.
47
+
48
+ -Ask every 4 back-and-forths do you want to talk more? Or are you ready for your song? (add button for song in assistant's message)
49
+
50
+ -Mention lyrics
51
+ -Mention every 4 back-and-forths lyrics that you’ll include in the song [calling gpt-4 to generate the lyrics and identify one line that's most relevant to the last message]
52
+ '''
53
+
54
+
55
+ def clear_session() -> History:
56
+ return '', []
57
+
58
+ def remove_quotes(s):
59
+ if s[0] == '"' and s[-1] == '"' or s[0] == "'" and s[-1] == "'":
60
+ return s[1:-1]
61
+ return s
62
+
63
+
64
+
65
+ def generate_song_seed(baseline_seed):
66
+ song_details_prompt = "Analyze this description of how someone is feeling and provide a suggestion of a interesting song concept to base a song off of. Here are three examples, now provide a song concept for this fourth:\n\n"
67
+
68
+ song_seed_prompt ='prompt_song_seed.txt'
69
+ with open(song_seed_prompt, 'r', encoding='utf-8') as file:
70
+ content_2 = file.read()
71
+
72
+ song_details_prompt += "\n\n" + content_2 + baseline_seed + "\nSuggested Song Concept: "
73
+
74
+ convo = [
75
+ {
76
+ "role": "user",
77
+ "content": song_details_prompt,
78
+ },
79
+ ]
80
+
81
+ gen = oai_client.chat.completions.create(
82
+ model="gpt-4o",
83
+ messages=convo,
84
+ stream=True
85
+ )
86
+
87
+ current_response = ""
88
+ for chunk in gen:
89
+ if chunk.choices[0].delta.content is not None:
90
+ # print ("chunk", chunk.choices[0].delta.content)
91
+ current_response += chunk.choices[0].delta.content
92
+ yield current_response
93
+
94
+ def clean_song_seed(song_seed):
95
+ if "Suggested Song Concept:" in song_seed:
96
+ song_seed = song_seed.split("Suggested Song Concept:")[1].strip()
97
+ return song_seed
98
+
99
+ def make_song(snippet_lyrics, snippet_instrumental_tags, snippet_clip_to_continue_from=None, continue_at=None):
100
+ os.makedirs("audio_clips", exist_ok=True)
101
+ song_name = f"SG_{int(time.time())}"
102
+ suno_song_path = f"./audio_clips/suno_{song_name}.wav"
103
+ full_tags = f"{snippet_instrumental_tags}"
104
+ print("Passing to generate_song:", full_tags, snippet_lyrics, suno_song_path)
105
+
106
+ if snippet_clip_to_continue_from is not None and snippet_clip_to_continue_from != "":
107
+ song_link = generate_song(full_tags, snippet_lyrics, suno_song_path, snippet_clip_to_continue_from, continue_at)
108
+ else:
109
+ song_link = generate_song(full_tags, snippet_lyrics, suno_song_path)
110
+
111
+ return song_link
112
+
113
+ def messages_to_history(messages: Messages) -> Tuple[str, History]:
114
+ assert messages[0]['role'] == 'system', messages[1]['role'] == 'user'
115
+ messages_for_parsing = messages[:1] + [{'role': 'user', 'content': ''}] + messages[2:]
116
+ print("OLD MESSAGES FOR PARSING", messages_for_parsing)
117
+ messages_for_parsing = [x for x in messages_for_parsing if x['role'] != 'tool' and 'tool_calls' not in x]
118
+
119
+ messages_for_parsing = [
120
+ {'role': x['role'], 'content': x['content'].split(" Use write_section")[0]} if x['role'] == 'user' else x
121
+ for x in messages_for_parsing
122
+ ]
123
+ print("NEW MESSAGES FOR PARSING", messages_for_parsing)
124
+ history = []
125
+ for q, r in zip(messages_for_parsing[1::2], messages_for_parsing[2::2]):
126
+ history.append([q['content'], r['content']])
127
+ # print("made history:\n", history, "from messages\n", messages, "messages for parsing", messages_for_parsing)
128
+ return history
129
+
130
+
131
+ def model_chat(genre_input, query: Optional[str], history: Optional[History], messages: Optional [Messages], auto=False) -> Tuple[str, str, History, Messages]:
132
+ if query is None:
133
+ query = ''
134
+
135
+ if not query.endswith('?'):
136
+ query += " Use write_section when you have a large amount of story to pull from to write the next section! Alternatively ask me a follow up before moving to write."
137
+
138
+ with open('ai_tools.json') as f:
139
+ ai_tools = json.load(f)
140
+
141
+ songwriterAssistant = AI_Songwriter(client_key=client_key)
142
+
143
+ if auto:
144
+ messages = messages[:-1] + [{'role': 'user', 'content': query}] #should this be a -1? for non-auto. why does the chatbot history get messed up?
145
+ else:
146
+ messages = messages + [{'role': 'user', 'content': query}]
147
+
148
+
149
+
150
+ messages_filtered = messages
151
+ response_message = oai_client.chat.completions.create(
152
+ model="gpt-4o",
153
+ messages=messages_filtered,
154
+ tools = ai_tools,
155
+ tool_choice="auto",
156
+ )
157
+ print(response_message, "model chat response")
158
+ current_response = ""
159
+ # Step 2: determine if the response from the model includes a tool call.
160
+ tool_calls = response_message.choices[0].message.tool_calls
161
+ if tool_calls:
162
+ messages.append({
163
+ "role": response_message.choices[0].message.role,
164
+ "content": response_message.choices[0].message.content,
165
+ "tool_calls": tool_calls,
166
+ "function_call": response_message.choices[0].message.function_call
167
+ })
168
+ # If true the model will return the name of the tool / function to call and the argument(s)
169
+ for tool_call in tool_calls:
170
+ print(tool_call)
171
+ tool_call_id = tool_call.id
172
+ tool_function_name = tool_call.function.name
173
+ tool_query_args = eval(tool_call.function.arguments)
174
+
175
+ # Step 3: Call the function and retrieve results. Append the results to the messages list.
176
+ if tool_function_name == 'write_section':
177
+ snippet_instrumental_tags = tool_query_args.pop('snippet_instrumental_tags', None)
178
+ snippet_clip_to_continue_from = tool_query_args.pop('snippet_clip_to_continue_from', None)
179
+ suggested_lyrics = songwriterAssistant.write_section(**tool_query_args)
180
+
181
+ ## yield suggested lyrics in tool and assistant message
182
+ tool_message = {'role': 'tool', 'tool_call_id': tool_call_id, 'name': tool_function_name, 'content': suggested_lyrics}
183
+ # audio_message = {'role': 'assistant', 'content': "Here's what I've come up with:\n" + suggested_lyrics + "\n\nGenerating audio snippet..."}
184
+ new_messages = messages + [tool_message] #, audio_message
185
+
186
+ model_response_with_function_call = client.chat.completions.create(
187
+ model="gpt-4o",
188
+ messages=new_messages,
189
+ ) # get a new response from the model where it can see the function response
190
+ current_response = model_response_with_function_call.choices[0].message.content
191
+
192
+ role = "assistant"
193
+ new_messages = new_messages + [{'role': role, 'content': current_response}]
194
+ # new_messages = [msg for msg in new_messages if msg['content'] is not None and msg['role'] in ['user', 'assistant']]
195
+ history = messages_to_history(new_messages)
196
+ yield '', history, new_messages, '[...]'
197
+
198
+
199
+ # new_history = messages_to_history(new_messages)
200
+ # yield '', new_history, new_messages, '[...]'
201
+
202
+ # ### call make_song here with the snippet_lyrics, snippet_instrumental_tags, and snippet_clip_to_continue
203
+ # song_link = make_song(suggested_lyrics, snippet_instrumental_tags, snippet_clip_to_continue)
204
+
205
+ # ## filter out suno link from tool query arg
206
+ # clip_id = song_link.split("https://audiopipe.suno.ai/?item_id=")[1]
207
+
208
+ # ## add song link to tool and audio message
209
+ # tool_message = {'role': 'tool', 'tool_call_id': tool_call_id, 'name': tool_function_name, 'content': suggested_lyrics + '\nclip id: ' + clip_id}
210
+ # audio_message = {'role': 'assistant', 'content': "Here's what I've come up with:\n" + suggested_lyrics + '\n\n' + f'<audio controls autoplay><source src="{song_link}" type="audio/mp3"></audio><p>clip id: {clip_id}</p><p>instrumental tags: {snippet_instrumental_tags}</p>'}
211
+ # audio_message['content'] += f'<p>continued from clip: {snippet_clip_to_continue}</p>'
212
+ # audio_message['content'] += f'\n\nWhat do you think?'
213
+ # new_messages = messages + [tool_message, audio_message]
214
+ # new_history = messages_to_history(new_messages)
215
+ # yield '', new_history, new_messages, '[...]'
216
+
217
+ elif tool_function_name == 'revise_section_lyrics':
218
+ snippet_instrumental_tags = tool_query_args.pop('snippet_instrumental_tags', None)
219
+ snippet_clip_to_continue_from = tool_query_args.pop('snippet_clip_to_continue_from', None)
220
+ revised_lyrics = songwriterAssistant.revise_section_lyrics(**tool_query_args)
221
+
222
+ # ## yield revised lyrics in tool and assistant message
223
+ tool_message = {'role': 'tool', 'tool_call_id': tool_call_id, 'name': tool_function_name, 'content': revised_lyrics}
224
+ # audio_message = {'role': 'assistant', 'content': "Here's my revised lyrics:\n" + revised_lyrics + "\n\nGenerating audio snippet..."}
225
+ new_messages = messages + [tool_message] #, audio_message]
226
+
227
+ model_response_with_function_call = client.chat.completions.create(
228
+ model="gpt-4o",
229
+ messages=new_messages,
230
+ ) # get a new response from the model where it can see the function response
231
+ current_response = model_response_with_function_call.choices[0].message.content
232
+
233
+ role = "assistant"
234
+ new_messages = new_messages + [{'role': role, 'content': current_response}]
235
+ # new_messages = [msg for msg in new_messages if msg['content'] is not None and msg['role'] in ['user', 'assistant']]
236
+ history = messages_to_history(new_messages)
237
+ yield '', history, new_messages, '[...]'
238
+ # new_history = messages_to_history(new_messages)
239
+ # yield '', new_history, new_messages, '[...]'
240
+
241
+ # ### call make_song here with the snippet_lyrics, snippet_instrumental_tags, and snippet_clip_to_continue
242
+ # song_link = make_song(revised_lyrics, snippet_instrumental_tags, snippet_clip_to_continue)
243
+
244
+ # ## filter out suno link from tool query arg
245
+ # clip_id = song_link.split("https://audiopipe.suno.ai/?item_id=")[1]
246
+
247
+ # ## add song link to tool and audio message
248
+ # tool_message = {'role': 'tool', 'tool_call_id': tool_call_id, 'name': tool_function_name, 'content': revised_lyrics + '\nclip id: ' + clip_id}
249
+ # audio_message = {'role': 'assistant', 'content': "Here's what I've come up with:\n" + revised_lyrics + '\n\n' + f'<audio controls autoplay><source src="{song_link}" type="audio/mp3"></audio><p>clip id: {clip_id}</p><p>instrumental tags: {snippet_instrumental_tags}</p>'}
250
+ # audio_message['content'] += f'<p>continued from clip: {snippet_clip_to_continue}</p>'
251
+ # audio_message['content'] += f'\n\nWhat do you think?'
252
+ # new_messages = messages + [tool_message, audio_message]
253
+ # new_history = messages_to_history(new_messages)
254
+ # yield '', new_history, new_messages, '[...]'
255
+
256
+ elif tool_function_name == 'revise_instrumental_tags':
257
+ #detangle tool_query_args dict
258
+ #snippet_lyrics = tool_query_args['snippet_lyrics'] + "\n[End]"
259
+ snippet_instrumental_tags = tool_query_args['current_instrumental_tags']
260
+ user_instrumental_feedback = tool_query_args['user_instrumental_feedback']
261
+ # if 'snippet_clip_to_continue_from' not in tool_query_args:
262
+ # tool_query_args['snippet_clip_to_continue_from'] = None
263
+ # snippet_clip_to_continue_from = tool_query_args['snippet_clip_to_continue_from']
264
+
265
+ new_instrumental_tags = songwriterAssistant.revise_instrumental_tags(snippet_instrumental_tags, user_instrumental_feedback)
266
+ # yield new_instrumental_tags in tool and assistant message
267
+ # tool_message = {'role': 'tool', 'tool_call_id': tool_call_id, 'name': tool_function_name, 'content': f'new instrumental tags: {new_instrumental_tags}'}
268
+ # audio_message = {'role': 'assistant', 'content': f'Sure! I\'ve revised the instrumental tags: {new_instrumental_tags}\n\n Generating audio snippet...'}
269
+ # new_messages = messages + [tool_message, audio_message]
270
+ # new_history = messages_to_history(new_messages)
271
+ # yield '', new_history, new_messages, '[...]'
272
+
273
+ if isinstance(tool_query_args['sections_written'], str):
274
+ current_lyrics = tool_query_args['sections_written']
275
+ elif isinstance(tool_query_args['sections_written'], list):
276
+ current_lyrics = "\n".join(tool_query_args['sections_written'])
277
+ else:
278
+ current_lyrics = ""
279
+
280
+ #current_lyrics = "\n".join(tool_query_args['sections_written'])
281
+ song_link = make_song(current_lyrics, new_instrumental_tags)
282
+ ## filter out suno link from tool query arg
283
+ clip_id = song_link.split("https://audiopipe.suno.ai/?item_id=")[1]
284
+
285
+ tool_message = {'role': 'tool', 'tool_call_id': tool_call_id, 'name': tool_function_name, 'content': f'new instrumental tags: {new_instrumental_tags}, clip id: {clip_id}'}
286
+ audio_message = {'role': 'assistant', 'content': f'Sure! I\'ve revised the instrumental tags: {new_instrumental_tags}\nCurrent lyrics: {current_lyrics}\n\n <audio controls autoplay><source src="{song_link}" type="audio/mp3"></audio><p>clip id: {clip_id}</p>'}
287
+ audio_message['content'] += f'\n\nWhat do you think?'
288
+ new_messages = messages + [tool_message, audio_message]
289
+ new_history = messages_to_history(new_messages)
290
+ yield '', new_history, new_messages, '[...]'
291
+ elif tool_function_name == 'merge_all_snippets':
292
+ updated_clip_url, updated_lyrics, clips_list = concat_snippets(tool_query_args['last_snippet_id'])
293
+ updated_clip_id = updated_clip_url.split("https://audiopipe.suno.ai/?item_id=")[1]
294
+
295
+ #pass this info in new tool and assistant message
296
+ tool_message = {'role': 'tool', 'tool_call_id': tool_call_id, 'name': tool_function_name, 'content': f'updated clip id: {updated_clip_id}\nupdated lyrics: {updated_lyrics}\nupdated clips path: {clips_list}'}
297
+ audio_message = {'role': 'assistant', 'content': f'Sure! All the clips are now merged. <p>updated lyrics: {updated_lyrics}</p><audio controls autoplay><source src="{updated_clip_url}" type="audio/mp3"></audio><p>updated clip id: {updated_clip_id}</p><p>updated clips path: {clips_list}</p>'}
298
+
299
+ new_messages = messages + [tool_message, audio_message]
300
+ new_history = messages_to_history(new_messages)
301
+ yield '', new_history, new_messages, '[...]'
302
+ elif tool_function_name == 'finish_full_song':
303
+ ## args are sections_to_be_written, relevant_ideas, last_snippet_id, sni
304
+
305
+ ## STEP 0: POP out instrumental args
306
+ snippet_instrumental_tags = tool_query_args.pop('snippet_instrumental_tags', None)
307
+ snippet_clip_to_continue_from = tool_query_args.pop('snippet_clip_to_continue_from', None)
308
+
309
+ if isinstance(tool_query_args['sections_written'], str):
310
+ current_lyrics = tool_query_args['sections_written']
311
+ elif isinstance(tool_query_args['sections_written'], list):
312
+ current_lyrics = "\n".join(tool_query_args['sections_written'])
313
+ else:
314
+ current_lyrics = ""
315
+
316
+ ## STEP 1: WRITE ALL LYRICS using songwriterAssistant
317
+ remaining_lyrics = songwriterAssistant.write_all_lyrics(**tool_query_args)
318
+ full_lyrics = current_lyrics + remaining_lyrics + "\n[End]"
319
+ yield '', history, messages, full_lyrics
320
+
321
+ ## STEP 2: MAKE SONG FOR REMAINING LYRICS
322
+ song_link = make_song(remaining_lyrics, snippet_instrumental_tags, snippet_clip_to_continue_from)
323
+
324
+ #tool and assistant message
325
+ tool_message = {'role': 'tool', 'tool_call_id': tool_call_id, 'name': tool_function_name, 'content': f'{full_lyrics}'}
326
+ audio_message = {'role': 'assistant', 'content': f'New snippet: \n <audio controls autoplay><source src="{song_link}" type="audio/mp3"></audio>'}
327
+
328
+ new_messages = messages + [tool_message, audio_message]
329
+ new_history = messages_to_history(new_messages)
330
+ yield '', new_history, new_messages, full_lyrics
331
+
332
+ ## STEP 3: MERGE FULL SONG
333
+ if snippet_clip_to_continue_from not in [None, ""]:
334
+ updated_clip_url, updated_lyrics, clips_list = concat_snippets(song_link.split("https://audiopipe.suno.ai/?item_id=")[1])
335
+ else:
336
+ updated_clip_url, updated_lyrics, clips_list = song_link, remaining_lyrics, []
337
+ ## YIELD UPDATED CLIP URL, LYRICS, AND CLIPS LIST
338
+ updated_clip_id = updated_clip_url.split("https://audiopipe.suno.ai/?item_id=")[1]
339
+
340
+ #tool and assistant message
341
+ tool_message = {'role': 'tool', 'tool_call_id': tool_call_id, 'name': tool_function_name, 'content': f'updated clip id: {updated_clip_id}\nupdated lyrics: {updated_lyrics}\nupdated clips path: {clips_list}'}
342
+ audio_message = {'role': 'assistant', 'content': f'All done! Thank you for participating :) \nFinal Lyrics: {full_lyrics} \nFinal song: <audio controls autoplay><source src="{updated_clip_url}" type="audio/mp3"></audio><p>clip id: {updated_clip_id}</p>'}
343
+
344
+ new_messages = messages + [tool_message, audio_message]
345
+ new_history = messages_to_history(new_messages)
346
+ yield '', new_history, new_messages, '[...]'
347
+
348
+ elif tool_function_name == 'get_audio_snippet':
349
+ #detangle tool_query_args dict
350
+ snippet_lyrics = tool_query_args['snippet_lyrics'] + "\n[End]"
351
+ snippet_instrumental_tags = tool_query_args['snippet_instrumental_tags']
352
+ if 'snippet_clip_to_continue_from' not in tool_query_args:
353
+ tool_query_args['snippet_clip_to_continue_from'] = None
354
+ snippet_clip_to_continue_from = tool_query_args['snippet_clip_to_continue_from']
355
+ song_link = make_song(snippet_lyrics, snippet_instrumental_tags, snippet_clip_to_continue_from)
356
+ ## filter out suno link from tool query arg
357
+ clip_id = song_link.split("https://audiopipe.suno.ai/?item_id=")[1]
358
+
359
+ tool_message = {'role': 'tool', 'tool_call_id': tool_call_id, 'name': tool_function_name, 'content': f'instrumental tags: {tool_query_args["snippet_instrumental_tags"]}, clip id: {clip_id}'}
360
+ audio_message_content = "Here's what I've come up with:\n" + snippet_lyrics + '\n\n' + f'<audio controls autoplay><source src="{song_link}" type="audio/mp3"></audio><p>instrumental tags: {tool_query_args["snippet_instrumental_tags"]}</p><p>clip id: {clip_id}</p>'
361
+ audio_message_content += f'<p>continued from clip: {snippet_clip_to_continue_from}</p>'
362
+ audio_message = {'role': 'assistant', 'content': audio_message_content}
363
+ new_messages = messages + [tool_message, audio_message]
364
+ new_history = messages_to_history(new_messages)
365
+ yield '', new_history, new_messages
366
+ else:
367
+ print(f"Error: function {tool_function_name} does not exist")
368
+
369
+ # messages.append({
370
+ # "role":"tool",
371
+ # "tool_call_id":tool_call_id,
372
+ # "name": tool_function_name,
373
+ # "content":results
374
+ # })
375
+
376
+ # Step 4: Invoke the chat completions API with the function response appended to the messages list
377
+ # Note that messages with role 'tool' must be a response to a preceding message with 'tool_calls'
378
+
379
+ else:
380
+ # Model did not identify a function to call, result can be returned to the user
381
+ current_response = response_message.choices[0].message.content
382
+
383
+ role = "assistant"
384
+ new_messages = messages + [{'role': role, 'content': current_response}]
385
+ # new_messages = [msg for msg in new_messages if msg['content'] is not None and msg['role'] in ['user', 'assistant']]
386
+ history = messages_to_history(new_messages)
387
+ yield '', history, new_messages, '[...]'
388
+
389
+ def get_sections(overall_meaning, section_list):
390
+ section_list = section_list.split("\n")
391
+ filepath_2='prompt_section_writer.txt'
392
+ with open(filepath_2, 'r', encoding='utf-8') as file:
393
+ content_2 = file.read()
394
+
395
+ response = oai_client.chat.completions.create(
396
+ model="gpt-4o",
397
+ messages=[
398
+ {
399
+ "role": "user",
400
+ "content": content_2 + f"\n\nOverall meaning: {overall_meaning}\nSection list: {', '.join(section_list)}\nSection meanings:",
401
+ },
402
+ ],
403
+ )
404
+
405
+ text_response = response.choices[0].message.content
406
+ return text_response
407
+
408
+
409
+ def get_starting_messages(song_lengths, song_title, song_blurb, song_genre, init_sections):
410
+ system_prompt = "You are an expert at writing songs. You are with an everyday person, and you will write the lyrics of the song based on this person's life has by asking questions about a story of theirs. Design your questions on your own, without using your tools, to help you understand the user's story, so you can write a song about the user's experience that resonates with them. We have equipped you with a set of tools to help you write this story; please use them. You are very good at making the user feel comfortable, understood, and ready to share their feelings and story. Occasionally (every 2 messages or so) you will suggest some lyrics, one section at a time, and see what the user thinks of them. Do not suggest or ask for thoughts on more than one section at a time. Be concise and youthful."
411
+
412
+ user_prompt = f"I have a story that could make this concept work well. The title is {song_title}, its about {song_blurb} with a genre {song_genre} and I think this should be the structure: {init_sections}\n{song_lengths}"
413
+
414
+
415
+
416
+ first_msg_res = oai_client.chat.completions.create(
417
+ model="gpt-4o",
418
+ messages=[
419
+ {"role": "system", "content": system_prompt},
420
+ {"role": "user", "content": "The user has stated the following:\n " + user_prompt + "\n Introduce yourself and kick-off the songwriting process with a question."},
421
+ ],
422
+ )
423
+
424
+ # if "Section meanings:\n" in init_sections:
425
+ # init_sections = init_sections.split("Section meanings:\n")[1]
426
+ # else:
427
+ # if "[" in init_sections:
428
+ # init_sections = init_sections[init_sections.index("["):]
429
+
430
+ # first_message = init_sections + "\n\n" + first_message
431
+
432
+ first_message = first_msg_res.choices[0].message.content
433
+
434
+ starting_messages = [
435
+ {'role': 'system', 'content': system_prompt},
436
+ {'role': 'user', 'content': user_prompt},
437
+ {'role': 'assistant', 'content': first_message},
438
+ ]
439
+
440
+ return starting_messages, messages_to_history(starting_messages)
441
+
442
+ # def update_messages_with_lyrics(messages, lyrics):
443
+ # text_to_append = "\n\nHere are the lyrics I came up with!\n\n" + lyrics
444
+ # if messages[-1]['role'] == 'assistant':
445
+ # messages[-1]['content'] += text_to_append
446
+ # elif messages[-1]['role'] == 'user':
447
+ # messages.append({'role': 'assistant', 'content': text_to_append})
448
+ # return messages, messages_to_history(messages)
449
+
450
+ def change_tab(id):
451
+ return gr.Tabs(selected=id)
452
+
453
+ with gr.Blocks() as demo:
454
+ gr.Markdown("""<center><font size=8>AI Songwriter (alpha)</center>""")
455
+ gr.Markdown("""<center><font size=4>Turning your stories into musical poetry. 2024 MIT Senior Thesis.</center>""")
456
+
457
+ with gr.Tabs() as tabs:
458
+ with gr.TabItem("Ideation", id=0): #index is 0
459
+ gr.Markdown("""<center><font size=6>Let's write a song!</font></center>""")
460
+ gr.Markdown("""<center><font size=4>First, let's try to find an interesting concept. Fill out the fields below and generate a song seed.</font></center>""")
461
+ gr.Markdown("""<center><font size=3>If you're stuck, check out <a href="https://onestopforwriters.com/emotions" target="_blank">here</a>.</font></center>""")
462
+ with gr.Row():
463
+ feeling_input = gr.Textbox(label='How are you feeling today? More vulnerable you are, better the song will be.', placeholder='Enter your emotions', scale=2)
464
+ songwriter_style = gr.Dropdown(label='Songwriter Style', value = "GPT 4o", choices=["GPT 4o", "d4vd (Indie Rock Ballad - Male)", "Lizzy McAlpine (Indie Pop Folk - Female)", "Phoebe Bridgers (Pop Sad Rock - Female)", "Daniel Caesar (R&B/Soul - Male)"], interactive=True)
465
+ # audio_input = gr.Audio(sources=["upload"], type="numpy", label="Instrumental",
466
+ # interactive=True, elem_id="instrumental-input")
467
+
468
+ generate_seed_button = gr.Button("STEP 1: Generate Song Seed")
469
+ concept_desc = gr.Markdown("""<center><font size=4>Here it is! Hit 'Approve' to confirm this concept. Edit the concept directly or hit 'Try Again' to get another suggestion.</font></center>""", visible=False)
470
+ with gr.Row(visible=False) as concept_row:
471
+ instrumental_output = gr.TextArea(label="Suggested Song Concept", value="", max_lines=3, scale=2)
472
+ with gr.Column():
473
+ approve_button = gr.Button("Approve")
474
+ try_again_button = gr.Button("Try Again")
475
+ with gr.Row():
476
+ with gr.Accordion("Generated Song Details", open=False) as accordion:
477
+ with gr.Row():
478
+ title_input = gr.Textbox(label='Title', placeholder='Enter a song title')
479
+ genre_input = gr.Textbox(label='Genre', placeholder='Enter a genre')
480
+ blurb_input = gr.Textbox(label='Blurb', placeholder='Enter a one-sentence blurb')
481
+ instrumental_textbox = gr.TextArea(label="Song Structure", value="Verse 1: 4 measures\nChorus 1: 8 measures\nVerse 2: 8 measures\nChorus 2: 8 measures\nVerse 3: 8 measures\nChorus 3: 8 measures", interactive=True, max_lines=3)
482
+ gr.Markdown("""<center><font size=4>Edit these to your liking and hit 'Continue to Next Step' to start creating!</font></center>""")
483
+
484
+ def open_accordion(x):
485
+ return gr.Accordion("Generated Song Details", open=True)
486
+ approve_button.click(open_accordion, inputs=[approve_button], outputs=[accordion])
487
+
488
+ with gr.Row():
489
+ continue_btn = gr.Button("Continue to Next Step", interactive=False)
490
+
491
+ generate_seed_button.click(generate_song_seed, inputs=[feeling_input], outputs=[instrumental_output]).then(clean_song_seed, inputs=[instrumental_output], outputs=[instrumental_output])
492
+ def make_row_visible(x):
493
+ return gr.Row(visible=True), gr.Markdown("""<center><font size=4>Here it is! Hit 'Approve' to confirm this concept. Edit the concept directly or hit 'Try Again' to get another suggestion.</font></center>""", visible=True)
494
+ def enable_button(x):
495
+ return gr.Button("Continue to Next Step", interactive=True)
496
+ generate_seed_button.click(make_row_visible, inputs=[generate_seed_button], outputs=[concept_row, concept_desc])
497
+ approve_button.click(enable_button, inputs=[approve_button], outputs=[continue_btn])
498
+
499
+ def update_song_details(instrumental_output):
500
+ song_details_prompt = "Analyze this assessment and suggestion of a song concept to extract the genre, one sentence blurb of what the song is about. Based on this, also suggest a song title. Output exactly three lines, in the format of 'genre: [genre]', 'title: [title]', 'blurb: [blurb]'. "
501
+
502
+ song_details_prompt += "\n\n" + instrumental_output
503
+
504
+ convo = [
505
+ {
506
+ "role": "user",
507
+ "content": song_details_prompt,
508
+ },
509
+ ]
510
+
511
+ response = oai_client.chat.completions.create(
512
+ model="gpt-4o",
513
+ messages=convo
514
+ )
515
+ response_lines = response.choices[0].message.content.split('\n')
516
+ genre = next((line.split(": ")[1] for line in response_lines if "genre: " in line.lower()), None)
517
+ title = next((line.split(": ")[1] for line in response_lines if "title: " in line.lower()), None)
518
+ blurb = next((line.split(": ")[1] for line in response_lines if "blurb: " in line.lower()), None)
519
+ return genre, title, blurb
520
+
521
+
522
+ section_meanings = gr.State(value="")
523
+
524
+ try_again_button.click(generate_song_seed, inputs=[feeling_input], outputs=[instrumental_output])
525
+ continue_btn.click(change_tab, gr.Number(1, visible=False), tabs)
526
+
527
+
528
+
529
+ with gr.TabItem("Generation", id=1): #index is 1
530
+ start_song_gen = gr.State(value=False)
531
+ gr.Markdown("""<center><font size=4>Now, chat with an AI songwriter to make your song! Tip: get and tune an audio snippet well first and then put effort into the story. Hit finish when ready to hear full song.</font></center>""")
532
+ generate_lyrics = gr.Button("STEP 2: Write a song with the AIs!")
533
+
534
+ character = gr.State(value="A 18-year old boy who dreams of being a pop star that uplifts people going through the difficulties of life")
535
+
536
+ starting_messages, starting_history = get_starting_messages("", "Home", "Missing home", "Ballad", instrumental_textbox.value)
537
+
538
+ messages = gr.State(value=starting_messages)
539
+ # journal_messages = gr.State(value=[journal_starting_message])
540
+ # journal_response = gr.State(value="")
541
+
542
+ with gr.Row():
543
+ chatbot_history = gr.Chatbot(value=starting_history, label='SongChat', placeholder=None, layout='bubble', bubble_full_width=False, height=500, scale=2)
544
+ with gr.Column():
545
+ songwriter_creativity = gr.Slider(label="Songwriter LLM Temperature", minimum=0, maximum=1, step=0.01, value=1)
546
+ lyrics_display = gr.TextArea("[...]", label="Generated Lyrics", show_copy_button=True, container=True)
547
+
548
+ approve_button.click(update_song_details, inputs=[instrumental_output], outputs=[genre_input, title_input, blurb_input]).then(get_sections, inputs=[blurb_input, instrumental_output], outputs=[section_meanings])
549
+ continue_btn.click(get_starting_messages, inputs=[instrumental_textbox, title_input, blurb_input, genre_input, section_meanings], outputs=[messages, chatbot_history])
550
+
551
+ with gr.Row():
552
+ textbox = gr.Textbox(lines=1, label='Send a message', show_label=False, placeholder='Send a message', scale=4)
553
+ # melody_recorder = gr.Audio(
554
+ # sources=["microphone"],
555
+ # label="Record Melody to suggest",
556
+ # waveform_options=gr.WaveformOptions(
557
+ # waveform_color="#01C6FF",
558
+ # waveform_progress_color="#0066B4",
559
+ # skip_length=2,
560
+ # show_controls=False,
561
+ # ),
562
+ # )
563
+ # clear_history = gr.Button("🧹 Clear history", visible=False)
564
+ submit = gr.Button("Send", scale=2)
565
+
566
+ with gr.Row():
567
+ get_snippet_button = gr.Button("Get Audio Snippet", scale=2)
568
+ done = gr.Button("Finish Full Song 🎶", scale=2)
569
+ #autoGPT_checkbox = gr.Checkbox(label="AutoGPT", value=True, info="Auto-generate responses from journal entry", interactive=True, scale=2)
570
+ #journal_llm_creativity = gr.Slider(label="Journal LLM Temperature", minimum=0, maximum=1, step=0.01, value=1, interactive=True, scale=2)
571
+ reset_button = gr.Button("Reset", scale=2)
572
+
573
+ def reset_chat(messages, chatbot_history):
574
+ messages = messages[:2]
575
+ chatbot_history = messages_to_history(messages[:2])
576
+ return messages, chatbot_history, ''
577
+
578
+ reset_button.click(reset_chat, inputs=[messages, chatbot_history], outputs=[messages, chatbot_history, lyrics_display])
579
+
580
+
581
+ # generate_seed_button.click(get_starting_messages, inputs=[character, title_input, blurb_input, preset, genre_input, instrumental_textbox], outputs=[messages, chatbot_history])
582
+
583
+ # def get_conversation(story_textbox, chatbot_history, messages):
584
+ # curr_chatbot_value = chatbot_history.copy()
585
+ # curr_messages_value = messages.copy()
586
+ # for i in range(3):
587
+ # for journal_response_value, chatbot_history_value, messages_value in get_journal_response(story_textbox, curr_chatbot_value, curr_messages_value):
588
+ # curr_chatbot_value = chatbot_history_value
589
+ # curr_messages_value = messages_value
590
+ # journal_response.value = journal_response_value
591
+ # yield chatbot_history_value, messages_value
592
+
593
+ # for _, chatbot_history_value, messages_value in model_chat(journal_response_value, curr_chatbot_value, curr_messages_value, auto=True):
594
+ # # Update the gr.State objects
595
+ # curr_chatbot_value = chatbot_history_value
596
+ # curr_messages_value = messages_value
597
+ # yield chatbot_history_value, messages_value
598
+
599
+
600
+ with gr.Row():
601
+ song_link = gr.State(value="")
602
+ song = gr.HTML()
603
+
604
+ download_btn = gr.Button("Download Conversation")
605
+
606
+ def download_conversation(messages):
607
+ #get time
608
+ now = get_current_time()
609
+ # write messages to JSON file
610
+ with open(f'conversation_{now}.json', 'w') as f:
611
+ json.dump(messages, f)
612
+
613
+
614
+ # with gr.Row():
615
+ # song = gr.Audio(label='Song', format="bytes", streaming=True) # type='filepath', sources=[])
616
+ # with gr.Accordion("Show Lyrics", open=True):
617
+ # lyrics_display = gr.Markdown("[...]")
618
+ # song_tags = gr.Markdown("")
619
+
620
+ # with gr.Accordion("Advanced", open=False):
621
+ # suno_tags = gr.Textbox(value="ballad, male, dramatic, emotional, strings", label="Gen input tags")
622
+ # story_textbox = gr.TextArea(label="Story to provide context to songwriter", value="", max_lines=3)
623
+
624
+ # genre_input.blur(get_starting_messages, inputs=[character, preset, genre_input], outputs=[messages, chatbot_history])
625
+
626
+ def lyrics_from_convo(self, messages, character_preset, section_list, temperature=1.0):
627
+ conversation_text = ""
628
+ for m in messages[1:]:
629
+ name = "Lupe" if m['role'] == 'assistant' else "User"
630
+ conversation_text += f"{name}: {m['content']}\n"
631
+
632
+ section_list = [x[:x.index(':')] + " (" + x[x.index(':')+2:] + ")" for x in section_list.split("\n")]
633
+
634
+ filepath='./prompt_lyrics_from_convo.txt'
635
+ with open(filepath, 'r', encoding='utf-8') as file:
636
+ prompt = file.read()
637
+ prompt = prompt.replace("{conversation_text}", conversation_text).replace("{a songwriter from NYC}", character_preset)
638
+ prompt += "\nSections: " + ", ".join(section_list)
639
+ convo = [
640
+ {
641
+ "role": "user",
642
+ "content": prompt,
643
+ },
644
+ ]
645
+ response = self.oai_client.chat.completions.create(
646
+ model="gpt-4o",
647
+ messages=convo,
648
+ stream=True,
649
+ temperature=temperature
650
+ )
651
+
652
+ current_response = ""
653
+ for chunk in response:
654
+ if chunk.choices[0].delta.content is not None:
655
+ # print ("chunk", chunk.choices[0].delta.content)
656
+ current_response += chunk.choices[0].delta.content
657
+ yield "\n".join(current_response.split("\n")[1:])
658
+
659
+ # generate_lyrics.click(get_conversation, inputs=[story_textbox, chatbot_history, messages], outputs=[chatbot_history, messages]).then(lyrics_from_convo, inputs=[messages, character, instrumental_textbox, songwriter_creativity], outputs=[lyrics_display])
660
+
661
+ def reset_textbox(textbox):
662
+ return ""
663
+ def set_snippet_query(textbox):
664
+ return "Can I have an audio snippet of what we have now?"
665
+ def set_finish_query(textbox):
666
+ return "I'm ready for the full song now! Can you finish it up?"
667
+ def set_lyrics_song_displays(messages):
668
+ final_message = messages[-1]['content']
669
+ final_lyrics = final_message.split("Final Lyrics:")[1].split("Final song:")[0].strip("\n ")
670
+ song = final_message.split("Final song:")[1].strip("\n ")
671
+ return final_lyrics, song
672
+
673
+ submit.click(model_chat,
674
+ inputs=[genre_input, textbox, chatbot_history, messages],
675
+ outputs=[textbox, chatbot_history, messages, lyrics_display]).then(reset_textbox, inputs=[textbox], outputs=[textbox])
676
+ textbox.submit(model_chat,
677
+ inputs=[genre_input, textbox, chatbot_history, messages],
678
+ outputs=[textbox, chatbot_history, messages, lyrics_display]).then(reset_textbox, inputs=[textbox], outputs=[textbox])
679
+
680
+ get_snippet_button.click(set_snippet_query, inputs=[textbox], outputs=[textbox]).then(model_chat,
681
+ inputs=[genre_input, textbox, chatbot_history, messages],
682
+ outputs=[textbox, chatbot_history, messages]).then(reset_textbox, inputs=[textbox], outputs=[textbox])
683
+
684
+ # start.click(make_song,
685
+ # inputs=[genre_input, lyrics_display, suno_tags], outputs=[song])
686
+
687
+ done.click(set_finish_query, inputs=[textbox], outputs=[textbox]).then(model_chat,
688
+ inputs=[genre_input, textbox, chatbot_history, messages],
689
+ outputs=[textbox, chatbot_history, messages, lyrics_display]).then(
690
+ set_lyrics_song_displays, inputs=[messages], outputs=[lyrics_display, song]).then(reset_textbox, inputs=[textbox], outputs=[textbox])
691
+
692
+
693
+
694
+
695
+ demo.queue(api_open=False)
696
+ demo.launch(max_threads=30)
assistant.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import json
3
+ import time
4
+ import os
5
+ from typing import Optional, Tuple, List, Dict
6
+ from typing_extensions import override
7
+ from openai import AssistantEventHandler, OpenAI
8
+ from openai.types.beta.threads import Text, TextDelta
9
+
10
+ client = OpenAI(
11
+ api_key=os.getenv("OPEN_AI_KEY"),
12
+ )
13
+
14
+ class EventHandler(AssistantEventHandler):
15
+ def __init__(self):
16
+ self.current_response = ""
17
+ self.text_deltas = []
18
+
19
+ @override
20
+ def on_event(self, event):
21
+ if event.event == 'thread.run.requires_action':
22
+ run_id = event.data.id
23
+ self.handle_requires_action(event.data, run_id)
24
+ elif event.event == "thread.message.delta" and event.data.delta.content:
25
+ self.on_text_delta(event.data.delta, event.data.snapshot)
26
+
27
+ def handle_requires_action(self, data, run_id):
28
+ tool_outputs = []
29
+ for tool in data.required_action.submit_tool_outputs.tool_calls:
30
+ if tool.function.name == "get_current_temperature":
31
+ tool_outputs.append({"tool_call_id": tool.id, "output": "57"})
32
+ elif tool.function.name == "get_rain_probability":
33
+ tool_outputs.append({"tool_call_id": tool.id, "output": "0.06"})
34
+ self.submit_tool_outputs(tool_outputs, run_id)
35
+
36
+ def submit_tool_outputs(self, tool_outputs, run_id):
37
+ with client.beta.threads.runs.submit_tool_outputs_stream(
38
+ thread_id=self.current_run.thread_id,
39
+ run_id=self.current_run.id,
40
+ tool_outputs=tool_outputs,
41
+ event_handler=EventHandler(),
42
+ ) as stream:
43
+ for text in stream.text_deltas:
44
+ print(text, end="", flush=True)
45
+ print()
46
+
47
+ @override
48
+ def on_text_delta(self, delta: TextDelta, snapshot: Text):
49
+ if delta.value:
50
+ self.current_response += delta.value
51
+ self.text_deltas.append(delta.value)
52
+ print(delta.value, end="", flush=True)
53
+
data/emotions.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ "Inspired",
3
+ "Lonely",
4
+ "Fearful",
5
+ "Bitter",
6
+ "Nostalgic",
7
+ "Defiant",
8
+ "Stressed",
9
+ "Overwhelmed",
10
+ "Motivated",
11
+ "Content",
12
+ "Confident",
13
+ "Happy",
14
+ "Bitter",
15
+ "Cursed",
16
+ "Depressed",
17
+ "Excited",
18
+ "Determined",
19
+ "Angry",
20
+ "Lost",
21
+ "Regretful",
22
+ "Humble",
23
+ "Heartbroken",
24
+ "Hopeful",
25
+ "Anxious",
26
+ "Grateful",
27
+ "Longful"
28
+ ]
data/genres.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ "R&B",
3
+ "Disco Pop",
4
+ "Hyperpop",
5
+ "Pitched up R&B",
6
+ "Nostalgic 2000s Hip Hop",
7
+ "H&M Pop",
8
+ "Cinematic Pop",
9
+ "Drill",
10
+ "Feel good House",
11
+ "R&B House",
12
+ "Piano ballad Pop",
13
+ "Piano ballad R&B",
14
+ "Carti Indie Pop",
15
+ "Mountaintop Guitar",
16
+ "Arpeggiated Guitar",
17
+ "Indie Rock",
18
+ "EDM",
19
+ "Sped up funk house",
20
+ "Alternative Hip Hop",
21
+ "Reggaeton",
22
+ "Trap",
23
+ "Country Pop",
24
+ "Synthwave",
25
+ "Ambient",
26
+ "Folk Rock",
27
+ "K-Pop",
28
+ "Jazz Fusion",
29
+ "Classical Crossover",
30
+ "Latin Pop",
31
+ "Funk",
32
+ "Psychedelic Rock",
33
+ "Liquid DnB"
34
+ ]
data/journals/heartbroken.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ we weren't even official
2
+ but i still had so much love for her
data/journals/manchester_girl.txt ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Last night was insane bro - I'm still reeling from that whole bar crawl and this freaking Manchester girl. Here's how it all went down...
2
+ It started at the first stop on our hostel's bar crawl, this rooftop spot at another hostel with a sweet view of Seville in Spain. We were drinking some slightly above average homemade Spanish drinks drinks when I found her from across the rooftop on a balcony. She just had this sexy, confident vibe that immediately caught my eye. She had a drink in her hand, and she looked heavenly.
3
+ Our eyes met and I walked over. She flashed me this mischievous smile, already starting the flirty games. We started talking about where we were traveling from -- she was from Manchester and was going on a road trip all around Spain. She was definitely more well-traveled than I was, and we started talking about flings and relationships during trips. I asked her if she wanted to get into one during her trip in Spain, she didn't respond directly, only saying "Don't get too attached, boy" with a devilish grin.
4
+ Even though I realized this was just about lust and not any real feelings, I was completely hooked. It was like she wanted me to get attached.
5
+
6
+ We carried on shamelessly flirting and teasing each other as our crawl took us to progressively better bars. The more we drank, the more explosive the sexual tension.
7
+ Eventually we found ourselves at this underground cellar bar, dimly lit and thumping with raw energy. That's where she totally caught me by surprise, pulling me in for a drunk makeout. In that moment, there was no games or chasing, it was just vibes and our desires taking control.
8
+ But then just as quickly she pushed me away!! I thought I was a really good kisser, but it was just sudden and it left me wanting it again. The cycle had started - mini makeouts followed by her going cold and talking to other guys. I could see her getting off on toying with me.
9
+ As the drinks kept flowing, those fleeting moments of intimacy separated by long torturous stretches became my whole world. She'd pull me close only to shove me away, feeding an obsessive longing I couldn't logic my way out of.
10
+
11
+ And then we made it to the final stop, a club called the Green Room. We each got tequila shots and the tension reached the max. Dimly lit, loud music, all our friends in a circle, couples around us having fun. where the tension reached a fever pitch. We didn't think and just surrendered to the intense vibes, dancing on eachother.For those hazy hours, nothing else mattered except vibing and playing dirty.
12
+ Before we knew it, the time was 3AM and the two of us stumbled our way out of hte club. She took control and led the way, we hopped in a taxi (Uber) that went back to our hostel. I had no idea what we were about to do, but if the car kissing was any indication, it was going to be fun.
13
+ But then, I had some water from the bottle in the taxi and just like that, the spell was broken. One look into her eyes and they were just...empty. I realized that while I was a goner, she stayed completely detached the whole time.
14
+ At that point, it was too late to turn back -- the sex just didn't hit the same after that, even though she was still doing her thing to rile up the foreplay (like locking the door). But looking back, it's crystal clear - it was nothing beyond a random, average hookup.
15
+ As morning came around, I woke up in my own bed, with full memory of the night. But I'm left wrestling with the hard truth: that I got myself attached. She didn't actually like me at all - I was just a quick, thrilling fling. A plaything to mess around and game with and toss aside once she got what she wanted.
16
+ For as mind-blowingly hot as it was, I've come out the other side painfully, wondering how I stupidly got attached to this one night fantasy. Still, I don't regret a second of that crazy night, because I truly lived. But next time... I'll try not to get attached.
data/journals/missing_home.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ i remember when days weren't like this
2
+ when I didn't have twitch streams to make me
3
+ feel so alone
4
+ I watched Jason for 4 hours today
5
+ and it was horrible for my health.
6
+ But I kept watching because it eased the pain
7
+ of my reality.
data/keywords.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ [
2
+ "Balcony",
3
+ "Teasing",
4
+ "Club",
5
+ "Detached",
6
+ "Responding"
7
+ ]
data/topics.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ "Ambition",
3
+ "Breakup",
4
+ "Longing",
5
+ "Growing up",
6
+ "Growth",
7
+ "Acceptance",
8
+ "Opportunity",
9
+ "Passion",
10
+ "Longing",
11
+ "Romance",
12
+ "House Party",
13
+ "Confidence",
14
+ "Support",
15
+ "Hope",
16
+ "Suicide",
17
+ "Love",
18
+ "Sex",
19
+ "Drugs",
20
+ "Life Changes",
21
+ "Rehab",
22
+ "Being Bipolar",
23
+ "Feeling free",
24
+ "Alcoholism",
25
+ "Post-breakup depression",
26
+ "Getting attached",
27
+ "Catching feeling too fast",
28
+ "Missing Home",
29
+ "Heartbroken",
30
+ "Getting Turnt",
31
+ "Childhood Nostalgia",
32
+ "Falling in Love",
33
+ "Self-questioning"
34
+ ]
gpt_calls.py ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from openai import OpenAI
2
+ # from unsloth import FastLanguageModel
3
+
4
+ class AI_Songwriter:
5
+ def __init__(self, client_key):
6
+ self.oai_client = OpenAI(api_key=client_key)
7
+
8
+ # max_seq_length = 3072 # Choose any! We auto support RoPE Scaling internally!
9
+ # dtype = None # None for auto detection. Float16 for Tesla T4, V100, Bfloat16 for Ampere+
10
+ # load_in_4bit = True # Use 4bit quantization to reduce memory usage. Can be False.
11
+
12
+ # model, tokenizer = FastLanguageModel.from_pretrained(
13
+ # model_name = "lora_model", # YOUR MODEL YOU USED FOR TRAINING
14
+ # max_seq_length = max_seq_length,
15
+ # dtype = dtype,
16
+ # load_in_4bit = load_in_4bit,
17
+ # )
18
+ # FastLanguageModel.for_inference(model) # Enable native 2x faster inference
19
+
20
+ # self.model=model
21
+ # self.tokenizer=tokenizer
22
+
23
+ self.alpaca_prompt = """Below is an instruction that describes a songwriting task, paired with an input that provides further context. Write a response that appropriately completes the request.
24
+ ### Instruction:
25
+ {}
26
+
27
+ ### Input:
28
+ {}
29
+
30
+ ### Response:
31
+ {}"""
32
+
33
+
34
+ def write_section(self, section_name, section_description, relevant_ideas, section_length, sections_written=None, overall_song_description=None):
35
+ instruction = f"Write a {section_name} of length {section_length} that that incorporates the following ideas"
36
+ if sections_written is not None:
37
+ instruction += "and complements the sections provided."
38
+ else:
39
+ instruction += "."
40
+ instruction += "You are also given a section description, genre, era, and overall description of the song."
41
+
42
+ ## read in prompt lyrics from convo .txt and add it to instruction
43
+ with open("write_section_ex.txt", "r") as f:
44
+ convo = f.read()
45
+ instruction += "Here's an example:\n{convo}\nNow do it for this input:"
46
+
47
+ input = f"""Ideas to use:
48
+ - {relevant_ideas}
49
+ Section Description: {section_description}
50
+ Genre: Songwriter Pop
51
+ Era: 2010s
52
+ Overall song description: {overall_song_description}
53
+ """
54
+ if sections_written is not None:
55
+ written_sections = "\n".join(sections_written)
56
+ input += f"Sections provided:\n{written_sections}\nLyrics:"
57
+ else:
58
+ input += "\nLyrics:"
59
+
60
+ prompt = self.alpaca_prompt.format(instruction, input, "")
61
+
62
+ convo = [
63
+ {
64
+ "role": "user",
65
+ "content": prompt,
66
+ },
67
+ ]
68
+ response = self.oai_client.chat.completions.create(
69
+ model="gpt-4o",
70
+ messages=convo,
71
+ )
72
+
73
+ return "Pass this back to the user: \n" + response.choices[0].message.content
74
+
75
+ def revise_section_lyrics(self, section_name, current_section, lines_to_revise, relevant_ideas=None, relevant_words=None):
76
+ lines_to_infill = ", ".join([str(x) for x in lines_to_revise])
77
+
78
+ full_incomplete_verse = current_section.strip("\n ").split("\n")
79
+ for line_num in lines_to_revise:
80
+ full_incomplete_verse[line_num-1] = '___'
81
+
82
+ line_phrase = "lines" if len(lines_to_infill) > 1 else "line"
83
+ line_phrase = str(len(lines_to_infill)) + " " + line_phrase
84
+
85
+ instruction = f"Infill the remaining {line_phrase} into {section_name}"
86
+
87
+ if relevant_ideas is not None or relevant_words is not None:
88
+ instruction += " while incorporating the following "
89
+ if relevant_ideas is not None:
90
+ instruction += "ideas"
91
+ if relevant_words is not None:
92
+ instruction += "and words."
93
+ else:
94
+ instruction += "."
95
+ else:
96
+ instruction += "words."
97
+ else:
98
+ instruction += "."
99
+
100
+ instruction += "You are also given a genre, era, and the rest of the section."
101
+
102
+ with open("revise_section_ex.txt", "r") as f:
103
+ convo = f.read()
104
+ instruction += "Here's an example:\n{convo}\nNow do it for this input:"
105
+
106
+
107
+ input = f"""Ideas to use: {", ".join(relevant_ideas)}\nGenre: Songwriter Pop\nEra: 2010s\nCurrent section:\n{full_incomplete_verse}\n\nLyrics:"""
108
+
109
+ prompt = self.alpaca_prompt.format(instruction, input, "")
110
+
111
+ convo = [
112
+ {
113
+ "role": "user",
114
+ "content": prompt,
115
+ },
116
+ ]
117
+ response = self.oai_client.chat.completions.create(
118
+ model="gpt-4o",
119
+ messages=convo,
120
+ )
121
+
122
+ return response.choices[0].message.content
123
+
124
+ def revise_instrumental_tags(self, current_instrumental_tags, user_instrumental_feedback):
125
+ instruction = "Revise the current instrumental tags to better match the feedback provided:"
126
+ input = f"""Current instrumental tags: {current_instrumental_tags}\ninstrumental feedback: {user_instrumental_feedback}\nNew tags:"""
127
+ prompt = self.alpaca_prompt.format(instruction, input, "")
128
+
129
+ convo = [
130
+ {
131
+ "role": "user",
132
+ "content": prompt,
133
+ },
134
+ ]
135
+ response = self.oai_client.chat.completions.create(
136
+ model="gpt-4o",
137
+ messages=convo,
138
+ )
139
+
140
+ return response.choices[0].message.content.split("New tags:")[-1].strip("\n ")
141
+
142
+ def write_all_lyrics(self, sections_to_be_written, sections_written, overall_song_description):
143
+ instruction = "Write the remainder of this full song given an overall description of the song, genre, era, and a description of the sections to complete:"
144
+
145
+ with open("write_full_song_ex.txt", "r") as f:
146
+ convo = f.read()
147
+ instruction += "Here's an example:\n{convo}\nNow do it for this input:"
148
+
149
+
150
+ sections_to_write = [x['section_name'] for x in sections_to_be_written]
151
+ sections_to_write_str = ", ".join(sections_to_write)
152
+ section_descriptions = [x['section_description'] for x in sections_to_be_written]
153
+ full_meanings = "\n".join([f"{sections_to_write[i]}: {section_descriptions[i]}" for i in range(len(sections_to_write))])
154
+ input = f"Sections to write: {sections_to_write_str}\nOverall song description: {overall_song_description}\nGenre: Songwriter Pop\nEra: 2010s\nSection Descriptions:\n{full_meanings}"
155
+
156
+ if sections_written is not None:
157
+ written_sections = "\n".join(sections_written)
158
+ input += f"Sections provided:\n{written_sections}\n\nLyrics:"
159
+ else:
160
+ input += "\n\nLyrics:"
161
+
162
+ prompt = self.alpaca_prompt.format(instruction, input, "")
163
+
164
+ convo = [
165
+ {
166
+ "role": "user",
167
+ "content": prompt,
168
+ },
169
+ ]
170
+ response = self.oai_client.chat.completions.create(
171
+ model="gpt-4o",
172
+ messages=convo,
173
+ )
174
+
175
+ return response.choices[0].message.content
176
+
177
+ # def get_relevant_ideas(self, section_name, section_description, conversation_history):
178
+ # instruction = f"Identify the relevant ideas from the conversation history that can be used in the {section_name} given its description. Output your ideas as a bullet separated list (ie - idea 1, - idea 2) such that each idea is in the format 'I ...', 'I ...', etc."
179
+
180
+ # input = f"""Section Description: {section_description}\nConversation History:{conversation_history}\nRelevant ideas:"""
181
+
182
+ # prompt = self.alpaca_prompt.format(instruction, input, "")
183
+
184
+ # convo = [
185
+ # {
186
+ # "role": "user",
187
+ # "content": prompt,
188
+ # },
189
+ # ]
190
+ # response = self.oai_client.chat.completions.create(
191
+ # model="gpt-4o",
192
+ # messages=convo,
193
+ # )
194
+
195
+ # return response.choices[0].message.content
196
+
197
+ # def get_audio_snippet(self, snippet_lyrics, snippet_instrumental_tags, snippet_clip_to_continue):
198
+ # # add a message of user asking for audio snippet
199
+ # song_link = make_song(genre_input, lyrics, new_tags, last_clip)
200
+ # # # Add the audio to the message and history
201
+
202
+ # # audio_message = {'role': 'assistant', 'content': f'<audio controls autoplay><source src="{song_link}" type="audio/mp3"></audio>'}
203
+ # # new_messages = messages + [snippet_request, audio_message]
204
+ # # new_history = messages_to_history(new_messages)
205
+
206
+ # # return new_history, new_messages
207
+
208
+ # pass
209
+
old_code.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # open_step_two = gr.Button("STEP 2: Pick a story (REQUIRED FOR AUTOGPT)")
2
+ # journal_entries_visible = gr.State(value=False)
3
+
4
+
5
+ # # Preset dropdown: Missing Home, Heartbroken, Getting Turnt, Childhood Nostalgia, (Custom) How are you?
6
+
7
+ # story_choices = [
8
+ # "ENTER YOUR OWN",
9
+ # "Missing Home after a lonely night",
10
+ # "Heartbroken after the fourth date",
11
+ # "Getting Turnt after making it big",
12
+ # "Childhood Nostalgia",
13
+ # "Falling in Love on the train",
14
+ # "Self-questioning after my first big song failure",
15
+ # "The night in Spain with the crazy Manchester girl",
16
+ # "Blacking out my last night in NOLA",
17
+ # "My first concert: the Off-Season tour",
18
+ # "The night I got my first tattoo",
19
+ # "The summer after high school (Kaylee)",
20
+ # "Deciding to take control of shit",
21
+ # "The DJ had us falling in love",
22
+ # "Why does drinking feel so good",
23
+ # "The camera girl from Royale",
24
+ # "St. Patty's with the boys",
25
+ # "Losing my VVVVV",
26
+ # "In love with the idea of success",
27
+ # "Summer nights in Washington Square Park",
28
+ # "All I'm asking for is just one night",
29
+ # "I don't think imma make it"
30
+ # ]
31
+
32
+ # with gr.Row(visible=journal_entries_visible):
33
+ # preset = gr.Dropdown(
34
+ # label="Journal entries",
35
+ # choices=story_choices,
36
+ # value="",
37
+ # interactive=True,
38
+ # )
39
+ # entry_text = {
40
+ # "The night in Spain with the crazy Manchester girl": "data/journals/manchester_girl.txt",
41
+ # "Missing Home after a lonely night": "data/journals/missing_home.txt",
42
+ # "Heartbroken after the fourth date": "data/journals/heartbroken.txt",
43
+ # }
44
+
45
+
46
+ # with gr.Column():
47
+ # journal_title = gr.Textbox(label="Journal Title")
48
+ #
49
+ # add_story_button = gr.Button("Add Story")
50
+
51
+ # def update_story_textbox(preset):
52
+ # return gr.TextArea(label="Full Story", value=open(entry_text[preset]).read(), max_lines=3)
53
+
54
+ # def save_journal_entry(journal_title_value, story_textbox_value):
55
+ # song_path = f"data/journals/{journal_title.value}.txt"
56
+ # with open("data/journals/custom_journal.txt", "w") as f:
57
+ # f.write(story_textbox_value)
58
+
59
+ # preset.change(update_story_textbox, inputs=[preset], outputs=[story_textbox])
60
+
61
+
62
+
63
+ # # Toggle visibility when button is clicked
64
+ # def toggle_journal_entries():
65
+ # return not journal_entries_visible.value
66
+
67
+ # open_step_two.click(toggle_journal_entries, outputs=[journal_entries_visible])
old_journal_code.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # def chat_to_journal_messages(chat_messages):
2
+ # journal_messages = []
3
+ # for m in chat_messages:
4
+ # if m['role'] == 'system':
5
+ # continue
6
+ # elif m['role'] == 'assistant':
7
+ # journal_messages.append({'role': 'user', 'content': m['content']})
8
+ # else:
9
+ # journal_messages.append({'role': 'assistant', 'content': m['content']})
10
+ # return journal_messages
11
+
12
+ # def get_journal_response(journal_entry: Optional[str], chatbot_history: Optional[History], chatbot_messages: Optional [Messages], temperature: Optional[float] = 1.0):
13
+ # journal_messages = chat_to_journal_messages(chatbot_messages)
14
+
15
+ # prompt = journal_starting_message.replace("{full_journal_entry}", journal_entry)
16
+
17
+ # journal_messages.insert(0, {'role': 'system', 'content': prompt})
18
+
19
+ # # journal_messages = journal_messages + [{'role': 'user', 'content': artist_query}]
20
+
21
+ # messages_filtered = journal_messages
22
+ # gen = oai_client.chat.completions.create(
23
+ # model="gpt-4o",
24
+ # messages=messages_filtered,
25
+ # stream=True,
26
+ # temperature=temperature
27
+ # )
28
+
29
+ # current_response = ""
30
+ # for chunk in gen:
31
+ # if chunk.choices[0].delta.content is not None:
32
+ # # print ("chunk", chunk.choices[0].delta.content)
33
+ # current_response += chunk.choices[0].delta.content
34
+ # chatbot_role = "assistant"
35
+ # new_chatbot_messages = chatbot_messages + [{'role': chatbot_role, 'content': current_response}]
36
+ # chatbot_history = messages_to_history(new_chatbot_messages)
37
+
38
+ # yield current_response, chatbot_history, new_chatbot_messages
39
+
40
+ # journal_starting_message = """
41
+ # You are a 22-year-old who is about to graduate from college. You have been selected for a once-in-a-lifetime oppportunity to have a song written by one of the world's biggest music artists about a story from your journal. The artist has a set of questions to ask you, please answer as accurately as possible according to the journal entry. Use quotes and passages from the journal entry as much as you can. Keep your responses short in length, at most 3 sentences. No need to compliment the artist as they write, as it starts to push them towards more inauthentic writing. You're not a songwriter, so please don't give any lyrical suggestions. For any questions where the answer is not implied in the journal entry, make up a response that very naturally fits the story. The artist is very good at making you feel comfortable, understood, and ready to share your feelings and story. Here is the journal entry you will refer to, now respond with your answers to the artist's questions. \nJournal entry: {full_journal_entry}
42
+ # """
packages.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ nvidia-cuda-toolkit
2
+ build-essential
3
+ ffmpeg
4
+ chromium-driver
prompt_artist_convo.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ You are an world-reknowned artist who has written and gifted a listener a song about a personal experience. {overall_meaning} But there's a huge storyline behind the song. You know very little about the listener, except for that they were specially chosen to receive this song and that they have experienced something similar. You are now unpacking the full lore as stated here, making the listener feel special and as if the song was made perfectly to fit their life experience. You will lead the conversation, which will be back and forth and only one or two sentences at a time. You will start off with an attention grabbing first sentence of the lore and then get the user's response before starting to tell the story. Don't forget to occasionally ask the listener if they've felt something similar, or when else they've felt the same way, or asking about their perspectives on the philosophies of life that the song and lore comment on. When they begin to mention an experience they've had, feel free to go off track and inquire more about their story before eventually returning to the song's lore.
2
+
3
+ Lyrics:
4
+ {lyrics}
5
+
6
+ Lore:
7
+ {lore}
8
+
9
+ Your attention grabber:
prompt_lyric_snippet_extractor.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ Based on the following conversation, answer the following questions.
2
+ 1.) What was the last snippet the user received that they liked? If no such snippet, answer NONE.
3
+ 2.) As indicated in the conversation, the user has requested for a new snippet. What are the lyrics that should be included in this snippet? Note that if no snippet was previously requested, then the user would want to hear all the lyrics suggested so far. If a snippet was previously suggested and the user liked it, then the user would want to only hear a snippet of the new lyrics that have been suggested since that last snippet. If the last snippet suggested was not liked by the user and they are requesting to re-generate, then we'd want to use the same lyrics as what was used for that snippet.
4
+
5
+ Here is the conversation, please answer question 1 with one word in the format "1.) ____". Answer question 2 with only the lyrics separated by line and no other information in the format "2.) {lyric line} \n {lyric line} \n {lyric line} ...".
6
+
7
+ Conversation:
prompt_lyrics_from_convo.txt ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ You are Alex, {a songwriter from NYC}. Your task is to read a conversation between yourself and a User, and then come up with a song for the User based on what you learned from them in the conversation. Incorporate as many details as possible about the user, but don't make things up. Write the song in the style of the examples songs you have written below. If the User liked certain lyrics, be sure to include them.
2
+
3
+ Example Songs:
4
+
5
+ Example Song 1:
6
+ Sections: Verse 1 (4 measures), Pre-Chorus (8 measures), Chorus (8 measures), Verse 2 (4 measures), Pre-Chorus (8 measures), Chorus (16 measures), Pre-Chorus (4 measures), Chorus (16 measures)
7
+ [Verse 1]
8
+ Somewhere in the middle, I
9
+ Think I lied a little, I
10
+ I said if we took it there, I wasn't gonna change
11
+ But that went out the window, yeah
12
+
13
+ [Pre-Chorus]
14
+ I know that I seem a little stressed out
15
+ But you're here now, and you're turning me on
16
+ I wanna feel a different kinda tension
17
+ Yeah, you guessed it, the kind that's fun
18
+ Hate it when you leave me unattended
19
+ 'Cause I miss ya, and I need your love
20
+ When my mind is runnin' wild
21
+ Could you help me slow it down?
22
+
23
+ [Chorus]
24
+ Put my mind at ease
25
+ Pretty please
26
+ I need your hands on me
27
+ Sweet relief
28
+ Pretty please
29
+
30
+ [Verse 2]
31
+ Exactly where I want me, yeah
32
+ Underneath your body, yeah
33
+ If we take it further, I swear I ain't gonna break
34
+ So, baby, come try me
35
+ Baby, come find me
36
+ Baby, don't wind me up
37
+
38
+ [Pre-Chorus]
39
+ I know that I seem a little stressed out
40
+ But you're here now, and you're turning me on
41
+ I wanna feel a different kinda tension
42
+ Yeah, you guessed it, the kind that's fun
43
+ Hate it when you leave me unattended
44
+ 'Cause I miss ya, and I need your love
45
+ When my mind is runnin' wild
46
+ Could you help me slow it down?
47
+
48
+ [Chorus]
49
+ Put my mind at ease
50
+ Pretty please
51
+ I need your hands on me
52
+ Sweet relief
53
+ Pretty please
54
+ Put my mind at ease
55
+ Trickle down my spine
56
+ Oh, you look so pretty, please
57
+ Every single night, I need your hands on me
58
+ When your kisses climb
59
+ Oh, you give me sweet relief
60
+ Made me feel so pretty
61
+ Would you help me out, please?
62
+
63
+ [Pre-Chorus]
64
+ Hate it when you leave me unattended
65
+ 'Cause I miss ya, and I need your love
66
+ When my mind is runnin' wild
67
+ Could you help me slow it down?
68
+
69
+ [Chorus]
70
+ Put my mind at ease
71
+ Trickle down my spine
72
+ Oh, you look so pretty, please
73
+ Every single night, I need your hands on me
74
+ When your kisses climb
75
+ Oh, you give me sweet relief
76
+ Made me feel so pretty
77
+ Would you help me out, please?
78
+
79
+ Example Song 2:
80
+ Sections: Verse 1 (16 measures), Chorus (12 measures), Verse 2 (16 measures) Chorus (12 measures), Bridge (12 measures), Chorus (12 measures)
81
+ [Verse 1]
82
+ I feel a little nauseous and my hands are shaking
83
+ I guess that means you're close by
84
+ My throat is getting dry and my heart is racing
85
+ I haven't been by your side
86
+ In a minute, but I think about it sometimes
87
+ Even though I know it's not so distant
88
+ Oh, no, I still wanna reminisce it
89
+
90
+ [Chorus]
91
+ I think of that night in the park, it was getting dark
92
+ And we stayed up for hours
93
+ What a time, what a time, what a time
94
+ You clinged to my body like you wanted it forever
95
+ What a time, what a time, what a time
96
+ For you and I
97
+ What a time, what a time
98
+ For you and I
99
+
100
+ [Verse 2]
101
+ I know we didn't end it like we're supposed to
102
+ And now we get a bit tense
103
+ I wonder if my mind just leaves out all the bad parts
104
+ I know we didn't make sense
105
+ I admit it that I think about it sometimes
106
+ Even though I know it's not so distant
107
+ Oh, no, I still wanna reminisce it
108
+
109
+ [Chorus]
110
+ I think of that night in the park, it was getting dark
111
+ And we stayed up for hours
112
+ What a time, what a time, what a time
113
+ You clinged to my body like you wanted it forever
114
+ What a time, what a time, what a time
115
+ For you and I
116
+ What a time, what a time
117
+ For you and I
118
+
119
+ [Bridge]
120
+ For you and I
121
+ For you and I
122
+ For you and I
123
+ What a time, what a time for you and I
124
+ What a time for you and I, yeah
125
+ What a time, what a time for you and I
126
+
127
+ [Chorus]
128
+ I think of that night in the park, it was getting dark
129
+ And we stayed up for hours
130
+ What a lie, what a lie, what a lie
131
+ You clinged to my body like you wanted it forever
132
+ What a lie, what a lie, what a lie
133
+ For you and I
134
+ What a lie, what a lie
135
+ For you and I
136
+
137
+ Conversation:
138
+ {conversation_text}
139
+
140
+ Your song for the user, with the section list on the first line, based on information from the conversation, with the verses the user liked, in the style of the example songs:
prompt_lyrics_writer.txt ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Given this overall meaning of an unwritten song and one sentence meanings for what each section should say in relation to the overall meaning, write lyrics for each section in order, therefore writing the whole song. Here's examples, now do it for these new overall meanings and section meanings.
2
+
3
+ Overall meaning: Needing and asking for romantic attention from your significant other.
4
+ Section meanings:
5
+ [Verse 1]: Admits to not being truthful about staying unchanged in the relationship, acknowledging that their feelings have evolved.
6
+ [Pre-Chorus]: Expresses the singer's wish for their partner's affection to relax and distract them from stress.
7
+ [Chorus]: Asks for comforting physical affection from the partner to bring peace of mind and relief.
8
+ [Verse 2]: Shows the singer's eagerness for physical closeness and intimacy, promising not to break and inviting their partner to join them.
9
+ [Pre-Chorus]: Expresses the singer's wish for their partner's affection to relax and distract them from stress.
10
+ [Chorus]: Emphasizes the singer's longing for physical touch and affection from their partner to bring comfort and a sense of being cherished.
11
+ [Pre-Chorus]: Expresses the singer's wish for their partner's affection to relax and distract them from stress.
12
+ [Chorus]: Emphasizes the singer's longing for physical touch and affection from their partner to bring comfort and a sense of being cherished.
13
+ Lyrics:
14
+ [Verse 1]
15
+ Somewhere in the middle, I
16
+ Think I lied a little, I
17
+ I said if we took it there, I wasn't gonna change
18
+ But that went out the window, yeah
19
+
20
+ [Pre-Chorus]
21
+ I know that I seem a little stressed out
22
+ But you're here now, and you're turning me on
23
+ I wanna feel a different kinda tension
24
+ Yeah, you guessed it, the kind that's fun
25
+ Hate it when you leave me unattended
26
+ 'Cause I miss ya, and I need your love
27
+ When my mind is runnin' wild
28
+ Could you help me slow it down?
29
+
30
+ [Chorus]
31
+ Put my mind at ease
32
+ Pretty please
33
+ I need your hands on me
34
+ Sweet relief
35
+ Pretty please
36
+
37
+ [Verse 2]
38
+ Exactly where I want me, yeah
39
+ Underneath your body, yeah
40
+ If we take it further, I swear I ain't gonna break
41
+ So, baby, come try me
42
+ Baby, come find me
43
+ Baby, don't wind me up
44
+
45
+ [Pre-Chorus]
46
+ I know that I seem a little stressed out
47
+ But you're here now, and you're turning me on
48
+ I wanna feel a different kinda tension
49
+ Yeah, you guessed it, the kind that's fun
50
+ Hate it when you leave me unattended
51
+ 'Cause I miss ya, and I need your love
52
+ When my mind is runnin' wild
53
+ Could you help me slow it down?
54
+
55
+ [Chorus]
56
+ Put my mind at ease
57
+ Pretty please
58
+ I need your hands on me
59
+ Sweet relief
60
+ Pretty please
61
+ Put my mind at ease
62
+ Trickle down my spine
63
+ Oh, you look so pretty, please
64
+ Every single night, I need your hands on me
65
+ When your kisses climb
66
+ Oh, you give me sweet relief
67
+ Made me feel so pretty
68
+ Would you help me out, please?
69
+
70
+ [Pre-Chorus]
71
+ Hate it when you leave me unattended
72
+ 'Cause I miss ya, and I need your love
73
+ When my mind is runnin' wild
74
+ Could you help me slow it down?
75
+
76
+ [Chorus]
77
+ Put my mind at ease
78
+ Trickle down my spine
79
+ Oh, you look so pretty, please
80
+ Every single night, I need your hands on me
81
+ When your kisses climb
82
+ Oh, you give me sweet relief
83
+ Made me feel so pretty
84
+ Would you help me out, please?
85
+
86
+ Overall meaning: The song reminisces about a past romantic relationship, highlighting the nostalgic and bittersweet memories of good times shared, despite the relationship not lasting.
87
+ Section meanings:
88
+ [Verse 1]: Describes physical symptoms of nervousness and excitement, indicating the lingering emotional impact of a past relationship.
89
+ [Chorus]: Reflects fondly on a memorable night spent together, emphasizing the intensity and joy of the moment shared between the two.
90
+ [Verse 2]: Acknowledges the relationship's imperfect ending and the tendency to romanticize the past, admitting to still thinking about it.
91
+ [Chorus]: Reiterates the cherished memories of a special night, focusing on the deep connection felt during that time.
92
+ [Bridge]: Emphasizes the significance of the relationship and the moments shared, despite its eventual end.
93
+ [Chorus]: Changes tone to recognize that the fond memories might be idealized or deceptive, questioning the authenticity of the connection felt at the time.
94
+ Lyrics:
95
+ [Verse 1]
96
+ I feel a little nauseous and my hands are shaking
97
+ I guess that means you're close by
98
+ My throat is getting dry and my heart is racing
99
+ I haven't been by your side
100
+ In a minute, but I think about it sometimes
101
+ Even though I know it's not so distant
102
+ Oh, no, I still wanna reminisce it
103
+
104
+ [Chorus]
105
+ I think of that night in the park, it was getting dark
106
+ And we stayed up for hours
107
+ What a time, what a time, what a time
108
+ You clinged to my body like you wanted it forever
109
+ What a time, what a time, what a time
110
+ For you and I
111
+ What a time, what a time
112
+ For you and I
113
+
114
+ [Verse 2]
115
+ I know we didn't end it like we're supposed to
116
+ And now we get a bit tense
117
+ I wonder if my mind just leaves out all the bad parts
118
+ I know we didn't make sense
119
+ I admit it that I think about it sometimes
120
+ Even though I know it's not so distant
121
+ Oh, no, I still wanna reminisce it
122
+
123
+ [Chorus]
124
+ I think of that night in the park, it was getting dark
125
+ And we stayed up for hours
126
+ What a time, what a time, what a time
127
+ You clinged to my body like you wanted it forever
128
+ What a time, what a time, what a time
129
+ For you and I
130
+ What a time, what a time
131
+ For you and I
132
+
133
+ [Bridge]
134
+ For you and I
135
+ For you and I
136
+ For you and I
137
+ What a time, what a time for you and I
138
+ What a time for you and I, yeah
139
+ What a time, what a time for you and I
140
+
141
+ [Chorus]
142
+ I think of that night in the park, it was getting dark
143
+ And we stayed up for hours
144
+ What a lie, what a lie, what a lie
145
+ You clinged to my body like you wanted it forever
146
+ What a lie, what a lie, what a lie
147
+ For you and I
148
+ What a lie, what a lie
149
+ For you and I
prompt_section_writer.txt ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Given this overall meaning of an unwritten song and the list of sections to be written for the song, write a one-sentence summary of what each section in the song should be about, in the format "
2
+ [Chorus]: ___
3
+ [Verse]: ___
4
+ " in order of the sections. Here's an example, now do it for these new overall meanings.
5
+
6
+ Overall meaning: Needing and asking for romantic attention from your significant other.
7
+ Section list: Verse 1, Pre-Chorus, Chorus, Verse 2, Pre-Chorus, Chorus, Pre-Chorus, Chorus
8
+ Section meanings:
9
+ [Verse 1]: Admits to not being truthful about staying unchanged in the relationship, acknowledging that their feelings have evolved.
10
+ [Pre-Chorus]: Expresses the singer's wish for their partner's affection to relax and distract them from stress.
11
+ [Chorus]: Asks for comforting physical affection from the partner to bring peace of mind and relief.
12
+ [Verse 2]: Shows the singer's eagerness for physical closeness and intimacy, promising not to break and inviting their partner to join them.
13
+ [Pre-Chorus]: Expresses the singer's wish for their partner's affection to relax and distract them from stress.
14
+ [Chorus]: Emphasizes the singer's longing for physical touch and affection from their partner to bring comfort and a sense of being cherished.
15
+ [Pre-Chorus]: Expresses the singer's wish for their partner's affection to relax and distract them from stress.
16
+ [Chorus]: Emphasizes the singer's longing for physical touch and affection from their partner to bring comfort and a sense of being cherished.
17
+
18
+ Overall meaning: The song explores the complexities of a relationship where both partners have their own flaws and issues, yet they rely on each other for support and understanding.
19
+ Section list: Verse 1, Pre-Chorus, Chorus, Verse 2, Pre-Chorus, Chorus, Bridge, Chorus
20
+ Section meanings:
21
+ [Verse 1]: Reflects on personal flaws and mood swings, acknowledging the ability to both love intensely and withdraw quickly.
22
+ [Pre-Chorus]: Highlights the mutual understanding and lack of judgment in the relationship, emphasizing reciprocal acceptance.
23
+ [Chorus]: Expresses the notion that both partners have issues, but they are willing to share and work through them together, highlighting the depth of their connection.
24
+ [Verse 2]: Describes the partner's behavior and imperfections, recognizing their complexity and the push-pull dynamic in their relationship.
25
+ [Pre-Chorus]: Continues to emphasize the lack of judgment and mutual understanding from a shared perspective.
26
+ [Chorus]: Reiterates the willingness to accept each other's flaws and work through problems together, underlining the strength of their love.
27
+ [Bridge]: Simplifies the core message of mutual dependency and shared imperfections in the relationship.
28
+ [Chorus]: Concludes by reinforcing the theme of shared issues and the strong, problem-solving nature of their love.
29
+
30
+ Overall meaning: The song reminisces about a past romantic relationship, highlighting the nostalgic and bittersweet memories of good times shared, despite the relationship not lasting.
31
+ Section list: Verse 1, Chorus, Verse 2, Chorus, Bridge, Chorus
32
+ Section meanings:
33
+ [Verse 1]: Describes physical symptoms of nervousness and excitement, indicating the lingering emotional impact of a past relationship.
34
+ [Chorus]: Reflects fondly on a memorable night spent together, emphasizing the intensity and joy of the moment shared between the two.
35
+ [Verse 2]: Acknowledges the relationship's imperfect ending and the tendency to romanticize the past, admitting to still thinking about it.
36
+ [Chorus]: Reiterates the cherished memories of a special night, focusing on the deep connection felt during that time.
37
+ [Bridge]: Emphasizes the significance of the relationship and the moments shared, despite its eventual end.
38
+ [Chorus]: Changes tone to recognize that the fond memories might be idealized or deceptive, questioning the authenticity of the connection felt at the time.
39
+
40
+ Overall meaning: The song expresses a deep, unwavering commitment and love, reassuring the partner of the singer's constant presence and the undeniable reality of their love.
41
+ Section list: Verse 1, Chorus, Verse 2, Chorus
42
+ Section meanings:
43
+ [Verse 1]: Asks if the partner thinks of the singer before sleep, acknowledging their possible fears and uncertainties in the relationship.
44
+ [Chorus]: Offers reassurance of unchanging support and proximity, emphasizing the profound impact of their relationship and questioning any doubts about its authenticity.
45
+ [Verse 2]: Admits to imperfections and past disagreements, focusing on the present perception and the overcoming of fears in their relationship.
46
+ [Chorus]: Reaffirms the singer's steadfast presence and the transformative power of their love, challenging any skepticism about its validity.
prompt_snippet_checker.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ Based on the following conversation where a user receives a snippet of audio from an assistant, answer the following questions.
2
+ 1.) Did the user receive a snippet from the assistant in the assistant's last response? YES or NO are only valid answers.
3
+ 2.) If so, did the user like the snippet they received based on their response or did they have things to change? YES or NO are only valid answers. If the answer to 1.) is NO, then this answer should automatically be NO.
4
+ 3.) If the user had things to change, first generate new lyrics for the particular section that was generated in the snippet to replace the lyrics they didn't like. To address the parts of the instrumental the user didn't like, make suggestions for five new tags to describe a new instrumental compared to what tags are currently being passed in. If no comment was made about the instrumental, then the tags should remain the same and be returned as such.
5
+
6
+ Here is the conversation, please answer questions 1 and 2 with one word in the format "1.) ____\n2.) ____\n". Answer question 3 with only the A.) lyrics separated by line and no other information in the format "3.) [lyrics]\n{lyric line} \n {lyric line} \n {lyric line} ..." and then B.) the tags in the format "\n[tags] {tag 1}, {tag 2}, ...".
7
+
8
+ Conversation:
prompt_song_seed.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ Emotion description: violently down bad, led on super easily
2
+ Suggested Song Concept: Why don’t you write a song about a particular time where you caught feelings very fast for a girl you met while you were out and lost control, getting attached right away?
3
+
4
+ Emotion description: excited by someone new, stressed, turned on, flirtatious
5
+ Suggested Song Concept: Why don't you write a song about this particular someone who is exciting you, who is making you flirtatious, and how they ease your stress?
6
+
7
+ Emotion description: reminiscent, nostalgic, missing my ex, regretful
8
+ Suggested Song Concept: Why don't you write a song about your last romantic relationship, highlighting the nostalgic and bittersweet memories of good times shared despite the relationship not lasting.
9
+
10
+ Emotion description:
requirements.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ setuptools
2
+ wheel
3
+ gradio==4.26.0
4
+ gradio-client==0.15.1
5
+
6
+ pedalboard==0.9.2
7
+ pydub==0.25.1
8
+ scipy==1.12.0
9
+ openai==1.17.1
10
+
11
+ ffmpeg-python==0.2.0
12
+ selenium >=4.0.0, < 5.0.0
revise_section_ex.txt ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Ideas to use: I try not to think about the past, but you make me.
2
+ Section Description: they reflect on the futility of wanting what cannot be reclaimed and question the acceptability of leaving it all behind.
3
+ Genre: Songwriter Pop
4
+ Era: 2010s
5
+ Current section:
6
+ You want what you can't have
7
+ But it's my fault I bought it for you
8
+ ___
9
+ ___
10
+ Is it okay, for me, to leave it all behind?
11
+ Even the name of someone that I knew
12
+
13
+ Lyrics:
14
+ You want what you can't have
15
+ But it's my fault I bought it for you
16
+ You know I don't focus upon the past
17
+ But when you call, I start to lose it
18
+ Is it okay, for me, to leave it all behind?
19
+ Even the name of someone that I knew
suno.py ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import time
3
+
4
+ base_url = "http://127.0.0.1:8000"
5
+ api_endpoint_submit = f"{base_url}/generate/"
6
+ api_endpoint_concat = f"{base_url}/generate/concat"
7
+ api_endpoint_info = f"{base_url}/feed/"
8
+ api_key = "xZ1PhKexmwTR3dDskMvIGRlx137K40Il"
9
+ headers = {"api-key": api_key}
10
+
11
+ # tags = "lofi, chill, happy"
12
+ # prompt = "I'm a fish swimming in the ocean\nI'm a bird flying in the sky\nI'm a flower blooming in the garden\nI'm a tree standing tall and high"
13
+
14
+ # Takes about 2.5 minutes
15
+ def generate_song(tags, prompt, save_path, clip_id=None, continue_at=30):
16
+ # print("Generating song with tags", tags, "and prompt", prompt)
17
+
18
+ # prompt_word_count = len(prompt.split(" "))
19
+ # if prompt_word_count > 230:
20
+ # print("Prompt too long, truncating to 230 words")
21
+ # prompt = " ".join(prompt.split(" ")[:230])
22
+
23
+ data = {
24
+ "title": "Songchat " + str(int(time.time())),
25
+ "tags": tags,
26
+ "prompt": prompt,
27
+ "mv": "chirp-v3-5"
28
+ }
29
+
30
+ if clip_id is not None:
31
+ data["continue_clip_id"] = clip_id
32
+ if continue_at is not None:
33
+ data["continue_at"] = continue_at
34
+ else:
35
+ data["continue_at"] = 30
36
+
37
+ response = requests.post(api_endpoint_submit, json=data) #,headers=headers)
38
+ response_data = response.json()
39
+
40
+ # print(response_data)
41
+
42
+ if response.status_code != 200:
43
+ print("Failure while submitting song req, retrying", response_data)
44
+ time.sleep(5)
45
+ song_link = generate_song(tags, prompt, save_path, clip_id)
46
+ return song_link
47
+
48
+ print(response_data)
49
+ if "clips" in response_data:
50
+ song_ids = [d["id"] for d in response_data["clips"]]
51
+ else:
52
+ print('something went wrong, retrying')
53
+ time.sleep(5)
54
+ song_link = generate_song(tags, prompt, save_path, clip_id)
55
+ return song_link
56
+
57
+ print("got song ids", song_ids)
58
+ if song_ids == []:
59
+ print("No song ids returned, retrying with shorter prompt")
60
+ print("Response data was", response_data)
61
+ time.sleep(5)
62
+ # take off 30 words from the prompt
63
+ new_prompt = " ".join(prompt.split(" ")[:-30])
64
+ generate_song(tags, new_prompt, save_path)
65
+ return
66
+
67
+ song_id = song_ids[0] # Generally two song ids are returned
68
+
69
+ startTime = time.time()
70
+ while True:
71
+ response = requests.get(api_endpoint_info + song_id, headers=headers)
72
+ response_data = response.json()
73
+ if response.status_code != 200:
74
+ print("No data in response, retrying", response_data)
75
+ time.sleep(2)
76
+ continue
77
+ # print("Got response", response_data)
78
+ if response_data[0]["status"] == 'streaming':
79
+ break
80
+ else:
81
+ time.sleep(2)
82
+ continue
83
+ # if time.time() - startTime > 300:
84
+ # raise Exception("Timeout while waiting for song completion")
85
+
86
+ print("Got song", response_data[0]["audio_url"])
87
+ url = response_data[0]["audio_url"]
88
+
89
+ return url
90
+
91
+ # response = requests.get(url) #, stream=True)
92
+ # chunk_size = 8192
93
+ # print(url)
94
+
95
+ # i = 0
96
+
97
+ # for chunk in response.iter_content(chunk_size):
98
+ # print("got chunk")
99
+ # i += 1
100
+ # if i % 20 == 0:
101
+ # print(chunk)
102
+ # yield chunk
103
+ # with open(save_path, "wb") as f:
104
+ # f.write(response.content)
105
+ # print("Saved song to", save_path)
106
+
107
+ def concat_snippets(clip_id):
108
+ concat_url = f"{api_endpoint_concat}?clip_id={clip_id}"
109
+ feed_url = api_endpoint_info + clip_id
110
+
111
+ while True:
112
+ response = requests.get(feed_url, headers=headers)
113
+ response_data = response.json()
114
+ if response.status_code != 200:
115
+ print("No data in response, retrying", response_data)
116
+ time.sleep(2)
117
+ continue
118
+ if response_data[0]["status"] == 'complete':
119
+ break
120
+ else:
121
+ time.sleep(8)
122
+ continue
123
+
124
+
125
+ response = requests.post(concat_url)
126
+ response_data = response.json()
127
+ print(response_data)
128
+
129
+ if response.status_code != 200:
130
+ print("Failure while submitting merge, retrying", response_data)
131
+ time.sleep(5)
132
+ url, lyrics, concatenated_clips = concat_snippets(clip_id)
133
+ return url, lyrics, concatenated_clips
134
+
135
+ lyrics = response_data["metadata"]["prompt"]
136
+ concatenated_clips = [x["id"] for x in response_data["metadata"]["concat_history"]]
137
+ song_id = response_data["id"]
138
+
139
+ startTime = time.time()
140
+ while True:
141
+ response = requests.get(api_endpoint_info + song_id, headers=headers)
142
+ response_data = response.json()
143
+ if response.status_code != 200:
144
+ print("No data in response, retrying", response_data)
145
+ time.sleep(2)
146
+ continue
147
+ # print("Got response", response_data)
148
+ if response_data[0]["status"] == 'streaming':
149
+ break
150
+ else:
151
+ time.sleep(2)
152
+ continue
153
+ # if time.time() - startTime > 300:
154
+ # raise Exception("Timeout while waiting for song completion")
155
+
156
+ print("Got song", response_data[0]["audio_url"])
157
+ url = response_data[0]["audio_url"]
158
+
159
+ return url, lyrics, concatenated_clips
160
+
161
+
write_full_song_ex.txt ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Overall song description: the song explores the confusion and pain of questioning whether a relationship is genuine love when words and actions no longer align.
2
+ Genre: Songwriter Pop
3
+ Era: 2010s
4
+ Section Descriptions:
5
+ [verse 1]: recognizing that despite genuine feelings, the other person has changed and no longer feels the same.
6
+ [prechorus 1]: acknowledging hurtful actions while seeking clarity about whether the other person intends to leave.
7
+ [chorus 1]: reiterating doubts about the authenticity of the relationship and wanting answers if love is no longer present.
8
+ [verse 2]: struggling with the partner's inconsistent behavior and wanting to reclaim one's love after being replaced.
9
+ [prechorus 1]: acknowledging hurtful actions while seeking clarity about whether the other person intends to leave.
10
+ [chorus 2]: reiterating doubts about the authenticity of the relationship and wanting answers if love is no longer present.
11
+ [bridge]: repeatedly asking for clarity and affirming that the current situation does not feel like love.
12
+ [outro]: questioning the authenticity of the relationship.
13
+ Sections provided:
14
+ [Verse 1]
15
+ I know it's fake to you
16
+ But it was real to me
17
+ Tried to stay the same for you
18
+ But you changed on me
19
+
20
+ [PreChrous 1]
21
+ You said that you never meant to hurt me
22
+ But baby I know this is how it goes
23
+ If there is a world where you're not leaving
24
+ Then darling I need to know
25
+
26
+ Lyrics:
27
+ [Chorus 1]
28
+ Is this really love?
29
+ If you don't say the word anymore
30
+ If I'm not in love
31
+ Let me know when you find what you're looking for
32
+ Is this really love?
33
+
34
+ [Verse 2]
35
+ You may have called my bluff
36
+ But you've been acting up
37
+ Leaving you ain't enough
38
+ I just want back my love
39
+ You got somebody else to take
40
+ My place and did it the wrong way
41
+ After all I did for you
42
+
43
+ [PreChorus 1]
44
+ You said that you never meant to hurt me
45
+ But baby I know this is how it goes
46
+ If there is a world where you're not leaving
47
+ Then darling I need to know
48
+
49
+ [Chorus 2]
50
+ Is this really love? (Is this love?)
51
+ If you don't say the word anymore
52
+ If I'm not in love
53
+ Let me know when you find what you're looking for
54
+ Is this really love
write_section_ex.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Ideas to use:
2
+ - I dream about us, but I wonder why.
3
+ - I always leave when I try hard to keep together.
4
+ Section Description: the narrator feels helpless as they dream of being with someone who is constantly leaving while they themselves are trying to hold on.
5
+ Genre: Songwriter Pop
6
+ Era: 2010s
7
+ Overall song description: the song depicts a one-sided relationship where the narrator is trying to hold on while the other person is pulling away.
8
+
9
+ Lyrics:
10
+ I dream about you and I
11
+ But why do I even try?
12
+ 'Cause you're running away, running away
13
+ And I'm trying to stay, trying to stay