Compile complete Suno style prompts
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user