Files
music-assistant/Sources/MusicAssistantCore/Services/AI/AIService.swift
T

187 lines
5.3 KiB
Swift

import Foundation
public protocol AIService: Sendable {
func generateSongProject(from request: SongProjectGenerationRequest) async throws -> SongProjectGenerationResult
func discussSongProject(from request: SongProjectDiscussionRequest) async throws -> SongProjectDiscussionResult
func reviseLyrics(from request: LyricsRevisionRequest) async throws -> LyricsRevisionResult
func proposeProjectUpdate(from request: SongProjectUpdateRequest) async throws -> SongProjectUpdateResult
}
public extension AIService {
func discussSongProject(from request: SongProjectDiscussionRequest) async throws -> SongProjectDiscussionResult {
throw AIServiceCapabilityError.discussionNotSupported
}
}
public enum AIServiceCapabilityError: Error, Equatable, Sendable {
case discussionNotSupported
}
public struct AIConversationMessage: Equatable, Identifiable, Sendable {
public let id: String
public var role: AIConversationRole
public var content: String
public init(
id: String = UUID().uuidString,
role: AIConversationRole,
content: String
) {
self.id = id
self.role = role
self.content = content
}
}
public enum AIConversationRole: String, Equatable, Sendable {
case user
case assistant
case system
}
public struct AIRequestContext: Equatable, Sendable {
public var userInstruction: String
public var conversation: [AIConversationMessage]
public var localeIdentifier: String?
internal var privateApplicationRules: PrivateApplicationRules?
public init(
userInstruction: String,
conversation: [AIConversationMessage] = [],
localeIdentifier: String? = nil
) {
self.userInstruction = userInstruction
self.conversation = conversation
self.localeIdentifier = localeIdentifier
self.privateApplicationRules = nil
}
internal mutating func injectPrivateApplicationRules(_ rules: PrivateApplicationRules?) {
privateApplicationRules = rules
}
}
public struct SongProjectGenerationRequest: Equatable, Sendable {
public var context: AIRequestContext
public var seedProject: SongProject?
public var discussionMode: ConversationMode
public init(
context: AIRequestContext,
seedProject: SongProject? = nil,
discussionMode: ConversationMode = .auto
) {
self.context = context
self.seedProject = seedProject
self.discussionMode = discussionMode
}
}
public struct SongProjectGenerationResult: Equatable, Sendable {
public var project: SongProject
public var notes: [String]
public var followUpQuestions: [String]
public init(
project: SongProject,
notes: [String] = [],
followUpQuestions: [String] = []
) {
self.project = project
self.notes = notes
self.followUpQuestions = followUpQuestions
}
}
public struct SongProjectDiscussionRequest: Equatable, Sendable {
public var context: AIRequestContext
public var project: SongProject
public init(context: AIRequestContext, project: SongProject) {
self.context = context
self.project = project
}
}
public struct SongProjectDiscussionResult: Equatable, Sendable {
public var questions: [String]
public var notes: [String]
public init(questions: [String], notes: [String] = []) {
self.questions = questions
self.notes = notes
}
}
public struct LyricsRevisionRequest: Equatable, Sendable {
public var context: AIRequestContext
public var project: SongProject
public var sourceLyrics: Lyrics
public var mode: LyricsRevisionMode
public init(
context: AIRequestContext,
project: SongProject,
sourceLyrics: Lyrics,
mode: LyricsRevisionMode
) {
self.context = context
self.project = project
self.sourceLyrics = sourceLyrics
self.mode = mode
}
}
public enum LyricsRevisionMode: String, Equatable, Sendable {
case writeFromIdea
case correct
case improve
case restructure
case complete
}
public struct LyricsRevisionResult: Equatable, Sendable {
public var lyrics: Lyrics
public var notes: [String]
public init(lyrics: Lyrics, notes: [String] = []) {
self.lyrics = lyrics
self.notes = notes
}
}
public struct SongProjectUpdateRequest: Equatable, Sendable {
public var context: AIRequestContext
public var project: SongProject
public var allowedScopes: [SongProjectUpdateScope]
public init(
context: AIRequestContext,
project: SongProject,
allowedScopes: [SongProjectUpdateScope]
) {
self.context = context
self.project = project
self.allowedScopes = allowedScopes
}
}
public struct SongProjectUpdateResult: Equatable, Sendable {
public var project: SongProject
public var changedScopes: [SongProjectUpdateScope]
public var notes: [String]
public var followUpQuestions: [String]
public init(
project: SongProject,
changedScopes: [SongProjectUpdateScope] = [],
notes: [String] = [],
followUpQuestions: [String] = []
) {
self.project = project
self.changedScopes = changedScopes
self.notes = notes
self.followUpQuestions = followUpQuestions
}
}