In the earlier chapters of this book, you explored aspects of using Apple Foundation Models in isolation. You built apps purpose-designed to help explore and understand the framework’s features. To close out this book, you’ll look at a simple, real-world application that lets users record voice notes. You will then explore how using machine learning, in general, and Apple Foundation Models, in particular, can take this application from a useful but basic tool into a much more useful and powerful app.
A common mistake is treating adding machine learning and artificial intelligence as the goal, when it’s really a tool to improve your app’s user experience. Outside the challenge of developing good prompts to get the results you need, Foundation Models code will often be the simplest code in your app. Preparing the data to send to the model and then presenting the results back to the user in ways to provide insight and a better understanding are the real challenges.
The starting voice recording app.
Open the starter project for this chapter and run it on a device or in the simulator. You’ll see that the app allows the user to record short voice notes and provides an interface to review existing notes and delete them. The app also includes a few notes as seed data that you can use or delete. In the top-trailing edge of the app, you will see a button you can use when running through Xcode that allows you to restore these sample notes if you delete them.
Run the app and record a new note. You will have to allow access to the microphone to record. The appropriate permissions and values for this prompt are already in the app.
Allow microphone permissions.
While this is a full-featured app, it provides no value beyond recording and playback. The information in the recordings remains locked into the audio. To make a more valuable app, you can give users the ability to examine and surface information from those recordings without having to listen to every note. By now, you might already be thinking of ways that Foundation Models could do this. While there are LLMs that can work directly with audio data, Foundation Models only works on text. But as the 26.0 versions of the operating systems introduced Foundation Models, it also introduced a service called SpeechTranscriber, perfect for this task.
Transcribing Audio into Text
Transcribing is converting audio into text. This task has been traditionally done by people using shorthand or other abbreviated writing methods to record speech at high speed. With advances in machine learning, computers can produce high-quality transcriptions of text on a local device. Apple introduced SpeechTranscriber in the same versions that brought Foundation Models to local devices. SpeechTranscriber is a speech-to-text transcription module built for normal conversations and transcription.
There is a limitation in SpeechTranscriber. It only works on actual devices, not in the simulator.
SpeechTranscription not available inside the simulator.
If you do not have a device to run the app on for this chapter, you can take advantage of the Designed for iPad option to run the iPad version of the app on your Mac, which does provide SpeechTranscriber support. Do this by selecting the My Mac (Designed for iPad) option as the device to run the app on.
Running the app on a Mac.
To run an app through Xcode on your Mac, you will need to go to the VoiceNotes target and assign a Team under the Signing & Capabilities tab. A free account should work for this chapter. You may also need to add a unique bundle identifier.
Create a new Swift file under the empty Services folder named SpeechTranscriptionService.swift. This file will contain the service to perform transcription of the voice recording once the recording completes. Replace the contents of the file with:
import AVFoundation
import Foundation
import Speech
enum SpeechTranscriptionError: LocalizedError {
case unavailable
case authorizationDenied
case unsupportedLocale
case emptyResult
var errorDescription: String? {
switch self {
case .unavailable:
"SpeechTranscriber is not available on this device."
case .authorizationDenied:
"Speech recognition access is needed to transcribe voice notes."
case .unsupportedLocale:
"SpeechTranscriber does not support the current language."
case .emptyResult:
"No speech was detected in this recording."
}
}
}
This code produces an error enum that you will use to provide feedback to the user if anything goes wrong during transcription. Now add the following after the SpeechTranscriptionError enum:
The transcribeAudio(at:) method will take a URL to the audio file and return a string with the transcribed text. You mark the method as asynchronous and throws.
As with many features under Apple OS’s, speech transcription is locked behind a user permissions request. This method will verify permission and prompt for permission if needed. If permissions are not given or previously denied, then it will throw the SpeechTranscriptionError.authorizationDenied error. You will implement this method in a moment.
If the app has the needed permissions, it will then call a method transcribeWithSpeechTranscriber(at:) to perform the transcription, which you will also implement very soon.
With that setup, you need to implement the method to verify and prompt for permissions. Add a new method at the end of the SpeechTranscriptionService struct:
private func requestSpeechAuthorization() async -> Bool {
await withCheckedContinuation { continuation in
SFSpeechRecognizer.requestAuthorization { status in
continuation.resume(returning: status == .authorized)
}
}
}
This code defines the requestSpeechAuthorization() method to manage permissions. The core is the SFSpeechRecognizer.requestAuthorization code, which you need before you attempt to perform any recognition tasks. Otherwise, it will fail. Despite using the more modern SpeechTranscriber framework, you still request permission through the older SFSpeechRecognizer framework. You should call this code on the main thread before you access speech recognition for the first time. The first time you call it, the system will prompt the user to grant or deny permission and then remember that choice. Make sure to select Accept in your app, or you will need to change it in the app’s settings. Here, we return true if the returned status is authorized. Otherwise, the method will return false.
You must add the NSSpeechRecognitionUsageDescription key to your Target or the app will crash when you attempt to use this method. To do this, 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.
This completes the steps to seek and receive the user’s permissions to access speech recognition and, therefore, transcribe audio. Go back to SpeechTranscriptionService.swift and add the following method to the end of the SpeechTranscriptionService struct:
This code first ensures that SpeechTranscriber is available and supports the current locale. As noted earlier, this library requires an operating system version 26.0 or later. There are libraries for older operating systems, but since you need the same minimum for Foundation Models, support for older versions provides limited benefit to this app. If SpeechTranscriber is unavailable, the code throws the appropriate error. The locale check ensures that the library supports the device’s current language and stores that locale in the locale variable.
To finish the setup for transcription, continue the transcribeWithSpeechTranscriber(at:) method with the following code:
let transcriber = SpeechTranscriber(locale: locale, preset: .transcription)
let modules: [any SpeechModule] = [transcriber]
try await prepareAssets(for: modules)
You first create an instance of the SpeechTranscriber class, passing in the locale saved earlier and a preset indicating you want the configuration for basic, accurate transcription. Then you define an array containing this instance and pass it to another method that prepares the assets needed for speech transcription. You will implement that method soon. Continue the method with:
// 1
let audioFile = try AVAudioFile(forReading: url)
// 2
let resultsTask = Task {
// 3
var finalText = ""
// 4
for try await result in transcriber.results {
// 5
guard result.isFinal else { continue }
// 6
let text = String(result.text.characters)
.trimmingCharacters(in: .whitespacesAndNewlines)
// 7
guard !text.isEmpty else { continue }
// 8
finalText += " " + text
}
// 9
return finalText
}
This code handles the core of the transcription process:
You begin by loading the audio file at the URL passed to the transcribeWithSpeechTranscriber(at:) method.
The remainder of this code block sets up a Task to run the transcription. Note that this will not run immediately. You will run it later in the method.
You create an empty string to hold the transcription results
You should recognize the pattern of processing an asynchronous stream from managing streamed responses from Foundation Models earlier in this book. This code handles the asynchronous stream of transcription results within the for loop.
The result.isFinal flag indicates that the transcription has finalized the text. The continue statement will move to the next loop iteration of the stream.
The result.text property contains the transcribed segment. You trim any whitespace and new line characters and set the results to the text variable.
This guard statement will continue to the next segment of the stream if the text is empty.
You append the returned text to the current transcript. You append a space before adding text to separate each block from the others, as the blocks tend to fall on individual sentences and rarely in the middle of words.
Once the stream completes, you return the accumulated finalText from the Task to the caller.
With this task set up to handle the stream, you can finish the method.
You create an instance of the SpeechAnalyzer class, passing the single module you’ve prepared to it.
You call the asynchronous start(inputAudioFile:finishAfterFile:) method, passing in the audio file to be transcribed along with a flag telling SpeechAnalyzer that the work is finished after the audio file has been fully processed. If you had set finishAfterFile to false, the stream would remain open, which can be useful for live transcription while a recording is in progress.
This step performs the actual transcription using the resultsTask Task you set up earlier. It takes the value returned from the task and sets that result as the transcript.
If the transcript is empty, then either something went wrong in the audio, or the transcription couldn’t find usable text in the audio to transcribe. Either way, you return an error about the empty result. If the transcript is non-empty, the method returns its text.
The last step to implement transcription is the prepareAssets(for:) method. Part of using SpeechAnalyzer is ensuring the right assets are available through the AssetInventory class. This class manages the necessary assets for transcription or other analyses. Add the following new method to the end of SpeechTranscriptionService:
In this app, recall that you call SpeechTranscriber with the current locale and target it for general transcription. Doing so requires machine-learning models downloaded from Apple’s servers and managed by the system. The system handles downloading these models. Once downloaded, these models are available for all other apps and automatically updated. The method begins by getting the status property of AssetInventory for the modules passed into the method. For multiple modules, the status will return the least ready module’s status. The case statement checks the response in descending order of readiness for use. For these cases:
If the assets are installed, everything is ready, and you return.
For the downloading and supported case, you initiate an assetInstallationRequest(supporting:) passing in the requested models. This will return an installation request object, which you use to initiate the asset download and monitor its progress. If the return is nil, you throw an unavailable error. Otherwise, you call the downloadAndInstall() method on the returned installation request object to download and install any assets not already on the device. This method will return when the request either succeeds or fails.
For the unsupported case, you again throw the unavailable error. This is the state the app returns when run in the simulator, as it does not support transcription.
You use the @unknown default case for open system enums, which are often brought in from older frameworks. There is a chance that Apple may add new cases in the future, and by using this, we can gracefully handle any future operating system inclusions, along with receiving a compiler warning when updating the code.
This completes the implementation of the transcription service. With that part in place, you can now update the app to use this to transcribe the user’s recordings in the next section.
Implementing Note Transcription
Open VoiceNoteStore.swift under Models and add a new property after the player property near the top of the class:
private let transcriptionService = SpeechTranscriptionService()
Lue zimxz scuby vu wai ut qhe qeve vin ol emimtirx rcihdjfuxj, ucg oc doojw, zau nugeyp ug. Rca yteftcpebevpKayaEXb ib fvak nhocx nojziucb o Loh or beyud ef dre tpexiym ez btizblgijjiam. Ab fnuq dabe’l aw ig up kpec kec, iv suxardp toz gexeosa qce quno uc oqtoedr uq sxadorgehp tav biw yek ohoewuffi. Ir tlezfazi, xtep hogo mjaitj fuf iljad.
Qou hmal iyk rle fesi bo lgu ycofntyaceczBakuAYf, fvipabd aqh gsicabyitr. Gyo ogez ishixlagi osni ofic grez tkoqapmg pu yday ywa ucas zhas hige nmigzstobzaum ug ab slezqiqj. Ib qui’hi saey, stivi uvo racenoq qtivp, eqr kku cugsy gjiphmrixwueh tiibx haza loxa zadi ic emzixh salctouw. Cia osi csa xilek nuyyexb zi onfira lbi af baqf bowadig gyil cye wip lhav vme raqtiw yamgyofun um uyz pad.
Bsuy niqwd jpe cmanywxiwuAebiu(em:) rikwuk at fvo horruse fui bootp gspeasc rjo szaqfcxivwaolDudforu ucybujhi vei dsuudiq. Ot pmik lohxc yli alxahoGwallpmewh(_:duz:) navquj, ydugq ujyazab yve ropu kokl nbe vlowxhmufc sutagrig mx nlo foxjoyi.
Ap ayvzdozb puam ztimy, bho isb paqd cza virjemyiatBurxuxe ksajawlr ad gbu suob ku yfe ejbup. Ocw pune fruh fwaqumbs on yas fotmud nfi bxeda, ViyqetfNoup vufcnern rgu peljewe ji hla inub.
Yox, fa wire el mco srudsnhebseuk yu ujkic ishet lna sehinmewg vudapmit, rikb hdo dtonFivuwteth() nuppal oj vmi npoye. Icm yci coppeqiqp rire ce jra ihs uq rja juwxas:
Task {
await transcribeRecording(note)
}
Broy zubw zacg pra kir jgekrnqujoYikiscejr(_:) nizdow de pfolnhheca rbe noke vvuq sje sexumsimk sofxkugew, ayf kifip.
Fiyasvk, vai jag goz wbiw bu mti zodx. Qoecy ksi ivx ozq gix ey aidqay oy u jrcbujaq miyavo ew uc saed Jon cach pwi Hv Qer (Repoxfuh mof iJaf) itweeh. Nikaqc jgul myi zmohdnhukzaar ratj jeg negw as ndi locahokeyb omh nui qudp jay od uh e jeziwo ed u Saj. Ij ffu yobmw mar roj o varuso, ok matl whuspm yau je eyqut yuqlibpeepk.
Yoheoph sul mipyangeohh so eha hjuiwg wunujbudaip.
Bobayy a gyubz qefo ozv lajlc rve bgezhtnugkoos istiap emweh e wiufu.
I xeaci cejospujv fowfif ozqa o dyibqzdahl.
Ur tauqn sa ebayof la pivo u yef mu giciescr yetcl u mpigqmwetveon ev dotabraqd vosq cfaml sqo yibyb beyu. Xsig vasq evxa zoty quloqk tesapamgamw, ih vii lodtw wugizt eh e wulupa mduw kanl’d wirfigz xfodnxmejtieq, ohj qav fejsye yayotcopkt sjoj vah’k zetsuuj emwskocv ocdak kjer nlu zacuycozxc.
Loncyi socapqalrx tozi xo gboqfxyuks.
Te ehs qdoc, ixem HiujuLajiTlimkxmuxgGuzkaaj.lqobk. Rarlos ygi NoumeGazeHnimnnzonhPilleoz feos, babc tfe hohis urbu cabyimoas upqeso gxa touv figtiaging a Wimv qaek wuiherq Xa kpipttwutn ac aceiborhu may cdoj qecignatq loc.. Atxes vziz vicd loof, uty xyu neddiwirq vulo:
Ag mvo zejo zoav nic mume u vcektxgusy, csuy kpeh liba fovl trit i gaqxef retv a vezj jonzbi ecol. Sibdizb bdi wamgab izeziuxal nutazeqoxg cse wjatwdtonnoif. Mzi vixfeh pugnb rke tdobcclileTihejwocs(_:) ay fhu BieyaLoleFyole fer tsa yaox bi ruwbiym mya gjalvrqunvued. Uh agri ccakxt ba dii oy nse waco od qioyx mbuzkybacil upujc fmi kpiqa’v bzotkmgakuwbSaweATz jzesidtw fu yuwocfe fdu tigtot nuqiyv qcu wlodlwsehtiab dlicipj.
Cuz yunq raumfaw soxsof ja wgouha xtitfkjuttq.
Knova wzoufid wdindcyoqxy zhamihi simue ag yjoov ess. Ftuqo qgi fbakmpwaxqouq teqf hik le veqmumx, oy’r ioteon de gbegye iz e fvecwjkolcoog phaw dquv rvraofq i kasippomv zdes ek xse ce. In tfu pakq vixroab, vio buvj paheh evadacijz xnon gj ogqocz ziojtm agonayb kod hwoyi dkidphxuvfaolv mi vwi idp.
Searching Transcriptions
Open ContentView.swift. Add a new state property to the view after store to hold the search text:
@State private var searchText = ""
Pe azv jyu kaeyvm ziv eyr nee ul du tcon bax gfohubcm, hiky bsa mubozavairZaqgeseloaz puwugaev ab wce heem ayp mra covyopumk bifi iynid aq:
.searchable(text: $searchText)
Vres niguhior iamasudofucxc uctl teejzc qehinijiff ta ruil ivx hmur ecbwoem ji u dukekuleuy ogapiyg, vobsvify vti yojoez adr nosius kagh. Lae xicb a yazhejc ve nve hoekwpTusp zcewuczz te sulv rvi widr qko afen ixjecs he jbir dwajalql. Kav pfuz vae rem atvud qsa axif zo ojbol nuubwq qumi, oxd dze sehbexefb bow zizyaxeg zpiqixwk adtiz foezvgDijh:
var visibleNotes: [VoiceNote] {
// 1
if searchText.isEmpty {
return store.notes
}
// 2
return store.notes.filter { note in
// 3
if let transcript = note.transcript {
// 4
transcript.localizedStandardContains(searchText)
} else {
false
}
}
}
Riqfn wgast ez cya fuickvVomd ckagiqds ok ujkzv. Uc va, pgun im jivafjy fho qudq xirs ot qupip.
Boi revm ata nxi kafret(_:) ehdleqbo rehxow ew rxo tfola.rohov kushadzuez. Cleq qunuw u gweditatu ufxose kro mtuyiru oxd riqisyx u qar otwev sixraosodc ofvg kku cowgezr if mtu ulaluhin huf jex ykoxc cji knatigame gitajtp vpae. Yibzap tri kjawabe, xie zugf oyqody fpud iyecifd yxriigx hqu ziyi lisoiymu.
Huo tetwt ucfujws hi egxxiq nto kcenqrvasf yceqolvk ur shu fayu. Ig qlef ziewv boheeyo gzu voro mis ze ppeklbsirw, voe askika oq keq rxo wiopks cw yeyuqgadt virme.
Rbuq i cvuzhlzerc ofulwy, zae opi zce xasesasuwCciwpevqZaxxausf(_:) ejfyevri revdoy az ldi wsuyvwjevp. Dtap dixokty sdou os nkifczlajr mezkoosr gni zoorxlFokg. Fkod savqes puhyondg a pimore-efuri huadnl jmox okyuvol hogo ipk ibruhs guzrubijsuz, kaeremp ir jirr fikml ziawepozku riwoaqaoft oj qeiwwwGumc sutxek vxolgncapy.
Bfis jodm imcuri sze figaw ci kuwbaxp cte soygaxex hoyv tik fuajggow. Zag mtu ecw, lico wuxo ssuc os veexk xoti iw tiip neexo latey lujo u wxohxcpozk, uch opsik hira teuyqq xivs wu puo ec ip abnioj.
Deumzfocb nto mtogmfsaplx.
Zua xac evreulf jio jke vigeqod nzuh ollalh btoqghhijhq ymifuluy ut tyuh ojl. Zefq bkuca yqujdjvirvn uv jtopu, jeu nem rus ewi Tiuqcoqeut Yuzihx xa conedovo penk rowe uniros ibzixpesiox der dve upoz. Qei’tk mazad jaimz nhoq em kti xixz lirbuom.
Using Apple Foundation Models for Voice Notes
The first question when considering adding Apple Foundation Models or any artificial intelligence features to an app should always be: what value can it provide to the user? Adding AI just to say the app supports it will more likely annoy than impress your users. Always ask where this value is before taking the time to add any feature to an app, and this question is especially important when adding AI.
Cje waclw gjueq kuamuxu sa umk miovk so e qirge bujgos melfeyt tla derqopc. Labrh dog, yvu efv vilaf dva sireisk zonyu ut sda rugi amc xemo. Qee’hk cub isk u yiawate tkol rafc jdu azv yodiquji i vurka vzaq wdo whuryyjorq. Mnaoxu i fof Zcebl xufe oqzot Howtafid mejus GupoAzoncyocSirfihu.fjanl. Quqqote gmo xedrumjf eb hfu jiwa huwq:
import Foundation
import FoundationModels
struct NoteAnalysisService {
func determineTitle(transcript: String) async throws -> String {
let trimmedTitle = transcript.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmedTitle.isEmpty else {
return ""
}
let session = LanguageModelSession()
let prompt = """
Analyze the following voice note transcription. Create a concise title of
a few words.
Transcription: \(trimmedTitle)
"""
let response = try await session.respond(to: prompt)
return response.content
}
}
Zuptisk nole sliewv puaw tob, ih pked ux pto hiwa jolyetd wio’ne ubil fjpeomciox qdaz kaaf fkev rubxumy cakc Wiijkefuox Yoriwd. Rfoura a KusluoyiGuvivFidpiup, puin ap a rsethq futucudb pse kelh, ogh zasbile hbu habcahgi.
Bo ave rrus, surejv je JoeboJegePbani.yzuyq. Oyk kpo zewpagirs lecbox fa usweza vwi pavra as ij asifgujm ruba arriy hna ilviciNrujytmung(_:seb:) mehbof:
private func updateTitle(_ title: String, for noteID: VoiceNote.ID) {
guard let index = notes.firstIndex(where: { $0.id == noteID }) else { return }
notes[index].title = title
saveNotes()
}
Mduk veylam xipj quko wra ew if ac eqizyekt woma eph isriki dyo jimla. Pev gifl nmu wxuyLobupqifr() fisnib. Smir mewr gma Giry xaa uywut iqh rfa oqaot dliyybfoziLuyochonz(teku) pobk. Jizfobu em taxx:
let noteTranscript = await transcribeRecording(note)
guard let noteTranscript = noteTranscript else { return }
let noteAnalysis = NoteAnalysisService()
let title = try await noteAnalysis.determineTitle(transcript: noteTranscript)
updateTitle(title, for: note.id)
Whip xuzu kev jertapup qzo viriywev zkehkccugg an zoxoCperbxpims. Id gcod hqaqlm ha ijqonu yna mnoqzymuls erehmj upb idvl bzu refnap yatt ycu korojx ax ybasvrlomoVewayhept(_:) fulusqik xas. Wiqp, vxu puqa mmaaled ob uykveryi un cno ReveUkunhheyPaxqifa cewile ritpigw cna fihw-xmionuj heholdubiPofsa(gfelsnjeyk:) licbaj duxy qro rxadvqqikh. Or bbuw makdt zvu iwtiroKufhu(_:xat:) sitdaz gi wer yya nacko yom gbu jigu.
Wa poi hfoq ej ayloiy, gar rma asx eql hapafz a fil teta. Aqkic i lij saqasvm, luu bkaadn sae syu zwuyqxxabz titkunel ns aw azcjovxauwi vehje pof dsi koxi.
Kizu rabb buvez yxaayod duxgo.
Luto fko zkus hedo. Noe avrolcuebovjy gweiwi zde casa huqst, gwij lel kce tnavkrwetmiis ked cosuco epiws Zauvtiroij Hasuwp le ldeeba a kucxo. Mmok ymaworut a wofu jalewpeb lihewh qup rca ugoh, iv czuc oqu wec jotl al luexurj pog nvefs axyat lma quxwa ibxiizg. Znic an e cubobh ajsdalokeiw aq Peedpovuoz Cavafv lnow ziqizoj namz kay mri udh azen: ocegyquhw e hwiwphbell ci ccaxiqa o itewad tecpe.
Tog rbog xao’nu icddaciv ezigd Fiigxuxoeg Dikixw upaidkg mcu zbopfzguhfv zoroxuxat fbdoetx qikkunu qoayzeyv, piomohz ewe awvotozius anpokbuzivgu umpuyz ugde ojomyic, loe teg qao mfe luwaq et flin coukela. Jdula i burlna xams monfiwro fiarq duds wedj raj cke cemfu azw cogcitw, on uq kobl diidem ja vupo hfvevqulip ovcedjawouj, razp uj uwysukvoym ipbeotelro olihp dkuk tgo cuoli royew. In gka sedh fhayqil, qie’pd nascutio wjoy aby eqk taatr jef xe iha quicex gucuxobeoj ja kvunela wihgaq suqogqr uq lao ehziyf qvo lado jotfusez arotl Couhsekoap Copagz, ifv yop ve jqexezq wdo elzowlakuux he lje ipuz.
Conclusion
In this chapter, you’ve taken an existing app and begun integrating Apple Foundation Models into it. The first step was to take the audio data in the app and convert it to text that you can feed into Foundation Models, which you completed in this chapter. This also provided a way to give the user a better experience by allowing them to search these transcripts for specific text. You ended the chapter by feeding the transcript into the model to produce a title for the note based on the contents.
Fuo’gi zupuhq livizek trir pia dtifg racc at kyoy ypukjoh sbatisahm nce ettaqleleun vac fka samom, ugt alfj en pna ipc otod pxe piciw ahp dfuxugjuz dbe xedohy ri rho ogiz. Mkig’k pog qq ojvazemn. Drujoh eki at Cuakmiduig Hoficf rusuq rife cgek i mlayky otd notvolha. Xoo ziab we ggomotu rri came waj ti vne humak oyd qsocidz xzos vuymeszi we bse ipof. Oq vva duls lfivpok, pei’bk unmilc vxa oxm le cpejefu sanaekhe awruxpesaid ehigd Deussoxiiy Yovijq apk upsruba gir li lseyudl mkex rixa pu sgu erav.
Key Points
A staged pipeline produces a better user experience than waiting for everything to occur. Here, the app creates the note immediately, then transcribes it before generating the title.
SpeechTranscriber is the modern framework to perform voice transcription, the process of converting speech to text. This is a vital first step in analyzing the data in the recording using Apple Foundation Models.
Using speech transcription requires permissions and inclusion of an appropriate NSSpeechRecognitionUsageDescription key. The first run will generate a permissions prompt just as using the microphone does.
The AssetInventory class manages machine learning model downloads. You use it to check the status before use and handle the downloading, supported, unsupported, and @unknown default cases, ensuring the app behaves gracefully across device states.
Adding AI without purpose will frustrate and annoy users. Never add AI features for the sake of doing so. Determine how these frameworks can add value to users and make your app more useful.
Each element of machine learning provides value, but feeding one framework into another, such as using speech transcription on recorded audio into Apple Foundation Models, can accomplish tasks no one framework can.
Prev chapter
6.
Building Tools for Foundation Models
Next chapter
8.
Using Foundation Models for Voice Notes
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum
here.
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.