Pojďme programovat elektroniku | ChatGPT | Javascript

Hrajeme si s ChatGPT API. Napojili jsme našeho hlasového asistenta Živáka na umělou inteligenci

  • Před dvěma lety jsme si ukázali, jak používat Wikipedia API
  • Vyrobili jsme si bota, který byl chytřejší než finalista AZ-kvízu
  • Teď ho napojíme na nové API od OpenAI

Svět se sice za poslední půlrok posadil na zadek z ChatGPT, nového Bingu a dalších textových AI z ranku tzv. velkých jazykových modelů (LLM), nicméně pravidelní čtenáři našeho seriálu pro kutily zůstali ledově klidní.

Většinu praktických znalostí robota z laboratoří OpenAI totiž už před dvěma lety zvládala přelomová technologie z Brna jménem hlasový asistent Živák!

No dobrá, tak moc přelomová zase nebyla, nicméně trošku odkrývala karty, jak do té doby fungovalo mnoho sémantických a zdánlivě vševědoucích botů a vyhledávačů.

Podívejte se na video, jak jsme do našeho hlasového asistenta Živáka napojili technologii ChatGPT:

Před nástupem AI dodávala chytrost Wikipedie

Podobné programy tehdy přehodily veškerou logiku na jeden velmi široký znalostní a licenčně svobodný zdroj, který všichni velmi dobře znáte, řeč je totiž o Wikipedii a jejím API pro vývojáře.

Když jsme tedy našemu Živákovi položili dotaz Co je to paprika, sám o sobě neprovedl naprosto žádnou sémantickou analýzu, ale textový řetězec v původním znění jednoduše přeposlal na server Wikipedie. Teprve ta rozklíčovala, že se asi ptáme na termín paprika a nabídla na toto téma všechny dostupné články.

138753e9-1e49-4378-a1df-37e436e80fdf
Živák uslyšel „Co je to paprika“ a dohledal odpověď na Wikipedii

Náš Živák si následně vybral ten první v pořadí a znovu skrze API požádal Wikipedii, aby mu vrátila stručný výtah. Tedy nikoliv text celého článku na komunitní encyklopedii, ale jen rychlý a informačně hutný perex o několika větách, který nakonec náš robot zobrazil na monitoru a přečetl jej skrze hlasový syntetizátor ve Windows 10/11 a hlas Microsoft Jakub.

Bylo to efektní, celé to běželo v Chromu, a byť měl kompletní HTML kód včetně Javascriptu a komentářů jen okolo stovky řádků, laik si mohl pomyslet, že právě opravdu komunikuje s jakousi sofistikovanou AI, kterou tým vývojářů budoval dlouhé měsíce kdesi na superpočítači.

Ale kdeže! Naši demonstrační apku by levou zadní sesumíroval kdejaký a na výkon orientovaný východoasijský školák.

Dnes napojíme na Živáka ChatGPT

Doba nicméně pokročila, dnes je trendy OpenAI, a tak na její technologii po dvou letech napojíme i našeho Živáka. Nebudeme znovu v celé šíři opakovat, jak vlastně funguje – tady vás odkážu na předchozí díly:

A rovnou se vrhneme na podstatu věci.

Nový model gpt-3.5-turbo

OpenAI nabízí aplikační rozhraní pro vývojáře už nějaký pátek a jeho dokumentaci a podmínky najdete na webu platform.openai.com. Každý uživatel dostane do začátku kredit na hraní, po jehož vyčerpání si už musí zřídit placený účet.

OpenAI Platform dnes umí pracovat s celou škálou vlastních technologií počínaje doplňováním a klasifikací textu a konče generováním obrázků. Před pár dny pak přibyly dva nové modely:

  • gpt-3.5-turbo
  • whisper-1

Zatímco první zmíněný a průběžně vylepšovaný model zpřístupní robůtka ChatGPT, Whisper umí překládat mluvené slovo nahrané třeba v MP3 na text.

Ve světě velkých jazykových modelů neplatíte za CPU čas, ale za zpracované tokeny, což je jejich nejmenší informační jednotka. Co to jsou tokeny v případě OpenAI a ChatGPT, jsme si vysvětlili na několika příkladech v samostatném článku.

Pouze tedy zopakuji, že jeden token má v průměru okolo čtyř znaků a případě modelu gpt-3.5-turbo, který od raných verzí prošel mohutnou optimalizací, si OpenAI účtuje 0,002 dolarů za tisíc tokenů. To je o řád méně než doposud.

Nejprve si vytvoříme klíč API

Pojďme si to vyzkoušet v praxi. Předpokládejme, že jste si zřídili účet na webu OpenAI Platform, máte do začátku ještě nějaký kredit, nebo si za přístup už platíte, a vygenerovali jste si svůj klíč API, kterým budete podepisovat dotazy na platformu OpenAI.

1c554ea7-4f8c-4e1e-a27a-cd5cad851d3e83101a9c-614f-4d94-8e10-92a0231a3d3a
Každý nový uživatel dostane do začátku zkušební kredit a vytvoří si přístupový klíč k API

Poté můžete s neuronkami a jejich modely komunikovat skrze knihovnu v některém z mnoha podporovaných programovacích jazyků. Přímo OpenAI vyvíjí vlastní knihovnu pro Python a Node.js, komunita pak i pro PHP, C#, Javu, Kotlin a další technologie.

A teď se zeptáme na papriku z příkazové řádky

Stejně tak ale můžete s API komunikovat přímo skrze prostý HTTP dotaz. Takže pokud máte na počítači dnes už prakticky standardní textový HTTP klient curl, dotaz na robota ChatGPT ve znění:

„Co je to paprika? Odpověď napiš v češtině“

By mohl vypadat v příkazové řádce takto:

curl https://api.openai.com/v1/chat/completions -H "Authorization: Bearer API klíč" -H "Content-Type: application/json" -d '{"model": "gpt-3.5-turbo", "messages": [{"role": "user", "content": "Co je to paprika? Odpověď napiš v češtině"}]}'

Stručně si to rozklíčujme:

  • https://api.openai.com/v1/chat/ je cílová HTTP adresa
  • -H "Authorization: Bearer API klíč" je HTTP hlavička s API klíčem
  • -H "Content-Type: application/json" je HTTP hlavička s formátem dat
  • -d XXX jsou HTTP POST data ve formátu JSON

JSON struktura s parametry dotazu má pak tuto podobu:

{
  "model": "gpt-3.5-turbo",
  "messages": [
    {
      "role": "user",
      "content": "Co je to paprika? Odpověď napiš v češtině"
    }
  ]
}

A opět si to rozklíčujeme:

  • model je AI z nabídky OpenAI, kterou chceme použít
  • role je role tohoto dotazu. Ptáme se jako uživatel, takže user
  • content je samotný dotaz v přirozené češtině

Všimněte si, že dotaz neobalujeme žádnými parametry. Třeba identifikací jazyka, ve kterém chceme dostat odpověď. Na straně OpenAI se textový dotaz nejprve přeloží na číselné identifikátory tokenů a ty se odešlou do samotné neuronové sítě a jejího modelu.

3b43d6cf-38ae-44e4-afcb-0f1019be9e5447e71216-ab7b-4928-93d0-c2cca290e132
Náš dotaz převedený na tokeny architektury GPT-3. Vyzkoušejte si to sami v tokenizéru

Modelem je vlastně naučená statistická struktura vazeb mezi jednotlivými tokeny, takže AI může odhadovat, jakému sledu tokenů asi nejpravděpodobněji odpovídá nějaký jiný sled tokenů o stanovené délce.

A takto bude vypadat odpověď

Překladač/detokenizér převede vygenerovaný sled tokenů zpět na čitelné znaky, které nám konečně odešle včetně spočítané statistiky ve formátu JSON.

8bdbc611-1dc8-48ff-929d-7e91ab720935
Kompletní dotaz a odpověď na OpenAI API z příkazové řádky

Odpověď ve strojově zpracovatelném formátu JSON a v lépe čitelné formě pak může vypadat v případě papriky třeba jako v ukázce níže. Ale pozor, ChatGPT není Wikipedie, takže každá odpověď je do jisté míry unikátní a může vypadat trošku jinak než ta předchozí.   

Odpověď ve formátu JSON:

{
  "id": "chatcmpl-6qmMNCSVreZN0Gw9JDvl93QGrMnJN",
  "object": "chat.completion",
  "created": 1678036971,
  "model": "gpt-3.5-turbo-0301",
  "usage": {
    "prompt_tokens": 28,
    "completion_tokens": 88,
    "total_tokens": 116
  },
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": "\n\nPaprika je pálivá nebo sladká koření, která se získává z různých odrůd paprikového pepře. Může být používána jako koření do jídel, jako zelenina, nebo se z ní vyrábí paprikový olej."
      },
      "finish_reason": "stop",
      "index": 0
    }
  ]
}

Už si nebudeme vysvětlovat, co přesně představuje každá z položek odpovědi – je to myslím docela jasné z ukázky –, takže jen ty nejdůležitější. V klíči model vidíme konkrétní verzi dané AI, kterou OpenAI použil. V klíči role vidíme, že se jedná o odpověď v režimu asistenta, no a její znění je v klíči content.

Velmi důležitá je i sekce usage, která nám napovídá, kolik jsme spotřebovali tokenů. Samotný dotaz jich zabral 28, poměrně stručná odpověď pak 88. U košatějších odpovědí to ale mohou být i stovky. Dohromady dotaz propálil 116 tokenů

A teď to samé v čistém Javascriptu a HTML

V příkazové řádce s HTTP klientem curl to funguje, ale teď si to pojďme celé přepsat do podoby jednoduché webové stránky, která bude fungovat i lokálně bez jakéhokoliv serveru prostým otevřením v prohlížeči.

48b7ee21-5072-4a53-b765-0748ad291f57
Jednoduché webové rozhraní ChatGPT API

Nezapomeňte nastavit hodnotu proměnné openai_api_klic vlastním identifikátorem, který jste si vygenerovali na webu OpenAI.

<!DOCTYPE html>
<html lang="cs">
    <head>
        <title>Dotaz na ChatGPT pomocí API</title>
        <script>
            // Funkce, která se spojí s OpenAI API skrze asynchronní HTTP klient Fetch API,
            // který podporují všechn ymoderní prohlížeče
            // Viz https://developer.mozilla.org/en-US/docs/Web/API/fetch
            function dotazGPT(){
                let openai_api_klic = "xxxxxxx";
                let dotaz = document.querySelector("#dotaz").value;
                document.querySelector("#vysledek").innerHTML = "<p style='font-size:150%'>Zjišťuji odpověď, chvíli to může trvat...</p>";
                fetch("https://api.openai.com/v1/chat/completions", {
                    method: "POST",
                    headers: {
                        "Authorization": "Bearer " + openai_api_klic,
                        "Content-Type": "application/json"
                    },
                    body: JSON.stringify({
                        "model": "gpt-3.5-turbo",
                        "messages": [
                            {
                                "role": "user",
                                "content": dotaz
                            }
                        ]
                    })
                })
                // Odpověď HTTP serveru zpracuj jako JSON
                .then((odpoved) => odpoved.json())
                // Teď už máme JSON a můžeme s ním pracovat
                .then((json) =>{
                    // Načteme odpověď AI
                    let odpoved = json.choices[0].message.content;
                    // Zjistíme, kolik jsme propálili tokenů
                    let tokeny_vstup = json.usage.prompt_tokens;
                    let tokeny_vystup = json.usage.completion_tokens;
                    let tokeny_celkem = json.usage.total_tokens;
                    // Do HTML kontejneru #vysledek napíšeme odpověď a seznam,
                    // koli ktokenů jsme propálili
                    document.querySelector("#vysledek").innerHTML = 
                        "<p style='font-size:150%'>" + odpoved + "</p>" +
                        "<ul>" + 
                        "<li><b>Spotřeba tokenů celkem:</b> " + tokeny_celkem + "</li>" + 
                        "<li><b>Spotřeba tokenů, dotaz:</b> " + tokeny_vstup + "</li>" + 
                        "<li><b>Spotřeba tokenů, odpověď:</b> " + tokeny_vystup + "</li>" + 
                        "</ul>";
                });
            }
        </script>
    </head>
    <body>
        <!-- Textový vstup pro dotaz -->
        <input id="dotaz" type="text" value="Na něco se zeptej" />&nbsp;
        <!-- Při klepnutí na tlačítko zavolej funkci dotazGPT() -->
        <input type="button" value="Odešli" onclick="javascript:dotazGPT()">
        <!-- Kontejner pro odpověď -->
        <div id="vysledek"></div>
    </body>
</html>

Jednoduchá stránka se skládá z textového vstupu, tlačítka a kontejneru, ve kterém se zobrazí odpověď od ChatGPT a pro lepší představu i statistika spotřebovaných tokenů.

Po klepnutí na tlačítko se skrze vestavěný asynchronní HTTP klient Fetch API spojíme se serverem OpenAI a po několika sekundách (dle vytížení) získáme odpověď v v JSON.

Jednoduché Fetch API už roky podporují prakticky všechny současné webové prohlížeče, takže není třeba i na podobné banality stále dokola používat externí knihovny jako třeba jQuery.

Nakonec integrujeme AI přímo do Živáka

Jak vidno, základní práce s OpenAI je velmi jednoduchá i z prosté HTML stránky a pro ostatní jazyky včetně oblíbeného Pythonu tu jsou knihovny přímo od tvůrců technologie, nebo komunity.

547362ae-bfba-41d1-8116-2d3b083c3e77
Živák tentokrát poslal dotaz „Co je to paprika“ na server OpenAI a žádá, aby jej zpracoval model gpt-3.5-turbo, který se chová stejně jako nejnovější ChatGPT

My si ale vystačíme s kódem výše, kterým rozšíříme našeho Živáka z roku 2021. Ve výchozím stavu budeme veškerý textový vstup, který jsme získali z vrstvy SST (Speech To Text) posílat právě na servery OpenAI.

Nechceme se ale zcela zbavit Wikipedie, a tak bude Živák podporovat oba znalostní zdroje, což se hodí pro porovnání schopností. Mezi oběma zdroji můžeme v aplikaci přepínat na klávesnici.

Přepínání zdroje hledání

Ve výchozím stavu hledá Živák odpověď na Wikipedii. Zdroj hledání lze přepnout stiskem kláves C a W:

  • C nastaví zdroj hledání na ChatGPT
  • W nastaví zdroj hledání na Wikipedii

Komentovaný kód Živáka v jednom jediném HTML souboru si můžete prohlédnout níže, no a pro jeho hlubší pochopení vás opět přesměruji na původní články, ve kterých jsme si nejprve ukázali, jak na Windows a v Chromu pracovat s převodem hlasu na text a naopak, no a následně jak se spojit s Wikipedií, dohledat články na kýžené téma a získat z nich stručný výtah, který naše aplikace posléze zobrazí a přeříká.

Kód Živáka, který používá ChatGPT i Wikipedii

Nezapomeňte v kódu nahradit text v proměnné openai_api_klic vlastním identifikátorem, který jste si vygenerovali na webu OpenAI.

<!DOCTYPE html>
<html lang="cs">
<head>
    <title>Asistent Živák</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Sofia+Sans+Semi+Condensed&display=swap" rel="stylesheet">
    <style>
        /* CSS styl stránky
         * Bez okraje, bez posuvníků
         * S rozložením tabulky
        */
        html, body{
            font-family: "Sofia Sans Semi Condensed", sans-serif;
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            display: table;
            overflow: hidden;
            cursor: pointer;
        }
        /* CSS styl tagu s indetifikatorem vysledek
         * Pružná velikost písma podle výšky okna,
         * zobrazení jako tabulková buňka s vycentrovaným obsahem
        */
        #vysledek{
            font-size: 5vh;
            display: table-cell;
            text-align: center;
            vertical-align: middle;
            padding: 50px 50px;
        }
        /* CSS styl tagu s indetifikatorem informace
         * Druhý řádek tabulky, funkce patičky stránky
        */
        #informace{
            color: #bbbbbb;
            font-size: 3vh;
            display: table-row;
            text-align: center;
        }
        /* Třída stylu error pro obarvfení chyby do ruda */
        .error{
            color:coral;
        }


    </style>
    <script>
        let stt; // Proměnná objektu převodu hlasu na text (Speech To Text)
        let cena_sezeni = 0; // Celková statistika spotřebovaných tokenů během sezení v OpenAI API
        let zdroj = "wikipedie"; // Zdroj, kterého se budeme dotazovat
        // Osobní OpenAI klíč
        // Po vytvoření účtu vygenerujete na adrese: https://platform.openai.com/account/api-keys
        let openai_api_klic = "xxxxxxxx";

        // Po kliknuti myší na stránku zavolej funkci posloucham
        document.onclick = (udalost) => posloucham();

        // Po stisku klávesy zavolej funkci posloucham
        // Stiskem W nastavím zdroj na Wikipedii
        // Stiskem C nastaví mzdroj na ChatGPT
        document.onkeydown = (udalost) => {
            if(udalost.keyCode == 87) zdroj = "wikipedie"
            else if(udalost.keyCode == 67) zdroj = "chatgpt"
            console.log("Zdroj: " + zdroj);
            document.title = "Asistent Živák (" + zdroj + ")";
            posloucham();
        }

        // Po kompletním načtení stránky zpracuj tuto anonymní funkci
        window.onload = (udalost) => {
            document.title = "Asistent Živák (" + zdroj + ")";
            hlavniOkno("Klepni a na něco se zeptej"); // Napiš hlášku do okna
            console.log("Komandére, okénko prohlížeče je připraveno k hrátkám"); // Vypiš do konzole prohlížeče uvítání
            stt = new webkitSpeechRecognition(); // Nastartuj technologii Web Speech API v prohlížeči Chrome
            stt.continuous = false; // Nechceme získávat průběžné výsledky, ale až celou větu
            stt.lang = "cs-CZ"; // Chceme na text převádět hlas v češtině
            stt.interimResults = false; // Nechcme dostávat (rychlejší) předběžné výsledky, ale až finální a kvalitní

            // Jakmile převod řeči na text uslyší delší ticho, přestane poslouchat, zpracuje zvuk a zavolá tuto anonymní funkci  
            stt.onresult = (udalost) => {
                if(udalost.results.length > 0){ // Pokud jsme získali alespoň 1 výsledek
                    let text = udalost.results[0][0].transcript; // Ulož do pomocné proměnné první výsledek z pole přepisů
                    console.log("========================================"); // Vypiš do konzole pro kontrolu, co prohlížeč uslyšel
                    console.log("Hlas: „" + text + "“");
                    hlavniOkno("Hledám odpověď..."); // Napiš hlášku do okna
                    zprocesuj(text.toLowerCase()); // Pošli text k sémantické analýze
                }
                // Pokud žádný výsledek nemáme,
                // resetuj pohled a do patičky naiš důvod
                else{
                    hlavniOkno("Klepni a něco řekni...");
                    informacniBox("Žádné mluvené slovo");
                }
            }
            stt.onspeechend = () => stt.stop(); // Na konci detekce mluveného slova ukonči poslech
            // V případě chyby převodu Speech To Text
            stt.onerror = (udalost) => {
                console.log(udalost.error);
                hlavniOkno("Klepni a něco řekni...");
                informacniBox("Chyba analýzy hlasu: <span class='error'>" + udalost.error + '</spann>');
            }
            // V případě, že Speech To Text nedokáže najít žádné mluvené slovo
            stt.onnomatch = (udalost) => {
                hlavniOkno("Klepni a něco řekni...");
                informacniBox("Nerozpoznal jsem žádné mluvené slovo");
            }
        }

        // Pomocí technologie pro syntézu řeči se prohlížeče zeptej, jestli má k dispozici nějaké syntetizátory
        // a vypiš je zpracováním této anynonymní funkce
        window.speechSynthesis.onvoiceschanged = () => {
            console.log("Výpis dostupných TTS služeb v Chromu:");
            let hlasy = window.speechSynthesis.getVoices(); // Získej seznam syntetizátrů
            for(hlas of hlasy){ // Projdi pole syntetizátorů a vypiš je do konzole do prohlížeče
                console.log(
                    ((hlas.default)? "D" : " ") + " " + // Pokud se jedná o výchozí syntetizátor, napiš „D“ jako defaultní                    
                    ((hlas.localService)? "✔️" : "☁️") + " " + // Pokud je syntetizátor přímo na zařízení, nakrseli fajfku, pokud je pozue online, nakresli emoji mráčku
                    hlas.lang + " " +  // Jazyk syntetizátoru
                    hlas.name  // Jméno syntetizátoru
                );
            }
        }

        // Funkce poslouchám spustí převod hlasu na text
        function posloucham(){
            console.log("🎤 Poslouchám...");
            window.speechSynthesis.cancel(); // Pokud hlasový syntetizátor právě mluví, ukončí ho
            hlavniOkno("Poslouchám...");// Do textového okna napiš informační zprávičku
            stt.start(); // Konečně aktivuj poslech
        }

        // Pomocná funkce pro zobrazení textu v patičce
        function informacniBox(text){
            document.querySelector("#informace").innerHTML = text;
        }

        // Pomocná funkce pro zobrazení hlavního textu na středu obrazovky
        function hlavniOkno(text){
            document.querySelector("#vysledek").innerHTML = text;
        }


        // Funkce rekni pomocí hlasového syntetizátoru přříká obsah vstupní porměnné text
        function rekni(text){
            hlavniOkno(text, true); // Vypiš text do okna
            let rec = new window.SpeechSynthesisUtterance(); // Objekt rec s konfigurací syntetizátoru
            rec.lang = "cs-CZ"; // Chceme použít (jakýkoliv) syntetizátor v nabídce, který umí mluvit česky
            rec.text = text; // Chceme, aby přeříkal obsah proměnné text
            rec.pitch = 1; // Výška zabarvení hlasu (0-2)  
            rec.rate = 0.9; // Rychlost hlasu (0,1-10)
            rec.volume = 2; // Hlasitost (0-2)
            rec.onend = (event) => {
                hlavniOkno("Klepni a na něco se zeptej");
                informacniBox("");
            }

            window.speechSynthesis.speak(rec); // Předej řeč hlasovému syntetizátoru ke zpracování
        }

        /* Hlavní funkce pro analýzu textu, který jsme získali z STT (Speech-To-Text) 
         * Pokud vstup obsahuje slovo „wikipedie“, zpracujeme jej funkci zeptejSeWikipedie
         * V opačném případě se zpetáme ChatGPT
        */
        function zprocesuj(text){ 
            if(text.length > 0){
                if(zdroj == "wikipedie"){
                    informacniBox("Ptám se Wikipedie");
                    zeptejSeWikipedie(text);
                }
                else{
                    informacniBox("Ptám se ChatGPT");
                    text += ". Piš v češtině";
                    zeptejSeChatGPT(text);
                }
            }
            else{
                console.log("🔊 Spouštím TTS"); // V konzoli nás informuj, že spouštíš hlasový syntetizátor
                rekni("Neslišel jsme žádnou otázku"); // Zavole funkci pro přeříkání textu hlasovým syntetizátorem
            }
        }

        /* Funkce pro vyhledání dotazu na Wikipedii skrze její API; mozek našeho znalostního asistenta
         * Nejprve se Wikipedie zeptáme, jestli má k našemu dotazu nějaké články
         * Pokud ano, zeptáme se jí znovu na stručné resumé/perex prvního nalezeného článku v pořadí
        */
        function zeptejSeWikipedie(text){
            // Pomocí veřejného API Wikipedie vyhledej články, které odpovídají dotazu a odpoveď získej ve formátu JSON
            fetch("https://cs.wikipedia.org/w/api.php?origin=*&action=query&list=search&utf8&format=json&srsearch=" + encodeURIComponent(text))
                .then((odpoved) => odpoved.json())
                .then((json) => {
                    // Pokud má pole s výsledky alespoň jednu položku
                    if(json.query.search.length > 0){
                        console.log("Na dotaz existuje " + json.query.search.length + " článků:"); // Vypiš do konzole počet nalezených výsledků
                        for(let clanek of json.query.search) console.log(" ✔️" + clanek.title); // Vypiš do konzole nalezené články
                        let clanek = json.query.search[0].title; // Vyber nadpis prvního nalezeného článku v pořadí
                        // Do patičky napíšeme odkaz článku, ze kterého čerpáme. Zdrojování je základ!
                        informacniBox("Zdroj odpovědi: <a target='_blank' href='https://cs.wikipedia.org/wiki/'" + encodeURIComponent(clanek)+ ">" + clanek + "</a>");
                        // Znovu kontaktuj skrze API Wikipedii a tentokrát získej stručné resumé/perex zvoleného článku
                        fetch("https://cs.wikipedia.org/w/api.php?origin=*&action=query&format=json&utf8&prop=extracts&exintro&explaintext&indexpageids&redirects=1&titles="+encodeURIComponent(clanek))
                        .then((odpoved) => odpoved.json())
                        .then((json) =>{
                            console.log("Vypisuji první odpověď");
                            let uryvek = json.query.pages[json.query.pageids[0]].extract; // Získej první extrakt/perex v pořadí
                            if(uryvek.length > 200){ // Perex může být i tak docela dlouhý. Pokud má tedy více než 200 znaků
                                console.log("Odpověď příliš dlouhá, krátím po větách");
                                let vety = uryvek.split("."); // Rozděl text na jednotlivé věty (děličem je znak tečky na konci věty)
                                let kratsi = ""; let i = 0;
                                while(kratsi.length < 200){ // Vytvoř krátší perex, který bude mít zhruba 200 znaků (plus znaky navíc do konce věty)
                                    kratsi += vety[i++] + ".";
                                }
                                uryvek = kratsi; // Prohoď původní perex za ten nový a kratší
                            }
                            console.log("🔊 Spouštím TTS"); // V konzoli nás informuj, že spouštíš hlasový syntetizátor
                            rekni(uryvek); // Zavole funkci pro přeříkání textu hlasovým syntetizátorem
                        });
                    }
                    // Pokud jsem k dotazu nedokázal na Wikipedii nalézt žádný odpovídající záznam
                    else{
                        console.log("Nenašel jsem odpověď");
                        rekni("Jsem nedokonalý idiot a zdaleka nerozumím všemu. Zeptej se raději Kuby Čížka, ten totiž ví úplně všechno."); // Pošli hlasovému syntetizátoru, aby se omluvil trošku barvitěji
                    }
                });
        }
        function zeptejSeChatGPT(text){
            // Spojíme se s OpenAI a pošleme textový vstup do modelu gpt-3.5-turbo
            console.log("🤖 Dotaz na ChatGPT: '" + text + "'")
            fetch("https://api.openai.com/v1/chat/completions", {
                    method: "POST",
                    headers: {
                        "Authorization": "Bearer " + openai_api_klic,
                        "Content-Type": "application/json"
                    },
                    body: JSON.stringify({
                        "model": "gpt-3.5-turbo",
                        "messages": [
                            {
                                "role": "user",
                                "content": text
                            }
                        ]
                    })
                })
                .then((odpoved) => odpoved.json())
                .then((json) =>{
                    // Textovou odpověď od OpenAI pošleme do hlasového syntetizátoru
                    // a zobrazíme ji v okně
                    console.log("🔊 Spouštím TTS"); 
                    rekni(json.choices[0].message.content);
                    // Zjistíme spotřebu tokenů
                    let cena_vstup = json.usage.prompt_tokens;
                    let cena_vystup = json.usage.completion_tokens;
                    let cena_celkem = json.usage.total_tokens;
                    cena_sezeni += cena_celkem;
                    // Vypíšeme spotřebu tokenů do patičky
                    informacniBox("Cena dotazu: <b>" + cena_celkem + "</b> tokenů (vstup: " + cena_vstup + ", výstup: " + cena_vystup + ", sezení: " + cena_sezeni + ")");
                    console.log("Cena dotazu: " + cena_celkem);
                    console.log("Cena sezení: " + cena_sezeni);
                });
        }
    </script>
</head>
<body>
    <!-- HTML prvek DIV s identifikátorem vysledek. Tady se budou zobrazovat výsledky -->
    <div id="vysledek">Klepni a na něco se zeptej</div>
    <!-- HTML prvek DIV s identifikátorem infrormace. Slouží jako patička s dodytatečnými informacemi -->
    <div id="informace">Budoucnost je nyní</div>
</body>
</html>
Diskuze (4) Další článek: „Temné asteoridy“ jsou téměř tak staré jako Sluneční soustava. A obsahují vodu

Témata článku: , , , , , , , , , , , ,