facebook LinkedIN LinkedIN - follow
Aktuality -> Podnikové aplikace a služby - 14. 8. 2023 - Filip Koňařík

Možnosti využití generativní AI v podnikovém softwaru

O generativních AI a jejich dopadu na (nejen) softwarový vývoj se vedou vášnivé diskuze. Nástroje jako ChatGPT, GitHub Copilot, Mid­journey a mnoho dalších, už v tuto chvíli značně ovlivňují způsob, jakým se dá vyvíjet software. Od inteligentního napovídání, přes automatizované psaní unit testů, až po strukturované vysvětlování různých konceptů a konstruktů. AI už je tady dnes a rapidně mění způsob naší práce. Nabízí se ale otázka, jak může AI změnit nejen způsob jakým software píšeme, ale i software, který píšeme. Jak jsme v kontextu aktuálních technologií schopni využít AI uvnitř softwaru, který píšeme, tak abychom ho posunuli zase o krůček dále?



Co to vlastně generativní AI je a jak funguje? Generativní umělá inteligence se odkazuje na typ algoritmu, který má schopnost tvořit nový, „originální“ obsah. Tento obsah může zahrnovat různé formáty, jako je text (ChatGPT, Bard, Bing), obrázky (Midjourney, DALL-E, Stable Diffusion), hudbu (Soundraw, AIVA, Soundful), nebo i video (Pictory, Synthesia).

Generativní AI funguje na základě tzv. generativních modelů, které se učí strukturu a vzorce v datech, na nichž byly trénovány, a poté vytvářejí nové vzorce dat, které jsou podobné těm trénovacím. Tento proces je založen na učení s dohledem a využívá sofistikované techniky strojového učení, jako jsou generativní sítě proti soupeřům (GAN) nebo transformační jazykové modely, jako je GPT. Jako takové tudíž pracují s pravděpodobností a jsou jen tak dobré, jak kvalitními vstupními daty disponují.

Svět AI je rozmanitý a aplikace jednotlivých typů modelů (jazykové nebo audio/vizuální) se bude velice lišit produkt od produktu. Nejširšího využití můžeme dosáhnout s LLM (Large Language Model) a na ty se i budeme výhradně zaměřovat v dnešním článku (konkrétně na GPT modely od OpenAI).

Kontextuální nápověda

Když bychom se bavili o podnikových informačních systémech, jako jsou například správa tisku, docházky, skladové hospodářství, ERP a další, v drtivé většině případů se jedná o velké a komplexní systémy, jejichž user experience zpravidla dost pokulhává (ať už jde o dost často starší UI technologie, nebo o celkovou komplexnost úkonů, které v nich člověk musí vykonávat). Jelikož většina podobných řešení jede iterativně už řadu let a jakékoliv změny user experience (obzvláště třeba pro adminy) jsou nákladné a málo kdy podložené reálnou vidinou zisku, jejich používání zpravidla vyžaduje delší dobu na zaučení (ERP systémy jsou perfektní příklad) a velice často k nim jsou extenzivní manuály, jak s nimi vlastně pracovat. AI může být jednou cestou, jak relativně snadno a levně výrazně lépe propojit UI, s kterým interaguje uživatel, a dokumentaci…

In-context learning

Na jedné straně máme složitý software, na straně druhé extenzivní dokumentaci, a z keře vykukuje GPT model. Jak je spojit dohromady? Jednou možností je natrénovat si vlastní model, ale to je časově a finančně náročné, proto se této variantě dnes věnovat nebudeme. Alternativou je takzvaný in-context learning, někdy také označovaný jako fine tuning. Zjednodušeně to znamená, že existujícímu natrénovanému GPT modelu předáme jako součást dotazu kontext, z kterého má vycházet při generovaní.

Kontext je způsob, kterým modelu říkáme, jak se má chovat, co od něj očekáváme a v jakých mezích má fungovat. Velice jednoduše si to můžete vyzkoušet na jakémkoliv veřejně dostupném modelu:

Vidíme, že AI velice rychle přijme svou roli a začne se podle ní chovat. Čím více specifičtí budeme, tím více můžeme chování modelu změnit. Model sám o sobě ale nic neví o našem softwarovém řešení, a tudíž by uživateli nebyl schopen poskytnout relevantní pomoc. Nad rámec popisu chování můžeme jako součást kontextu předat modelu i širokou škálu dat, z kterých poté bude vycházet při generovaní odpovědi, od dokumentace, až po export support ticketů a jejich řešení.

Zásadním problémem ale je, že GPT modely omezují maximální množství tokenů, s kterými jsou schopny pracovat. Pro zjednodušení si pod tokenem můžete představit 4 znaky vstupního textu. Ti zvídavější se mohou podívat na https://platform.openai.com/tokenizer pro hlubší vhled do funkce OpenAI tokenizéru. Omezení je na úrovni od 4096 pro GPT-3.5 až po 32768 pro GPT-4-32k, a limit se stále posouvá. Dalším úskalím je cenový model, který se odvíjí od počtu zpracovaných tokenů. Z toho nám vyplývá, že jen tak jednoduše nemůžeme vzít celou naši dokumentaci a poslat ji GPT modelu jako kontext pro dotaz. To nás přivádí k vektorizovaným indexům.

LlamaIndex (https://github.com/jerryjliu/llama_index)

Jedním ze způsobů, jak efektivně využívat existující dokumentaci (nebo obecně jakékoliv data) s GPT modelem, je převést ji na vektorizovaný index (např. právě pomocí LlamaIndex). Query operace nad takovýmto indexem jsou poté velice efektivní a jsme tak rychle schopni dohledat veškeré relevantní úseky dokumentace ke konkrétnímu vstupu. Souhrn relevantních úryvků dokumentace je poté poskytnut GPT modelu jako kontext pro konkrétní dotaz (čímž snížíme vstupní počet tokenů dotazu). Výstupem GPT modelu je už strukturovaný text, který bude pro uživatele srozumitelný v jeho rodném jazyce a můžeme ho také zobrazit v UI.

Zde přikládáme velice jednoduchý příklad toho, jak jsme schopni pomoci LlamaIndex knihovny pro Python vzít naši dokumentaci, indexovat ji a použít ji jako kontext pro dotaz vůči OpenAI GPT modelu:

from llama_index import VectorStoreIndex, SimpleDirectoryReader
import os

os.environ['OPENAI_API_KEY'] = 'OpenAPI api klíč'

# Načtení dokumentace ze souborů
documents = SimpleDirectoryReader('složka_s_dokumentací').load_data()

# Vytvoření indexu z načtených dokumentů
index = VectorStoreIndex.from_documents(documents)

# Uložení indexu pro budoucí použití
index.storage_context.persist()

# Processing dotazu skrze vygenerovaný index na GPT model
query_engine = index.as_query_engine()
response = query_engine.query('Co je smyslem života?')
print(response)

Jde sice o velice primitivní příklad s velice omezenou použitelností, ale jde vidět, že se v jádru nejedná o žádnou raketovou vědu. Takto vyprodukovaný text už poté můžeme zobrazit kdekoliv v aplikaci, bude vždy reflektovat aktuální stav dokumentace a jeho integrace do řešení nebude až tak náročná (v rámci firemního hackatonu jsme byli schopni mít prototyp za 2 dny).

Když už teď máme způsob, jak komunikovat s GPT modelem, který „rozumí“ našemu řešení, co to tak celé posunout o krůček dál a zbavit se prostředníka.

Chatbot v1

Různé formy více či méně inteligentních chatbotů jsou všude kolem nás, ale často s nimi bohužel nelze mít vyloženě použitelnou interakci. Na druhou stranu, když se podíváme na průměrnou interakci například s ChatGPT, je to trochu jiná úroveň. Pojďme si spolu projít příklad jádra naprosto jednoduchého chatbota. Tentokrát psaného v .NETu s pomocí knihovny OpenAI-API-dotnet (https://github.com/OkGoDoIt/OpenAI-API-dotnet).

// Vytvoření OpenAI API connectoru
OpenAIAPI api = new OpenAIAPI("api-key");
Conversation chat;

// Pokud uživatel teprve zahajuje konverzaci
if (string.IsNullOrEmpty(chatRequest.SessionId) || !Conversations.ContainsKey(chatRequest.SessionId))
{
    // Vytvoříme novou konverzaci
    chat = api.Chat.CreateConversation();

    // Předáme kontext pro daný systém
    chat.AppendSystemMessage(context);

    // Nastavíme temperature (o té více později)
    chat.RequestParameters.Temperature = 0.5;

    // Uložíme si chat session pro zpracování kontinuálního dialogu
    chatRequest.SessionId = Guid.NewGuid();
    Conversations.Add(chatRequest.SessionId, chat);
} 
else
{
    chat = Conversations[chatRequest.SessionId];
}

// Předáme GPT modelu vstup uživatele. Zde bychom například mohli přidat relevantní úseky dokumentace k dotazu uživatele (výstup LlamaIndexu z prvního příkladu)
chat.AppendUserInput(chatRequest.RequestMessage);

// Získáme výstup, který následně zobrazíme uživateli
var response = await chat.GetResponseFromChatbotAsync();
…

Jak lze vidět, opět se jedná o ve skrze jednoduchý kód bez zbytečných složitostí. Stačí vyřešit stavovost chatu pro uživatele, při vytvoření chatu předat GPT modelu kontext v rámci kterého má fungovat a už jen posílat zprávy uživatele a číst odpovědi. Fungování chatbota nejvíce ovlivníme skrze context a temperature.

Context

Jak se říká: kontext je všechno. V případě LLM to platí dvojnásob. Co to kontext je, jsme si vysvětlili již dříve. Jako takový bychom ho mohli rozdělit na dva typy. Ten první je vstupní kontext, který jsme v příkladu předali GPT modelu skrze AppendSystemMessage. Takový kontext by mohl vypadat například následovně:

  • Jsi profesionálně vystupující chatbot uvnitř aplikace pro firemní print management. Uživatelé se tě budou ptát na dotazy související s aplikací, ke kterým vždy dostaneš relevantní úryvky z dokumentace, které použiješ pro pomoc uživateli. V případě, že nebudeš schopen uživateli odpovědět, doptáš se na doplňující dotazy.

Je to opravdu tak jednoduché… Prostou textovou formulací toho, co chceme, aby náš chatbot dělal, jsme schopni dramaticky ovlivnit, jakým způsobem bude fungovat (v dalším příkladu si ukážeme daleko komplexnější použití kontextu). Čím přesněji (a pro GPT model srozumitelněji) kontext definujeme, tím lepších výsledků docílíme. Chtěli bychom například přidat menší easter egg? Můžeme přidat do kontextu následující větu:

  • Když by tě uživatel oslovil frází „Hello there“, odpovíš mu „General Kenobi?“ a budeš s ním jednat jako s rytířem Jedi.

Jak se říká, sky is the limit. Druhou formou kontextu je celá konverzace sama o sobě. To v podstatě znamená, že interně se celá uběhlá konverzace vždy poskytuje modelu jako celkový kontext pro každý další dotaz. Díky tomu se uživatel může odkazovat na kterékoliv předchozí místo v konverzaci a vést s chatbotem kontinuální diskuzi. Taktéž jsme schopni v průběhu pokládání dotazů stále vkládat další a další relevantní kontext (například data získaná z dokumentace pomocí již zmíněného LlamaIndexu).

Temperature

Druhým klíčovým parametrem, který ovlivní, jak se náš chatbot bude chovat, je atribut Temperature (v příkladu nastavený na 0.5). Jde o parameter softmaxové funkce, který určuje, jak „jistý“ nebo „nejistý“ bude model při generování výstupu.

Při nižších hodnotách (pod 0.5) se model bude chovat více deterministicky, to znamená, že bude vybírat slova a fráze, které jsou statisticky nejpravděpodobnější. Výsledek poté bude více konzistentní, ale méně kreativní. Zároveň se bude velice striktně držet kontextu, který jsme mu předali, tedy každý jeho nedostatek bude velice zřetelný. Například, pokud v kontextu zadáme chatbotu za úkol, aby od uživatele zjistil konkrétní sadu informací, mezi nimiž bude například: PC client IP address (jelikož budeme mít kontext definici v angličtině), ale komunikace s uživatelem bude například v češtině, je velká šance, že při dotazovaní použije právě originální anglickou formulaci a nepokusí se o překlad (i když všechen okolní generovaný text bude česky).

Při vyšších hodnotách (nad 0.7) bude model daleko více kreativní, věty budou znít více jako od reálného člověka a bude si schopen domyslet mezery v kontextu, který mu byl dán. Na druhou stranu ale bude mít větší tendenci se ne až tak striktně držet daného kontextu, nebo reality. Příkladem by mohlo být, že z dokumentace dostane úryvek o podpoře dvou výrobců: Ricoh a Fujifilm. Uživateli nicméně řekne informaci o podpoře Fujitsu (i když tato značka není nikde v celém kontextu, který dostal k dispozici). Vybalancování dobrého chování chatbota poté spočívá v poměru detailu kontextu a nastaveném temperature.

Chatbot v2

Nyní už máme základ chatbota, víme, jak mu předat kontext a jak z něj pro uživatele získat relevantní odpověď na dotaz. Co to ale posunout ještě dále, co umožnit chatbotovi „vykonávat akce na základě uživatelského vstupu“. Jeden by řekl, že s jazykovým modelem, který přijímá text a na základě něj generuje textovou odpověď, něco podobného nepůjde… Ale ono to jde. Klíčem je opět kontext. Pojďme vzít originální kontext chatbota v1 a rozšířit ho o následující:

  • Uživatelé tě mohou požádat, aby si za ně vykonal akce uvnitř systému. Docílíš toho tak, že v uživatelských vstupech budeš hledat informace k naplnění modelu, který až budeš schopen naplnit celý, vypíšeš do výstupu v JSON formátu. Když ti budou chybět informace pro kterýkoliv atribut modelu, položíš uživateli doplňující otázku pro jeho získání. JSON nikdy přímo nebudeš zmiňovat ve svých odpovědích. Ve chvíli, kdy budou všechny parametry vyplněny, nebudeš se už doptávat na potvrzení, verifikaci anebo správnost. Atributy modelu jsou následující:
    Název atributu je IP adresa zařízení a ve výstupním JSONu bude reprezentována atributem ipAddress. Tento atribut obsahuje informace o …
    Název atributu je Název zařízení a ve výstupním JSONu bude reprezentována atributem deviceName. Tento atribut obsahuje informace o …

Jak lze vidět, komplexnost kontextu už se zvýšila a v některých ohledech už je přesnější. Každá věta tohoto kontextu plní svůj účel a většina z nich byla přidána během jeho ladění (jako například věta:

  • Ve chvíli, kdy budou všechny parametry vyplněny, nebudeš se už doptávat na potvrzení, verifikaci anebo správnost).

Kontext nám tak postupně bobtná ve velikosti, ale ačkoliv se jedná o text, není zde nutnost držet jej v celku. Velice jednoduše se dá skládat dynamicky podle potřeby z atributů a operací, které jsou v tu chvíli relevantní (například přes custom atributy, které budou obsahovat sémantický význam daného atributu pro předání v rámci kontextu).

Cílem je, aby uživatel vedl s chatbotem standardní komunikaci a jakéhokoliv JSON modelu „na pozadí“ si nikdy nebyl vědom:

// Pokud odpověď obsahuje JSON, pokusíme se ji vyparsovat ven
if (ContainsJson(response))
{
    var json = ExtractJsonFromText(response);
    var actionModel = JsonSerializer.Deserialize<ActionModel>(json);

    // Ačkoliv jsme modelu řekli, že nemá JSON vypisovat dokud není naplněn, stejně se to může stat (obvzláště v závislosti na použité Temperature)
    if (actionModel.hasEmptyFields()) {
        // Explicitně tak řekneme modelu, aby se doptal
        chat.AppendSystemMessage("Doptej se uživatele na informace o prázdných atributech.");
        response = await ProcessOpenAIResponse(chat);
    } else {
        // Pokud se nám model podařilo úspěšně získat, můžeme na jeho základě provést akci uvnitř systému
        await doAction(actionModel);

        // Model donutíme k tomu, aby uživateli řeknul, to co chceme my (bude respektovat jazyk uživatele)
        chat.AppendSystemMessage( "Řekni uživateli, že jsi úspěšně provedl jeho požadavek a zeptej se, jestli potřebuje další asistenci");
        response = await ProcessOpenAIResponse(chat);
    }

Největším problémem takového řešení je, jak moc deterministické budou odpovědi, které nám GPT model bude vracet (obzvláště pak výstupní model, použitý pro vykonání akce). Tento konkrétní příklad jsem zkoušel primárně na modelu GPT-3.5 a v 90 % případů dělal vše, jak měl, ale ve zbytku… U GPT-4 a dalších generací už to ale je, a ještě bude, výrazně lepší, jelikož technologie se v tomto směru posouvá každým dnem.

Další možnosti využití generativní AI

Ukázali jsme si, jak můžeme LLM naučit náš produkt, aby byl schopen uživateli poradit na základě existující dokumentace. Jak jej využít k získání akce, kterou chce uživatel udělat, abychom ji mohli udělat za něj. Stejným způsobem bychom jej mohli napojit na existující systémy typu Jira, tak aby z reported issues byl schopen dát adminovi troubleshooting help anebo ho odkázat na existující limitaci. V případě, že bychom nepoužívali model od OpenAI, ale například Bing (který má aktivní přístup k internetu), mohli bychom dále obohatit kontext chatbota tak, aby znal nejen informace o produktu, ale taktéž o zákazníkovi, který ho používá (zákazník je firma, která má tři pobočky, dvě v Evropě, jednu v Asii, zabývá se tím a tím, apod.), tak aby byl schopen radit adminovi více specificky, například ohledně rozložení skupin zařízení apod.

Pro mě osobně je celá tato oblast velice fascinující a imponuje mi, že bariéra pro vstup, aby si člověk mohl začít hrát, je relativně nízká. Tyto technologie se neustále posouvají kupředu a představují obrovský potenciál pro ty, kteří je budou schopni dobře využít.

Filip Koňařík Filip Koňařík
Autor článku je Principal Software Engineer společnosti Y Soft.

 
  

- PR -

„Se vším, co vidíte, pomáhá Helios“

bylo motto prezentace Asseco Solutions a Gatema IT na letošním MSV


Expozice společností Asseco Solutions a Gatema IT se nacházela v sekci MSV s názvem Digitální továrna. (Zdroj: Asseco Solutions)Stejně, jako každoročně, i byl letošní ročník Mezinárodního strojírenského veletrhu v Brně příležitostí k setkání nejen pro strojírenské firmy, ale i pro všechny společnosti, které mohou strojařům nabídnout něco přínosného.

  

- PR -

Tokeny patří do muzea

Snadnější elektronické schvalování, podepisování i pečetění


Spolupráce firem Gordic a Soft­ware­602 přináší organizacím ve­řej­né správy všech typů unikátní službu, kterou lze co do rychlosti, jednoduchosti i spolehlivosti bez nadsázky označit za revoluci v procesu schvalování dokumentů i podepisování a pečetění. Nahlédněme tedy trochu pod pokličku, konkrétně na 3 nejzásadnější ingredience celého „lektvaru“. Těmi jsou webová aplikace Spisové služby GINIS, navazující Elektronická podpisová kniha s manažerským semaforem a flexibilní řešení Software602 eIDAS Platform.

- inzerce -