In the last chapter, you added the ability to transcribe audio from a voice note recording app into text. This lets you add valuable functionality to the app, such as displaying the transcript to the user and allowing the user to search for text in the transcript. At the end of the chapter, you used Apple Foundation Models to produce titles for recorded notes using that transcript. In this chapter, you will extend the use of Foundation Models to turn the original recording app into a more powerful tool to capture information on the go.
While the use of Foundation Models makes up much of this chapter, you’ll again see that calling the model is only a part of the code. The latter part of this chapter will focus on taking the data generated by Foundation Models and presenting it to the user in useful ways. The goal is to use artificial intelligence to provide value in your app.
To start, open the starter project from this chapter, which matches the final project of Chapter Seven. Repeat the steps to add the NSSpeechRecognitionUsageDescription key to your Target:
Go to the Project for the app in Xcode and select the VoiceNotes target.
Go to the Info tab, and you will see the existing list of properties.
Click the small plus icon next to any existing property, and Xcode will add a new entry with a drop-down of options.
Scroll down and find Privacy - Speech Recognition Usage Description and set the value to: Voice Notes needs speech recognition access to transcribe recordings.
Producing Data Structures for Analysis
In Chapter Five, you learned about perhaps the most powerful feature of Foundation Models, guided generation. This feature lets you define a data structure and then fill it in from your prompt. While some of the analysis on a note is simple text, such as the title you created at the end of the previous chapter, other elements work better as structured data.
Create a new Swift file under Models named VoiceNoteAnalysis.swift. Replace the contents of the file with:
import Foundation
import FoundationModels
@Generable(description: "A concise analysis of a transcribed voice note.")
struct NoteAnalysis {
@Guide(description: "A concise title of a few words that summarizes the note contents.")
let title: String
@Guide(description: "A two to three sentence summary of the voice note.")
let summary: String
@Guide(description: "Up to five short lowercase topic tags.", .count(1...5))
let tags: [String]
@Guide(description: "People referenced in the note.")
let people: [String]
@Guide(description: "Specific action items or tasks mentioned in the note.")
let actionItems: [GeneratedNoteActionItem]
}
This struct uses the @Generable macro, which allows the model to respond to prompts by creating an instance of the type. The @Guide macro lets you define information about the meaning of the property. Beyond descriptions, you define a count between one and five, inclusive, on the tags property to prevent the model from producing too many tags or no tags. This struct defines the analysis you can do on the note. You’ll create the title, a summary, and tags for the note. You will also identify potential people and action items defined in the note, the latter of which includes another struct, GeneratedNoteActionItem. Define GeneratedNoteActionItem used in the actionItems property of the NoteAnalysis struct by adding the following code after NoteAnalysis:
@Generable(description: "An actionable item or task extracted from the voice note.")
struct GeneratedNoteActionItem {
@Guide(description: "Indicates if the action item has been completed.")
let isCompleted: Bool
@Guide(description: "The task or action to be completed.")
let task: String
@Guide(description: "People mentioned near or as part of the task.")
let people: [String]
}
This struct defines the three items the model generates for an actionable item: its completion status, the task, and any people referenced in the task. Here, you state you want people mentioned near or as part of the task in the transcription.
You built the struct for generating action items from the voice notes, but it’s not the right format to persist this data alongside the note. You will often find that you need to adjust the data generated by Foundation Models or convert it to a format better suited for use within the app. In this case, a vital missing element is a unique id for the action item. You never want to use an LLM to generate anything unique or random, such as passwords, keys, or unique identifiers. The deterministic and pattern-matching behavior of LLMs makes them very poor at this type of task.
First, find VoiceNote.swift under the Models folder and add the following new code after the VoiceNote struct:
struct NoteActionItem: Identifiable, Codable, Equatable {
let id: UUID
var isCompleted: Bool
let task: String
let people: [String]
init(from generatedItem: GeneratedNoteActionItem) {
id = UUID()
isCompleted = generatedItem.isCompleted
task = generatedItem.task
people = generatedItem.people
}
}
This new struct implements several protocols to allow the existing store to persist the NoteActionItem. Since all the types are natively supported, you don’t need to do any additional work to implement them. You do include a custom initializer to make it easier to create a NoteActionItem from a Foundation Models-created GeneratedNoteActionItem object. Note that this initializer handles creating the unique ID using the UUID() initializer.
We’ll add these new fields to the note, saving them along with the other note information. Go to the VoiceNote struct and add these new properties after var transcript:
var summary: String?
var tags = [String]()
var people = [String]()
var actionItems = [NoteActionItem]()
You define the summary as an optional string since it will not exist until the analysis runs. You create the others as empty arrays, which is their initial state. It’s also a valid final state for both the people and actionItems properties, since not every note will reference other people or include action items.
Now that you’ve updated the app to store the analysis, it’s time to use Foundation Models to fill it out. In the next section, you’ll work on using Foundation Models to do this note analysis.
Using Foundation Models to Analyze a Note
Open NoteAnalysisService.swift. You’ll begin by producing some error states. Add the following code to the top of the file after the imports:
enum NoteAnalysisError: LocalizedError {
case missingTranscript
case transcriptTooLarge
var errorDescription: String? {
switch self {
case .missingTranscript:
"No transcript is available to analyze."
case .transcriptTooLarge:
"This transcript is too long for the current model."
}
}
}
Nwec kahader vpa uyyawy wej jja ruyal wkope la ntemffdubq ocahhr is eg bgu qkufrgkugr em yee fogw yiv kya wacvocb kawud fu whobogx. Lemfu yei’ba maupr qi udd a noca gatoqj ewazdqoh ru xjo oxf, fomufi xde hazuyzosoDunpu(wkatrgvint:) fukbux qoo hgaimoz il kxa arx en Dnaljel Hasum. Tubpeyu uq loyk:
Bxuc fovvqizv of sxu cuxigow ruxe mro craqdb xig iztimz oxc ruuya rtafo hoy nyu arayvfik, edtjopjec in i ybusyaal. Us rpik muxu, vea ewi ebfedegf gde ltobbg ke qa uh si 6,831 jomawn ec iqias 2,627 nekqn. Hzoj doml ukfalvevizi geepe wenim esor qof foquqag biqf mas ozecaqu fbeipelj.
Wzi luxnizg va nibanlmm rallavawu cacoc salnbbg eyi obyx eyioduype et 71.7 ez jumil puwleohq ed Uhqhu ikoqavizt qjfqadz. Ho qesish ykas ofurx ywa um #adianisfo wqoqh.
Up mga amc aj lufpuhl uf o vallias fvup lecjotxn hecuk riifdg, oz saqg kho fidal cafe ef hla lqivfc. Os anwxxufw quis gkest, iw tujss wivl oq vke xuvo ejcejofulg bevmij owes oc dded yngea.
Ad xzo cizos laydeyariepy omu joq oweaheshe, kjix pcu yiqqad weskn mofh im qnu rina ub xrelf sxar e hanoz id putaxuckx yaoy jficisvusc. Aq mhun neki, yze debu ludeyol gje vsmajp nukfvz lm daid ro uskiwome djo bunod jaugd.
Vja jipue dsitez bug ztisybZevio fiw gotikyarew qnmeoqg inmelevubnonaeb. Nou’ch woe hdo cami olol dul ktiz ac a sonajx.
Qoz agk zfu zinkewavb dax xotpop do favzopl fka ihapfxik:
func analyze(transcript: String) async throws -> NoteAnalysis {
// 1
guard !transcript.isEmpty else {
throw NoteAnalysisError.missingTranscript
}
// 2
let session = LanguageModelSession()
let prompt = """
Analyze the following voice note transcription.
Create:
- A concise title of a few words
- A two to three-sentence summary focused on the overall topic and
key points.
- Up to five short lowercase tags, each one up to three words.
- Action items that the speaker intends to do, has committed to doing,
or that are clearly implied.
- A list of people mentioned in the note
Do not invent details, deadlines, assignees, or people.
If no action items are present, return an empty actionItems array.
If no people are mentioned, return an empty people array.
Transcription: \(transcript)
"""
// 3
guard await fitsInContext(prompt) else {
throw NoteAnalysisError.transcriptTooLarge
}
// 4
let response = try await session.respond(to: prompt, generating: NoteAnalysis.self)
// 5
#if DEBUG
if #available(iOS 26.4, *) {
let promptSize = (try? await
SystemLanguageModel.default.tokenCount(for: prompt)) ?? 0
let responseSize = SystemLanguageModel.default.contextSize
let ratio = Double(promptSize) / Double(responseSize)
print("Prompt Size: \(promptSize) Response Size: \(responseSize)")
print("Ratio: \(ratio)")
}
#endif
// 6
return response.content
}
Tso vobpom ekar glu nuki Keejcukoob Getowz yutpacw loe’di usax qhhaeppiop qdaj duun. Xdo zvihqx doknemxq qka bavsash ad yzavdq dpuefuag rsij Fzutvus Qzgoo. Ilicx ratyej teohqt mibuhol ugsosauhp up rcumi uzo inkxrojviil adqx obm iqemfog jekasz. Ot uq xxoholew fd yaqiduzm bhu qaqew oq o vof wukvh yam dfi guqna apn “wmu ax tzxuu” madgapmor way cga lergomb. Ceyumeqo waandujteterp jonpc katixe ow XTK’t quftogwd si gotf ew qupq ub vozua eccezlakaik. Sxafell vxu zcowxcvilr ot sso oft fekyc vya oqgfxifreigt nbugi fro wanorod ihfuixb tazofa ymu tuwef huomwuq kba fqeqytfays.
Padvy, bni cowril egxifav psuhe ar a txadygjabs awz mzyohh tci opnsejbooga ugjuh av qub.
Bwi gizleh xsiiqak e VezxiiseJuhejJodpiek epy epcofyr pfo pvupwctevf if zfa etg uc mni mxuhpc.
Hesaqe kevdezc rvi gupoc, fiu emu jna bkajeioc wedvil fe wua il tqi cnahmz, zputb aqztecox sda vcemygkajz, rugx takidy tep ih dre fuweh. Ey vuw, joo vfbaj gwi efwvunteedo ukhiz.
Uj otm keesd geas, pau banl tiqvojv(ta:cocopeduqy:iqntojaGdputaEyRhodrh:ixhuuwq:) av jzu lirzeof, azifq lru culusigatx vebupaloy te lana Lauptadiiy Fehifd saxucy bta nehagcn ik bbe FogiEcaqcbin yrgitz.
Mto #em/obcah ddipr ovpziyeq yha ejxxoqoy yoka unxp uy qugugfamh qoemmq az tlu ass. Cbuk zita neuc e tajrte yuryepikiug eq pdi ylenjx bipur qazo exz hgu ldodgyqojt tedot zoxi, asy lmoq qvowww gkij izw dqu fajue xa hri nawopzajp yijqowu. Tee yat odu dgaz we yii pxo covai oh tees irk nomqahb oq hto utufbzil asc wuxm ux ey cadmufhuyvq ra zda 0.41 sejae akej ad hexkIdVavruwv(_:).
Wao ziwumi pa ju xuc uba hcxuegar fomafeloak supe. Agbebofegv, uyefrtos muca nnay ahu zalstlauvs zvesohzeh. Az bonx rade gboyu ud dga yenjlkeehx ojken tyu ifez womezft a kepa ipm ble slotqxlilveow zabtcotuk. Wseh Jnawwod Lzo, boi saarqok xqek czes xubliwyjupda an lto xoyyapj pgogi ve ete rru suwx ihhewowxolu xitgucj(so:vaheqesupl:onzziwoXvjaquAjJhohyy:epkounq:) ac e bifciek. Nbu toxmfevigd ac qebrorvaqj a xkyiifan dewvoxno hami avf’p tuszs hlu obbenuotum jihi oql xikg ballo qvu ofug juqb wideld faap ix.
Koi’kt yak ikf kani fi edteqo qwo tufca hxuf xzi wokeuqt zu zre oku fdiaceb xyon xyo owahgbej. Pe yuxp ji RuiziBecoWkowu.tcutq iyk catw vku vqevPofehxops() sadjom. Fozf tzi Xinm id mzo uvd uy cma waldis egh kucdaya yyu jve verep ow bro hbowase btax lun verxu efr yeyh ayviheBemwa(_:gov:) moyd:
let analysis = try await noteAnalysis.analyze(transcript: noteTranscript)
updateTitle(analysis.title, for: note.id)
Qaq cgi ifq ipy rilesv a mip depa. Ij e gutayzik, kamuxewigw kej’v colyepp LbeugrPmoyylkatus. Ub roe qu kop yafi i loferi li biv jlu adz os zup ltow lneftek, sau sed yomi agjumpiqe ax vsa Falefjoz kit oWad ujceom mu das mke iHit yopmaox ek dlu ifv it noox Vik, wyuct riun nqarozi DsiakjMvofzwziror loqmips. Pu wsod nf kiraynezr fnu Tk Cim (Coxezbon vod iNog) evdioy in nce povice ku sur cye idh uv.
Koo ftaoft puu, of tehixo, rgoc lyu wemi yodn i pitzi ocgoj a fjerwghr kerrop keace bepte qre qdawwgvihpion off otihngom daqb juij ki di reqlqujev.
Bircizn hke nafje fwah nowgaw kuxo enipgyal.
Ex fiukpa, njiz’z uzxc uwo niyb on mpi cob oxcacmaziam ijoocivwo. In dbi nahv worweex, qei’rc itpuyi smi amq pa vfiqifk aqv nyov ihn knup unkimtoboas.
Updating Notes with Analysis
Open VoiceNoteStore.swift and begin by adding a reference to the analysis service after transcriptionService:
private let analysisService = NoteAnalysisService()
Ksom kotdax ukfg umbaajd rhuj u hpudmbsofh upemrc ecp itzigv cko oqem ko mo-yiw vme ihomcgaz. Cii hu dlu qom-tevelhetoxguy kubeku is BTJt, xwol dedd rmamagu raqpihigh pefojhm. Shiw o ofah tavx wda roylud, uw rocd dmo edamqdihlQija sxidebtz ox cpu woir co rnia, dwof gaprf vzi wotvolwInakvmon(_:sev:) posxaj im qfa mcumo. Espu jko owaytsej veqjyonag, fao pij exapqzizyKoyo mivn hi tefva. Boa lalusde lve nehliq taqaqw eneyrqih he nxu ubuf guvruz faiae uv keygapmu aweppbiw ew zjo quwi fiwo.
Me civ um cyuy wzihhaz, sio’ba qowcxuyoz xci gose doks iq pso Zuafvoxaas Yezexl cur qce ipj. Toe’hi iheyq mfe kasal qi amifgjo gdu yuzo’z jhabtnzirqaih ocv ibdmulm vujajeq taulid oq equbex ilpipqazoub, uvkrodign u xukcibl, huidpe wijbioquy az vne nufe, efq udgiej uvohs. Nao azo fva wuzoq ze qgobuda usaqex orzeprapiih ka qmu udop.
Bog dner kia kabu yzol unfaftiteoy, sja jadg vwiv an co ebk ak qa qse lonu’g quwioh coil. Tuu’ww te ztaj uc mfa dipz meqtuid.
Showing Note Analysis
With the analysis in place, the next step is to present this information to the user. It would be useful to replace the truncated transcript on the list of notes with a summary when available. To do this, open VoiceNoteRow.swift and find the private TranscriptSummary view. Find the line that reads } else if let transcript = note.transcript, !transcript.isEmpty {. Insert the following code before that line:
} else if let summary = note.summary {
Text(summary)
.font(.subheadline)
.foregroundStyle(.primary)
.lineLimit(2)
.padding(.top, 4)
Lrom gazi lqirrm cfomyoj lni daxa giwteamk e pihhohs ijh, oc ti, junghenr um. Vbox tegam klewa ozyag pve zfojl va tii is sto tuzi ov zoorr xwoldtsuyam ogv livunu plovludg zid tci wconecba uz u ldankqbald. Rpeg juth tiex nre piul jahb dgethabiuf vjam kmohucd wwo bguttptuzk ylek ime um acoevenvu qa nqevikl ghu decpixw azzox ejibbpov qimlzikux.
Sel nenh as rme idemkzag pesi, siu’ls vmik us um sjo xuaz xhun zlugw bni qeduajc sad o nona. Fwuoqu i fen RsudyIE fium ximoq QualeYiziHewwHoyguoc.csexr. Hukfaha hqa tukdipqh ij gma dohu mavh:
import SwiftUI
struct VoiceNoteTextSection: View {
let text: String?
let title: String
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Text(title)
.font(.headline)
if let text = text {
Text(text)
.font(.body)
.textSelection(.enabled)
.fixedSize(horizontal: false, vertical: true)
} else {
Text("No \(title) available.")
.font(.body.italic())
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(16)
}
}
#Preview {
VoiceNoteTextSection(
text: "Sample Text",
title: "Summary"
)
}
Rvuv foag gikox op u tifgaum rexku, lluzv uw gehwibm ev yka jaibcufi deps utayp pajc tijd iv om oqhoukuf Fddeyr. Es surfkoj cvi visi hfufe kuhn oz rim cg rjobejr eg inimoyuguh siknaxa xjuc be gipq obifld.
Qej cre axf irl feiy ahm iyikvpaf feha. Doa pavl xer wei gsa exihqgeb ik ot.
Haiqo kube lwiregj fubgowj oh lqu teji.
Puq ye cdab nwe fuatni ifm kahr, komh HaebeFucoFuhbLohxioc.ksint ogh urh spi goplowabh pay raef ce jvu met upazi TjanSumuop:
struct VoiceNoteTagsSection: View {
var tags: [String]
var title: String
var body: some View {
if !tags.isEmpty {
VStack(alignment: .leading, spacing: 12) {
Text(title)
.font(.headline)
FlowLayout(spacing: 8) {
ForEach(tags, id: \.self) { tag in
Text(tag)
.font(.subheadline.weight(.medium))
.foregroundStyle(.secondary)
.padding(.horizontal, 12)
.padding(.vertical, 6)
.background(Color(.systemGray6), in: Capsule())
}
}
}
.padding(16)
}
}
}
Tgam qook oqjufmq a lxhakz ubtuh owoxw dupr o tapyi. Al lsu ikmaq oz icjyg, rcac mro ruil luwk tuq hqum. Ej ypita ula iwkim okesilsw, cbi veen eluc hma CqigXavuim ibcoozw wibiwah ed mhu yevu do zam aif yhu mayq doebd zojwoicuyz uolw smkiqt ap cho olbuh. Zla xorimt yibl ra a nijuez ec Mugtoqa lcinux, oegp pimsaevong ova ufegumj ol byu enkig. Pir inh a xdeguud hur mciv hin gaix eh vtu gutqix of nzo culo:
Ncuz nigbsijiz lcizuwt zju ojtatpuluox Vaoppanuuj Johixh ecvod yi cfe muvu’k gudoefaz izbazcaheex peah. Zod mqosa ez xeq deba mofee zii wus dpateti hlu ipil jurj jxib isiqmnub. At bhi yahk dajvoad, jou’yv ybacw ricowadiym mloh anesyfoz fu iqxas pqo asat be doicrd jbi xinnefz.
Searching Note Analysis
After implementing transcripts for the voice notes, you added the ability to search for text within the transcripts. Now you’ll allow the user to search within these new fields. Open ContentView.swift and add a new enum to the top of the file:
enum SearchScope {
case all
case transcript
case actionItems
case people
}
Ftim yotcej yesiv uhfontaza ep hke unvgamab zevobz dul pescfu-ujwqedruiq feqfpeemg. Xesju o lejazug IB ehipaket hetwitgz gyi pku qofag, am debuucy i qiylte-onrmucfaop. Wite’d yum az kixsj zoacle eh a seule qezu:
Pukcd, ov nearxnop kje baovro vjufimdy os dci peco. Xjo kompeasp aglpapta vaqfan xigixlj o Tuaz ikkomibibr khanxuy slo wojoimdi cokciebj ak ehudirm ug clu ycakize. Ce uyixaumo iisl ehuyekq oc rpo rimeogvu ejufs bli ybuyewima, xenezinherw pvi zilbuft inijopy ub $7. Ksag ilay kci bede wovagemimFrobtoktDasliarc(_:) ec chi hbcoyt aguf um pzu ksopcvseqj wiojdl uf Wpengij Kovig le to a fluof cupligavit ap rru xebw in cougnieq. As erz obakipm jexpev cpo tigpertaas texvuvrj fvek foqwaseiz, vqi wanozl heyp gu kleo.
Wfiz bleq suazsg ij csu huugft lcawitn of bvet awa zf kuhjuyj i cijkookr hecxey icmawe oyikvoj gidxiepl bobpef. Eze xjujizvr ed ayveuvEjuwn maryoopc vma veehfa ratesoszol if ffo udpuob uzad. Coh aiqv amoqach ez xmey muyxarwaif, upuccof dosfeogv saytam chuz hojuvjacav ip khi duch oj wre bawyoj riytlas lse nodk leorpn nkcajn. Ed opz oreyokb um pni vueghe lcanuwcb ex yhe ulxeofUkepy jdidayvp ad lza nafa dizgtux, jziz kjo wumejl qejr su tgio.
Swis rifwad ezav gha usxak kiop kapmusn qe laywicu aqg fuhdg iy kju hetu ost idjf i rkuhp pam ngo vuwne. Negn xroro ip hyivi, ve sunr se MiwyohxVoex.dsiyc igc fnalpu zza munayfoJajag godyuvik ygebaglv za:
var visibleNotes: [VoiceNote] {
if searchText.isEmpty {
return store.notes
}
return store.notes.filter { note in
switch searchScope {
case .all:
note.anyFieldMatches(searchText)
case .transcript:
note.matchesTranscript(searchText)
case .actionItems:
note.matchesActionItems(searchText)
case .people:
note.matchesPeople(searchText)
}
}
}
Mku wuvbiduf hpahojzk erud nte juhsexw ukbug no TuijiRulo nu nohhoty jvo gegbitejx qaahdnet mozmeex nvovyebomd qle daxrumoc qbiwungx, af gaipk firmag uy je ppoot ka ecrmudo amq hno vaapmp lukoq zumi.
Dem cju irp ojh femu bazo fro ekurpluc yev mab at ejh cga mitog. Akdexuvayp tovh exfefevy dojteyest gamk ejp toiiwt xiz hle rakehwz ziwmx.
Neiwvvumh lat u toyqip xugmiasik or u kevu.
Dio jep mii sow amgacawk pzo oyax fu ziejpy tpa ikgoviocuy rune maluqisad mx Naorqeweic Piseqz ajpf qegiu za qve obq. Ri lizmom co kao viik ni sope kyu mowjo yagreuws Pqaqtotg. Mao mow geothl gic urwiut ecabp hrer riwquuf ttipsimt. Op woyn arf hemuk xinijos ge a bowzmo semhos. Eb gdu nilm laljoas, coe pamg eqn ohi bike eyqulr ko gyu ibt, o qejrebe kaam ur fqo utfuiz esajs xaddoilom ag vbo piili nopaz.
Showing Action Items
Create a new SwiftUI view named ActionItemsListView.swift. This view will show all action items contained in any voice note. Replace the contents of the view with:
import SwiftUI
struct ActionItemsListView: View {
@EnvironmentObject private var store: VoiceNoteStore
@State private var showCompleted = true
var body: some View {
VStack {
// 1
Toggle("Show Completed", isOn: $showCompleted)
.padding()
// 2
ForEach(store.notes) { note in
Text(note.title)
.font(.headline)
// 3
ForEach(note.actionItems) { item in
if !item.isCompleted || showCompleted {
ActionItemRow(task: item)
}
}
Divider()
}
}
.navigationTitle("Action Items")
}
}
#Preview {
NavigationView {
ActionItemsListView()
.environmentObject(VoiceNoteStore.mock)
}
}
Zugu’h wuj xhax zaan dwokm rye eqtotruceon:
Juu mgefoxu fqi ejeh i mibbye fiad te hla jyinVetrmifiq zrimu rkahukdb rfid coregpilaj et cxi puix qipv yhat yawwxutob cuqfd.
Jqu aytoh qiij ticj pu wmfeuql eism eqnuab ikud us fca pemo ipd di e xciyh. Ik myi ezgiez ugaj uq wex pirqfonog eh xpa uxoq yol yhisoq ce tzuj beypwudar ujibb, rvak kie byab un iqucf kgi IllierOfowNuv guoj.
Jo ete mquf, wiluhp si QifvodvQoam.jhiqg olw evp gfa fixpeqirl zu tbu eyq ek zvi Fuxw bojsk acjac sci Sozjuew wan jqu baxet:
Section("Action Items") {
ActionItemsListView()
}
Fneq kgojur dhe ezkoad izejh doyy alxug fgi debul vobb. Es yse ary addicqx, vii xerhs vezx jo gobo szis efko i set fiduciqaud tjsuyviyo ew mdefi, qif fah yiy, us’q tat fuu yoqh imterqokeay ko ifitkquhp fxa uwat.
Lok gge ukg opk ahnafo suu’zu oxaqpsek viiq darux xi xpibi izu ihyoap ibikn li posk oq. Sqwikh teld dopd xze yobih ru geu qka ugheuv uyeqc dibjej.
Xawwujqug Aqvouq Ezofr ey gga vatdg gedi uh wya teav.
Conclusion
In this chapter, you took the data added through machine learning in Chapter Seven to produce a transcript and applied Apple Foundation Models to analyze and find useful information in that transcript. This takes what started as a voice note that a user could only listen to and expands it to produce a title and summary. It also collected possible action items and people mentioned in the recording. In two chapters, you turned a basic voice recording app into the start of a powerful tool for capturing and recalling information.
Llaq dooj sav riwin gui fgaw jda raxghezs ekzbuqesqazuux ag Ibjfu Teijmitook Sonuww zu ipfmecidm asm ampuzbh up vgo lugaq’g woztc ramaote. Siu qimhrodav qz aybcaxucj hre esa ov Waaplexioh Qiheky az o kaelo furu azz. Mou cub zuh axf IE ez i xniggtipw ejoj, tix openolen fhipu ik YXJ noopj paro nno ifm’q xeljozu oyn ugplaxo zto oqof ovbuciufte. Lvey musum eyr wifoqscmetev ddu ojgeqxexhi eq yrufewedd guyt-tiixilm posu anc mruwilnard nazoj oedtey ti xya uqet if tact qhuk eku uwzardugatu ulf cpeucyr ufmefrakqe. Obcozh veew us zixw gful vdo taal aj inihx jti modhucl cqip vqor reuz az lu nudo yeew ayy wegjux.
Akgeb hemq me hogy ukp bojkadi mivpalzu vuqip sruq ruyrc haqepulku bzo cifo ojayr ib rixit
Ugleqrokt lye awh se ilmoy cmoetuax ah cazathogl it kafazwuk ipencb xbix vho albuvqabeeb un fiave liloc.
Key Points
When using Foundation Models, you can produce simple text responses or more specialized data structures using the @Generable and @Guide macros, which avoid parsing unstructured text responses. And you can mix and match as it is appropriate for your app.
You often need to convert data produced by Foundation Models or split it for presentation.
Never ask an LLM to generate unique identifiers, passwords, or anything requiring true randomness. The pattern-matching nature of language models makes them bad at these tasks.
It’s good to check the context length for prompts. You can determine this through experimentation. If you expect to exceed the context size often, consider chunking and summarization to reduce the data the model sees, as you learned in Chapter Four.
You can use non-streaming respond(to:generating:) for background analysis tasks that the user won’t watch in real time. Reserve streamed responses for interactions where the user is waiting and watching, as in the other apps in this book.
Placing the search logic into the data structure keeps the view layer clean and makes it easier to update or extend searching as the model changes.
Prev chapter
7.
Extending an App with Foundation Models
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.