티스토리 뷰
[1] Foundation Models
Foundation Models 는 온디바이스 LLM 을 제공하는 프레임워크입니다.
https://developer.apple.com/documentation/foundationmodels
Foundation Models | Apple Developer Documentation
Perform tasks with the on-device model that specializes in language understanding, structured output, and tool calling.
developer.apple.com
HIG 에 Generative AI 도 함께 추가되었는데 사용하면서 함께 읽어보면 좋을 것 같아요
[2] 사용법
LanguageModelSession 을 만들고 session 에 prompt 를 넘겨서 response 를 받습니다.
성능이 아쉽지만...... 무료니까...

Session 에는 다음과 같은 이니셜라이저가 제공되는데 문서에 필드 설명이 잘 나와있어요
init(model:guardrails:tools:instructions:)
ㄴ model 중 content tagging 유용해보임

또한 다양한 Request 함수를 제공하고 있습니다. (참고: Generating a request)
[2.1] Structured Ouput
Generable 매크로를 활용해서 LLM이 구조화된(Generable) 응답을 반환할 수 있게 합니다.
Guide 매크로는 필수는 아니지만 함께 활용하면 정확도를 높일 수 있습니다.

(MyTextEditor 는 앱 이름..)
Generable 은 struct 뿐만 아니라 enum 에도 붙일 수 있고 재귀도 가능해서 편하게 쓸 수 있을 것 같고

Guide 도 다양하게 쓸 수 있습니다. (Regex 도 되다니.. 🤍)




참고: Generating Swift data structures with guided generation
[2.2] 런타임 동적 스키마
위의 방식이 '컴파일 타임 스키마'라면 (컴파일 시점에 모델이 어떤 출력을 생성해야 할지 미리 알 수 있음)
런타임 동적 스키마를 사용하는 방법도 있습니다.
DynamicGenerationSchema 로 요청을 하고 GeneratedContent 타입을 받아서
value(_:forProperty:) 를 사용하는 방식입니다.


참고: 예제
[3] Tool Calling
Tool Calling 은 모델의 기능을 여러분의 사용 사례에 맞게 확장할 수 있는 수단을 제공합니다.
Tool Calling 을 통해 모델은 여러분이 만든 코드와 상호작용할 수 있으며,
이를 통해 다음과 같은 일을 할 수 있습니다
- 최신 정보를 가져오기 (ex. 외부 API 호출)
- 별도로 제공하는 신뢰가능한 데이터에 기반해서 응답 생성하기 (ex. Contacts 나 HealthKit 같은 다른 프레임워크와 연동, 앱의 데이터베이스에서 항목을 조회하고 이를 응답에 참조하도록 하기)
- 사이드 이펙트 실행하기 (ex. 다크모드 켜기)
[3.1] Tool Calling 사용법
Tool 프로토콜을 채택해서 Tool 을 만든 다음, Session 의 이니셜라이저에 넘기는 방식으로 사용합니다.
예제 1) 날씨 정보 요청


예제 2) 연락처(Contacts) 통합
온디바이스 모델의 강점을 잘 보여주는 예제
개인 정보가 서버로 업로드되지 않기 때문에 프라이버시를 보장하며 이런 기능을 통합할 수 있습니다.


툴이 처음 호출될 때, 사용자에게 접근 권한 요청이 표시된다고 합니다.

[3.2] Tool Calling 작동방식
작동방식은 다음과 같습니다.
- 세션 시작 시 Tool 과 Instruction 를 함께 등록
- 모델이 프롬프트를 분석해서 적절한 툴 판단
- Tool 과 Instruction 기반으로 Tool 에 전달될 Input Arguments 생성
- Tool 의 call() 메서드 호출 → 결과 반환 후 모델이 다음 응답 생성
ex) 캘린더 툴을 통합했을 때

Instruction 에 있는 날짜 정보랑 사용자가 세션에 입력한 프롬프트를 보고
'이벤트' 에 대해 묻는 질문인 것을 파악 후, 캘린더 툴을 호출하는 게 적합하다고 모델이 판단합니다.
Arguments 를 만들어서 캘린더 툴의 call 을 호출한 후, Ouput 을 참고해서 응답을 생성합니다.

주의사항이 있는데,
툴은 하나의 요청에 의해 여러번 호출될 수 있고 call 메서드는 병렬로 실행됩니다.
따라서 툴 내부에서 데이터를 접근하거나 처리할 때는 동시성(concurrency) 를 반드시 고려해야합니다.

참고: Expanding generation with tool calling
[4] Custom Adapter

특수한 사용 사례와 커스텀 데이터셋을 가진 머신러닝 전문가라면,
Apple의 어댑터 학습 툴킷(adapter training toolkit)을 사용해
맞춤형 어댑터를 직접 학습시킬 수도 있습니다.
하지만 유의할 점은,
Apple이 모델을 지속적으로 개선함에 따라
어댑터를 다시 학습시켜야 하는 책임이 따르기 때문에
상당한 관리 부담이 있다는 점입니다.
[5] 기타 유용한 기능
streaming 기능을 제공합니다. 응답으로 async sequence 를 반환합니다.
이 시퀀스의 각 요소는 부분적으로 생성된 타입의 인스턴스이며,
각 요소는 갱신된 스냅샷(snapshot) 포함하고 있습니다.

스트림 응답을 순회하며 요소들을 저장하면,
UI가 실시간으로 생동감 있게 구성되는 것을 볼 수 있으며 지연(latency)를 감출 수 있습니다.

contentTransition 함께 쓰는 것 좋아보여서 캡쳐

session 의 모든 프롬프트와 응답을 포함하고 있습니다.
session 은 stateful 하기 때문에 (상태를 유지) 모든 프롬프트와 응답은 transcript에 기록됩니다.

디버깅 및 UI 표시에 사용할 수 있으며 새로운 세션을 만들 때 transcript 를 넘겨 컨텍스트 유지를 할 수 있습니다.
session 이 최대 컨텍스트 사이즈를 초과했을 때, 새로운 session 을 시작해야하는데
transript 를 넘기면 이전 대화 히스토리를 기억하며 대화흐름을 이어갑니다.
init(model:guardrails:tools:transcript:)



히스토리를 전부 다 넘기는게 아니라 Summarizer 를 두고 transcript 를 요약해서 넘기는 게 좋습니다.
외부 라이브러리를 사용해서 할 수도 있고, Foundation Models 자체를 이용해 Transcript의 일부를 요약하는 것도 가능합니다. (위의 코드 스샷 참고)

[6] 모델 응답 생성 방식 세부 조정
GenerationOptions 을 통해 모델 세부 조정이 가능합니다. 세가지 필드를 세팅할 수 있습니다.
1) sampling : 출력 토큰을 선택하는 방식 설정

이를 통해 출력 결과의 무작위성(randomness) 을 제어가능한데,
아래에서 추가적으로 살펴보겠습니다.
2) temperature : 출력의 다양성 조정 (temperature 가 높을 수록 다른 결과를 생성)

3) maximumResponseTokens: 너무 긴 응답을 방지하기 위한 제한
[6.1] Sampling
모델이 출력을 생성할 때는 한 번에 하나의 토큰씩 생성합니다.
이 과정은 각 토큰에 대한 확률 분포(distribution)를 만든 후, 그 중 하나를 선택하는 방식으로 진행됩니다.
Foundation Models는 기본적으로 일정한 확률 범위 내에서 토큰을 선택합니다.
예를 들어, 첫 번째 토큰으로 어떤 경우엔 “Ah”를, 다른 경우엔 “Well”을 선택할 수 있습니다.
이러한 과정이 모든 토큰 생성마다 반복됩니다.

이러한 토큰 선택 행위를 “샘플링(sampling)“이라고 부르며,
기본 설정은 무작위(random) 샘플링입니다.
다양한 무작위성 출력이 필요한 경우 random 옵션을 기본적으로 사용해도 좋지만,
일관된 출력이 필요한 경우 결정적(deterministic) 출력이 필요합니다.
이를 위해 greedy 옵션을 제공합니다.
샘플링 방식을 greedy로 설정하면 같은 세션 상태에서 같은 프롬프트를 입력시 항상 같은 출력을 얻게 됩니다.
다만 이 보장은 같은 버전의 온디바이스 모델을 사용할 때만 유효합니다. (OS 업데이트로 모델이 바뀌면, 같은 프롬프트와 설정이어도 결과가 달라질 수 있습니다.)
[7] 유의사항
[7.1] Availability
1) Model Availability
Scheme > Option 에서 설정을 바꿔볼 수 있으며

다음과 같이 대응하기를 권장합니다.


2) Language Support
프롬프트에 사용자 입력을 포함할 때는 해당 언어가 지원되지 않을 수 있다는 점도 유의해야 합니다.
이 경우에는 unsupportedLanguageOrLocale라는 전용 오류가 발생하며,
이를 포착하여 처리할 수 있습니다.
이 오류를 활용하면 UI에서 사용자에게 맞춤 안내 메시지를 보여주는 데 유용할 수 있습니다.
또한, 특정 언어가 모델에서 지원되는지를 확인하는 API도 제공됩니다.
예를 들어, 사용자의 현재 언어가 지원되는지 확인하고,
지원되지 않는 경우 주의 문구(disclaimer) 를 표시할 수 있습니다.

[7.2] Guardrails
입력 (instructions, prompt, tool call input) 과 출력 (모델의 응답) 에 모두 작동하는 AI 안전장치 입니다.

Guardrails 은 디폴트 값 하나만 있고 개발자가 커스텀할 수 없는 것 같습니다.
가드레일이 작동하면 에러로 전달되는데

적절한 핸들링이 필요합니다.

[7.3] 온비다이스 모델에 대한 이해
대형 서버 기반 모델은 수백억~수천억 파라미터를 갖고 있고, 그만큼 복잡한 작업을 수행할 수 있지만, 온디바이스 모델은 몇 가지 한계가 있습니다:
- 복잡한 추론 과제는 여러 단계를 나눠 프롬프트로 설계해야 합니다.
- 계산기처럼 수학 계산을 맡기면 안 됩니다. 코드 생성 작업도 피하세요.
- 최신 정보에 대한 지식이 없기 때문에, 정확한 사실에 의존해서는 안 됩니다.
[8] 최적화
1) prewarm
session.respond를 호출하면, 운영체제는 해당 모델이 아직 메모리에 없다면 모델을 로드합니다.
하지만 프리워밍(Prewarming) 을 통해 요청을 보내기 전에 미리 모델을 로드해 세션을 더 빠르게 시작할 수 있습니다.
이 프리워밍은 앱이 비교적 유휴 상태일 때, 그리고 사용자가 세션을 사용할 조짐을 보일 때 수행하는 것이 가장 좋습니다.
예를 들어, 사용자가 프롬프트를 입력하게 될 텍스트 필드에 입력을 시작한 직후가 좋은 타이밍입니다.
예제 앱의 경우, 사용자가 랜드마크를 탭하면 곧 “여행 일정 생성” 버튼을 누를 가능성이 높기 때문에,
그 전에 미리 모델을 로딩할 수 있습니다.사용자가 설명을 다 읽고 버튼을 누를 즈음엔 모델이 이미 준비된 상태가 되어, 빠르게 응답할 수 있게 되는 것입니다.
respond(to:generating:includeSchemaInPrompt:options:isolation:) 를 사용하면
프레임워크는 해당 데이터 구조의 생성 스키마(generation schema) 를 자동으로 프롬프트에 삽입합니다.
하지만 이렇게 하면 토큰 수가 증가해, 지연 시간(latency)과 컨텍스트 크기(context size)도 함께 증가하게 됩니다.
그런데 만약 모델이 이미 응답 형식(response format) 을 충분히 이해하고 있는 상황이라면,
연속되는 request 에서는 includeSchemaInPrompt를 false로 설정해 스키마 삽입을 생략하고 성능을 개선할 수 있습니다.

사용가능한 경우는 다음과 같습니다.
첫 번째 경우는
• 동일한 유형의 요청을 여러 번 수행하는 멀티턴 대화에서입니다.
• 첫 번째 요청에서 이미 프롬프트에 스키마가 포함되었기 때문에, 이후 요청들에는 굳이 반복해서 포함할 필요가 없습니다.
두 번째 경우는
• instructions 안에 예시 응답을 포함시킨 경우입니다.
• 구조가 간단하고 옵셔널 속성이 없는 경우, instructions에 포함된 예시만으로 충분합니다. 만약 구조체에 옵셔널 속성(optional properties) 이 있다면, 예시를 줄 때는 해당 속성이 채워진 경우와 nil인 경우 둘 다 제공해야 합니다.

[9] 모델 피드백 하기
- 모델 latency 를 분석할 수 있는 instrument 가 제공됩니다.

- LanguageModelFeedbackAttachment 이라는 인코딩 가능한 피드백 첨부용 데이터 구조가 제공됩니다.
이 구조를 통해 파일형태로 Feedback Assistant 에 첨부할 수 있습니다.

[10] WWDC 영상
- WWDC 25 > Meet the Foundation Models framework
- WWDC 25 > Deep dive into the Foundation Models framework
- WWDC 25 > Explore prompt design & safety for on-device foundation models
- WWDC 25 > Code-along: Bring on-device AI to your app using the Foundation Models framework > 최적화 (prewarm, includeSchemaInPrompt) 관련 내용이 있음
'🍏 > Swift' 카테고리의 다른 글
| [Swift] Swift Concurrency > MainActor deinit 헷갈리는 것 정리 (0) | 2025.09.27 |
|---|---|
| [Swift] Swift Testing 헷갈리는 것 정리 (0) | 2025.01.29 |
| [Swift] 매크로 (Macro) (4) | 2024.12.07 |
| [Swift] @isolated(any) (4) | 2024.11.15 |
| [Swift] @unchecked, @preconcurrency, @retroactive (9) | 2024.11.06 |
- Total
- Today
- Yesterday
- 구글 Geocoding API
- METAL
- Flutter Clipboard
- 장고 Custom Management Command
- PencilKit
- Sketch 누끼
- Watch App for iOS App vs Watch App
- Django Firebase Cloud Messaging
- SerializerMethodField
- ipad multitasking
- Flutter 로딩
- flutter build mode
- Flutter Spacer
- ribs
- 장고 URL querystring
- 플러터 얼럿
- flutter 앱 출시
- Python Type Hint
- Django Heroku Scheduler
- flutter deep link
- Dart Factory
- drf custom error
- 플러터 싱글톤
- Django FCM
- github actions
- Flutter Text Gradient
- flutter dynamic link
- DRF APIException
- cocoapod
- Flutter getter setter
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |