-
Notifications
You must be signed in to change notification settings - Fork 362
Add basic iOS phi-3 sample #433
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 15 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
534a51b
initial ios phi-3 app
a857127
update to remove tests etc.
b09a546
update brief read me
9690f88
minor update
7d9dda5
update
75cc778
address pr comments
YUNQIUGUO 9252074
minor update
YUNQIUGUO 05693d0
minor updates
YUNQIUGUO 76282ba
remove the unnecessary delay step
YUNQIUGUO 3dd064f
Update mobile/examples/phi-3/ios/LocalLLM/LocalLLM/README.md
YUNQIUGUO b9a9a6c
address pr comments
YUNQIUGUO 94884ab
pr comments
YUNQIUGUO 780ecf0
minor update
YUNQIUGUO 82977d5
pr comments
YUNQIUGUO ebf1a64
update
YUNQIUGUO b465e2f
Update mobile/examples/phi-3/ios/LocalLLM/LocalLLM/README.md
YUNQIUGUO File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
477 changes: 477 additions & 0 deletions
477
mobile/examples/phi-3/ios/LocalLLM/LocalLLM.xcodeproj/project.pbxproj
Large diffs are not rendered by default.
Oops, something went wrong.
11 changes: 11 additions & 0 deletions
11
...e/examples/phi-3/ios/LocalLLM/LocalLLM/Assets.xcassets/AccentColor.colorset/Contents.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"colors" : [ | ||
{ | ||
"idiom" : "universal" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
mobile/examples/phi-3/ios/LocalLLM/LocalLLM/Assets.xcassets/AppIcon.appiconset/Contents.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"idiom" : "universal", | ||
"platform" : "ios", | ||
"size" : "1024x1024" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
mobile/examples/phi-3/ios/LocalLLM/LocalLLM/Assets.xcassets/Contents.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
mobile/examples/phi-3/ios/LocalLLM/LocalLLM/ContentView.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
import SwiftUI | ||
|
||
struct ContentView: View { | ||
@ObservedObject var tokenUpdater = SharedTokenUpdater.shared | ||
|
||
var body: some View { | ||
VStack { | ||
ScrollView { | ||
VStack(alignment: .leading) { | ||
ForEach(tokenUpdater.decodedTokens, id: \.self) { token in | ||
Text(token) | ||
.padding(.horizontal, 5) | ||
} | ||
} | ||
.padding() | ||
} | ||
Button("Generate Tokens") { | ||
DispatchQueue.global(qos: .background).async { | ||
// TODO: add user prompt question UI | ||
GenAIGenerator.generate("Who is the current US president?"); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
struct ContentView_Previews: PreviewProvider { | ||
static var previews: some View { | ||
ContentView() | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
mobile/examples/phi-3/ios/LocalLLM/LocalLLM/GenAIGenerator.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
#ifndef GenAIGenerator_h | ||
#define GenAIGenerator_h | ||
|
||
#import <Foundation/Foundation.h> | ||
#import <UIKit/UIKit.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@interface GenAIGenerator : NSObject | ||
|
||
+ (void)generate:(NSString *)input_user_question; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END | ||
|
||
#endif /* GenAIGenerator_h */ |
49 changes: 49 additions & 0 deletions
49
mobile/examples/phi-3/ios/LocalLLM/LocalLLM/GenAIGenerator.mm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
#import "GenAIGenerator.h" | ||
#include "LocalLLM-Swift.h" | ||
#include "ort_genai.h" | ||
#include "ort_genai_c.h" | ||
|
||
|
||
@implementation GenAIGenerator | ||
|
||
+ (void)generate:(nonnull NSString*)input_user_question { | ||
NSString* llmPath = [[NSBundle mainBundle] resourcePath]; | ||
const char* modelPath = llmPath.cString; | ||
|
||
auto model = OgaModel::Create(modelPath); | ||
auto tokenizer = OgaTokenizer::Create(*model); | ||
|
||
NSString* promptString = [NSString stringWithFormat:@"<|user|>\n%@<|end|>\n<|assistant|>", input_user_question]; | ||
const char* prompt = [promptString UTF8String]; | ||
|
||
auto sequences = OgaSequences::Create(); | ||
tokenizer->Encode(prompt, *sequences); | ||
|
||
auto params = OgaGeneratorParams::Create(*model); | ||
params->SetSearchOption("max_length", 200); | ||
params->SetInputSequences(*sequences); | ||
|
||
// Streaming Output to generate token by token | ||
auto tokenizer_stream = OgaTokenizerStream::Create(*tokenizer); | ||
|
||
auto generator = OgaGenerator::Create(*model, *params); | ||
|
||
while (!generator->IsDone()) { | ||
generator->ComputeLogits(); | ||
generator->GenerateNextToken(); | ||
|
||
const int32_t* seq = generator->GetSequenceData(0); | ||
size_t seq_len = generator->GetSequenceCount(0); | ||
const char* decode_tokens = tokenizer_stream->Decode(seq[seq_len - 1]); | ||
|
||
NSLog(@"Decoded tokens: %s", decode_tokens); | ||
|
||
// Add decoded token to SharedTokenUpdater | ||
NSString* decodedTokenString = [NSString stringWithUTF8String:decode_tokens]; | ||
[SharedTokenUpdater.shared addDecodedToken:decodedTokenString]; | ||
} | ||
} | ||
@end |
9 changes: 9 additions & 0 deletions
9
mobile/examples/phi-3/ios/LocalLLM/LocalLLM/LocalLLM-Bridging-Header.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
#ifndef LocalLLM_Bridging_Header_h | ||
#define LocalLLM_Bridging_Header_h | ||
|
||
#import "GenAIGenerator.h" | ||
|
||
#endif /* LocalLLM_Bridging_Header_h */ |
14 changes: 14 additions & 0 deletions
14
mobile/examples/phi-3/ios/LocalLLM/LocalLLM/LocalLLMApp.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
|
||
import SwiftUI | ||
|
||
@main | ||
struct LocalLLMApp: App { | ||
var body: some Scene { | ||
WindowGroup { | ||
ContentView() | ||
} | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
...xamples/phi-3/ios/LocalLLM/LocalLLM/Preview Content/Preview Assets.xcassets/Contents.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# **Local LLM sample application running Phi3-mini on iOS** | ||
|
||
## **Steps** | ||
|
||
### General prerequisites | ||
|
||
See the general prerequisites [here](../../../../../README.md#General-Prerequisites). | ||
|
||
For this application, the following prerequisites are preferred: | ||
|
||
1. macOS 14+ | ||
|
||
2. Xcode 15+ (latest Xcode version perferred.) | ||
|
||
3. iOS SDK 16.x + (iPhone 14 or iPhone 15 powered by a A16 or A17 preferred) | ||
|
||
**Note**: | ||
The current Xcode project contains a built .dylib for ORT and ORT GenAI. The following steps `A, B, C` under `step 1.` for building from source for the libraries are optional. | ||
However if you want to build from source to include the latest updates, please use the `step 1.` as a reference. | ||
|
||
### 1. Steps to build from source for ONNX Runtime and Generative AI libraries [Optional] | ||
|
||
#### **A. Preparation** | ||
|
||
- Install Python 3.10+ | ||
|
||
- Install flatbuffers | ||
``` | ||
pip3 install flatbuffers | ||
``` | ||
|
||
- Install [CMake](https://cmake.org/download/) | ||
|
||
#### **B. Compiling ONNX Runtime for iOS** | ||
|
||
```bash | ||
|
||
git clone https://github.com/microsoft/onnxruntime.git | ||
|
||
cd onnxruntime | ||
|
||
./build.sh --build_shared_lib --skip_tests --parallel --build_dir ./build_ios --ios --apple_sysroot iphoneos --osx_arch arm64 --apple_deploy_target 16.6 --cmake_generator Xcode --config Release | ||
|
||
``` | ||
|
||
***Notice*** | ||
|
||
1. Before compiling, you must ensure that Xcode is configured correctly and set it on the terminal | ||
|
||
```bash | ||
|
||
sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer | ||
|
||
``` | ||
|
||
2. ONNX Runtime needs to be compiled based on different platforms. For iOS, you can compile for arm64 or x86_64 based on needs. If you are running an iOS simulator on an Intel mac, compile for x86_64. Use arm64 for an ARM based mac to run the simulator, and to run on an iPhone. | ||
|
||
3. It is recommended to directly use the latest iOS SDK for compilation. Of course, you can also lower the version to be compatible with past SDKs. | ||
|
||
#### **C. Compiling Generative AI with ONNX Runtime for iOS** | ||
|
||
```bash | ||
|
||
git clone https://github.com/microsoft/onnxruntime-genai | ||
|
||
cd onnxruntime-genai | ||
|
||
python3 build.py --parallel --build_dir ./build_iphoneos --ios --ios_sysroot iphoneos --ios_arch arm64 --ios_deployment_target 16.6 --cmake_generator Xcode | ||
|
||
``` | ||
|
||
#### **D. Copy over latest header files and required .dylibs built from source** | ||
|
||
If you build from source and get the latest .dylibs for ORT and ORT GenAI, please copy the .dylibs over to `mobile\examples\phi-3\ios\LocalLLM\LocalLLM\lib` and copy the latest header files over to `mobile\examples\phi-3\ios\LocalLLM\LocalLLM\header` | ||
|
||
Usually the build output path for libonnxruntime.dylib is under `<ORT_PROJECT_ROOT>/build/intermediates/<platform>_<arch>/<build_config>/<build_config-platform>/libonnxruntime.dylib` and the build output path for libonnxruntime-genai.dylib is under `<ORT_GENAI_PROJECT_ROOT>/build/<build_config-platform>/libonnxruntime-genai.dylib`. For example: | ||
it may look like: `onnxruntime/build/intermediates/iphoneos_arm64/Release/Release-iphoneos/libonnxruntime.1.19.0.dylib` | ||
and similarly `onnxruntime-genai/build/Release/Release-iphoneos/libonnxruntime-genai.dylib`. | ||
(The absolute path may be slightly different based on build folder/config/architecture.) | ||
|
||
The resulting header directory should correctly contains: | ||
`mobile\examples\phi-3\ios\LocalLLM\LocalLLM\lib\libonnxruntime-genai.dylib` | ||
`mobile\examples\phi-3\ios\LocalLLM\LocalLLM\lib\libonnxruntime.1.19.0.dylib` | ||
|
||
And the source header files required including: | ||
YUNQIUGUO marked this conversation as resolved.
Show resolved
Hide resolved
|
||
`<ORT_MAIN_SOURCE_REPO>/onnxruntime/core/session/onnxruntime_c_api.h`, | ||
skottmckay marked this conversation as resolved.
Show resolved
Hide resolved
|
||
`<ORT_GENAI_MAIN_SOURCE_REPO>/src/ort_genai.h`, | ||
`<ORT_GENAI_MAIN_SOURCE_REPO>/src/ort_genai_c.h`. | ||
|
||
### 2. Create/Open the iOS application in Xcode | ||
|
||
The app uses Objective-C/C++ since using Generative AI with ONNX Runtime C++ API, Objective-C has better compatiblility. | ||
|
||
### 3. Copy the ONNX quantized INT4 model to the App application project | ||
|
||
Download from hf repo: <https://huggingface.co/microsoft/Phi-3-mini-128k-instruct-onnx/tree/main/cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4> | ||
|
||
After downloading completes, you need to copy files over to the `Resources` directory in the `Destination` column of `Target-LocalLLM`->`Build Phases`-> `New Copy File Phases` -> `Copy Files`. | ||
|
||
Upon app launching, Xcode will automatically copy and install the model files from Resources folder and directly download to the iOS device. | ||
|
||
### 4. Run the app and checkout the streaming output token results | ||
|
||
**Note**: The current app only sets up with a simple initial prompt question, you can adjust/try your own or refine the UI based on requirements. | ||
|
||
***Notice:*** The current Xcode project runs on iOS 16.6, feel free to adjust latest iOS/build for lates iOS versions accordingly. |
17 changes: 17 additions & 0 deletions
17
mobile/examples/phi-3/ios/LocalLLM/LocalLLM/SharedTokenUpdater.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
import Combine | ||
import Foundation | ||
|
||
@objc class SharedTokenUpdater: NSObject, ObservableObject { | ||
@Published var decodedTokens: [String] = [] | ||
|
||
@objc static let shared = SharedTokenUpdater() | ||
|
||
@objc func addDecodedToken(_ token: String) { | ||
DispatchQueue.main.async { | ||
self.decodedTokens.append(token) | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
**Note**: | ||
This folder contains the latest C++ headers that's required for the project. Copied over from the ORT and ORT GenAI repo matches the latest build. | ||
skottmckay marked this conversation as resolved.
Show resolved
Hide resolved
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: We need to fix the genai ios build to include the architecture in the output path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right good catch.. - forgot how xcode generate those path, but possibly a build variable is not correctly read for "ARCHS"