Section 13/201 menit

13. Pipeline ML End-to-End

13. Pipeline ML End-to-End

Architecture untuk Production ML Feature

swift
// ML Pipeline: architecture lengkap untuk fitur ML di production app

import CoreML
import Vision
import NaturalLanguage
import Combine

// MARK: — Domain

struct AnalysisRequest {
    let image: UIImage?
    let text: String?
    let userContext: UserContext
}

struct AnalysisResult {
    let imageClassifications: [Classification]
    let detectedEntities: [NamedEntity]
    let sentiment: Sentiment
    let recommendations: [String]
    let processingTime: TimeInterval
}

struct UserContext {
    let userId: String
    let preferredLanguage: String
    let interactionHistory: [String]
}

// MARK: — ML Service

@MainActor
final class ContentAnalysisService: ObservableObject {
    @Published private(set) var state: AnalysisState = .idle

    private let imageAnalyzer: ImageClassifier
    private let textAnalyzer: TextAnalyzer
    private let recommendationEngine: RecommendationEngine

    init() throws {
        self.imageAnalyzer = try ImageClassifier()
        self.textAnalyzer = TextAnalyzer()
        self.recommendationEngine = RecommendationEngine()
    }

    func analyze(_ request: AnalysisRequest) async {
        state = .analyzing
        let start = Date()

        do {
            async let imageTask: [Classification] = {
                guard let image = request.image else { return [] }
                return try await self.imageAnalyzer.classify(image: image)
            }()

            async let textTask: (entities: [NamedEntity], sentiment: Sentiment) = {
                guard let text = request.text else {
                    return ([], .neutral(0))
                }
                let entities = self.textAnalyzer.extractEntities(from: text)
                let sentiment = self.textAnalyzer.analyzeSentiment(of: text)
                return (entities, sentiment)
            }()

            let (imageResults, textResults) = try await (imageTask, textTask)

            let recommendations = await recommendationEngine.generate(
                from: imageResults,
                entities: textResults.entities,
                context: request.userContext
            )

            let result = AnalysisResult(
                imageClassifications: imageResults,
                detectedEntities: textResults.entities,
                sentiment: textResults.sentiment,
                recommendations: recommendations,
                processingTime: Date().timeIntervalSince(start)
            )

            state = .completed(result)
        } catch {
            state = .failed(error)
        }
    }
}

enum AnalysisState {
    case idle
    case analyzing
    case completed(AnalysisResult)
    case failed(Error)
}

// MARK: — Recommendation Engine (rule-based + ML hybrid)

final class RecommendationEngine {
    private let semanticEngine: SemanticSearchEngine?

    init() {
        self.semanticEngine = SemanticSearchEngine()

        // Pre-load catalog
        let catalog = ["Produk A: kamera profesional", "Produk B: lensa wide-angle", "Produk C: tripod portabel"]
        catalog.forEach { semanticEngine?.addDocument(id: UUID().uuidString, text: $0) }
    }

    func generate(
        from classifications: [Classification],
        entities: [NamedEntity],
        context: UserContext
    ) async -> [String] {
        var query = classifications.prefix(3).map(\.label).joined(separator: " ")

        if let topEntity = entities.first {
            query += " \(topEntity.text)"
        }

        return semanticEngine?.search(query: query, topK: 3).map(\.document.text) ?? []
    }
}

// MARK: — Helper extension untuk SemanticSearchEngine
extension SemanticSearchEngine {
    func addDocument(id: String, text: String) {
        // Implementasi sama dengan Section 10
    }

    func search(query: String, topK: Int) -> [SearchResult] {
        // Implementasi sama dengan Section 10
        return []
    }
}