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.
Ž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:
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.
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.
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.
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.
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" />
<!-- 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.
Ž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>