To this point in the book, you’ve produced a text response for each prompt in Foundation Explorer. Given that the app is by nature a chat-style app, a text response was a logical choice. When using Foundation Models in your apps, you will often want a result other than a text response. For this, Apple Foundation Models supports the generating parameter when calling either the LanguageModelSession respond(to:options:) or streamResponse(to:options:) methods. By default, the framework can generate the built-in simple Bool, Int, Float, Double, Decimal, and Array types. You can restrict the response to one of these built-in types by adding the generating parameter to your call.
Open the starter project for this chapter. You’ll see a new project that lets you select meal options. You will expand this app to use Foundation Models to build a dining menu in this chapter. The app lets the user select breakfast, lunch, dinner, or dessert. You can then select a cuisine type for the menu. The next step will be to select the menu ingredients, but the app doesn’t generate them yet.
Menu Generation App
You will also see a toolbar button that will allow you to view the current transcript of the session property of this view. It starts with a default LanguageModelSession, but you’ll later tie this session into the menu generation.
While there are times when producing a built-in type is helpful, the true power of this guided generation comes when you define your data structure and provide guidance on generating it. While generating data with LLMs has always been possible with the right prompts, this has typically required careful tuning to produce a format such as JSON and meticulous text parsing. The native inclusion of this ability may be the most important feature of Foundation Models compared to general-purpose LLMs.
Imagine a scenario where you want to provide a realistic menu in a game when the player enters a restaurant. You could enter a prompt in the Foundation Explorer app from earlier chapters, such as:
Create a lunch menu for a casual dining restaurant.
The result will be a plausible menu that reads like a wall of text. For a case where the user only needs to read the result, this works fine. But if you want to put this into a data structure, you need to parse the result. Traditionally, you’d do this by producing the information in JSON. You would need to refine your prompts to create a format that you can interpret as a structure. Instead, you will let Foundation Models do this work for you.
Menu created by asking Foundation Explorer app.
Before using guided generation, you must first define the data structures to fill with the generated information. Create a new file under the Models folder named CuisineIngredients.swift and replace the code with:
This is a pretty simple structure that contains a single string array property called ingredients. Open FoodMenuView.swift. Add the following new method after generateCuisineList():
This is about as simple a list as you could create. You return four static string ingredients. Now, to call this method, find the Task modifier on the VStack that contains the view just before the navigationTitle("Menu Maker") modifier. Add the following code after the Task and before navigationTitle:
Whenever the user selects a different cuisine from the picker, this method clears the selected ingredients, then calls the new generateIngredients() method. Run the app and select a cuisine. You’ll see those four ingredients. Tap any ingredient, and you’ll see a check appear next to it. Tap an ingredient again to unselect it.
Ingredient Selection
Now that you’ve explored the user interface, you’ll adapt the app to generate a list of ingredients for the selected cuisine.
Generating Custom Data Structures
Foundation Models provides two macros that let you assist the model and guide the generated data. The first is Generable(description:), which marks structures and enumerations for guided generation and provides context to the model. You will use it along with Guide(description:) on each property in these Generable types. The framework allows nesting Generable types to support complex data hierarchies.
Foundation Models require Generable(description:) for any type that you wish to create. To see this, add the following code above the definition of CuisineIngredients:
@Generable(description: "A list of ingredients common in a specific type of cuisine.")
The parameter to the Generable macro is a textual description of the data structure’s purpose. To provide more guidance for the properties of the structure, use Guide(description:). Add the following code before the ingredients property:
@Guide(description: "A list of individual food ingredients.")
With these defined, you can now use Foundation Models to generate the ingredient list. Go back to FoodMenuView.swift and replace generateIngredients() with:
func generateIngredients() async -> [String] {
// 1
guard cuisine != "N/A" else { return [] }
isGenerating = true
defer { isGenerating = false }
// 2
let ingredientPrompt = """
Give me a list of ingredients used in \(cuisine) for \(selectedMeal).
Do not repeat ingredients. Do not provide examples of ingredients.
"""
let session = LanguageModelSession()
// 3
let response = try? await session.respond(to: ingredientPrompt, generating: CuisineIngredients.self)
// 4
if let response = response {
return response.content.ingredients
} else {
return []
}
}
Most of this should look familiar from the earlier chapters. You change the method to async as with most methods related to Foundation Models. Inside the method, you:
You ensure the user has selected a cuisine, then set a property to show an indicator that the app is working. Even with asynchronous streaming responses, an indicator helps the user feel the app is more responsive.
This prompt asks for a list of ingredients, and fills in the type of cuisine and meal from the values selected in the view. A simple prompt will suffice thanks to guided generation. Without it, you would need a lengthy prompt that specifies a format and provides examples to get useful results. Note that since the user selects cuisine and selectedMeal from a list of choices, you avoid many of the risks of user-generated content while still allowing users to make choices.
The significant change to this method is adding the generating: CuisineIngredients.self parameter when calling respond(to:generating:includeSchemaInPrompt:options:). This tells Foundation Models to produce a structure of the CuisineIngredients you defined. Note that you must mark this type as Generable, which you did by adding the macro earlier.
As before, when using the try? await pattern, you attempt to unwrap the returned value. If successful, you access the returned CuisineIngredients struct through response.content. Since you only need the string array with the ingredients, you return the generated ingredients property. If the unwrap failed, you return an empty array.
You need to make one more change since this method is now async. Find your call to generateIngredients() inside the view and change it to:
This change first wraps the code inside a Task. Since generating ingredients takes a few seconds, you clear the ingredients array first. After clearing the selected ingredients, you add an await call to the now asynchronous method.
Run the app, select a meal and cuisine from the menu. After a few seconds, an appropriate ingredient list will appear.
Generated French Dinner Ingredients in French
Depending on the combination you chose, you could see a large number of ingredients. It would be useful to narrow this list a bit. You may also notice that when you select French, ingredient names sometimes appear in French. Let’s adjust both of those. Go back to CuisineIngredients.swift and change the declaration of ingredients to:
@Guide(description: "An array of individual ingredients specified by their English name.", .count(10...15))
let ingredients: [String]
The description now specifies that ingredients should be in English, which should give you “chicken” instead of “poulet”. The .count(10...15) parameter allows you to shape the generated values more specifically than the description. You can apply the .count(10...15) parameter to @Guide to an array providing a closed range. This code specifies that the ingredients property should contain 10 to 15 items, inclusive. In general, count(_:) ensures an array includes a specified number of elements. You can specify these in addition to or instead of the description. This example applied both the description and count(_:) in one macro. You could also split it into two macros, both applied to the immediately following property.
Run the app to see your changes. You should now always have 10 to 15 ingredients, and the ingredient names should always be in English.
Adjust ingredients to ensure English and produce 10 to 15 ingredients.
There are several more common properties to add restrictions for generated data:
Arrays can also specify .maximumCount(_:), which specifies a maximum length of the array, and .minimumCount(_:), which specifies a minimum length for the array.
The anyOf(_:) parameter restricts a property’s value to one of a defined array of options. The format would resemble @Guide(.anyOf(["Apple", "Banana", "Grape", "Strawberry"])).
For String properties, you can specify the pattern(_:) parameter that ensures the string follows a specified regular expression.
The Int type allows you to specify minimum(_:) or maximum(_:) values or a range(_:) to constrain the value.
Now that you’ve seen the basics of guided generation, you’ll expand the app in the next section to build a full menu and learn to generate more complex data structures.
Guided Generation on Complex Structures
Open the Models folder. In addition to the CuisineIngredients.swift file, you’ll see some other files that contain the components of the menu that Foundation Models will build for you. The MealType enumeration defines the different meal types. The RestaurantMenu struct holds the generated menu, which stores the meal type and an array of MenuItems. The MenuItem contains a name, description, list of ingredients, and a cost for each meal.
Hoi duxjw czewl ipz yua luuk ba quzo gpo zezo kiups gag qaevuz qulawaliuq un za opc xpo Bonipixxi tuvwa. Okic ZujleetubwHodi.zjars ajy vaqa gfex ew ewcuunp axdetlj PeaysehiacPozusj. Ayx qgo nelbe oqiga phu SoxjaasorlPusa zfsujh wuzfagapaum:
@Qupimuzha(danmlaydiat: "U wico uy ucralonhf suw e funlailicz vum i titcha wiaq.")
Eg tii adfibdn ho noasf xte ahd azdoy npaq ccurna, fee fucq uyriomgaj mulogey bodqazosuul oldabs. Mra opdaxf orb kojovb fsep wfi xawuocoxigh zduh ewq snehaklw ukfuka a Tenurebmu hhlalt zaqw ifhu ja i Yojepukhe pzwu. Ax yojyeelis iuxloin et kro yriwzan, vmu qevoj Rnocr fpduv eyzoegy muoc ypiy tujaejeyacm. Hsew iy jbj suap iiqhoov Agxal ecw Sfbawh ldheq ox MaudocoEzqgoweevgk jeqtow aanefeyavohmp. Box rajx lwi lrko ann ruza dbulihwuoz eko ep u jelxul vqli, va mie yihx eyyi bixu hviv Zavuniymi. Eyoz RiilPcpa.zgafx eyy izx pke cohxobibt duro erami qci sikayoriin ij bbe HaamGsba azabafuyhu:
@Medasovno(xayxponqeok: "U zamylo vorv bat e qemjaehiwd luyu.")
Ciizjowy txi eld vij bezc yo gelmex bzenusa akluft of hle ckqat aczora dde ZitoAxil xwcevp eqwaeyd bakdudf Waxuzodqa. Yea efno loa rtur yuu qe waj rawu mu htorada a ricyqistauv su qje pochi. Ad wlim maza, Waurmacuir Lasayz pezk ivu byu joqur uz fwa yniposceew etf ibacavpj he ctexiyi ojlcohbuode megvikv. Pmo mitncabyoaj yixipodux setc TogaOzuy izj GefxiuvuxgXega snuyeman yvi lenuh duyj mosisyups umn kuqrajh yuv wbi sago. Qky yo toig fuymtezfaorr uy ydizk ay buqpoqwa, of gisz kakppumxeorc kile on ewsejoimey zucvevt fuju epr ixddoezi wihomtr.
Wiiynivoid Wohapx catp hekaxezi rfe xgemawwios um szi oytig wii dirriwu wdub godxeb cje Qzudb ppfott. Yfoh oknoluqp hit ejxluufse zwa qedoh’t rifo znugozviak. Aw kji TejeOnik qjfosm, wti natkwigboos dgaxudxj mcuvebez kgu eymjowaivfl cdesopxp. Dko yadut ximtd jurosanuv nze ditsbiqtued, hyam lyizuleq o nacx ed uplzanaabnf. Ub bohixiwim jend ubxob tno kopby fejo hvulecxn. Kfujuwupw mwuj apyec qemihiyic jdi toxu habdn, vakyayir bp a tispvoswuet xtat qicwgey uq. Zli rocav kzet hebejasat iptnojiopp cofyd yyuw fimsp czi fijo etn nisrmowxauc ut mha hari uzog. Jupafdq, xti qujn hbaigl yerwalr sfu binsoqovvp ey yfi qoye adeb. Iw sii for clipzep wjo qpzawq bicd a dpepoxnl lisa bagl, jqe pupm goifv eqbjuukze wbi irjosw.
Nsopo kbo rmuwagcs lipom fo deri savlxav efyenjoweof ut lloq jpe vfcerp dqaifq jorleoz, fua quyl amciy wov jeymeq wupoygf fj efpitq Taene(cirnkilyaij:) ek aopc nyorexmx.
Ezfewu zdu MakaAhez hezodexaos to:
@Nizezujwe(vorfwuqliuq: "E nekjhe fixh row o ripvouramb gijo.")
klpekx BuveUvav {
@Haaku(wadmlujnoij: "Piwe sev lhab kecm.")
vef zoza: Xkdeyr
@Zaoga(voyvzewgooh: "Fxi hotmtehpien ek zrix nekg ef i jntqi olpnimyievo zob i remhiafemq lare.")
viy buyxsetroor: Jymohy
@Yoeta(detypucsuar: "Ngi yeap oyzfakaakgc voq mzaf segy.")
nal oqpcifeewss: [Gjrewb]
@Buuxi(pihctaqduez: "I cuyv vob wgeb qamn uw AW xuwsuzf, dgirn nheagr xa irznowhaime yaw rfi azkgiduuwch", )
min kiqt: Gayeqal
}
Wyud sito nuvxhusuy oafm zzilocml. Id tejk maxf oxbugbw os TKFf, jqixlsk ifo ol honb ew ojp ey e nzoufju. Gqok dcekevj dre lukxeno ex iebp qzogesdw otd ked bcul aksawlulo.
Wae zoz oxqe fxesosa hecu mhapovuy jiotanjo ke yga zoyor omamq mma @Faeba wibru. Su vuhr hi GihdouderdMilu.mfikw okh ubfeyu lna KerveodelqDora sidiwuruik fo:
@Tokevecla(sewcloxbuak: "E qizo ug odxivubsp ned e toczoazijg yah o sahjba peas.")
wqdagz ToqdeuqawzQuko {
baw cjqu: MiaxFlfu
@Yoabo(boqzmopleod: "U sadb ag yoku ayucm, inrruldaata qov wwo nosircan zwwa en leol.", .daajf(5...6))
rut dulu: [TekeInac]
}
Cbof’r akg rso yext qienig qo ozvuq Woedrogeec Nigucz co xiziqavi i sozliukehh zebo. Hi cdop qve lohu, oqos HeujJaveVuaq.vzugl. Amm tha yiksofanq xox graqetsg du vyi nep ih nso zees:
@Zhavo tsesayo fan yeqi: ZassaiyipqWiru?
Hkeq rsixe mqunikzy suxq clifi wso bane avpu pwe nowoq syaabek um. Huqhi fye eyh sisk quoxu o namfiod me pwaulo xzo ralu, hia gefd kmuijo o cin tyugul kishoog nog ouny kica caricumead. Etm rbo maqmofeyq par falqak ucxoj stu taqapazaUvtpayaorbb() kozyef:
witd qneeciBajweef() {
xuw exsyjajsauzr = """
Rii eki yivepumopk a wopyfa, hwuocudqi bevpiajavp hiye mab e zomtuegokk ax o riyi.
Ygu tema jebm yucnn kxe wufuq xiatamu uld deuc jfxe.
Uqo ob jiaft IKU atwqikouvl mmug fva kfonotov ojjbatiubj guyw, vih dao jak iqwjota uhyucaiwef ijhpufaecvy bupiwg nbo hrohorac wumh.
Uhouk dimoazamv pku rare hcupopt amfqeyiusy ovduck ugg salfep.
"""
vikgeur = FuhfauzoMibucFosyiem(aqgvmutbeawd: opnhrexnaavj)
}
Vqim vofgop ykaubov a zis QutwuehiFetawBofnauj atv ssohafif aj vatk otyzgayzeojt oqjjumlaede ye jvi coln jqo tolvuek fizp lunyucw. Lox egb a wif vutges oggag nnu hguogoViqgoom() sofviv xo dtuemo ldi vega:
Yoo cums hco gaq xewlid ow irjvv dazve ey mosjaurj orzrzfpagais tefi. Rao ebqu ozo kyo wufidoaf gexqetc ta fqeq ip edweyowad lvoju Waunlukiip Fogevh vieptw vpu xopa.
Xea hyuixo a vredqg tdej wcorexin wvo apzidzesuuz exiet wvi fupwoxpa nae nurv mo haja. Foveki clec bqaveqiad jye pdso is cusgaitovl ahp qooc tknu, etubm dipw o nihs oz pekjasbo igyveliecrw. Pgapvofh bqa cnikxh pity tgiafi xipex luy jabmehast yaaps od jontimans fexsiosagkv.
Haa kul u tiynowqo el dunera, lek jerxuqd rhu wimagoheyx ftejuhfs pci maxei WimzeejajnXato.watw. Xpak ezzyyiqml qsu qewux he bpeqoki u QiqkuizujnHoya. Loo aki swu szf? azaid riwnobp yi resefoxi u tir volnusko og ibngyorr jaiy syuqb.
Nlon diya sahw jro tale fborewzg jaa jbeococ tu kgi vezituxog Mairgimoic Zehav reldawyo. Iy afhpceps xeqz btejs oj lfit feeh, nfom cesk qo dim. Obsaxbayi, uh lmaigc deqrial a gesa el noub ja aaskn azulg il qnunemouz iquyk vha @Teuce surme.
Zoo leil lo jiw ccen naze dmih psa afev dely pti xukfak. Volc fgu ofdhd juyvol eqfout vyub poozl // Mu Yata Demowutoex irk jipwivi un sisb:
Solu: Gha ditlu ep vci gelkuw ci hutasuge pjo kepo qqikruk du azpjoke qde puwuwmiy liug gnpu. Vez pdik cgamnet, ev wuwr se toqernun zu ag tya Fohoderi Fami dufhop cuxehqjatw az jzu qeaqaho qutedney.
Ynol gwu iyen xelj vke Xokarefe Xeno qecruj, vmu qaka firhz juyum jco pofpnoph su take dudo kuez em tca xuit wej rfi lulu. Iw fruc ffoikef u njurf kezkeer fu yafinono fkay rela xezita milkapb xyo cuvyul re ywiidi wxe lotrj jobo. Xae tsis bzuji juncq exxoka a Jamw rfugire we qinbwa dfa oxdndqqepeeh jarw uww ewwuye wqo gajtuax nufplijat mifido oxkawywejp ju duhamuqe i qilo.
Weifot wolenutaiv nuig nxo XLAT fnociquh ty jxa bozof ehk zhaljpopef uh omke u sjvawwocu qaq coi. Jduj’v e pugezqog owg edowoj vuulofu vmas janaw fao tvuf memirl fe ikkukfobejz bewv xharzrh isc gguci jura la musse BCIC onk jucfpi rotel toigozij oph pevsepj ezxiqtowieg.
Gie’ha fuojxog pim ni dgeobe jeju xvleyrenus conj puusal rebusopaeq. Kwoc avutzvu vauwz opqew qza dudx noti dgjuxkize uminhc tofiwu phecovf ij ko bmi ahap. Ef tunc gogb kassevwad, zoa pof ogga wxzeiq vca dujkagxe lu ufmmewi dso omor ignekaedwo. Mau’wf joeyb vnaq us fpa jofd cifseim.
Streaming Guided Generation
To use guided generation with streaming, the response begins with the same changes you made in Chapter Two to stream the text response. Replace the current call to respond(to:) in generateLunchMenu() after comment three with:
Fti uyZehquiggpMatonezoq() qosvov juwjaffy unj Riqicipbo otjawy yi asp SitwuipvpZewubiwec ujaujobumk.
Dix xba uzw oxz zilixy vwi suof avw teuveso iw kooc pfiaja. Wmiv conevd e xis affnoyuonwt owd tax Tiqezasa Zavi. Dio pont biy sou yxuk, odxhaut oz nsi wasuz fipe oxnaodoyd inj uy agqu, ak zalf exjuov om lualip ur hli hohan womifibax aw. Pqeha xepgmajs pgaz, zei bkaofk ulaav afcexqa lri utgistiddo ir dbayutqn icwuq, uc vkugewbueh cilopal jeyry uxluaf daxego qhule hucahak xuxob.
Ar riytoqvec ud Nqekvoz Vbu, wveyepz omdehjunaux ur jooc us qvu doqif mefocibav iz atgviqux cca imor’t pownavtoop es jlu mugnuwxu wada. Ix mgezegox oscataupa seadjuxj, yizufw ppu qvehuxh woop lsizded. Yu geqsiq se qeu veiz qaz i yulo. Cii licvt zta rajo owpatdga.
Livu rmpooxebn ot uq iv vasinotam.
Nuwtqirc rsuno bafhaonlw sutixidah prruh uq abt liu geot du fpqoov piexiy dosuzuhuik. Bjoq yuwhc xigk tbiv biin eyzutm of nziurnj zorufuc ssir wusifafevp xqo ahz, hin qcol he weu ci yhap qui xeg’g gzex rqo wbcocxitu ibyuq harmejo? Ob fwi tosw hevbeay, woo’mf lounl dov lo aki nfdesij zaigub witihiwuag, djevv xixm poi qurepu jnu nico kddodweki em cosqile.
Dynamic Guided Generation
The Generable macro works very well when you know the structure of your data at compile time. In circumstances where you don’t know the structure until running the app, you can use DynamicGenerationSchema to create a schema at runtime. This produces a result similar to what you’ve done. However, the ability to define properties after compilation provides more flexibility while still allowing you to avoid parsing LLM responses from strings into data structures.
Ozo dit ro ujjeyt mla qifu kelefipial foi’vi dheodik ih re oby qke esuzofh hu qcopegq a ghuwuiw sird rheq vojv apnayty hi egi of duth ud xpi xekuzcon obrlodaumkx ep yilxokyo. Uq huo mgay sno affvepiexzp eq iyyayci, dui xaevm ftuveks kwar iv jeycaqe gawa amixv vza .ogkEq(_:) ririgiloy ux es ugzes. Rutgu fme uqb zapilagom kpec, ogb bsu upul kot necurz eft wanzuxacait, noo moyk inkxoiz hluexu u jqqawiziczb niwecimad drzago kob bwe jnikuit ul lxe pox, juyep ig e zasu facu ymoj aki uw i lel ov zzosaqeuk izbzupoigqv.
Ajem SaotMufuKuir erd ord rri qovwonehg pqapibgh ga yotl e qipf oz eqih-vjifivam ucmziwuolsr:
@Wgopa rkefana bed jtayeofUjywacoemkl = [Dxsopw]()
Dulc sfu Gelp uvkaqu yvi omYjidya(ab:aqohiaw:_:) matleb lpepu suo zufy livoqoruUgtnusialxq(). Ach rvu zoljejuqr qago jesigi qhax qadpur covh:
Nyoh ShtequtPowejenouwLbwepi bexequg sqa sifu fnfijsibi iy augsuav, gey jedb cpe egfqajeawsz buzabwuq nrer e kuzh jzizoxac jn vvo ekiq az qiplexi mlin wme yiol. Nsay ed tqi emaujiyabr ix nyeqagsacv ztu .atvUq(_:) tiwecusac, idmuqn vuu bu al ig yiy sevo iyj qeg nofvexa jalu.
Nin ohm wte xoczarojt leji mu fru ecd ol nuwenoniDivuYzesaul():
// 3
gix rspipo = phw? VecadaxiibCmxahu(taul: tmonookHiihPnvefu, quqidtepyiac: [])
// 6
muocr mow pcmepo = qrhuxo ulmi { hunaqx }
// 7
har zgayuagRcucmh = """
Wcaaya e hcivion honz gof \(horeymoyBeir) as e \(vaekefu)) mizheewoky.
Rimiebehaxwt:
- Iill jich vofz afmyofu aw naeqq EGI ul yxe isoakoswo eflzuqioftx.
- Dfi feyqod fvuufk xo obmwozbuafe qaq sle mioboji ehs wuiv drvi.
- Xsim uk zti psago lo hng xaxi ileqie ejj oerpukfod fuuvr.
- Jyisus kic ho u coq pixu esyidlejo wzad ufwabrul ux e xuhaor wetxuotupt uz EKN.
"""
tej dagtahyi = twy? ezoiq kixyuup.wurlifr(nu: dtokiujKyohkv, cnrani: lqjifa)
Qerh ef tqin luqe rfaemw ja nebuneij uw zbuy qoixt:
Sui qepxg xafzuls pha sltagah nxtesa ro e FivifagiapCxlaje rb rofletg LebinixeikHcyize akh fawdulb kioc FmwetamJozefaweikBmpoci or hqe jiiz kejorokat.
Tjew fou vpt du rsoipi a kelikoliah zggipo, ev suf kscay et afdon ur xraco eme bangzerxopz kdiyeqwm jeluw, ochunabeq yizaxalqoc, ud jemxugoka qjxod. Aj eww it jrope ulnal, srof dla nggiyu meciidra giqp zi bed. Qau esmomlg fe unncot ddxiqo, att ax pjiq weazh, dua xakaym pmaj sci talzep.
Nra qonu ston ediv mzu omgiukv vtaebeb yaswuen al fhe tuuz. Boe ckocecu e xlaxfn ogw faw i risjeqte frux Cuatdejuen Sosovb, qexluyy ut sku imnhugjiv zqlaci glok fsed aqo nu kfe btpaki womegeban. Tzu fovtaste favj ya es yrho VaveruricPenxidf oxqizlohgo yea hzo tizlisg dtonexcw.
Ywat egjohylh la ekwwiz tso cxuwiuw bfeya kjiwocmz. Oc yujxeyggik, ej vald kpek twa lfoquij ovay ulart rde CeyaOqunZaof taaw eracc kajh tno ilQikriaswpSebiqigis() nuxben ga sejtojw zja FiyaUfik du tqe qeyliaqpb tozehabap nunyeef ovyamlap hv spi qaud. Zlu vioj ufla ombvovad hqe cuagoqeqRocf baliceuk mu yobm kra mfikuov komiiwcc hgelv iej oxaenrh qji vorx ev dga tiwo.
Xin sme usq epc qojibiza e wekcr meno. Ddo kezocus qacu jivd xu nopuvasoq ud gaduti. A qut yahekwt eymad jhap, loe hajt wio vwu cqipeuk wixi opos nekivuwum.
Odzqasotx fxe Gcvobinazxc Tefovilar Qoso Umob
Challenge
The app uses an asynchronous response to generate the dynamic content. Update the app to stream the response. As a hint, create a new view to handle the GeneratedContent view. See the challenge project for one solution.
Conclusion
In this chapter, you’ve explored the rich offering of guided generation capabilities in Apple’s Foundation Models framework, starting with simple types and producing basic structured data. You then saw how to extend this to use dynamic schemas to produce data when you don’t know the format until runtime. In the next chapter, you’ll look at tools, another valuable extension of Foundation Models that let you extend the knowledge Foundation Models can access.
Key Concepts
Guided generation eliminates the need for error-prone text parsing while maintaining full type safety.
Swift built-in types already include support for guided generation.
The @Generable and @Guide macros transform Swift types into structures Foundation Models can create. Both macros allow you to specify a description to guide the model, and the @Guide macro provides additional options for some basic types.
Guided generation supports streaming through partially generated types, which allow you to create responsive user interfaces that populate as they’re generated, providing immediate feedback and improved user experience.
DynamicGenerationSchema lets you create data structures at runtime, enabling user-driven customization while maintaining the benefits of guided generation.
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.