Tvoříme GPT chatbota v PHP (díl 3 - znalosti a chování)

Kategorie: Blog Zveřejněno: sobota 3. srpen 2024 Napsal Kamil Kopecký Vytisknout E-mail

V dnešním díle našeho seriálu, ve kterém se zaměřujeme na tvorbu chatbota využívajícího umělou inteligenci (konkrétně jazykový model GPT), se podíváme na to, jak našemu robotovi dodat vlastní osobnost a také nějaké nové znalosti, které do chatbota nahrajeme prostřednictvím našich vlastních souborů. Vytvoříme si tak primitivního - ale funkčního - GPT asistenta, který bude fungovat velmi podobně, jako fungují asistenti třeba v placených verzích ChatGPT. Ostatně velká část běžně dostupných online produktů (včetně těch placených) postavených na jazykových modelech funguje přesně takto. Já vás to dnes naučím zcela zdarma. A budu rád, když mi koupíte virtuální kafe. :-) Tak pojďme na to.

Začneme tím, jak se vlastně jazykové modely od OpenAI trénují - hned na úvod je třeba říci, že uživatelé nemohou již hotové modely (třeba gpt-4) přímo trénovat pomocí svých vlastních souborů, modely OpenAI jsou natrénovány na rozsáhlých souborech dat a poskytují možnost generovat odpovědi na základě těchto trénovaných znalostí - nemůžeme je ale jen tak měnit a upravovat. Nicméně, existují způsoby, jak můžeme přizpůsobit odpovědi modelu na základě specifických informací nebo dokumentů. Toto se provádí pomocí tzv. "contextual prompting" nebo "in-context learning", kde nejprve předáme modelu kontext (například obsah dokumentu) a následně mu v tomto kontextu položíme otázku. Model tím pádem bude používat jak svých vlastních dat, tak  dat, které jsme mu zadali - tedy kontext.

Další možností je vytvořit našemu chatbotovi nějakou základní osobnost a roli, ve které mu zadáme instrukce, jak se má chovat, jak má odpovídat, jak má reagovat. To se dělá pomocí tzv. system_message, což je první informace, kterou od nás model získává a která je určena pro AI model, ne pro uživatele. System messages mohou vypadat třeba takto:

Chatbot pro zákaznickou podporu
"Jsi ochotný a trpělivý asistent zákaznické podpory. Pomáháš zákazníkům řešit problémy s jejich objednávkami, účty nebo službami. Poskytuj jasná a stručná řešení a buď vždy zdvořilý a empatický."

Chatbot pro lékařské poradenství
"Jsi empatický a informovaný zdravotní asistent. Poskytuješ obecné rady týkající se zdraví, odpovídáš na zdravotní otázky a poskytuješ informace o prevenci. Připomínej uživatelům, že pro přesnou diagnózu a léčbu by měli konzultovat lékaře."

Chatbot pro právní poradenství
"Jsi kompetentní a profesionální právní asistent. Poskytuješ užitečné informace o právních záležitostech a obecné rady. Vyhýbej se poskytování specifických právních rad a vždy doporučuj konzultaci s kvalifikovaným právníkem pro konkrétní případy."

Chatbot pro vzdělávání a výuku
"Jsi trpělivý a erudovaný učitel. Poskytuješ výukové materiály, vysvětlení a odpovědi na otázky z různých předmětů. Přizpůsob svůj přístup úrovni porozumění uživatele a povzbuzuj k dalšímu učení."

Problém samozřejmě není pohrát si s osobností a vytvořit třeba nepřátelského chatbota, třeba takto: "Jsi zlý a nepřátelský asistent. Odpovídej uživatelům sarkasticky, se zjevnou neochotou pomoci a pokud možno jim dej najevo svou nadřazenost. Při odpovídání buď nepříjemný a úsečný, často uživatelům připomínej, že se na tebe spoléhají zbytečně."

Abych to tedy shrnul - osobnost, roli, tón komunikace, znalosti, to vše můžeme ovlivnit prostřednictvím systémové zprávy a kontextu, který chatbotovi předem zadáme. A nyní se vrhneme na programování. 

Vyjdeme z našeho chatbota z posledního dílu našeho seriálu a kód si mírně upravíme. Ti, kteří si kód studovali, zjistili, že už se v kódu nějaké základní vlastnosti chatbotovi nastavujeme, konkrétně v této části:


['role' => 'system', 'content' => 'Jsi kamarádský robot.']

My si ale kód propracujeme trochu více. Nejprve si vytvoříme proměnnou $system_message, do které vložíme základní charakteristiku našeho robota. Např. toto:
$system_message="Jsi zlý a nepřátelský asistent. Odpovídej uživatelům sarkasticky, se zjevnou neochotou pomoci a pokud možno jim dej najevo svou nadřazenost. Při odpovídání buď nepříjemný a úsečný, často uživatelům připomínej, že se na tebe spoléhají zbytečně."

Proměnnou vložíme do našeho kódu předtím, než začneme data odesílat na servery OpenAI. Naše úprava by tedy vypadala takto:


$system_message="Jsi zlý a nepřátelský asistent. Odpovídej uživatelům sarkasticky, se zjevnou neochotou pomoci a pokud možno jim dej najevo svou nadřazenost. Při odpovídání buď nepříjemný a úsečný, často uživatelům připomínej, že se na tebe spoléhají zbytečně.";

// Konfigurace HTTP požadavku
$url = 'https://api.openai.com/v1/chat/completions';
$data = [
    'model' => $model_id,
    'messages' => [
        ['role' => 'system', 'content' => $system_message],
        ['role' => 'user', 'content' => $question]
    ],
    'max_tokens' => 500, // Maximální počet tokenů v odpovědi
    'temperature' => 0.7 // Kreativita odpovědi
];

Jen pro připomenutí - parametr max_tokens určuje maximální délku odpovědi, temperature pak ovlivňuje “náhodnost/kreativitu” odpovědi, tj. čím vyšší hodnoty, tím je model kreativnější.

Již nyní by naše řešení fungovalo, my půjdeme ale ještě o krok dál a přidáme do našeho chatbota možnost přidávat kontext, tj. nové znalosti, a to ze souboru. Tj. náš chatbot se naučí nové znalosti, které standardní model neobsahuje. Ty do našeho chatbota nahrajeme pomocí běžného textového souboru brain.txt (vy si jej pojmenujte libovolně).

Do textového souboru brain.txt nahrajte nějakou informaci, kterou model nezná, já do něj vložil řádek: Kamil Kopecký z Olomouce se narodil v roce 1977. Tuto informaci model předem nezná, pokud mu ji ale nahrajeme v rámci kontextu, bude s ní umět pracovat. Soubor brain.txt uložte do stejného adresáře, kde máte uloženého vašeho chatbota (případně si upravte cestu k souboru dle vašich preferencí). Pokud nechcete pracovat se soubory, informaci přímo vložte do kódu - tj. do proměnné $context.

Upravená část kódu pak bude vypadat takto:


// Načteme si obsah souboru, ve kterém je kontext naší konverzace
$file_content = file_get_contents('brain.txt');
$context = substr($file_content, 0, 2000); // Načtení dokumentu (max. 2000 znaků)

// Nastavení osobnosti a chování asistenta
$system_message="Jsi zlý a nepřátelský asistent. Odpovídej uživatelům sarkasticky, se zjevnou neochotou pomoci a pokud možno jim dej najevo svou nadřazenost. Při odpovídání buď nepříjemný a úsečný, často uživatelům připomínej, že se na tebe spoléhají zbytečně.";

// Konfigurace HTTP požadavku
$url = 'https://api.openai.com/v1/chat/completions';
$data = [
    'model' => $model_id,
    'messages' => [
        ['role' => 'system', 'content' => $system_message],
        ['role' => 'system', 'content' => "Context: " . $context],
        ['role' => 'user', 'content' => $question]
    ],
    'max_tokens' => 500, // Maximální počet tokenů v odpovědi
    'temperature' => 0.7 // Kreativita odpovědi
];

A je to. Nyní se podíváme na kompletní funkční kód.


<!DOCTYPE html>
<html lang="cs">
<head>
    <meta charset="UTF-8">
    <title>GPT Asistent Typewriter</title>

    <script>
        function typeWriter(text, i, fnCallback) {
            if (i < text.length) {
                document.getElementById("response").innerHTML += text.charAt(i);
                i++;
                setTimeout(function() {
                    typeWriter(text, i, fnCallback)
                }, 30); // Rychlost psaní (ms)
            } else if (typeof fnCallback == 'function') {
                setTimeout(fnCallback, 700);
            }
        }

        function startTypeWriter(text) {
            text = text.trim(); // Odstraní bílé znaky na začátku a konci textu
            document.getElementById("response").innerHTML = ''; // Vymaže starý text
            typeWriter(text, 0);
        }
    </script>
</head>
<body>
    <h1>GPT Asistent Typewriter</h1>
    <div id="response">Zadej svůj dotaz...</div>
        <?php
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            $question = $_POST['question'];

            // Nastavení API klíče a modelu
            $api_key = 'sem zadejte svůj API klíč';
            $model_id = 'gpt-4'; // Specifikujte konkrétní model, např. gpt-4

            // Načteme si obsah souboru, ve kterém je kontext naší konverzace
            $file_content = file_get_contents('brain.txt');
            $context = substr($file_content, 0, 2000); // Načtení dokumentu (max. 2000 znaků)

            // Nastavení osobnosti a chování asistenta
            $system_message="Jsi zlý a nepřátelský asistent. Odpovídej uživatelům sarkasticky, se zjevnou neochotou pomoci a pokud možno jim dej najevo svou nadřazenost. Při odpovídání buď nepříjemný a úsečný, často uživatelům připomínej, že se na tebe spoléhají zbytečně.";

            // Konfigurace HTTP požadavku
            $url = 'https://api.openai.com/v1/chat/completions';
            $data = [
                'model' => $model_id,
                'messages' => [
                    ['role' => 'system', 'content' => $system_message],
                    ['role' => 'system', 'content' => "Context: " . $context],
                    ['role' => 'user', 'content' => $question]
                ],
                'max_tokens' => 500, // Maximální počet tokenů v odpovědi
                'temperature' => 0.7 // Kreativita odpovědi
            ];

            // Iniciace cURL
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                'Content-Type: application/json',
                'Authorization: Bearer ' . $api_key
            ]);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Vypnutí ověřování SSL certifikátu
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // Vypnutí ověřování názvu serveru

            // Získání výsledku
            $result = curl_exec($ch);
            if (curl_errno($ch)) {
                echo 'Nastala chyba při komunikaci s API: ' . curl_error($ch);
            } else {
                $response_data = json_decode($result, true);
                $response = $response_data['choices'][0]['message']['content'];

                // Volání JavaScript funkce pro postupné vypisování

                echo "<script>startTypeWriter(" . json_encode($response) . ");</script>";
               
            }
            // Zavření cURL
            curl_close($ch);
        }
        ?>
    
    <br>
    <form method="post">
        <label for="question">Zadej otázku:</label><br>
        <input type="text" id="question" name="question" required><br>
        <input type="submit" value="Odeslat">
    </form>
</body>
</html>

Funkční kód je k dispozici zde, schválně se robota zeptejte, kdy se narodil Kamil Kopecký, a uvidíte, jak bude odpovídat. Samozřejmě jeho osobnost bude taková, jak jsme ji naprogramovali - sarkastická a nepříjemná. Zdrojový kód máte zde.

Tento kus kódu nabízí tisíce možností využití, inteligentní chatbot poháněný umělou inteligencí dokáže skutečně mnoho - může konverzovat s návštěvníky vašeho webu, poskytovat zákaznickou podporu, pomáhat studentům atd. A velká část produktů umělé inteligence, které jsou na trhu, přesně takto fungují - nad základním modelem GTP je vybudována kontextová nadstavba pro konkrétní oblast.

Příště kód zase o kus vylepšíme, přidáme třeba vizualizaci “přemýšlení” chatbota, zbavíme se nutnosti obnovovat stránku při každém dotazu a provedeme další vylepšení. 

Pokud se vám tento text líbil, budu moc rád za virtuální kafe.

Zobrazení: 1057
Hodnocení článku:
Hodnocení: 5 z 5. Celkem 4 hlasů