Takaisin blogiin
Toteutus2. syyskuuta 20265 min lukuaikaPäivitetty 5. syyskuuta 2026

Rakenna robusti tekoäly-chatbotin striimaus: Reconnect, osa-vastaukset ja saavutettavat tilailmoitukset

Käsittele verkkosivusto-chatbotteissa striimattuja vastauksia luotettavasti verkkokatkojen, uudelleenyritysten ja ruudunlukijoiden yhteydessä – ilman tuplia tai puolittaisia lausuntoja.

Teknikko yhdistää työpöydällä numeroituja valomoduuleja yhtenäiseksi signaaliketjuksi
Robustissa striimauksessa jokainen vaihe on jäljitettävissä ja sitä voidaan jatkaa turvallisesti keskeytyksen jälkeen.

Striimaus tekee tekoäly-chatbotista nopeamman tuntuisen, koska ensimmäiset sanat ilmestyvät ennen kuin koko vastaus on laskettu. Teknisesti tämä luo kuitenkin hajautetun prosessin: palvelin, mallintarjoaja, välityspalvelin, selain ja käyttöliittymä ylläpitävät tilaa yhdessä sekuntien tai minuuttien ajan. Mobiiliverkko vaihtuu, välilehti siirtyy taustalle, välityspalvelin katkaisee hiljaisen yhteyden tai käyttäjä lähettää pyynnön vahingossa uudelleen. Ilman selkeää protokollaa tekstinosia näkyy kahteen kertaan, puolittaiset lausunnot merkitään valmiiksi tai sama työkaluaktio käynnistyy kahdesti.

Robust verkkosivusto-chatbot käsittelee striimausta siksi tilakoneena eikä animaationa. Tämä opas näyttää, miten tapahtuma-ID:t, uudelleenyhdistäminen, atominen päätös ja maltilliset ruudunlukijailmoitukset toimivat yhdessä.

Viesti tarvitsee p pysyvän identiteetin

Määritä lähetettäessä asiakaspuolen pyyntö-ID ja palvelinpuolen muuttumaton viesti-ID. Jokainen striimiosa saa lisäksi juoksevan sekvenssinumeron. Jos sama tehtävä saapuu uudelleen yhteyden katkeamisen jälkeen, palvelin ei saa käynnistää toista itsenäistä suoritusta, vaan sen täytyy palauttaa olemassa oleva tila tai jatkaa sitä turvallisesti.

Identiteeteillä on eri tehtävät: pyyntö-ID tekee kirjoitustapahtumasta idempotentti, viesti-ID yksilöi tuloksen ja sekvenssinumero järjestää fragmentit. Pelkkä aikaleima ei riitä, koska rinnakkaiset pyynnöt voivat törmätä tai saapua viiveellä.

Erota kuljetus- ja liiketoimintatila

Se, käytetäänkö Server-Sent Events -tekniikkaa, Fetch-striimejä vai WebSocketeja, ei muuta liiketoiminnallista elinkaarta. Mallinna vähintään tilat hyväksytty, käynnissä, valmistunut, keskeytetty ja epäonnistunut. Vain eksplisiittinen päätöstapahtuma tekee vastauksesta sitovan. TCP-yhteyden päättyminen ei sitä vastoin tarkoita automaattisesti onnistumista.

Server-Sent Events -tekniikassa HTML-standardi kuvaa uudelleenyhdistämisen ja viimeisimmän tapahtuma-ID:n välittämisen. Tämä mekaniikka on hyödyllinen, mutta se ei korvaa palvelinpuolen historiaa. Palvelimen on tiedettävä, mitkä fragmentit kuuluvat viestiin ja voiko uudelleennoudossa hypätä jo lähetettyjen sekvenssien yli.

Uudelleenyhdistäminen ilman kaksoistekstiä

Tallenna rajoitettu tapahtumapuskuri jokaista käynnissä olevaa viestiä kohden. Uudelleenyhdistämisessä asiakas lähettää viimeisimmän vahvistetun sekvenssin. Palvelin toimittaa vain myöhemmät tapahtumat. Jos puskuri on vanhentunut, se ei vastaa arvailluilla fragmenteilla, vaan nykyisen täydellisen tekstin tilannevedoksella (snapshot) ja uudella kantasekvenssillä.

Asiakas käsittelee tapahtumat idempotentisti: sekvenssit, jotka ovat pienempiä tai yhtä suuria kuin viimeksi sovellettu arvo, ignoroidaan. Suuremmat aukot käynnistävät tilannevedoksen noudon. Näin näyttö pysyy oikeana, vaikka välityspalvelin toistaisi dataa tai selain palaisi lyhyen offline-ajan jälkeen.

Osa-vastaukset eivät saa laukaista toimintoja

Striimattu teksti on alustavaa. Linkit voivat olla vielä keskeneräisiä, rajoitus saattaa ilmestyä vasta seuraavassa lauseessa ja jäsennellyt työkalun parametrit ovat syntaktisesti virheellisiä loppuun asti. Renderöi tekstiä progressiivisesti, mutta aktivoi kriittiset toiminnot vasta valmistumisen ja erillisen validoinnin jälkeen.

Tämä pätee erityisesti tilauksiin, ajanvarauksiin, asiakastietojen muutoksiin tai sähköpostien lähettämiseen. Työkalun suoritus vaatii oman idempotentin toiminto-ID:n, käyttöoikeustarkistuksen ja tarvittaessa näkyvän vahvistuksen. Uudelleenyhdistäminen ei saa koskaan suorittaa samaa vaikutusta uudelleen.

Käsittele keskeytys todellisena protokollatapahtumana

Pysäytyspainikkeen ei pitäisi vain pysäyttää visuaalista esitystä. Asiakas lähettää keskeytyspyynnön viesti-ID:n kanssa; palvelin merkitsee suorituksen ja lopettaa mahdollisuuksien mukaan malli- ja työkalutyön. Myöhemmin saapuvat fragmentit hylätään. Käyttöliittymässä säilyy tieto siitä, että vastaus keskeytettiin.

Jos keskeytys ei tavoita palvelinta, työ saattaa jatkua siellä. Siksi myös palvelin tarkistaa tilan säännöllisesti. Kustannus- ja latenssimetriikoiden tulisi laskea keskeytetyt suoritukset erikseen, muuten ne näyttävät normaaleilta virheiltä tai katoavat analyysistä kokonaan.

Tee virheistä ymmärrettäviä ja toistettavia

Erota toisistaan vähintään verkkokatkos, aikakatkaisu, tarjoajan virhe, turva-alueen estämä pyyntö ja liiketoiminnallinen validointi. Käyttäjälle suunnatun viestin ei tarvitse paljastaa sisäistä tekniikkaa, mutta sen tulisi kertoa turvallinen seuraava askel. ”Yhteys katkesi – vastausta jatketaan” on eri asia kuin ”Tätä toimintoa ei suoritettu”.

Uudelleenyrityspainike käyttää alkuperäistä pyyntö-ID:tä vain silloin, kun on tarkoitus jatkaa samaa suoritusta. Aitoa uutta luontia varten luodaan uusi ID, eikä käyttöliittymä näytä molempia versioita yhtenä ainoana tuloksena.

Älä tulvita ruudunlukijaa jokaisella tokenilla

Dynaamisen sisällön on oltava havaittavissa avustavilla teknologioilla. WAI-ARIA määrittelee tätä varten live-alueet (Live Regions) ja eri kiireellisyystasot. Token kerrallaan päivittyvä alue, jossa on aria-live voi kuitenkin aiheuttaa satoja keskeytyksiä. Parempi ratkaisu on visuaalinen striimausnäyttö yhdistettynä erilliseen, maltilliseen tilakanavaan.

Ilmoita esimerkiksi ”Vastausta luodaan”, sen jälkeen järkevin väliajoin valmis lause tai osio ja lopuksi ”Vastaus valmis”. Käytä aria-live="polite" -arvoa normaalissa edistymisessä; assertive sopii vain todella kiireellisiin virheisiin. Kohdistus (fokus) pysyy syötekentässä tai käyttäjän valitsemassa kohdassa eikä hypi jokaisen fragmentin mukana.

Aseta aria-busy="true" vastausalueelle niin kauan kuin sisältö on keskeneräistä, ja poista se atomisen päätöksen yhteydessä. Pysäytyspainike tarvitsee selkeän nimen ja sen on oltava käytettävissä näppäimistöllä. Tarkista myös animaatioiden vähentäminen (reduced motion), skalaatio ja pienet mobiilinäkymät.

Testaa tilakonetta kohdennetusti

Standardipolun (Happy Path) testaus ei riitä. Automatisoi vähintään seuraavat tapaukset:

  • Katkaise yhteys useiden fragmenttien jälkeen ja jatka ilman kaksoistekstiä.
  • Toimita sama tapahtuma kaksi kertaa ja sovella se vain kerran.
  • Jätä yksi sekvenssi väliin ja pyydä tilannevedos.
  • Pysäytä välilehti, vaihda verkkoa ja näytä sen jälkeen oikea päätöstila.
  • Keskeytä työkalun valmistelun aikana äläkä suorita toimintoa.
  • Merkitse näkyvän osa-vastauksen jälkeinen aikakatkaisu keskeneräiseksi.
  • Tarkista ruudunlukijailmoitusten järkevä taajuus ja kohdistuskäyttäytyminen.

Mittaa aika ensimmäiseen näkyvään osioon, aika täydelliseen valmistumiseen, uudelleenyhdistämisprosentti, kaksois- tai hylätyt sekvenssit sekä keskeytyksen onnistuminen. Aika ensimmäiseen tokeniin voi yksinään näyttää hyvältä, vaikka monet vastaukset eivät koskaan valmistuisi luotettavasti.

Vaiheittainen käyttöönottosuunnitelma

  1. Määritä viesti- ja tapahtumatilat palvelinpuolella.
  2. Toteuta idempotentit ID:t ja sekvenssit ennen käyttöliittymäanimaatiota.
  3. Lisää uudelleenyhdistäminen puskurilla ja tilannevedos-fallbackilla.
  4. Erota työkalutoiminnot tiukasti alustavasta tekstistä.
  5. Tarkista tilailmoitukset näppäimistöllä ja ruudunlukijalla.
  6. Testaa virhetilanteet rajoitetussa ja vaihtelevassa verkossa.
  7. Aktivoi striimaus tuotantoliikenteelle vasta tämän jälkeen vaiheittain.

Yhteenveto: Nopeasti näkyvillä, yksiselitteisesti valmis

Hyvä striimaus yhdistää koetun nopeuden selkeään totuusmalliin. Pysyvät ID:t, järjestetyt tapahtumat, atominen päätös ja turvallinen uudelleenyhdistäminen estävät kaksois- ja puolittaiset vastaukset. Maltillinen live-alue tekee prosessista saavutettavan ilman, että ruudunlukijan käyttäjää keskeytetään jokaisella tokenilla.

Testaa seuraavaksi todellista chatia epävakaassa mobiiliverkossa. Jos keskeytyksen ja uudelleenyhdistämisen jälkeen ei ole yksiselitteisen varmaa, mikä viesti on valmis ja mikä toiminto todella suoritettiin, korjausta kaipaa ensin protokolla – ei latausanimaatio.

Lähteet

Muuta verkkosivukäynnit paremmiksi keskusteluiksi

Vähennä tukikuormaa samalla kun vastaukset pysyvät yhdenmukaisina

Tarjoa kävijöille välitöntä tukea sivustolla, ohjaa reunatapaukset tiimillesi ja pidä jokainen vastaus linjassa hyväksytyn tietokannan kanssa.

Aiheet, jotka saattavat kiinnostaa

Jatka lukemista