Skip to content

Commit 0de2e66

Browse files
YUNQIUGUOrachguoskottmckay
authored
Add basic iOS phi-3 sample (#433)
* initial ios phi-3 app * update to remove tests etc. * update brief read me * minor update * update * address pr comments * minor update * minor updates * remove the unnecessary delay step * Update mobile/examples/phi-3/ios/LocalLLM/LocalLLM/README.md Co-authored-by: Scott McKay <[email protected]> * address pr comments * pr comments * minor update * pr comments * update * Update mobile/examples/phi-3/ios/LocalLLM/LocalLLM/README.md Co-authored-by: Scott McKay <[email protected]> --------- Co-authored-by: rachguo <[email protected]> Co-authored-by: Scott McKay <[email protected]>
1 parent 8dc4650 commit 0de2e66

File tree

19 files changed

+6067
-0
lines changed

19 files changed

+6067
-0
lines changed

mobile/examples/phi-3/ios/LocalLLM/LocalLLM.xcodeproj/project.pbxproj

Lines changed: 477 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"colors" : [
3+
{
4+
"idiom" : "universal"
5+
}
6+
],
7+
"info" : {
8+
"author" : "xcode",
9+
"version" : 1
10+
}
11+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"images" : [
3+
{
4+
"idiom" : "universal",
5+
"platform" : "ios",
6+
"size" : "1024x1024"
7+
}
8+
],
9+
"info" : {
10+
"author" : "xcode",
11+
"version" : 1
12+
}
13+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"info" : {
3+
"author" : "xcode",
4+
"version" : 1
5+
}
6+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
import SwiftUI
5+
6+
struct ContentView: View {
7+
@ObservedObject var tokenUpdater = SharedTokenUpdater.shared
8+
9+
var body: some View {
10+
VStack {
11+
ScrollView {
12+
VStack(alignment: .leading) {
13+
ForEach(tokenUpdater.decodedTokens, id: \.self) { token in
14+
Text(token)
15+
.padding(.horizontal, 5)
16+
}
17+
}
18+
.padding()
19+
}
20+
Button("Generate Tokens") {
21+
DispatchQueue.global(qos: .background).async {
22+
// TODO: add user prompt question UI
23+
GenAIGenerator.generate("Who is the current US president?");
24+
}
25+
}
26+
}
27+
}
28+
}
29+
30+
struct ContentView_Previews: PreviewProvider {
31+
static var previews: some View {
32+
ContentView()
33+
}
34+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
#ifndef GenAIGenerator_h
5+
#define GenAIGenerator_h
6+
7+
#import <Foundation/Foundation.h>
8+
#import <UIKit/UIKit.h>
9+
10+
NS_ASSUME_NONNULL_BEGIN
11+
12+
@interface GenAIGenerator : NSObject
13+
14+
+ (void)generate:(NSString *)input_user_question;
15+
16+
@end
17+
18+
NS_ASSUME_NONNULL_END
19+
20+
#endif /* GenAIGenerator_h */
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
#import "GenAIGenerator.h"
5+
#include "LocalLLM-Swift.h"
6+
#include "ort_genai.h"
7+
#include "ort_genai_c.h"
8+
9+
10+
@implementation GenAIGenerator
11+
12+
+ (void)generate:(nonnull NSString*)input_user_question {
13+
NSString* llmPath = [[NSBundle mainBundle] resourcePath];
14+
const char* modelPath = llmPath.cString;
15+
16+
auto model = OgaModel::Create(modelPath);
17+
auto tokenizer = OgaTokenizer::Create(*model);
18+
19+
NSString* promptString = [NSString stringWithFormat:@"<|user|>\n%@<|end|>\n<|assistant|>", input_user_question];
20+
const char* prompt = [promptString UTF8String];
21+
22+
auto sequences = OgaSequences::Create();
23+
tokenizer->Encode(prompt, *sequences);
24+
25+
auto params = OgaGeneratorParams::Create(*model);
26+
params->SetSearchOption("max_length", 200);
27+
params->SetInputSequences(*sequences);
28+
29+
// Streaming Output to generate token by token
30+
auto tokenizer_stream = OgaTokenizerStream::Create(*tokenizer);
31+
32+
auto generator = OgaGenerator::Create(*model, *params);
33+
34+
while (!generator->IsDone()) {
35+
generator->ComputeLogits();
36+
generator->GenerateNextToken();
37+
38+
const int32_t* seq = generator->GetSequenceData(0);
39+
size_t seq_len = generator->GetSequenceCount(0);
40+
const char* decode_tokens = tokenizer_stream->Decode(seq[seq_len - 1]);
41+
42+
NSLog(@"Decoded tokens: %s", decode_tokens);
43+
44+
// Add decoded token to SharedTokenUpdater
45+
NSString* decodedTokenString = [NSString stringWithUTF8String:decode_tokens];
46+
[SharedTokenUpdater.shared addDecodedToken:decodedTokenString];
47+
}
48+
}
49+
@end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
#ifndef LocalLLM_Bridging_Header_h
5+
#define LocalLLM_Bridging_Header_h
6+
7+
#import "GenAIGenerator.h"
8+
9+
#endif /* LocalLLM_Bridging_Header_h */
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
5+
import SwiftUI
6+
7+
@main
8+
struct LocalLLMApp: App {
9+
var body: some Scene {
10+
WindowGroup {
11+
ContentView()
12+
}
13+
}
14+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"info" : {
3+
"author" : "xcode",
4+
"version" : 1
5+
}
6+
}

0 commit comments

Comments
 (0)