Skip to content

Instantly share code, notes, and snippets.

@theoknock
Last active July 17, 2025 23:35
Show Gist options
  • Save theoknock/eac91b73056c6dfcc510b36a7fec6a1f to your computer and use it in GitHub Desktop.
Save theoknock/eac91b73056c6dfcc510b36a7fec6a1f to your computer and use it in GitHub Desktop.
Hosts the function that streams the response from a chat model to the client submitting a prompt
//
// ContentView.swift
// ChatGPTCoreModel_playground
//
// Created by Xcode Developer on 7/15/25.
//
import SwiftUI
import FoundationModels
// MARK: - Model for a single queued Psalm abstract
struct PsalmAbstract: Identifiable {
let id = UUID()
let psalmNumber: Int
var response: String = "Pending..."
var isCompleted: Bool = false
}
// MARK: - Actor for safe queueing
actor PsalmQueue {
private(set) var items: [PsalmAbstract] = []
func addPsalm(_ psalmNumber: Int) -> PsalmAbstract {
let abstract = PsalmAbstract(psalmNumber: psalmNumber)
items.append(abstract)
return abstract
}
func updateResponse(for id: UUID, response: String) {
if let index = items.firstIndex(where: { $0.id == id }) {
items[index].response = response
items[index].isCompleted = true
}
}
var currentItems: [PsalmAbstract] {
items
}
}
// MARK: - Main View
struct ContentView: View {
@State private var psalmNumber: Int = .zero
@State private var psalmNumberInput: String = String()
var quotedPsalmNumberInput: Binding<String> {
Binding<String>(
get: {
"\(psalmNumberInput)"
},
set: { newValue in
if newValue.hasPrefix("\"") && newValue.hasSuffix("\"") {
psalmNumberInput = String(newValue.dropFirst().dropLast())
} else {
psalmNumberInput = newValue
}
}
)
}
@State private var abstracts: [PsalmAbstract] = []
private let queue = PsalmQueue()
@State private var responseStream: AbstractPsalmResponse.PartiallyGenerated?
var partialResponseStream: Binding<AbstractPsalmResponse.PartiallyGenerated?> {
Binding<AbstractPsalmResponse.PartiallyGenerated?>(
get: {
responseStream
},
set: { newValue in
responseStream = newValue
}
)
}
// Timer properties for stepper acceleration
@State private var timer: Timer?
@State private var timerInterval: TimeInterval = 0.5
@State private var isIncrementing: Bool = true
var body: some View {
ZStack {
// Linear gradient background
LinearGradient(
gradient: Gradient(colors: [
Color.primary.opacity(0.25),
Color.accentColor.opacity(0.25)
]),
startPoint: .bottomTrailing,
endPoint: .topLeading
)
.ignoresSafeArea()
VStack(content: {
ZStack(alignment: (.center), content: {
// HStack {
// TextField(("Enter a psalm (1-150)..."), text: $psalmNumberInput, axis: .horizontal)
// .padding(.leading)
// Spacer()
// }
GlassEffectContainer(spacing: CGFloat.zero) {
HStack {
Button {
decrementPsalm()
} label: {
Image(systemName: "minus.circle")
.foregroundColor(Color(UIColor.white))
.symbolRenderingMode(.hierarchical)
.font(.largeTitle)
.imageScale(.small)
.labelStyle(.iconOnly)
.clipShape(Circle())
.padding(8)
.glassEffect()
}
.padding(.leading, 2)
.buttonStyle(PlainButtonStyle())
.shadow(color: Color.white.opacity(0.5), radius: 2, x: 2, y: 2)
.simultaneousGesture(
LongPressGesture().onEnded { _ in
startTimer(incrementing: false)
}
)
.simultaneousGesture(
DragGesture(minimumDistance: 0).onEnded { _ in
stopTimer()
}
)
// Spacer()
// Number input field
TextField("Psalm \(psalmNumber)", text: quotedPsalmNumberInput) // "Psalm", text: $psalmNumberInput)
.keyboardType(.numberPad)
.multilineTextAlignment(.center)
.textFieldStyle(DefaultTextFieldStyle())
.shadow(color: Color.black.opacity(0.5), radius: 2, x: 0, y: 0)
.onChange(of: psalmNumberInput) { oldValue, newValue in
let filtered = newValue.filter { "0123456789".contains($0) }
if let value = Int(filtered) {
psalmNumber = min(max(value, 1), 150)
}
psalmNumberInput = "\(psalmNumber)"
}
.font(.largeTitle)
.foregroundColor(Color(UIColor.white))
.background(Color(UIColor.clear))
.padding(4)
// Spacer()
Button {
incrementPsalm()
} label: {
Image(systemName: "plus.circle")
.padding(8)
.foregroundColor(Color(UIColor.white))
.symbolRenderingMode(.hierarchical)
.font(.largeTitle)
.imageScale(.small)
.labelStyle(.iconOnly)
.clipShape(Circle())
.glassEffect()
}
.simultaneousGesture(
LongPressGesture().onEnded { _ in
startTimer(incrementing: true)
}
)
.simultaneousGesture(
DragGesture(minimumDistance: 0).onEnded { _ in
stopTimer()
}
)
} // END OF HSTACK
} // END OF GLASSEFFECTCONTAINER
.fixedSize()
.glassEffect(.regular.tint(Color.accentColor.opacity(0.25)))
// .background(Color.init(uiColor: UIColor(white: 1.0, alpha: 0.2)))
// .clipShape(RoundedRectangle(cornerSize: CGSize(width: 25, height: 25), style: .continuous))
// .padding(.trailing, 75)
// Button {
// dismissKeyboard()
// addPsalmAndRun()
// } label: {
// Image(systemName: "pencil")
// .padding(8)
// .foregroundColor(Color(UIColor.white))
// .symbolRenderingMode(.monochrome)
// .font(.largeTitle)
// .imageScale(.medium)
// .labelStyle(.iconOnly)
// .clipShape(Circle())
// }
// // .padding(.leading, 100)
// .glassEffect(in: .rect(cornerRadius: 25.0))
// // .shadow(color: Color.white.opacity(0.5), radius: 2, x: 0, y: 0)
})
ScrollView {
VStack(alignment: .leading, spacing: 16) {
ForEach(abstracts) { item in
VStack(alignment: .leading, spacing: 8) {
Text("Psalm \(item.psalmNumber)")
.font(.title2)
.fontWeight(.medium)
.padding(.vertical)
.frame(idealWidth: UIScreen.main.bounds.size.width, maxWidth: UIScreen.main.bounds.size.width)
.glassEffect(in: .rect(cornerRadius: 25.0))
if item.isCompleted {
Text(item.response)
.dynamicTypeSize(DynamicTypeSize.xSmall)
.font(.body)
.frame(maxWidth: UIScreen.main.bounds.size.width)
} else {
ProgressView()
.progressViewStyle(CircularProgressViewStyle())
}
}
.padding()
.background(Color.gray.opacity(0.1))
.cornerRadius(28)
.glassEffect(in: .rect(cornerRadius: 25.0))
.padding(.vertical)
}
}
// .padding(.bottom, 50)
Spacer()
}
// .frame(width: .infinity, height: .infinity)
// .border(Color.white.opacity(1.0), width: 0.2)
// .backgroundStyle(Color.white.opacity(1.0))
.ignoresSafeArea()
})
.padding()
.onAppear {
psalmNumberInput = "\(psalmNumber)"
Task {
await refreshQueue()
}
}
VStack {
Spacer()
HStack(alignment: .bottom, content: {
Spacer()
Text("James Alan Bush")
.font(.caption)
.foregroundColor(.primary)
Spacer()
Text("Commit ID 0863a4e")
.font(.caption2)
.foregroundColor(.secondary)
Spacer()
})
}
// .frame(width: .infinity, height: .infinity)
// .border(Color.white.opacity(1.0), width: 0.2)
// .backgroundStyle(Color.white.opacity(1.0))
}
}
private func dismissKeyboard() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
// MARK: - Stepper Logic
private func incrementPsalm() {
if psalmNumber < 150 {
psalmNumber += 1
psalmNumberInput = "\(psalmNumber)"
}
}
private func decrementPsalm() {
if psalmNumber > 1 {
psalmNumber -= 1
psalmNumberInput = "\(psalmNumber)"
}
}
private func startTimer(incrementing: Bool) {
isIncrementing = incrementing
timerInterval = 0.5
stopTimer()
timer = Timer.scheduledTimer(withTimeInterval: timerInterval, repeats: true) { _ in
if isIncrementing {
incrementPsalm()
} else {
decrementPsalm()
}
accelerateScrolling()
}
}
private func stopTimer() {
timer?.invalidate()
timer = nil
}
private func accelerateScrolling() {
if timerInterval > 0.1 {
timerInterval -= 0.05
stopTimer()
timer = Timer.scheduledTimer(withTimeInterval: timerInterval, repeats: true) { _ in
if isIncrementing {
incrementPsalm()
} else {
decrementPsalm()
}
accelerateScrolling()
}
}
}
// MARK: - Add & Execute
private func addPsalmAndRun() {
Task {
let abstract = await queue.addPsalm(psalmNumber)
await refreshQueue()
Task.detached {
await runPsalmAbstract(abstract)
}
}
}
private func runPsalmAbstract(_ abstract: PsalmAbstract) async {
do {
let instructions: Instructions = Instructions("""
Your instructions:
Your task is to write a 6-paragraph academic abstract of psalm \(abstract.psalmNumber). Following are the specifications for each paragraph, which describe some of the different ways biblical scholars and theologians analyze Scripture.
Paragraph 1: Start by selecting a verse or passage within psalm \(abstract.psalmNumber) that is central to its message. The response format will simply be a standard scripture quote from the King James Version (i.e., the verse(s)) and then the reference on a new line). Proceed to write paragraph 2. If you did not proceed to paragraph 2, explain why in your response.
Paragraph 2: Describe the purpose of psalm \(abstract.psalmNumber), explaining its spiritual intent and how it serves or helps the believer. Avoid mentioning the writer unless referring to the Psalm's direct impact on worship or spiritual life.
Paragraph 3: Identify and summarize the key themes found in the psalm, supported by references from the text itself.
Paragraph 4: Summarize any theological connections in psalm \(abstract.psalmNumber) and how these connections contribute to an understanding of God, faith, and spiritual matters.
Paragraph 5: Summarize any Christological connections in psalm \(abstract.psalmNumber) and how these connections contribute to an understanding of the nature and work of Christ; quote any relevant scripture found elsewhere in the Bible, if necessary.
Paragraph 6: Draw direct parallels to Christian teachings, using New Testament scriptures to illustrate how the message of the psalm is fulfilled or mirrored in Christ and His teachings, and give advice on how Christians today can apply the psalm's lessons in their own lives.
""")
let session: LanguageModelSession = LanguageModelSession(instructions: instructions)
let prompt: Prompt = Prompt("""
Psalm \(abstract.psalmNumber)
""")
let stream = session.streamResponse(
to: prompt,
generating: AbstractPsalmResponse.self
)
var accumulatedContent = ""
for try await pstream in stream {
// Store the current stream state
await MainActor.run {
self.responseStream = pstream
}
// Extract the content from the stream
// abstractPsalmResponse is Optional<Array<String>>
if let partialResponse = pstream.abstractPsalmResponse {
// Join the array of strings into a single string
let content = partialResponse.joined(separator: "\n")
accumulatedContent = content
} else {
// If no response yet, continue to next iteration
continue
}
// Update the queue with the accumulated content
await queue.updateResponse(for: abstract.id, response: accumulatedContent)
// Refresh the UI
await refreshQueue()
}
// Final update to mark as completed
await queue.updateResponse(for: abstract.id, response: accumulatedContent)
} catch {
await queue.updateResponse(for: abstract.id, response: "Error: \(error.localizedDescription)")
}
await refreshQueue()
}
@MainActor
private func refreshQueue() async {
abstracts = await queue.currentItems
}
}
#Preview {
ContentView()
.preferredColorScheme(.dark)
}
private func runPsalmAbstract(_ abstract: PsalmAbstract) async {
do {
let instructions: Instructions = Instructions("""
Your instructions:
Your task is to write a 6-paragraph academic abstract of psalm \(abstract.psalmNumber). Following are the specifications for each paragraph, which describe some of the different ways biblical scholars and theologians analyze Scripture.
Paragraph 1: Start by selecting a verse or passage within psalm \(abstract.psalmNumber) that is central to its message. The response format will simply be a standard scripture quote from the King James Version (i.e., the verse(s)) and then the reference on a new line). Proceed to write paragraph 2. If you did not proceed to paragraph 2, explain why in your response.
Paragraph 2: Describe the purpose of psalm \(abstract.psalmNumber), explaining its spiritual intent and how it serves or helps the believer. Avoid mentioning the writer unless referring to the Psalm's direct impact on worship or spiritual life.
Paragraph 3: Identify and summarize the key themes found in the psalm, supported by references from the text itself.
Paragraph 4: Summarize any theological connections in psalm \(abstract.psalmNumber) and how these connections contribute to an understanding of God, faith, and spiritual matters.
Paragraph 5: Summarize any Christological connections in psalm \(abstract.psalmNumber) and how these connections contribute to an understanding of the nature and work of Christ; quote any relevant scripture found elsewhere in the Bible, if necessary.
Paragraph 6: Draw direct parallels to Christian teachings, using New Testament scriptures to illustrate how the message of the psalm is fulfilled or mirrored in Christ and His teachings, and give advice on how Christians today can apply the psalm's lessons in their own lives.
""")
let session: LanguageModelSession = LanguageModelSession(instructions: instructions)
let prompt: Prompt = Prompt("""
Psalm \(abstract.psalmNumber)
""")
let stream = session.streamResponse(
to: prompt,
generating: AbstractPsalmResponse.self
)
var accumulatedContent = ""
for try await pstream in stream {
// Store the current stream state
await MainActor.run {
self.responseStream = pstream
}
// Extract the content from the stream
// abstractPsalmResponse is Optional<Array<String>>
if let partialResponse = pstream.abstractPsalmResponse {
// Join the array of strings into a single string
let content = partialResponse.joined(separator: "\n")
accumulatedContent = content
} else {
// If no response yet, continue to next iteration
continue
}
// Update the queue with the accumulated content
await queue.updateResponse(for: abstract.id, response: accumulatedContent)
// Refresh the UI
await refreshQueue()
}
// Final update to mark as completed
await queue.updateResponse(for: abstract.id, response: accumulatedContent)
} catch {
await queue.updateResponse(for: abstract.id, response: "Error: \(error.localizedDescription)")
}
await refreshQueue()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment