Skip to content

Commit 0de4f59

Browse files
committed
Add thinking mode toggle
1 parent b2eac7d commit 0de4f59

File tree

1 file changed

+108
-79
lines changed

1 file changed

+108
-79
lines changed

examples/demo-apps/apple_ios/LLaMA/LLaMA/Application/ContentView.swift

Lines changed: 108 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ struct ContentView: View {
6262
@State private var isGenerating = false
6363
@State private var shouldStopGenerating = false
6464
@State private var shouldStopShowingToken = false
65+
@State private var thinkingMode = false
66+
@State private var showThinkingModeNotification = false
6567
private let runnerQueue = DispatchQueue(label: "org.pytorch.executorch.llama")
6668
@StateObject private var runnerHolder = RunnerHolder()
6769
@StateObject private var resourceManager = ResourceManager()
@@ -100,107 +102,134 @@ struct ContentView: View {
100102

101103
var body: some View {
102104
NavigationView {
103-
VStack {
104-
if showingSettings {
105-
VStack(spacing: 20) {
106-
HStack {
107-
VStack(spacing: 10) {
108-
Button(action: { pickerType = .model }) {
109-
Label(modelTitle, systemImage: "doc")
110-
.lineLimit(1)
111-
.truncationMode(.middle)
112-
.frame(maxWidth: 300, alignment: .leading)
113-
}
114-
Button(action: { pickerType = .tokenizer }) {
115-
Label(tokenizerTitle, systemImage: "doc")
116-
.lineLimit(1)
117-
.truncationMode(.middle)
118-
.frame(maxWidth: 300, alignment: .leading)
105+
ZStack {
106+
VStack {
107+
if showingSettings {
108+
VStack(spacing: 20) {
109+
HStack {
110+
VStack(spacing: 10) {
111+
Button(action: { pickerType = .model }) {
112+
Label(modelTitle, systemImage: "doc")
113+
.lineLimit(1)
114+
.truncationMode(.middle)
115+
.frame(maxWidth: 300, alignment: .leading)
116+
}
117+
Button(action: { pickerType = .tokenizer }) {
118+
Label(tokenizerTitle, systemImage: "doc")
119+
.lineLimit(1)
120+
.truncationMode(.middle)
121+
.frame(maxWidth: 300, alignment: .leading)
122+
}
119123
}
124+
.padding()
125+
.background(Color.gray.opacity(0.1))
126+
.cornerRadius(10)
127+
.fixedSize(horizontal: true, vertical: false)
128+
Spacer()
120129
}
121130
.padding()
122-
.background(Color.gray.opacity(0.1))
123-
.cornerRadius(10)
124-
.fixedSize(horizontal: true, vertical: false)
125-
Spacer()
126131
}
127-
.padding()
128132
}
129-
}
130133

131-
MessageListView(messages: $messages)
132-
.simultaneousGesture(
133-
DragGesture().onChanged { value in
134-
if value.translation.height > 10 {
135-
hideKeyboard()
134+
MessageListView(messages: $messages)
135+
.simultaneousGesture(
136+
DragGesture().onChanged { value in
137+
if value.translation.height > 10 {
138+
hideKeyboard()
139+
}
140+
showingSettings = false
141+
textFieldFocused = false
136142
}
143+
)
144+
.onTapGesture {
137145
showingSettings = false
138146
textFieldFocused = false
139147
}
140-
)
141-
.onTapGesture {
142-
showingSettings = false
143-
textFieldFocused = false
144-
}
145-
146-
HStack {
147-
Button(action: {
148-
imagePickerSourceType = .photoLibrary
149-
isImagePickerPresented = true
150-
}) {
151-
Image(systemName: "photo.on.rectangle")
152-
.resizable()
153-
.scaledToFit()
154-
.frame(width: 24, height: 24)
155-
}
156-
.background(Color.clear)
157-
.cornerRadius(8)
158148

159-
Button(action: {
160-
if UIImagePickerController.isSourceTypeAvailable(.camera) {
161-
imagePickerSourceType = .camera
149+
HStack {
150+
Button(action: {
151+
imagePickerSourceType = .photoLibrary
162152
isImagePickerPresented = true
163-
} else {
164-
print("Camera not available")
153+
}) {
154+
Image(systemName: "photo.on.rectangle")
155+
.resizable()
156+
.scaledToFit()
157+
.frame(width: 24, height: 24)
165158
}
166-
}) {
167-
Image(systemName: "camera")
168-
.resizable()
169-
.scaledToFit()
170-
.frame(width: 24, height: 24)
171-
}
172-
.background(Color.clear)
173-
.cornerRadius(8)
159+
.background(Color.clear)
160+
.cornerRadius(8)
174161

175-
TextField(placeholder, text: $prompt, axis: .vertical)
176-
.padding(8)
177-
.background(Color.gray.opacity(0.1))
178-
.cornerRadius(20)
179-
.lineLimit(1...10)
180-
.overlay(
181-
RoundedRectangle(cornerRadius: 20)
182-
.stroke(isInputEnabled ? Color.blue : Color.gray, lineWidth: 1)
183-
)
184-
.disabled(!isInputEnabled)
185-
.focused($textFieldFocused)
186-
.onAppear { textFieldFocused = false }
187-
.onTapGesture {
188-
showingSettings = false
162+
Button(action: {
163+
if UIImagePickerController.isSourceTypeAvailable(.camera) {
164+
imagePickerSourceType = .camera
165+
isImagePickerPresented = true
166+
} else {
167+
print("Camera not available")
168+
}
169+
}) {
170+
Image(systemName: "camera")
171+
.resizable()
172+
.scaledToFit()
173+
.frame(width: 24, height: 24)
174+
}
175+
.background(Color.clear)
176+
.cornerRadius(8)
177+
178+
Button(action: {
179+
thinkingMode.toggle()
180+
showThinkingModeNotification = true
181+
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
182+
showThinkingModeNotification = false
183+
}
184+
}) {
185+
Image(systemName: "brain")
186+
.resizable()
187+
.scaledToFit()
188+
.frame(width: 24, height: 24)
189+
.foregroundColor(thinkingMode ? .blue : .gray)
189190
}
191+
.background(Color.clear)
192+
.cornerRadius(8)
193+
194+
TextField(placeholder, text: $prompt, axis: .vertical)
195+
.padding(8)
196+
.background(Color.gray.opacity(0.1))
197+
.cornerRadius(20)
198+
.lineLimit(1...10)
199+
.overlay(
200+
RoundedRectangle(cornerRadius: 20)
201+
.stroke(isInputEnabled ? Color.blue : Color.gray, lineWidth: 1)
202+
)
203+
.disabled(!isInputEnabled)
204+
.focused($textFieldFocused)
205+
.onAppear { textFieldFocused = false }
206+
.onTapGesture {
207+
showingSettings = false
208+
}
190209

191-
Button(action: isGenerating ? stop : generate) {
192-
Image(systemName: isGenerating ? "stop.circle" : "arrowshape.up.circle.fill")
193-
.resizable()
194-
.aspectRatio(contentMode: .fit)
195-
.frame(height: 28)
210+
Button(action: isGenerating ? stop : generate) {
211+
Image(systemName: isGenerating ? "stop.circle" : "arrowshape.up.circle.fill")
212+
.resizable()
213+
.aspectRatio(contentMode: .fit)
214+
.frame(height: 28)
215+
}
216+
.disabled(isGenerating ? shouldStopGenerating : (!isInputEnabled || prompt.isEmpty))
196217
}
197-
.disabled(isGenerating ? shouldStopGenerating : (!isInputEnabled || prompt.isEmpty))
218+
.padding([.leading, .trailing, .bottom], 10)
198219
}
199-
.padding([.leading, .trailing, .bottom], 10)
200220
.sheet(isPresented: $isImagePickerPresented, onDismiss: addSelectedImageMessage) {
201221
ImagePicker(selectedImage: $selectedImage, sourceType: imagePickerSourceType)
202222
.id(imagePickerSourceType.rawValue)
203223
}
224+
225+
if showThinkingModeNotification {
226+
Text(thinkingMode ? "Thinking mode enabled" : "Thinking mode disabled")
227+
.padding(8)
228+
.background(Color(UIColor.secondarySystemBackground))
229+
.cornerRadius(8)
230+
.transition(.opacity)
231+
.animation(.easeInOut(duration: 0.2), value: showThinkingModeNotification)
232+
}
204233
}
205234
.navigationBarTitle(title, displayMode: .inline)
206235
.navigationBarItems(

0 commit comments

Comments
 (0)