Compile complete Suno style prompts

This commit is contained in:
diyaa
2026-09-14 22:06:32 +02:00
parent 4fa477bdb0
commit 9e6e94e7cb
3 changed files with 123 additions and 3 deletions
@@ -49,11 +49,12 @@ public struct SongProjectPromptCompiler: PromptCompiling {
var components: [String] = []
append(project.genres.map(\.name).joined(separator: " + "), to: &components)
append(project.moods.map(\.name).joined(separator: ", "), to: &components)
append(moodPhrase(for: project), to: &components)
append(context.sunoStyleInstrumentPhrase, to: &components)
append(vocalPhrase(for: project), to: &components)
append(musicalParametersPhrase(for: project), to: &components)
append(project.productionDirections.map(\.text).joined(separator: ", "), to: &components)
append(emotionPhrase(for: project), to: &components)
append(productionPhrase(for: project), to: &components)
return components.joined(separator: "; ")
}
@@ -88,6 +89,76 @@ public struct SongProjectPromptCompiler: PromptCompiling {
return parameters.joined(separator: ", ")
}
private func moodPhrase(for project: SongProject) -> String {
let moods = project.moods.map(\.name).compactMap(normalized)
guard !moods.isEmpty else { return "" }
return "mood: \(moods.joined(separator: ", "))"
}
private func emotionPhrase(for project: SongProject) -> String {
let sectionEmotions = project.orderedSections.compactMap { section in
directedPhrase(
sectionTitle: section.title,
emotion: section.emotion,
energy: section.energy,
direction: nil
)
}
let arcEmotions = project.emotionalArc.compactMap { point in
directedPhrase(
sectionTitle: sectionTitle(for: point.sectionID, in: project),
emotion: point.emotion,
energy: point.energy,
direction: point.direction
)
}
let details = unique(sectionEmotions + arcEmotions)
guard !details.isEmpty else { return "" }
return "emotion: \(details.joined(separator: "; "))"
}
private func productionPhrase(for project: SongProject) -> String {
let sectionDirections = project.orderedSections.compactMap { section in
directedPhrase(sectionTitle: section.title, direction: section.productionDirection)
}
let projectDirections = project.productionDirections.compactMap { direction in
directedPhrase(
sectionTitle: sectionTitle(for: direction.sectionID, in: project),
direction: direction.text
)
}
let details = unique(sectionDirections + projectDirections)
guard !details.isEmpty else { return "" }
return "production: \(details.joined(separator: "; "))"
}
private func directedPhrase(
sectionTitle: String?,
emotion: String? = nil,
energy: Int? = nil,
direction: String? = nil
) -> String? {
var details = [normalized(emotion), energy.map { "energy \($0)" }, normalized(direction)]
.compactMap { $0 }
guard !details.isEmpty else { return nil }
if let sectionTitle = normalized(sectionTitle) {
details.insert(sectionTitle, at: 0)
}
return details.joined(separator: ", ")
}
private func sectionTitle(for sectionID: String?, in project: SongProject) -> String? {
guard let sectionID else { return nil }
return project.sections.first { $0.id == sectionID }?.title
}
private func unique(_ values: [String]) -> [String] {
var seen = Set<String>()
return values.filter { seen.insert($0).inserted }
}
private func append(_ value: String?, to components: inout [String]) {
guard let normalizedValue = normalized(value) else { return }
components.append(normalizedValue)