Files
hyungi_document_server/clients/ds-app/contract/fixtures/foundationmodels-respond.json
T

97 lines
4.9 KiB
JSON

{
"_meta": {
"fixture": "foundationmodels-respond",
"purpose": "S2-3a — Apple FoundationModels live capture (OnDeviceProvider 결선 + 테스트 동결 기준)",
"captured_on": "M5 Max MacBook Pro (128GB, Apple Intelligence)",
"captured_date": "2026-06-04",
"sdk": "macOS 26.5 SDK / FoundationModels.framework",
"note": "SDK 가 marshaling 하므로 raw request_body 는 없음. 이 파일은 응답 모양 + 에러 타입 + 취소 동작의 동결 기준."
},
"availability": {
"observed": "available",
"is_available_convenience": true,
"read_is_synchronous": true,
"api": "SystemLanguageModel.default.availability",
"enum": {
"available": "case available",
"unavailable_reasons": ["deviceNotEligible", "appleIntelligenceNotEnabled", "modelNotReady"]
},
"supports_korean": true,
"supported_language_count": 23
},
"happy_path": {
"api": "session.respond(to: String, options: GenerationOptions) async throws -> Response<String>",
"content_accessor": "response.content (Response<String>.content : String)",
"observed_content": "압력용기의 충격시험(Charpy) 면제 판정은, 용기의 압력 등급이 10MPa 이하인 경우, 충격 시험을 면제할 수 있으며, 이는 용기의 안전성을 보장하기 위한 중요한 기준입니다.",
"observed_latency_ms": 1291.3,
"transcript_entries_count": 1,
"is_responding_after": false,
"quality_note": "내용은 부정확(온디바이스 ~3B/2-bit QAT). corpusAsk 부적합·quickSummarize/classify 적합 라우팅 정합 — 사실성은 RemoteDS 코퍼스가 담당."
},
"session_init": {
"api": "LanguageModelSession(model: .default, tools: [], instructions: String?)",
"instructions_timing": "init (per-call 아님)",
"instructions_nil_handling": "systemPrompt == nil 이면 instructions 인자 생략 (빈 문자열 금지)",
"prewarm": "session.prewarm() — 동기 반환(관찰 ~1.3ms), 백그라운드 워밍",
"stateless_per_request": "호출마다 새 세션 생성 → instructions(init-time) + rateLimited/concurrentRequests(세션 상태) 둘 다 우회"
},
"generation_options": {
"api": "GenerationOptions(sampling: SamplingMode? = nil, temperature: Double? = nil, maximumResponseTokens: Int? = nil)",
"mapping": "AICompletionRequest.maxTokens -> maximumResponseTokens",
"temperature_note": "AICompletionRequest 에 temperature 필드 없음(동결) → 미설정(모델 기본). LocalMLX 와 동일 정책(둘 다 미설정)."
},
"generation_error": {
"_source": "Xcode jump-to-def / swiftinterface (LanguageModelSession.GenerationError) — authoritative, version-accurate",
"type": "LanguageModelSession.GenerationError : Error, LocalizedError",
"associated_value": "각 case 는 GenerationError.Context (refusal 은 (Refusal, Context))",
"cases": [
"exceededContextWindowSize(Context)",
"assetsUnavailable(Context)",
"guardrailViolation(Context)",
"unsupportedGuide(Context)",
"unsupportedLanguageOrLocale(Context)",
"decodingFailure(Context)",
"rateLimited(Context)",
"concurrentRequests(Context)",
"refusal(Refusal, Context)"
],
"plan_corrections": [
"plan 가정 'refusal 케이스명 없음' = 틀림 → refusal 은 별도 case 로 존재(guardrailViolation 과 구분).",
"plan 에 없던 concurrentRequests case 존재 — rateLimited 와 함께 stateless 세션에서 뜨면 세션 공유 버그 신호.",
"assetsUnavailable 정확명 확정(모델 자산 미가용)."
],
"reproduced_live": {
"exceededContextWindowSize": {
"trigger": "의도적 컨텍스트 오버플로(긴 프롬프트)",
"errorDescription": "Exceeded model context window size"
}
},
"finish_reason_mapping": {
"guardrailViolation": ".refused",
"refusal": ".refused",
"exceededContextWindowSize": ".unavailable",
"rateLimited": ".unavailable + loud log (stateless 인데 발생 = 세션 재사용 버그 신호)",
"concurrentRequests": ".unavailable + loud log (동일 — stateless 위반 신호)",
"unsupportedLanguageOrLocale": ".unavailable (+ supportedLocale 사전체크로 회피)",
"unsupportedGuide": ".unavailable",
"decodingFailure": ".unavailable",
"assetsUnavailable": ".unavailable",
"@unknown default": ".unavailable + loud log"
}
},
"cancellation": {
"_finding": "S2-Fe 전제 확정 — COOPERATIVE",
"cancel_requested_at_ms": 500,
"threw": "CancellationError",
"elapsed_ms": 533.6,
"interpretation": "respond() 는 mid-flight Task 취소를 협조적으로 honor(요청 33ms 후 CancellationError throw).",
"implication": "OnDevice complete() 에 surrounding Task.checkCancellation() 은 belt-and-suspenders(실제 중단은 respond() 내부). streamResponse 토큰단위 취소 폴백 불필요(선전환 금지)."
}
}