[Feature] Add Microsoft.Maui.Essentials.AI - Apple Intelligence#33519
[Feature] Add Microsoft.Maui.Essentials.AI - Apple Intelligence#33519mattleibow merged 35 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces Microsoft.Maui.Essentials.AI, a new cross-platform AI library providing Apple Intelligence integration through Microsoft.Extensions.AI abstractions. The PR adds comprehensive test infrastructure including unit tests for JSON/plain text streaming, test data files for various AI scenarios, and model classes for structured output testing.
Changes:
- Uncommented Debug mode PublicAPI generation in
PublicAPI.targets - Added extensive unit test suite for
JsonStreamChunkerandPlainTextStreamChunker(internal streaming classes) - Added test data files (emotional responses, itineraries) in
.txtand.jsonlformats - Added model classes for Weather, Itinerary, Landmark, and PointOfInterest
- Added empty
PublicAPI.Unshipped.txtfor netstandard
Reviewed changes
Copilot reviewed 128 out of 132 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/PublicAPI.targets | Enabled Debug mode PublicAPI generation |
| PlainTextStreamChunkerTests/*.cs | Unit tests for plain text delta computation (basic, progressive, edge cases) |
| JsonStreamChunkerTests/*.cs | Unit tests for JSON streaming (basic, properties, nested, integration) |
| TestHelpers/DataStreamsHelper.cs | Helper for loading test data files |
| TestData/**/*.txt | Expected streaming output for various AI scenarios |
| TestData/**/*.jsonl | Progressive JSON snapshots for streaming tests |
| Models/*.cs | Test models for Weather, Itinerary, Landmark, PointOfInterest |
| PublicAPI.Unshipped.txt | Empty netstandard API tracking file |
Files not reviewed (1)
- src/AI/src/AppleNative/EssentialsAI.xcodeproj/project.xcworkspace/contents.xcworkspacedata: Language not supported
rolfbjarne
left a comment
There was a problem hiding this comment.
I don't really know enough this to review the PR properly - so maybe just add the [Experimental] attribute in any new managed code until it's gotten some real world testing?
FWIW it's a rather big PR, GitHub even says so:
Due to the large number of changes in this pull request, only one file is being shown at a time.
9a26e3e to
0cabbb6
Compare
… workflow Introduces the Essentials.AI module with a Trip Planner sample demonstrating production-ready AI integration patterns using Microsoft.Extensions.AI and Microsoft.Agents.AI. Sample Application (Essentials.AI.Sample): - 4-agent workflow: TravelPlanner → Researcher → ItineraryPlanner → Translator - RAG with embedding-based semantic search for destination matching - Streaming JSON responses with partial deserialization for progressive UI - Function calling (findPointsOfInterest tool) and structured JSON output - Conditional translation branching for non-English requests Services & Utilities: - StreamingJsonDeserializer, JsonMerger, BufferedChatClient - DataService (landmarks + embeddings), TaggingService, ItineraryService Library Skeleton (Essentials.AI): - Multi-platform TFM support with PublicAPI tracking - Foundation for future Apple Intelligence, Windows Copilot, Gemini Nano Test Infrastructure: - Unit tests: JSON streaming, merging, buffering (real AI response data) - Device tests: Reusable IChatClient/IEmbeddingGenerator base classes - Benchmarks: BenchmarkDotNet infrastructure
- Add AppleBindings.targets for reusable XcodeProject logic - Automatic XcodeProject handling (macOS only) - Pre-built artifact inclusion for Windows CI builds - IntelliSense support for generated binding files - Update Core.csproj to use XcodeProject instead of pre-built xcframework - Build MauiPlatformInterop.xcframework from source on macOS - Use downloaded artifacts on Windows CI - Update stage-pack.yml pipeline - Add pack_net_macOS job to build and publish Mac native binaries - Add download task to pack_net_Windows job to retrieve artifacts - Windows pack job now depends on macOS job completion - Remove obsolete files - Deleted MauiPlatformInterop.xcframework.zip (now built dynamically) - Deleted build-xcframework.sh (XcodeProject handles this)
…et#33519) <!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description This PR introduces **Microsoft.Maui.Essentials.AI**, a new library that provides cross-platform AI capabilities through the [Microsoft.Extensions.AI](https://github.com/dotnet/extensions) abstractions. This enables .NET MAUI developers to leverage on-device AI features while maintaining a consistent programming model across different AI backends. ### What's Added #### Core Library (`Microsoft.Maui.Essentials.AI`) **Apple Intelligence Chat Client (iOS 26+, macOS 26+, Mac Catalyst 26+, tvOS 26+)** `AppleIntelligenceChatClient` - Full `IChatClient` implementation for Apple's FoundationModels framework: | Feature | Description | |---------|-------------| | **Synchronous Responses** | `GetResponseAsync()` for complete responses | | **Streaming Responses** | `GetStreamingResponseAsync()` returns `IAsyncEnumerable<ChatResponseUpdate>` for real-time UI updates | | **Function/Tool Calling** | Register `AIFunction` tools that the model can invoke; automatic JSON argument parsing and result handling | | **Structured JSON Output** | Use `ChatResponseFormatJson` with JSON Schema to enforce typed responses matching your C# models | | **Generation Options** | Configure `Temperature`, `TopK`, `Seed`, and `MaxOutputTokens` | | **Cancellation Support** | Full `CancellationToken` support with proper native task cancellation | | **Middleware Compatible** | Works with `IChatClient` pipeline builders (`.AsBuilder().UseLogging().Build()`) | **Embedding Generator (iOS 13+, macOS 10.15+, Mac Catalyst 13.1+, tvOS 13+)** `NLEmbeddingGenerator` - `IEmbeddingGenerator<string, Embedding<float>>` implementation using Apple's NaturalLanguage framework: | Feature | Description | |---------|-------------| | **Sentence Embeddings** | Generate vector embeddings for text using `NLEmbedding` | | **Language Support** | Specify language via `NLLanguage` or use default (English) | | **Thread Safety** | Internal semaphore ensures thread-safe access to underlying `NLEmbedding` | | **Wrap Existing** | Constructor accepts existing `NLEmbedding` instance | **Extension Method:** - `NLEmbedding.AsIEmbeddingGenerator()` - Wrap existing `NLEmbedding` as `IEmbeddingGenerator<string, Embedding<float>>` **Internal Stream Processing (not public API):** - `JsonStreamChunker` - Converts complete JSON snapshots into incremental streaming deltas for smooth UI updates - `PlainTextStreamChunker` - Handles plain text streaming with simple delta computation --- ### Capabilities | Feature | Status | Notes | |---------|--------|-------| | **Chat Completion** | ✅ Supported | Full non-streaming via `GetResponseAsync()` | | **Streaming Responses** | ✅ Supported | `IAsyncEnumerable<ChatResponseUpdate>` via Channels | | **Text Embeddings** | ✅ Supported | `NLEmbeddingGenerator` via NaturalLanguage framework | | **Function/Tool Calling** | ✅ Supported | `AIFunction` tools with JSON argument parsing and result handling | | **Structured JSON Output** | ✅ Supported | `ChatResponseFormatJson` with JSON Schema via `JsonSchemaDecoder` | | **System Prompts** | ✅ Supported | Via `ChatMessage` with `ChatRole.System` or `ChatOptions.Instructions` | | **Multi-turn Conversation** | ✅ Supported | Full message history preserved | | **Image Input** | ❌ Not Supported | FoundationModels is text-only | | **Temperature** | ✅ Supported | Via `ChatOptions.Temperature` | | **TopK** | ✅ Supported | Via `ChatOptions.TopK` | | **TopP** | ❌ Not Supported | Not exposed by FoundationModels | | **Seed** | ✅ Supported | Via `ChatOptions.Seed` for reproducible outputs | | **Max Output Tokens** | ✅ Supported | Via `ChatOptions.MaxOutputTokens` | | **Cancellation** | ✅ Supported | Full `CancellationToken` with native Swift task cancellation | --- ### Architecture: Swift Native Layer & C# Integration The Apple Intelligence integration uses a **two-layer architecture** to bridge .NET with Apple's Swift-only FoundationModels framework: ``` ┌─────────────────────────────────────────────────────────────────┐ │ .NET MAUI Application │ │ IChatClient / IEmbeddingGenerator<string, Embedding<float>> │ └─────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ C# Layer (Essentials.AI) │ │ AppleIntelligenceChatClient : IChatClient │ │ • Implements Microsoft.Extensions.AI abstractions │ │ • Converts ChatMessage ↔ ChatMessageNative │ │ • Handles streaming via System.Threading.Channels │ │ • Wraps AIFunction tools as AIFunctionToolAdapter │ │ NLEmbeddingGenerator : IEmbeddingGenerator │ │ • Uses NaturalLanguage framework (Obj-C API, no Swift needed) │ └─────────────────────────────────────────────────────────────────┘ │ (ObjC Binding) ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Swift Layer (EssentialsAI) │ │ ChatClientNative │ │ • Wraps FoundationModels.LanguageModelSession │ │ • Manages Swift async Tasks with cancellation │ │ ToolNative : FoundationModels.Tool │ │ • Bridges C# AIFunction → Apple's Tool protocol │ │ JsonSchemaDecoder │ │ • Parses JSON Schema → GenerationSchema │ └─────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Apple FoundationModels Framework (iOS/macOS 26+) │ └─────────────────────────────────────────────────────────────────┘ ``` **Why Swift is Required for Chat Client:** - Apple's FoundationModels framework is Swift-only with no Objective-C API - Uses Swift-specific features: `async/await`, `Sendable`, result builders - Swift code compiles into a static library bound via Xamarin binding definitions **Layer Responsibilities:** | Layer | Responsibility | |-------|----------------| | **C# (AppleIntelligenceChatClient)** | `IChatClient` implementation, type conversion, streaming orchestration | | **C# (NLEmbeddingGenerator)** | `IEmbeddingGenerator` implementation using NaturalLanguage framework directly | | **Swift (ChatClientNative)** | Wraps FoundationModels, manages async Tasks, native callbacks | | **Swift (ToolNative)** | Bridges `AIFunction` → Apple's `Tool` protocol | | **Swift (JsonSchemaDecoder)** | JSON Schema → `GenerationSchema` for structured output | **Note:** Embedding generators (`NLEmbeddingGenerator`) use Apple's NaturalLanguage framework which has Objective-C APIs, so no Swift layer is needed. --- ### Why 1. **Unified AI API**: Write AI features using `IChatClient`/`IEmbeddingGenerator` abstractions—same code works with cloud AI (OpenAI, Azure) or on-device (Apple Intelligence) 2. **On-Device Privacy**: Apple Intelligence runs entirely on-device, keeping user data private 3. **Future Platform Support**: Architecture supports additional platforms (Android MLKit/Gemini Nano) as on-device AI expands --- ### Samples | Sample | Description | |--------|-------------| | `Essentials.AI.Sample` | .NET MAUI sample demonstrating chat client configuration and usage | | `AppleNative/EssentialsAISample` | Native Objective-C sample demonstrating Swift framework interop | --- ### Test Coverage | Category | Test Files | Description | |----------|------------|-------------| | **Unit Tests** | 56 | JsonStreamChunker, PlainTextStreamChunker, BufferedChatClient, streaming roundtrip scenarios | | **Device Tests** | 2 | AppleIntelligenceChatClient, NLEmbeddingGenerator on-device validation | | **Benchmarks** | 3 | Streaming JSON deserialization performance | **Device test coverage:** - **Chat client**: instantiation, messaging, streaming, JSON schema output, cancellation - **Embeddings**: concurrency, similarity, disposal, language support --- ### Public API Surface **Namespace: `Microsoft.Maui.Essentials.AI`** ```csharp // Apple Intelligence Chat Client (iOS/macOS/MacCatalyst/tvOS 26+) public sealed class AppleIntelligenceChatClient : IChatClient { public AppleIntelligenceChatClient(); public Task<ChatResponse> GetResponseAsync( IEnumerable<ChatMessage> messages, ChatOptions? options = null, CancellationToken cancellationToken = default); public IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync( IEnumerable<ChatMessage> messages, ChatOptions? options = null, CancellationToken cancellationToken = default); } // Sentence Embedding Generator (iOS 13+, macOS 10.15+, MacCatalyst 13.1+, tvOS 13+) public class NLEmbeddingGenerator : IEmbeddingGenerator<string, Embedding<float>>, IDisposable { public NLEmbeddingGenerator(); // Default: English public NLEmbeddingGenerator(NLLanguage language); // Specify language public NLEmbeddingGenerator(NLEmbedding embedding); // Wrap existing public Task<GeneratedEmbeddings<Embedding<float>>> GenerateAsync( IEnumerable<string> values, EmbeddingGenerationOptions? options = null, CancellationToken cancellationToken = default); public void Dispose(); } ``` **Namespace: `Microsoft.Extensions.AI`** (extension methods) ```csharp public static class NLEmbeddingExtensions { public static IEmbeddingGenerator<string, Embedding<float>> AsIEmbeddingGenerator( this NLEmbedding embedding); } ``` --- ### Usage Examples ```csharp // Chat with Apple Intelligence var chatClient = new AppleIntelligenceChatClient(); // Simple response var response = await chatClient.GetResponseAsync([ new ChatMessage(ChatRole.User, "Hello!") ]); // Streaming response await foreach (var update in chatClient.GetStreamingResponseAsync(messages)) { Console.Write(update.Text); // Progressive output } // Structured JSON output var options = new ChatOptions { ResponseFormat = ChatResponseFormat.ForJsonSchema<MyModel>() }; var structured = await chatClient.GetResponseAsync(messages, options); // With middleware pipeline var client = new AppleIntelligenceChatClient() .AsBuilder() .UseLogging(loggerFactory) .Build(); // Sentence Embeddings var generator = new NLEmbeddingGenerator(NLLanguage.English); var embeddings = await generator.GenerateAsync(["text to embed"]); // From existing NLEmbedding var nlEmbedding = NLEmbedding.GetSentenceEmbedding(NLLanguage.Spanish); var generator = nlEmbedding.AsIEmbeddingGenerator(); ``` --- ### Not in Scope (Future Work) - Android platform implementation (MLKit/Gemini Nano) - Windows platform implementation - Additional embedding model types --------- Co-authored-by: Rui Marinho <me@ruimarinho.net>
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [Microsoft.Extensions.Logging.Debug](https://dot.net/) ([source](https://github.com/dotnet/dotnet)) | nuget | patch | `10.0.3` -> `10.0.4` | | [Microsoft.Maui.Controls](https://github.com/dotnet/maui) | nuget | patch | `10.0.41` -> `10.0.50` | --- ### Release Notes <details> <summary>dotnet/maui (Microsoft.Maui.Controls)</summary> ### [`v10.0.50`](https://github.com/dotnet/maui/releases/tag/10.0.50) [Compare Source](dotnet/maui@10.0.41...10.0.50) #### What's Changed .NET MAUI 10.0.50 introduces significant improvements across all platforms with focus on quality, performance, and developer experience. This release includes 78 commits with various improvements, bug fixes, and enhancements. #### AI - Enable packing and independent preview versioning for Essentials.AI by [@​mattleibow](https://github.com/mattleibow) in dotnet/maui#33976 - Move Essentials.AI preview iteration to eng/Versions.props by [@​mattleibow](https://github.com/mattleibow) in dotnet/maui#34025 - \[Feature] Add Microsoft.Maui.Essentials.AI - Apple Intelligence by [@​mattleibow](https://github.com/mattleibow) in dotnet/maui#33519 #### Ai Agents - Copilot agent infrastructure, emulator reliability, and try-fix workflow improvements by [@​PureWeen](https://github.com/PureWeen) via [@​Copilot](https://github.com/Copilot) in dotnet/maui#33937 - Update PR agent models to claude-sonnet-4.6 and gpt-5.3-codex by [@​kubaflo](https://github.com/kubaflo) in dotnet/maui#34109 - ci-copilot: set pipeline run title early using build.updatebuildnumber by [@​jfversluis](https://github.com/jfversluis) via [@​Copilot](https://github.com/Copilot) in dotnet/maui#34156 - Revamp find-reviewable-pr skill: priorities, defaults, and doc fixes by [@​PureWeen](https://github.com/PureWeen) in dotnet/maui#34160 - Add correct CI pipeline names to Copilot instructions by [@​jfversluis](https://github.com/jfversluis) in dotnet/maui#34255 - Add resilience to UI tests for frozen/unresponsive apps by [@​PureWeen](https://github.com/PureWeen) in dotnet/maui#34023 - Copilot CI: Structured phase outputs, autonomous execution, iOS support, and CI pipeline by [@​kubaflo](https://github.com/kubaflo) in dotnet/maui#34040 - Agent Workflow Metrics via GitHub Labels by [@​kubaflo](https://github.com/kubaflo) in dotnet/maui#33986 #### Animation - \[Android] Fixed TransformProperties issue when a wrapper view is present by [@​Ahamed-Ali](https://github.com/Ahamed-Ali) in dotnet/maui#29228 <...
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Description
This PR introduces Microsoft.Maui.Essentials.AI, a new library that provides cross-platform AI capabilities through the Microsoft.Extensions.AI abstractions. This enables .NET MAUI developers to leverage on-device AI features while maintaining a consistent programming model across different AI backends.
What's Added
Core Library (
Microsoft.Maui.Essentials.AI)Apple Intelligence Chat Client (iOS 26+, macOS 26+, Mac Catalyst 26+, tvOS 26+)
AppleIntelligenceChatClient- FullIChatClientimplementation for Apple's FoundationModels framework:GetResponseAsync()for complete responsesGetStreamingResponseAsync()returnsIAsyncEnumerable<ChatResponseUpdate>for real-time UI updatesAIFunctiontools that the model can invoke; automatic JSON argument parsing and result handlingChatResponseFormatJsonwith JSON Schema to enforce typed responses matching your C# modelsTemperature,TopK,Seed, andMaxOutputTokensCancellationTokensupport with proper native task cancellationIChatClientpipeline builders (.AsBuilder().UseLogging().Build())Embedding Generator (iOS 13+, macOS 10.15+, Mac Catalyst 13.1+, tvOS 13+)
NLEmbeddingGenerator-IEmbeddingGenerator<string, Embedding<float>>implementation using Apple's NaturalLanguage framework:NLEmbeddingNLLanguageor use default (English)NLEmbeddingNLEmbeddinginstanceExtension Method:
NLEmbedding.AsIEmbeddingGenerator()- Wrap existingNLEmbeddingasIEmbeddingGenerator<string, Embedding<float>>Internal Stream Processing (not public API):
JsonStreamChunker- Converts complete JSON snapshots into incremental streaming deltas for smooth UI updatesPlainTextStreamChunker- Handles plain text streaming with simple delta computationCapabilities
GetResponseAsync()IAsyncEnumerable<ChatResponseUpdate>via ChannelsNLEmbeddingGeneratorvia NaturalLanguage frameworkAIFunctiontools with JSON argument parsing and result handlingChatResponseFormatJsonwith JSON Schema viaJsonSchemaDecoderChatMessagewithChatRole.SystemorChatOptions.InstructionsChatOptions.TemperatureChatOptions.TopKChatOptions.Seedfor reproducible outputsChatOptions.MaxOutputTokensCancellationTokenwith native Swift task cancellationArchitecture: Swift Native Layer & C# Integration
The Apple Intelligence integration uses a two-layer architecture to bridge .NET with Apple's Swift-only FoundationModels framework:
Why Swift is Required for Chat Client:
async/await,Sendable, result buildersLayer Responsibilities:
IChatClientimplementation, type conversion, streaming orchestrationIEmbeddingGeneratorimplementation using NaturalLanguage framework directlyAIFunction→ Apple'sToolprotocolGenerationSchemafor structured outputNote: Embedding generators (
NLEmbeddingGenerator) use Apple's NaturalLanguage framework which has Objective-C APIs, so no Swift layer is needed.Why
Unified AI API: Write AI features using
IChatClient/IEmbeddingGeneratorabstractions—same code works with cloud AI (OpenAI, Azure) or on-device (Apple Intelligence)On-Device Privacy: Apple Intelligence runs entirely on-device, keeping user data private
Future Platform Support: Architecture supports additional platforms (Android MLKit/Gemini Nano) as on-device AI expands
Samples
Essentials.AI.SampleAppleNative/EssentialsAISampleTest Coverage
Device test coverage:
Public API Surface
Namespace:
Microsoft.Maui.Essentials.AINamespace:
Microsoft.Extensions.AI(extension methods)Usage Examples
Not in Scope (Future Work)