The Evaluations framework in iOS 27 lets developers iteratively improve AI-powered features by running structured evaluations, scoring outputs with a model judge, and measuring alignment between model and human ratings using Cohen's kappa coefficient. This hill-climbing workflow enables systematic prompt and feature quality improvement with confidence.
⢠Provides a scientific, repeatable process for improving AI prompt quality ā replacing guesswork with measurable alignment scores (Cohen's kappa)
⢠Catches model judge 'drift' early by quantifying how much the AI rater diverges from your own expert human ratings
⢠Integrates directly into Swift Testing and Xcode's Evaluations report, making AI quality a first-class CI/CD concern
Demonstrates how to write an alignment evaluation that computes Cohen's kappa between a human expert's ratings and a ModelJudgeEvaluator's scores, enabling hill-climbing of a prompt used to generate book tags.
import Evaluations
import FoundationModels
import Testing
// MARK: - Score Dimensions
struct TagScoreDimensions: ScoreDimensions {
@ScoreDimension(scale: 1...4, description: "How well tags represent plot, theme, and book info")
var relevance: Score
@ScoreDimension(scale: 1...4, description: "How useful the tags are as search terms")
var usefulness: Score
}
// MARK: - Dataset Entry
struct TagAlignmentEntry: EvaluationInput {
let bookSummary: String
let generatedTags: [String]
let expertRelevance: Int // Human expert rating 1-4
let expertUsefulness: Int // Human expert rating 1-4
}
// MARK: - Cohen's Kappa Helper
func cohensKappa(expertRatings: [Int], modelRatings: [Int]) -> Double {
guard expertRatings.count == modelRatings.count, !expertRatings.isEmpty else { return 0 }
let n = Double(expertRatings.count)
// Observed accuracy
let matches = zip(expertRatings, modelRatings).filter { $0.0 == $0.1 }.count
let po = Double(matches) / n
// Expected accuracy (chance agreement)
let scale = 1...4
let pe = scale.reduce(0.0) { sum, k in
let expertFrac = Double(expertRatings.filter { $0 == k }.count) / n
let modelFrac = Double(modelRatings.filter { $0 == k }.count) / n
return sum + expertFrac * modelFrac
}
guard pe < 1.0 else { return 1.0 }
return (po - pe) / (1.0 - pe)
}
// MARK: - Alignment Evaluation
struct TagJudgeAlignmentEvaluation: Evaluation {
typealias Input = TagAlignmentEntry
typealias Output = [String]
typealias Dimensions = TagScoreDimensions
let dataset: [TagAlignmentEntry] = [
TagAlignmentEntry(
bookSummary: "A young boy joins pirates on a treasure hunt, facing loyalty vs betrayal.",
generatedTags: ["adventure", "pirates", "treasure", "coming-of-age"],
expertRelevance: 4,
expertUsefulness: 2
),
TagAlignmentEntry(
bookSummary: "Four sisters navigate love and loss in Civil War-era New England.",
generatedTags: ["poignant", "quiet-steadiness", "family", "women"],
expertRelevance: 4,
expertUsefulness: 2
)
]
func subject(for input: TagAlignmentEntry) async throws -> [String] {
// Return pre-generated tags from the dataset (no model call needed here)
return input.generatedTags
}
var evaluators: [any Evaluator<[String], TagScoreDimensions>] {
[
ModelJudgeEvaluator(
model: SystemLanguageModel.default,
prompt: """Rate these book tags on relevance (how well they capture plot/theme) \
and usefulness (how good they are as search terms). Scale: 1=poor, 4=excellent."""
)
]
}
func aggregate(
results: [EvaluationResult<TagAlignmentEntry, [String], TagScoreDimensions>]
) -> [String: Double] {
let expertRel = results.map { $0.input.expertRelevance }
let expertUse = results.map { $0.input.expertUsefulness }
let modelRel = results.compactMap { $0.scores.relevance.map { Int($0.value.rounded()) } }
let modelUse = results.compactMap { $0.scores.usefulness.map { Int($0.value.rounded()) } }
let kappaRel = cohensKappa(expertRatings: expertRel, modelRatings: modelRel)
let kappaUse = cohensKappa(expertRatings: expertUse, modelRatings: modelUse)
let overallKappa = (kappaRel + kappaUse) / 2.0
return [
"kappa.relevance": kappaRel,
"kappa.usefulness": kappaUse,
"kappa.overall": overallKappa
]
}
}
// MARK: - Swift Testing Integration
@Test func judgeAlignmentMeetsThreshold() async throws {
let evaluation = TagJudgeAlignmentEvaluation()
let metrics = try await evaluation.run()
let overallKappa = metrics["kappa.overall"] ?? 0
// 0.6+ = substantial agreement per Cohen (1960)
#expect(overallKappa >= 0.6, "Judge drift detected: kappa=\(overallKappa). Refine judge prompt.")
}Foundation Models is a new Apple framework introduced in iOS 27 that gives developers on-device access to the same Apple Intelligence language model powering system features, enabling text generation, structured output, and tool-calling entirely on-device without a network connection.
Visual Intelligence brings iOS 17's Visual Look Up capabilities to a new developer-facing API surface in iOS 27, letting apps pipe live camera frames or static images through on-device scene understanding to extract subjects, text, barcodes, and rich semantic labels without any cloud round-trip.
iOS 27 opens the Foundation Models framework to third-party LLM providers via a new public LanguageModel protocol, allowing anyone to integrate server-based or local models (e.g. Claude, Gemini, CoreAI, MLX) using the same API as Apple's on-device system model.
In-depth guide
iOS 27 On-Device AI & Apple Intelligence ā⢠A Cohen's kappa score ā„ 0.6 is the recommended minimum threshold for 'substantial' alignment ā scores below this mean your judge's ratings cannot be trusted as a proxy for human judgment
⢠The alignment evaluation requires a pre-generated dataset from a prior evaluation run (stored as Xcode attachments) ā you cannot run alignment checks without first having human expert ratings to compare against
⢠Custom aggregation methods for Cohen's kappa must be implemented manually; the framework does not ship a built-in kappa calculator
Apple Intelligence device required; on-device model judge requires A17 Pro / M-series chip
iOS 27 opens the Foundation Models framework to third-party LLM providers via a new public LanguageModel protocol, enabling anyone to integrate custom, server-based, or open-source models using the same Swift API as Apple's on-device system model.