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 []
}
}