ABONAMENTE VIDEO REDACȚIA
RO
EN
NOU
Numărul 165
Numărul 164 Numărul 163 Numărul 162 Numărul 161 Numărul 160 Numărul 159 Numărul 158 Numărul 157 Numărul 156 Numărul 155 Numărul 154 Numărul 153 Numărul 152 Numărul 151 Numărul 150 Numărul 149 Numărul 148 Numărul 147 Numărul 146 Numărul 145 Numărul 144 Numărul 143 Numărul 142 Numărul 141 Numărul 140 Numărul 139 Numărul 138 Numărul 137 Numărul 136 Numărul 135 Numărul 134 Numărul 133 Numărul 132 Numărul 131 Numărul 130 Numărul 129 Numărul 128 Numărul 127 Numărul 126 Numărul 125 Numărul 124 Numărul 123 Numărul 122 Numărul 121 Numărul 120 Numărul 119 Numărul 118 Numărul 117 Numărul 116 Numărul 115 Numărul 114 Numărul 113 Numărul 112 Numărul 111 Numărul 110 Numărul 109 Numărul 108 Numărul 107 Numărul 106 Numărul 105 Numărul 104 Numărul 103 Numărul 102 Numărul 101 Numărul 100 Numărul 99 Numărul 98 Numărul 97 Numărul 96 Numărul 95 Numărul 94 Numărul 93 Numărul 92 Numărul 91 Numărul 90 Numărul 89 Numărul 88 Numărul 87 Numărul 86 Numărul 85 Numărul 84 Numărul 83 Numărul 82 Numărul 81 Numărul 80 Numărul 79 Numărul 78 Numărul 77 Numărul 76 Numărul 75 Numărul 74 Numărul 73 Numărul 72 Numărul 71 Numărul 70 Numărul 69 Numărul 68 Numărul 67 Numărul 66 Numărul 65 Numărul 64 Numărul 63 Numărul 62 Numărul 61 Numărul 60 Numărul 59 Numărul 58 Numărul 57 Numărul 56 Numărul 55 Numărul 54 Numărul 53 Numărul 52 Numărul 51 Numărul 50 Numărul 49 Numărul 48 Numărul 47 Numărul 46 Numărul 45 Numărul 44 Numărul 43 Numărul 42 Numărul 41 Numărul 40 Numărul 39 Numărul 38 Numărul 37 Numărul 36 Numărul 35 Numărul 34 Numărul 33 Numărul 32 Numărul 31 Numărul 30 Numărul 29 Numărul 28 Numărul 27 Numărul 26 Numărul 25 Numărul 24 Numărul 23 Numărul 22 Numărul 21 Numărul 20 Numărul 19 Numărul 18 Numărul 17 Numărul 16 Numărul 15 Numărul 14 Numărul 13 Numărul 12 Numărul 11 Numărul 10 Numărul 9 Numărul 8 Numărul 7 Numărul 6 Numărul 5 Numărul 4 Numărul 3 Numărul 2 Numărul 1
×
▼ LISTĂ EDIȚII ▼
Numărul 165
Abonamente

Ghid de design pentru GenAI în producție

Tudor Topoleanu
Software Engineer @ Cognizant Romania



PROGRAMARE

În 2017 un grup de cercetători Google publică articolul care lansează arhitectura Transformer. În câțiva ani, această arhitectură este scalată atât în dimensiunea modelului, cât și a datelor cu care sunt antrenate modelele, devenind rapid etalonul în domeniul procesării lingvistice. În noiembrie 2022, OpenAI lansează oficial ChatGPT care cucerește atenția întregii lumi în timp record și introduce în vocabularul comun termenul de model lingvistic mare (LLM).

Noul val de soluții GenAI este cel al agenților. Un agent este definit ca un LLM care are libertate de decizie și acces la funcții pentru a îndeplini un scop, ulterior fiind adăugat și conceptul de planificare și de utilizator în buclă.

Soluțiile GenAI pot lua multe forme și nivele de complexitate (a se vedea Figura 1), dar toate au la bază aceste modele lingvistice mari care realizează diverse taskuri în diverse modele de design precum: generarea îmbunătățită prin recuperare (RAG, un LLM cu recuperare date), agent cu funcții, sisteme flow-agent, sistem multi-agenți ierarhici, sistem distribuit multi-agent (swarm). Din punct de vedere arhitectural, toate exemplele de mai sus pot fi implementate prin intermediul grafurilor aciclice care permit control asupra pașilor de la întrebare la răspuns.

Sistemele GenAI în producție pot lua multe forme, cele mai cunoscute arhetipuri fiind sisteme tip chatbot, tip copilot, și agenți ambientali (deep agents).

Practici obligatorii

Din această categorie fac parte necesitățile non negociabile care țin de axa securitate și confidențialitate, respectiv evaluare și observabilitate, ambele fiind esențiale pentru succesul oricărui proiect GenAI.

Securitatea și confidențialitatea datelor este un aspect de multe ori puțin important în proiecte demonstrative sau de tip produs minim viabil. Pentru sistemele de producție autentificarea utilizatorului (bazată pe roluri) de-a lungul întregului lanț de servicii (interfață grafică, API agenți și API funcții) este obligatorie. Acest lucru asigură evitarea situațiilor de escaladare privind accesul la date la care utilizatorul nu are acces (de exemplu, autentificare pe bază de conturi funcționale tipică pentru aplicații demonstrație) sau utilizarea nepermisă a API-urilor din sistem.

Figura 1. Exemple de soluții GenAI în funcție de caracteristici

Din punctul de vedere al confidențialității datelor trebuie asigurat faptul că atât comunicația între serviciile sistemului, cât și informația stocată (documente, tabele, imagini și date utilizator) sunt criptate pentru a preveni interceptarea în tranzit sau accesarea la sursă. Fiecare API din sistem poate fi accesat prin autentificarea SSO (single sign on).

În aceeași categorie intră și funcționalitățile de tip "guardrails" pentru siguranța conținutului, menite să prevină utilizarea sistemului în scopuri nepermise. Aceste mecanisme trebuie să verifice atât solicitările utilizatorului, cât și răspunsurile generate, astfel încât ele să nu includă informații care încalcă termenii de utilizare sau prevederile legale. Astfel de protecții sunt incluse, de regulă, în pachetul standard de securitate al serviciilor GenAI din cloud, precum Azure OpenAI, Google Gemini sau Anthropic Claude. În schimb, în cazul unei infrastructuri de inferență auto-găzduite, fie on-premises, fie în cloud, aceste "guardrails" trebuie proiectate și implementate în mod explicit.

Evaluarea și observabilitatea soluției, precum și feedbackul utilizatorilor reprezintă mecanisme principale de îmbunătățire, debugging și de verificare a sistemului înainte de punerea în funcțiune într-un mediu superior (de exemplu, UAT în producție).

Principiul de funcționare general este următorul: mecanismul de feedback permite utilizatorilor să evalueze ca fiind pozitiv sau negativ fiecare răspuns al sistemului și să adauge opțional anumite observații/ comentarii. Această evaluare este asociată urmei (eng. trace) de observație. Urma de observație salvează tot parcursul sistemului de la întrebare la răspuns și permite depanarea ulterioară a sistemului pentru orice interacțiune, realizând practic un jurnal complet al acțiunilor și răspunsurilor întregului sistem. În acest fel, interacțiunile pozitive sunt agregate și păstrate într-un set de date etalon al sistemului, utilizat pentru evaluarea înainte de punerea în funcțiune (pre-deployment evaluation) a unei versiuni noi în mediul superior, pentru a putea identifica eventuale regresii ale noii versiuni, dar și pentru a evalua îmbunătățirile prin intermediul setului de metrici utilizate (BLEU, ROUGE, METEOR, LLM as a judge etc.) Selecția setului de metrici se realizează în concordanță cu tipul de soluție implementat dar și pe sub-componente, de exemplu subcomponenta de traducere sau recuperare se evaluează distinct de întreg sistemul. Ideal este ca fiecare sub-sistem care realizează o funcționalitate importantă să fie evaluat cu setul potrivit de metrici și date de evaluare.

În mod asemănător evaluările negative împreună cu urmele de observație asociate sunt agregate în setul de date de îmbunătățire din răspunsurile utilizatorilor pentru a fi ulterior analizate și reparate problemele care au condus la rezultate inadecvate conform feedbackului utilizatorului.

De asemenea, mai există setul de date delta realizat manual pentru a putea evalua funcționalități nou adăugate cu o versiune nouă. De exemplu, un set de întrebări pentru a evalua capacitatea de planificare a soluției prin întrebări cu rezolvare multi-pas care nu funcționează în versiunea actuală. Acest tip de set delta poate fi utilizat și în procesul de dezvoltare a funcționalității. Ulterior, setul de îmbunătățire și cel delta se alătură datelor etalon de evaluare pre-deployment, acesta fiind legat de versiunea care urmează să fie pusă în funcțiune.

Observabilitatea poate fi descrisă ca un jurnal al tuturor pașilor realizați de sistem pentru o singură interacțiune întrebare-răspuns. Acest jurnal trebuie să cuprindă eventuale decizii de orchestrare a altor agenți sau funcții, răspunsuri intermediare sau ale serviciilor auxiliare apelate (DBs, tools etc.), starea globală a sistemului, conversația anterioară, și feedbackul primit de la utilizator dacă este cazul. Fără acest jurnal unificat, care menține atât starea sistemului, cât și parcursul apelurilor de la întrebare până la răspuns, depanarea rapidă a eventualelor probleme (buguri în codul agenților sau al funcțiilor, erori în stratul de date, schimbări ale schemelor API ale serviciilor auxiliare sau ale LLM-urilor, lipsa accesului utilizatorului, erori de tip gateway timeout, servicii oprite etc.) devine dificilă. Pentru funcționalitatea de observabilitate se poate utiliza una dintre librăriile: OpenTelemetry, Langfuse, Weave și Langsmith. De menționat că librăriile de agenți încă nu au soluții native pentru acest scop.

Ultimul punct obligatoriu pentru sistemul de producție este cel al protocoalelor. Acesta este important pentru a oferi modularitate și un cadru bine definit în partea de comunicare a unui sistem GenAI.

Deși aceste protocoale specifice domeniului încă nu au doi ani de existență, dintre ele s-au remarcat drept cele mai cunoscute următoarele: comunicare sistem - UI AG-UI și A2UI, comunicare agent-agent A2A (Agent to Agent), comunicare agent-funcții MCP Model Context Protocol. API-urile de agenți și funcții folosesc fie protocolul SSE (Server Sent Event), fie WebSockets [^9]care permit streaming (de sus în jos, respectiv bidirecțional) și update al stării către interfața utilizator. Stabilirea protocoalelor de comunicare permite extinderea și adăugarea de noi agenți sau funcții într-un mod robust și modular fără efecte secundare sau probleme de formatare. ( A se vedea Figura 2).

Considerente de infrastructură

O practică importantă este separarea serviciilor AI (endpointurile LLM) în mediile aferente (dev, UAT și prod), astfel încât traficul din fiecare mediu să fie izolat și serviciile să poată fi scalate dinamic în mod corespunzător cu numărul de utilizatori activi concomitent din fiecare mediu. În mod ideal, serviciul LLM din producție nu este împărțit cu alte proiecte pentru a evita supra-încărcarea prin trafic încrucișat cu alte proiecte. Acest lucru este esențial pentru a minimiza timpul de răspuns în mediul de producție și pentru a evita așteptarea aferentă mecanismului back-off response, atunci când serviciile sunt saturate de apeluri de la utilizatori, care măresc substanțial timpul de așteptare.

Figura 2. Exemplu de organizare stratificată a unui sistem GenAI

Un alt mecanism des întâlnit este cel de folosire a unui Gateway care are rolul de rutare a traficului către endpointurile separate pe mediu și/sau proiecte. Acesta oferă, de asemenea, posibilitatea echilibrării încărcăturii de apeluri, respectiv cea de apel de rezervă către alt serviciu de inferență LLM, când cel principal nu funcționează. Unele server gateway pentru LLMs pot fi, de asemenea, configurate să realizeze filtrarea pe bază de guardrails de siguranță prin apeluri de verificare a întrebării și răspunsului tranzitate de gateway către un LLM diferit specializat în evaluarea siguranței, guvernării și conformității, precum și a respectării termenilor de utilizare etc.

Considerente de optimizare

Cea mai des întâlnită axă de optimizare a sistemelor GenAI este cea a costului și latenței, acestea fiind strâns legate. Aceasta se realizează mai nou prin intermediul disciplinei de inginerie a contextului. LLM-urile de frontieră actuale permit ferestre de context de milioane de tokenuri (un fel de silabe), dar asta nu înseamnă că este o practică bună să folosești întreaga capacitate a LLM-ului din cauză că: timpul de inferență crește cvadratic cu lungimea contextului, iar costul este liniar. Pentru sisteme optimizate pentru interacțiune continuă cu utilizatorul, contextul trebuie administrat în așa fel încât să fie trimis strictul necesar pentru pasul respectiv din graful de rulare al sistemului. Acesta este un principiu bun de design, întrucât un graf de rulare poate avea un număr considerabil de apeluri LLM și, în general, sunt de preferat mai multe apeluri cu context relativ mic decât câteva apeluri cu context mare. (Divide et impera). Totuși trebuie să existe un echilibru între numărul de apeluri către LLM și complexitatea problemei, respectiv timpul total de răspuns, de o parte, și acuratețea respectiv utilitatea răspunsurilor, de cealaltă parte. Mai clar, complexitatea și numărul de apeluri din flow pot fi incrementate ulterior pentru a ajunge la metricile și utilitatea răspunsurilor dorite.

Un alt considerent de optimizare important este cel al deciziei de apelare sau de delegare a responsabilității către un agent sau funcții specializat(e). Primul principiu este cel al separării distincte a funcțiilor sau sub-agenților. Scopul principal este gruparea după funcționalitate și descrieri, astfel încât selecția unei căi corecte să fie cât mai probabilă. Scopul separării este de a evita căi/rute care au descrieri care se suprapun, acest principiu se aplică atât la agenți sub orchestrator, cât și pentru un agent cu diverse funcții. O problemă des întâlnită în sistemele de producție este selecția unei căi/rute de apel incorecte pentru întrebarea utilizatorului. Descrierile de sub-agenți sau funcții cu descrieri asemănătoare se grupează împreună (de exemplu, un sub-agent de date care răspunde despre KPI-uri de performanță va avea acces la o colecție de funcții KPI distincte cu descrieri apropiate).

În sprijinul acestui principiu vine optimizarea deciziilor de alegere a căii/rutei de delegare pentru situații în care suprapunerea funcționalităților (și prin extensie a descrierii sale) nu poate fi rezolvată prin delegare. În aceste cazuri se aplică una din sau ambele soluții: limitarea posibilelor decizii prin selecție pe bază de similaritate semantică a descrierii agentului/funcției și/sau cu exemple corecte întrebare-rută agent/funcție și a clasificării unei întrebări către o rută de delegare (clasificarea rutei putând fi realizată cu LLM sau cu metode clasice de machine learning).

Funcționalități recomandate

Prima și cea mai frecvent întâlnită funcționalitate este cea de personalizare specifică utilizatorului. În termeni tehnici este vorba de memorarea conversațiilor, respectiv a datelor încărcate de utilizator (care nu sunt legate de datele la care are acces sistemul prin agenți și funcții). Personalizarea depinde de memoria sistemului, aceasta poate fi de termen scurt (conversația activă), dar și de termen lung (conversațiile anterioare). Această memorie este salvată separat pentru fiecare utilizator în parte și trebuie gestionată din punct de vedere al recuperării din partiția de date de termen lung, adică selectare/filtrare din cea de termen scurt pentru a ancora asistentul la conversațiile fiecărui utilizator în parte.

O altă funcționalitate recomandată este cea de caching care optimizează timpul de răspuns în cazul în care întrebarea unui utilizator a fost deja rezolvată anterior pentru alt utilizator, bineînțeles cu un timp de resetare potrivit al cache-ului. Este important de luat în considerare următorul fapt: cache-ul poate să fie realizat prin similaritate semantică a întrebărilor utilizatorilor sau în mod clasic prin potrivire exactă. Acest mecanism permite răspunsuri rapide pentru întrebări comune și poate reduce timpul de așteptare respectiv costul. Cache-ul poate fi implementat atât la nivel global al agentului orchestrator, cât și la nivelurile inferioare unde se află sub-agenți respectiv funcții (tools).

Concluzii

Un design bun necesită decizii corecte privind protocoalele de comunicații, cadrul tehnologic și potrivirea cu nivelul de complexitate a cerințelor și necesităților soluției și tipului de cloud disponibil.

Din punct de vedere tehnic, o soluție GenAI poate fi scrisă în mai multe limbaje (Python, Java, C# și TypeScript) folosind diverse librării schelet pentru agenți (LangGraph, Google ADK, Pydantic AI, OpenAI Agents SDK, Microsoft Agent Framework, Strands Agents SDK, Crew AI, Mastraetc.) și încapsulată prin API-uri pentru modularizare oferind un spectru larg de posibilități. Totuși, de cele mai multe ori, soluțiile GenAI nu sunt de sine stătătoare și trebuie integrate cu sisteme și servicii existente, încorporate în aplicații noi sau existente.

Din punct de vedere arhitectural, stratul GenAI este poziționat ca ultimul strat de automatizare dintr-o stivă tehnologică, înaintea interfețelor cu utilizatorul și integrat cu stratul de servicii și cel de date.

Acest strat realizează automatizarea anumitor sarcini cum ar fi: căutare de informații, suport tehnic, analiză date, generare și testare cod. Aceste exemple sunt cunoscute acum, putând fi realizate și gestionate de utilizatori non-tehnici care fie nu au cunoștințele tehnice necesare (SQL și limbaje de programare) pentru a realiza aceste sarcini, fie aleg să utilizeze soluții GenAI pentru a accelera procesele și a delega, până la un punct, sarcini de cercetare și suport unui asistent AI. Designul este centrat pe utilizator, acesta fiind un concept esențial de design care conduce la succes, întrucât utilizatorul ghidează și direcționează activitățile sistemelor GenAI și, în același timp, evaluează sistemul cu care interacționează.

Conferință TSM

NUMĂRUL 165 - CyberSecurity & AI

Sponsori

  • BT Code Crafters
  • Betfair
  • MHP
  • .msg systems
  • P3 group
  • Cognizant Softvision
  • BMW TechWorks Romania

INTERVIURI