Siirtymä ”LLM-keskustelubotista” ”työtä tekeväksi LLM-pohjaiseksi järjestelmäksi” tapahtuu rakenteisten tuotosten ja funktiokutsujen kerroksessa. Siinä LLM lakkaa tuottamasta pelkkää proosaa ja alkaa tuottaa tietoa, tehdä toimintapäätöksiä ja integroitua muuhun infrastruktuuriin.
Tuotannossa ”rakenteinen tuotos” ei tarkoita sitä, että ”JSON-tila toimi kerran testissäni”. Se tarkoittaa vankkaa putkea, joka käsittelee mallien vaihtelua, virheellisesti muotoiltuja tuotoksia, osittaisia epäonnistumisia, skeemojen kehittymistä ja ohjeita epätäydellisesti noudattavien LLM-mallien arkista todellisuutta.
Tämä artikkeli käsittelee tuotannossa todella kestäviä malleja. Oletamme, että tunnet perusteet ja olet käyttänyt OpenAI:n tool_choice-asetusta, Anthropicin työkalukutsuja ja JSON-skeeman rajoitteita. Perehdymme syvemmin siihen, mikä tekee näistä järjestelmistä luotettavia.
Kaksi toimintatapaa
Kyse on kahdesta toisiinsa liittyvästä mutta erillisestä kyvykkyydestä:
Rakenteinen tuotos: LLM tuottaa skeeman mukaista sisältöä, tavallisesti JSON-muodossa. Tätä käytetään, kun LLM:n vastaus tarvitaan ohjelmallisesti käsiteltävässä muodossa.
Funktio- tai työkalukutsu: LLM saa joukon kutsuttavia funktioita, päättää, mitä niistä kutsutaan, jos mitään, ja tuottaa kutsun parametrit. Isäntäjärjestelmä suorittaa funktion ja palauttaa tulokset. LLM voi kutsua lisää funktioita tai tuottaa lopullisen vastauksen.
Mallirajapinnat tarjoavat nämä yleensä seuraavasti:
- Tavallisia rakenteisia tuotoksia varten annetaan JSON-skeeman vastaanottava
response_format-parametri tai vastaava, kuten OpenAI:n ”Structured Outputs” tai Google GemininresponseSchema. - Käytettävissä olevat funktiot kuvataan
tools-taulukossa, ja kutsun yhteydessä palautetaan työkalukutsuvastaus. Anthropicin työkalurajapinta toimii myös keinona rajata tuotos skeemaan: määrität yhden työkalun haluamallasi skeemalla ja pakotat mallin kutsumaan sitä.
Molemmat toimivat ja liittyvät toisiinsa. ”Funktiokutsu” on pohjimmiltaan rakenteinen tuotos, jonka skeema on funktion allekirjoitus.
Malli 1: tiukat ja yksiselitteiset skeemat
Suurin yksittäinen luotettavuushyöty syntyy skeemoista.
Väljä skeema:
{
"type": "object",
"properties": {
"category": { "type": "string" },
"priority": { "type": "string" }
}
}
Tiukka skeema:
{
"type": "object",
"properties": {
"category": {
"type": "string",
"enum": ["billing", "technical", "account", "feature_request", "complaint"],
"description": "The ticket category. Use 'technical' for product bugs and 'account' for login/password issues."
},
"priority": {
"type": "string",
"enum": ["low", "medium", "high", "urgent"],
"description": "Use 'urgent' only for outages or business-critical impact. 'high' for blocking issues on important customers. 'medium' for standard impact. 'low' for nice-to-haves."
}
},
"required": ["category", "priority"],
"additionalProperties": false
}
Tiukka versio:
- Rajaa arvot tunnettuihin enum-arvoihin, jolloin vapaamuotoista vaihtelua ei synny.
- Sisältää sisäisinä kehotteina toimivat kuvaukset, joita malli hyödyntää.
- Määrittää kentät pakollisiksi, joten osittaisia vastauksia ei synny.
- Kieltää ylimääräiset kentät, joten satunnaisia hallusinoituja avaimia ei synny.
Tuotannossa jokaisella skeeman kentällä pitäisi olla kuvaus. Jokainen enum pitäisi määrittää yksiselitteisesti. Jokainen pakollinen kenttä pitäisi merkitä. Tässä skeema toimii kehotteena eli skeema tekee osan kehotesuunnittelusta.
Malli 2: rajoitettu generointi
Merkittävät palveluntarjoajat tukevat nykyään rajoitettua generointia: dekoodaustaso rajoittaa mallin tuottamaan vain kelvollisia tuotoksia.
- OpenAI:
response_format: { type: "json_schema", json_schema: { ..., strict: true } } - Anthropic: työkalut tiukoilla skeemoilla.
- Avoin lähdekoodi:
outlines,lm-format-enforcer,jsonformerja vLLM:n kielioppipohjainen dekoodaus.
Käytä näitä aina. Ne poistavat kokonaisen virheluokan: virheellisen JSON-rakenteen, hallusinoidut kentät ja puuttuvat pakolliset kentät. Suorituskykykustannus on mitätön.
Jos rajoitettua generointia ei ole käytettävissä joissakin avoimissa malleissa tai kokoonpanoissa, varavaihtoehtona on validointi ja uusi yritys (katso Malli 4).
Malli 3: skeemojen versiointi
Skeemat kehittyvät. Kenttiä lisätään, vanhennetaan ja luetteloita muutetaan.
Skeemamuutos on koodimuutos. Sen pitäisi olla:
- Versioitu. Merkitse jokaiseen skeemaan versionumero.
- Testattu. Arviointikokonaisuus ajetaan uudella skeemalla ennen käyttöönottoa.
- Viestitty. Tuotoksen jatkokäsittelijät tietävät muutoksesta.
- Mahdollisuuksien mukaan taaksepäin yhteensopiva. Lisää uusia valinnaisia kenttiä, älä poista pakollisia.
Hyvin toimiva malli on tallentaa skeemat TypeScript-tyyppeinä tai Pydantic-malleina, versioida ne lähdekoodin versionhallinnassa ja tuottaa niistä JSON Schema. Samat tyypit palvelevat sekä mallirajapintaa että sovelluskoodia.
class TicketClassificationV2(BaseModel):
category: Literal["billing", "technical", "account", "feature_request", "complaint"]
priority: Literal["low", "medium", "high", "urgent"]
confidence: float = Field(ge=0, le=1, description="Confidence in this classification, 0-1")
needs_human_review: bool = Field(description="True if any field has low confidence or unusual signal")
reasoning: str = Field(description="Brief reasoning for the classification, especially for non-obvious cases")
Pydantic-malli määrittää skeeman, validoi tuotoksen ja toimii Python-koodisi tyyppinä. Käytössä on yksi ensisijainen lähde.
Malli 4: validointi ja uusi yritys
Validoi tuotos ennen käyttöä myös rajoitettua generointia käytettäessä:
from pydantic import ValidationError
def call_with_validation(prompt, schema, max_retries=2):
for attempt in range(max_retries + 1):
response = llm_call(prompt, response_format=schema)
try:
parsed = schema.model_validate_json(response.content)
return parsed
except ValidationError as e:
if attempt < max_retries:
prompt = build_retry_prompt(prompt, response.content, e)
continue
raise
Uuden yrityksen kehotteeseen pitäisi sisällyttää alkuperäiset ohjeet, mallin edellinen tuotos ja täsmällinen kuvaus virheestä:
Your previous response had a validation error:
{error message}
Your previous output:
{previous output}
Please correct the issue and produce a valid response.
Uudet yritykset toimivat yllättävän hyvin: mallin virhe korjaantuu yleensä yhdellä uudella yrityksellä.
Rajoitukset: älä yritä loputtomasti uudelleen, vaan yritä enintään 2-3 kertaa. Älä yritä uudelleen muiden kuin validointivirheiden, kuten nopeusrajoitusten tai sisältösuodattimen, yhteydessä. Kirjaa uudet yritykset lokiin, jotta niiden määrää voidaan seurata. Kasvava määrä kertoo mallin ajautumisesta tai kehotteen ongelmista.
Malli 5: tuloksen arviointi
Pyydä mallia arvioimaan työkalutuloksia ennen niiden käyttöä, kun funktiokutsun seuraukset ovat merkittäviä.
Pelkistetty silmukka:
1. Call LLM with tools available.
2. Model decides to call tool X.
3. Execute X.
4. Pass result back to model.
5. Model produces final response.
Arviointisilmukka:
1. Call LLM with tools available.
2. Model decides to call tool X.
3. Execute X.
4. Pass result back to model.
5. Model evaluates: does this result match what I expected? Should I act on it?
6. If yes, model produces final response. If no, model calls another tool or asks for clarification.
Tällä havaitaan esimerkiksi seuraavat tapaukset:
- Työkalu palautti 0 tulosta, vaikka tietoja olisi pitänyt löytyä → malli tunnistaa tyhjän tuloksen.
- Työkalu palautti virheen → malli käsittelee sen erikseen eikä sivuuta sitä.
- Työkalu palautti odottamattomia tietoja → malli huomaa tilanteen ja mukautuu.
Toteuta tämä kehottamalla mallia arvioimaan työkalutulokset erikseen esimerkiksi rakenteisella ”arvioi ja toimi” -mallilla.
Tämä lisää viivettä ja tokenien käyttöä. Se kannattaa seurauksiltaan merkittävissä toimissa, kuten sähköpostin lähettämisessä, maksun käsittelyssä ja tietueiden muuttamisessa. Vähäisen riskin tiedonhaussa sen voi jättää pois.
Malli 6: idempotenssi
LLM saattaa kutsua saman työkalun kahdesti tai yrittää jo onnistunutta kutsua uudelleen. Ilman idempotenssia syntyy kaksoiskappaleita: kaksi hyvitystä, kaksi lähetettyä sähköpostiviestiä tai kaksi luotua tietuetta.
Idempotenssin toteutusmalleja:
Idempotenssiavaimet. Jokainen työkalukutsu saa yksilöllisen avaimen, joka luodaan asiakaspuolella ja sisällytetään kutsuun. Jatkorajapinta tai työkalusi rajapintakerros tunnistaa avaimen avulla kaksoiskappaleet ja palauttaa aiemman tuloksen.
Hae tai luo -semantiikka. Tietueita luovat työkalut tekevät ensin tarkistushaun. ”Luo asiakas sähköpostiosoitteella X” tarkistaa ensin, onko samalla osoitteella jo asiakas. Jos on, työkalu palauttaa olemassa olevan asiakkaan eikä luo kaksoiskappaletta.
Toimintolokit. Työkalut kirjaavat jokaisen toiminnon. Rajapintakerros tarkistaa lokin ennen suorittamista. Jos toiminto on jo tehty, se palauttaa välimuistiin tallennetun tuloksen.
Varovainen työkalusuunnittelu. Seurauksellisia toimia tekevät työkalut suunnitellaan vaatimaan nimenomainen vahvistus tai ihmisen hyväksyntä. LLM ei voi käynnistää niitä vahingossa tiiviissä silmukassa.
Suunnittele kaikki sivuvaikutuksia aiheuttavat työkalut idempotenteiksi. Tämän ohittaminen on merkittävä tuotantovirheiden lähde.
Malli 7: työkalukutsujen havainnoitavuus
Sinun on tiedettävä, mitä työkalukutsuissa tapahtuu. Kirjaa jokaisesta kutsusta:
- Aikaleima.
- Työkalun nimi ja argumentit.
- Tulos tai virhe.
- Kesto.
- Käyttäjä tai istunto, johon kutsu kuuluu.
- Tämän vuoron kutsuketju eli kuuluiko työkalukutsu pidempään ketjuun.
Rakenna tiedoista koontinäytöt. Tavallisia näkymiä ovat:
- Työkalukohtainen kutsumäärä.
- Työkalukohtainen virheprosentti.
- Työkalukohtainen keskimääräinen kesto.
- Työkalusarjojen mallit eli mitä työkaluja yleensä kutsutaan yhdessä.
- Hallusinoidut työkalukutsut, joissa LLM yritti kutsua työkalua, jota ei ole olemassa.
Näistä tiedoista näet, missä järjestelmä epäonnistuu ja missä kustannuksia syntyy.
Malli 8: hallusinoidut argumentit
LLM-mallit keksivät joskus arvoja työkalujen parametreihin. Ne voivat kutsua search_customers(email="...")-funktiota sähköpostiosoitteella, joka ei liity käyttäjän varsinaiseen kysymykseen, tai book_meeting(date="...")-funktiota päivämäärällä, jota ei ole mainittu.
Lieventämiskeinot:
Tiukka skeema ja kuvaukset. ”user_id-arvon on oltava aiemmin keskustelussa mainittu tunniste. Älä keksi tunnisteita.”
Validointi työkalun rajapintakerroksessa. Jos arvo ei ole uskottava, esimerkiksi user_id-tunnistetta ei ole tai päivämäärä on menneisyydessä, työkalu palauttaa rakenteisen virheen ja malli harkitsee uudelleen.
Arviointi. ”Varmista ennen työkalun kutsumista, että käyttämäsi arvot perustuvat keskusteluun.”
Rajatut työkalukuvaukset. Tiettyjä kohteita käsittelevät työkalut tarjoavat vain aiemmin keskustelussa haettujen kohteiden tunnisteet. Älä tarjoa rajoittamatonta hakua.
Tarkastuslokit. Havaitse hallusinoitujen argumenttien mallit ja säädä kehotteita tai skeemoja.
Malli 9: hallittu heikentyminen
Työkalut epäonnistuvat, rajapinnat kaatuvat ja nopeusrajoitukset ylittyvät. Oikea vastaus on harvoin kertoa käyttäjälle, ettei mikään toimi.
Toimintamalleja:
Välimuistissa oleva tai vanhentunut tieto. Jos reaaliaikainen tietolähde ei ole käytettävissä, palauta välimuistissa oleva tieto ja ilmoita sen olevan vanhentunutta.
Osittainen valmistuminen. Jos 3 tehtävää 5 osatehtävästä onnistuu, kerro, mitä tehtiin ja mitä ei.
Varapolut. Jos ensisijainen työkalu epäonnistuu, malli tuntee varavaihtoehdon. Jos esimerkiksi ”search_documents” epäonnistuu, käytä ”search_web”-työkalua asianmukaisin varauksin.
Käyttäjälle näkyvät virhetilat. Jos työkalu ei todella pysty suorittamaan tehtävää, malli tuottaa käyttäjälle selkeän virheilmoituksen eikä hallusinoitua onnistumista.
Mallin on tunnettava nämä toimintamallit. Dokumentoi ne järjestelmäkehotteessa:
If a tool returns an error:
- Try the alternate tool if one exists.
- Report partial results clearly if the user has already provided information.
- Never claim success when a tool returned an error.
Malli 10: rakenteisten tuotosten suoratoisto
Osittaisen rakenteisen tuotoksen suoratoisto parantaa käyttökokemusta: käyttäjä näkee tulosten muodostuvan reaaliajassa odottamisen sijaan.
Toteutus:
- Useimmat nykyiset mallirajapinnat suoratoistavat JSON-tuotoksen tokeni kerrallaan.
- Jäsennä osittainen JSON vaiheittain esimerkiksi
partial-json-parser-kirjastolla tai pienellä itse kirjoitetulla suoratoistojäsentimellä. - Päivitä käyttöliittymää kenttien saapuessa.
Tämä toimii erityisen hyvin moniosaisissa tuotoksissa. Pitkä tuotekuvaus, useita havaintoja sisältävä analyysi tai useita löydöksiä sisältävä koodikatselmointi tuntuu paljon nopeammalta suoratoistettuna.
Varoitus: älä tee päätöksiä osittaisen tuotoksen perusteella. Suoratoista näyttämistä varten, mutta odota valmistumista ennen rakenteisen tuloksen käyttöä.
Malli 11: funktiokutsut vai erilliset päätöskutsut
Natiivi funktiokutsu on kätevä, koska malli ”päättää”, milloin työkalua kutsutaan. Joissakin työnkuluissa erillinen päätöskutsu on kuitenkin luotettavampi.
Esimerkkinä asiakastukityönkulku, jossa mallin täytyy valita useasta toiminnosta.
Natiivi funktiokutsu: Anna mallille 5 työkalua (refund, send_article, escalate_to_human, ask_clarifying_question ja close_ticket) ja anna sen päättää.
Erillinen päätöskutsu: Kutsu mallia ensin yhdellä decide_action-työkalulla, joka vastaanottaa yhden parametrin: valitun toiminnon. Kutsu mallia päätöksen perusteella uudelleen vain asianmukaisen työkalun kanssa.
Erillinen tapa on hitaampi ja monisanaisempi mutta luotettavampi. Malli keskittyy paremmin jokaisessa vaiheessa, ja isäntäjärjestelmä hallitsee työnkulkua tarkemmin.
Seurauksiltaan merkittävissä työnkuluissa erillinen tapa on usein parempi. Tutkivissa tai yksinkertaisissa työnkuluissa natiivi funktiokutsu riittää.
Malli 12: työkalutulosten muotoilu
Työkalutulosten palautustavalla on merkitystä. Malli lukee tuloksen, joten muoto vaikuttaa.
Huono:
{"id": "cus_123", "n": "John", "p": "12345"}
Parempi:
{
"customer_id": "cus_123",
"name": "John Doe",
"phone": "+1-555-0123",
"tier": "premium",
"open_tickets": 0
}
Paras joissakin tapauksissa:
Customer found:
- ID: cus_123
- Name: John Doe
- Tier: Premium
- Phone: +1-555-0123
- Open tickets: 0
This customer is in the premium tier and has no open tickets.
”Paras” muoto on ihmisen luettavissa, sisältää kontekstin ja on mallille helpompi hyödyntää myöhemmässä generoinnissa. ”Parempi” muoto on rakenteisempi ja koneellisesti luettavissa. Käytä muotoa, jota malli käsittelee parhaiten jatkotehtävissäsi, ja testaa valinta.
Joidenkin työkalujen yhteydessä sekä rakenteisen että kertovan muodon palauttaminen toimii hyvin: ”Tässä tulos: [kertova kuvaus]. Raakadata: [JSON].”
Malli 13: skeematietoiset uudelleenyritykset
Joistakin validointivirheistä ei voi palautua, koska malli on ymmärtänyt tehtävän olennaisesti väärin. Toiset on helppo korjata.
Hyödyllinen malli on luokitella virhe ja vastata sen mukaisesti.
def handle_validation_error(error):
if "missing required field" in str(error):
return retry_with_message("You omitted required field X. Please include it.")
elif "value not in enum" in str(error):
return retry_with_message("Value X is not in the allowed set. Choose from: ...")
elif "type mismatch" in str(error):
return retry_with_message("Field X must be a number, not a string.")
else:
# Unknown error — single generic retry
return retry_with_message("There was an error in your response. Please try again.")
Virheeseen mukautetut uudet yritykset onnistuvat yleisiä uusia yrityksiä useammin.
Malli 14: yhdisteltävyys
Työkalujen pitäisi olla yhdisteltävissä. Malli voi yhdistää yhteen asiaan keskittyviä pieniä työkaluja monimutkaisiksi työnkuluiksi.
Kaiken tekevä monoliittinen process_customer_request(query)-työkalu on musta laatikko. Malli ei voi havaita eikä ohjata sen sisäistä logiikkaa.
Malli voi yhdistää joukon kohdennettuja työkaluja — search_customer(email), get_recent_orders(customer_id), check_subscription_status(customer_id) ja escalate_to_human(reason) — kuhunkin tilanteeseen sopivaksi työnkuluksi.
Suunnittele työkalut sopivalla tarkkuustasolla. Jokainen työkalu tekee yhden asian, ja työkaluista muodostetaan työnkulkuja.
Malli 15: skeema ”en tiedä” -vastaukselle
Hienovarainen mutta tärkeä malli on epävarmuuden esittäminen skeemassa.
class CustomerInfo(BaseModel):
name: str
name_confidence: Literal["high", "medium", "low"]
needs_clarification: bool
clarification_question: Optional[str] = None
Malli voi palauttaa matalan luottamustason ja tarkentavan kysymyksen tietojen keksimisen sijaan.
Tämä on paljon parempi kuin malli, joka täyttää kentät aina itsevarmasti ja käyttää joskus hallusinoitua tietoa.
Käytännön esimerkki: laskujen käsittely
Yhdistetään mallit tuotantotasoiseen laskujenkäsittelyjärjestelmään.
Syötteet: sähköpostiin liitetty PDF-lasku. Tavoite: poimia rakenteiset tiedot ja välittää ne taloushallintojärjestelmään.
Skeema:
class LineItem(BaseModel):
description: str
quantity: float
unit_price: float
total: float
confidence: Literal["high", "medium", "low"]
class Invoice(BaseModel):
vendor_name: str
vendor_id: Optional[str] = None # null if not found in our records
invoice_number: str
invoice_date: date
due_date: Optional[date] = None
line_items: List[LineItem]
subtotal: float
tax: float
total: float
currency: str # ISO 4217
confidence: Literal["high", "medium", "low"]
needs_review: bool
review_reasons: List[str] # Specific reasons review is needed
Työnkulku:
- OCR-vaihe: kuvamalli poimii tekstin PDF-tiedostosta.
- Poimintavaihe: LLM-kutsu käyttää edellä olevaa skeemaa, ja rajoitettu generointi on käytössä.
- Validointivaihe: Pydantic validoi tuotoksen. Validointivirhe käynnistää yhden uuden yrityksen, johon sisältyy virhepalaute.
- Ristiintarkistus: työkalukutsu hakee toimittajan omista tietueistamme. Jos
vendor_namevastaa tunnettua toimittajaa, lisäävendor_id. Muussa tapauksessa asetaneeds_review=true. - Laskutoimitusten tarkistus: varmista, että
sum(line_items.total) ≈ subtotaljasubtotal + tax ≈ total. Jos ei, asetaneeds_review=true. - Luottamuksen tarkistus: jos
confidenceon matala tai jonkin laskurivin luottamustaso on matala, asetaneeds_review=true. - Reititys: jos
needs_review=true, lähetä ihmisen tarkistusjonoon. Muussa tapauksessa välitä taloushallintojärjestelmään. - Lokitus: kirjaa jokaisesta vaiheesta syöte, tuotos, kesto ja virheet.
Käsitellyt virhetilat:
- Virheellinen JSON: rajoitettu generointi ehkäisee virheen, ja uusi yritys käsittelee reunatapaukset.
- Hallusinoidut kentät: skeema on tiukka.
- Laskuvirheet: validoidaan.
- Tuntemattomat toimittajat: merkitään.
- Pieni luottamus: merkitään.
- Työkaluvirheet: käsitellään erikseen.
Tuotannon suorituskyky: ~95% laskuista käsitellään automaattisesti alusta loppuun ja 5% merkitään tarkistettavaksi. Automaattisesti käsiteltyjen virheprosentti on <0.5% eli hyvin hyväksyttävällä tasolla. Tarkistusjonossa olevista ~80% vahvistetaan oikeiksi ja 20% vaatii korjauksia.
Tältä tuotantotasoinen rakenteinen tuotos näyttää. Kyse ei ole vain siitä, että ”JSON-tila toimi kerran”, vaan todellisten virhetilanteiden käsittelyyn kykenevästä putkesta.
Yleiset virheet
Näemme toistuvasti seuraavia malleja:
Virhe 1: ei validointia. Käytä Pydanticia, zodia tai mitä tahansa sopivaa, mutta validoi. Älä luota malliin.
Virhe 2: epämääräiset kuvaukset. ”category: string” ei auta mallia. ”category: one of billing, technical, account_access, where billing covers…” auttaa.
Virhe 3: liikaa työkaluja. Kun käytettävissä on 30 työkalua, malli valitsee vääriä. Rajaa jokaiselle kutsulle <10 olennaista työkalua.
Virhe 4: validointivirheen jälkeen ei yritetä uudelleen. Yksi virheellisesti muotoiltu tuotos pysäyttää koko työnkulun. Yritä kerran uudelleen ja anna palautetta.
Virhe 5: ei havainnoitavuutta. Kun työkalukutsut epäonnistuvat tuotannossa, syytä ei voi selvittää ilman jäljityksiä.
Virhe 6: sivuvaikutuksia aiheuttavat työkalut eivät ole idempotentteja. Kaksoishyvitykset ja kahteen kertaan lähetetyt sähköpostiviestit ovat ennakoitava virhe.
Virhe 7: LLM:n valitsemia argumentteja ei validoida. Hallusinoidut käyttäjätunnisteet ja päivämäärät. Validoi työkalujen argumentit ennen suorittamista.
Virhe 8: skeemojen versiointi ohitetaan. Skeemamuutokset rikkovat jatkokäsittelijät. Versioi skeema.
Demosta tuotantojärjestelmäksi
Rakenteiset tuotokset ja funktiokutsut muodostavat sillan ”puhuvasta LLM:stä” ”työtä tekeväksi LLM:ksi”. Hyvin toteutettuina ne mahdollistavat tuotantotekoälyn. Huonosti toteutettuina ne rikkoutuvat kiinnostavilla ja kalliilla tavoilla.
Olennaisia malleja ovat tiukat skeemat, rajoitettu generointi, validointi ja uusi yritys, työkalutulosten arviointi, idempotenssi, hallittu heikentyminen, skeemat huomioiva virheenkäsittely sekä kokonaisvaltainen havainnoitavuus.
Jokainen näistä malleista erottaa demon tuotantojärjestelmästä. Rakenna ne mukaan alusta alkaen.



