Of AI-oplossingen zoals ChatGPT de Turingtest kunnen doorstaan, staat nog steeds ter discussie. Destijds stelde Turing zich een menselijke operator voor die antwoorden op vragen die werden verzonden en ontvangen met behulp van een elektromechanische teletype-machine moest beoordelen. Hier bouwen we een 21e-eeuwse versie van Turing’s oorspronkelijke experimentele concept, waarbij we een ESP32 met toetsenbord en TFT-display gebruiken om exclusief met ChatGPT te communiceren via het internet. Bovendien kunt u met Google tekst-naar-spraak in combinatie met een kleine I2S-versterkermodule en luidspreker de conversatie beluisteren. In ons geval is het van meet af aan duidelijk dat we met een machine communiceren – toch?
 

Het lijdt geen twijfel dat AI-tools zoals OpenAI’s ChatGPT en Google’s Gemini in veel situaties een echte game changer kunnen zijn. Ik heb ChatGPT gebruikt om behoorlijk complexe besturingsoplossingen te ontwikkelen. Ik lever het initiële idee en naarmate ik meer input geef, verfijnt het de code en wordt deze met elke iteratie beter. Het kan zelfs Python-code omzetten naar MicroPython of een Arduino-sketch. De sleutel is om het proces zorgvuldig te begeleiden om te voorkomen dat het te ver afdwaalt. Er zijn momenten waarop het wel afwijkt en dezelfde fouten herhaalt, maar ik vind het eigenlijk wel leuk om deze fouten te vinden en de uitvoer van ChatGPT zo te sturen dat deze beter overeenkomt met wat ik wil.

AI terminal main
AI terminal

Hardware

Het hart van dit project is de ESP32-ontwikkelmodule van Espressif. Zijn dual-core architectuur heeft voldoende verwerkingsreserve om de WiFi-communicatie te verzorgen, de seriële invoer van een PS2-toetsenbord te verwerken, gegevens naar het 3,5-inch TFT-display te sturen en digitale audiogegevens naar de I2S-module te sturen. Het volledige schema van de ChatGPT-terminal is te zien in figuur 1.

Schematic of the talking ChatGPT AI terminal.
Figuur 1. Het schema van de sprekende ChatGPT-terminal.

U zult misschien verbaasd zijn over het gebruik van een oud PS2-toetsenbord; de enige reden is dat ik er niet in geslaagd ben om een USB-poort voor dit doel te implementeren op de ESP32. In de beperkte tijd die beschikbaar was, heb ik gekozen voor de eenvoudigere PS2-interface, die veel minder resources gebruikt. Een PS2-connector voor het toetsenbord kan worden gevonden bij verschillende distributeurs van elektronische componenten op het web. De pinning van het PS2-toetsenbord is te zien in het schema. Ongetwijfeld zullen er ontwikkelaars zijn die staan te popelen om het systeem te upgraden naar USB en ik verwelkom hun input.

Het gebruikte 3,5 inch TFT-aanraakdisplay heeft een parallelle interface in plaats van de meer gebruikelijke SPI-interface. Dit gebruikt onvermijdelijk meer verbindingen, maar in deze toepassing hebben we genoeg GPIO’s over en de interface reageert aanzienlijk sneller. De aanraakfunctionaliteit wordt in deze toepassing niet gebruikt.

The audio amp module converts I2S digital audio to 3◦W of audio.
Figuur 2. De audio-versterkermodule zet digitale I2S-signalen om in 3W-audio.

Een MAX98357A I2S-versterkermodule (figuur 2) zet het digitale I2S-audiosignaal van de ESP32 om in analoge audio. Een ingebouwde klasse D-versterker van 3 W versterkt het signaal om een goed geluidsniveau te bereiken. De versterkingsingang ligt aan massa, waardoor de versterker een maximaal volume produceert. De klasse D-versterkeruitgang kan een 4Ω-luidspreker aansturen.

Inschrijven
Schrijf u in voor tag alert e-mails over Embedded & AI!

Verlies de sleutel niet

ChatGPT is ontwikkeld door OpenAI. Het genereert op tekst gebaseerde antwoorden op prompts of vragen die door de gebruiker zijn ingevoerd. Meestal werkt het via een browserinterface. De OpenAI API is ontworpen voor gebruik door ontwikkelaars en bedrijven, zodat ze AI-functies kunnen integreren in hun eigen applicaties, software of websites. Het is niet alleen een chatbot-interface, maar een flexibele programmeerinterface waarmee bedrijven de mogelijkheden van chatGPT in hun producten kunnen integreren. Ontwikkelaars sturen gegevens programmatisch naar de API en krijgen antwoorden terug. Om de OpenAI API te gebruiken, hebt u een unieke sleutel nodig, die wordt gegenereerd voor uw account wanneer u zich aanmeldt. Ga naar de OpenAI-website en klik op de knop Sign up.

Vul het registratieformulier in met uw e-mailadres, wachtwoord en andere vereiste informatie. Zodra u dit hebt ingevuld, navigeert u naar het dashboard van uw OpenAI-account en klikt u op de knop New Project. Geef uw project een naam en beschrijving (optioneel). Klik in de projectinstellingen op het tabblad API Keys. U ziet een lijst met bestaande geheime sleutels (figuur 3). Klik op de knop Create new secret key om een nieuwe sleutel te genereren. Maak een kopie van deze gegenereerde API-sleutel en sla deze veilig op, omdat u deze om veiligheidsredenen niet nog een keer kunt ophalen. U hebt deze sleutel nodig om uw applicaties te authenticeren met de services van OpenAI. Op hun site staat ook een snelstartgids voor ontwikkelaars die u begeleidt bij het genereren van een antwoord via de API met behulp van de gegenereerde sleutel om uw toegang te autoriseren.

The OpenAI page to register for the OpenAI API.
Figuur 3. De OpenAI-pagina waar u zich kunt registreren voor de OpenAI-API.

Op het moment van schrijven biedt OpenAI gratis credits als u zich voor het eerst aanmeldt; u kunt die credits gebruiken om te experimenteren met de API. Nadat u al deze credits hebt verbruikt, moet u betalen op basis van uw gebruik. Als u nog geen betaalmethode hebt ingesteld om te factureren, moet u dat alsnog doen. Lees de gebruiksrichtlijnen en servicevoorwaarden van OpenAI door.

Tekst-naar-spraak

Een Text to Speech (TTS) API wordt gebruikt om de tekstuele respons van OpenAI om te zetten in een digitale audio-datastroom. Er bestaat een aantal tekst-naar-spraak API’s die we hiervoor kunnen gebruiken. OpenAI heeft zijn eigen TTS-API die een aantal verschillende stemalternatieven biedt die heel natuurlijk klinken. Om toegang te krijgen tot deze API gebruikt u dezelfde sleutel die u hebt gekregen om de OpenAI API te gebruiken.

Voor dit project maken we gebruik van de Google Cloud Text-to-Speech API. Deze biedt een breed scala aan stemmen in verschillende talen en dialecten. Vergeleken met OpenAI TTS klinken de stemmen iets mechanischer. Bij lange tekstreeksen valt de uitvoer uit elkaar. Deze API kan echter gratis worden gebruikt op het moment van schrijven, terwijl OpenAI TTS API kosten met zich meebrengt.

Om Google TTS te gaan gebruiken, moeten we eerst een project aanmaken op Google Cloud en de Google TTS-API inschakelen om onze API-sleutel te krijgen. Tekststrings kunnen nu samen met de sleutel naar de API worden gestuurd met een HTTP POST-request. De resulterende digitale I2S-audiostream wordt vervolgens opgeslagen en afgespeeld om een analoog audiosignaal te produceren via de MAX98357A.

Inschrijven
Schrijf u in voor tag alert e-mails over OpenAI!

Software: bibliotheken

De Arduino-sketch maakt deel uit van de download . Controleer alle bibliotheken waar in de header van de sketch naar wordt verwezen om er zeker van te zijn dat ze geïnstalleerd zijn in uw omgeving. Zo niet, installeer ze dan nu met behulp van de bibliotheekmanager van de Arduino IDE. Met behulp van de methoden in de Audio.h-bibliotheek was het een eenvoudige klus om de audio-uitvoer te produceren die de tekstuitvoer naar het TFT-display moet begeleiden. Het was alleen nodig om een paar regels in de loop toe te voegen om de audio te genereren. Bekijk dit in de Arduino sketch.

#include <PS2Keyboard.h>//Keyboard specific

#include <WiFi.h>

#include <HTTPClient.h>

#include <ArduinoJson.h>

#include <SPI.h>

#include <TFT_eSPI.h>// Hardware-specific library

#include "Audio.h"   //Audio header file

 

// GPIO connections to I2S board

#define I2S_DOUT  21

#define I2S_BCLK  22

#define I2S_LRC   23

Audio audio;  //audio instance creation

ArduinoJSON.h wordt gebruikt om de JSON-geformatteerde responsgegevens van de OpenAI API te ontleden tot een formaat dat kan worden gebruikt door de Arduino-code.

Software: ChatGPT API-request

De eigenlijke interactie met de OpenAI API zit in de functie makeApiRequest(String prompt1):

 

1. Eerst stellen we een HTTP client in:

 

HTTPClient http;

http.setTimeout(24000); // 24 seconds timeout

http.begin("https://api.openai.com/v1/chat/completions");

http.addHeader("Content-Type", "application/json");

http.addHeader("Authorization", "Bearer " +

                   String(api_key));

 

2. Bereid vervolgens de payload voor (alleen JSON-geformatteerd):

 

StaticJsonDocument<1024> jsonPayload; 

    // setting a maximum size of 1KB

jsonPayload["model"] = "gpt-3.5-turbo";    

    // model is gpt-3.5-turbo,

      // change if you have access to 4 or 4.5

jsonPayload["temperature"] = 0.8;

    // randomness of response, the higher

     // the value, the higher the randomness

jsonPayload["max_tokens"] = 2000;

    // maximum words & punctuations

    // limit to be generated by response

 

3. Bereid het bericht voor (een geneste array van berichten), serialiseer naar JSON-formaat en verzend het request:

 

JsonArray messages = jsonPayload.

    createNestedArray("messages"); 

    //put in a nested format not random

JsonObject userMessage = messages.createNestedObject();

userMessage["role"] = "user";

userMessage["content"] = prompt1;

String payloadString;

serializeJson(jsonPayload, payloadString);

 

4. Het request verzenden en het antwoord ontvangen:

 

int httpResponseCode = http.POST(payloadString);  

    //transfer to the open page

if (httpResponseCode == HTTP_CODE_OK) {  

  String response = http.getString();   

    // if everything goes OK get the

    // reply = output and put in a string

...

 

5. De webpagina zal over het algemeen een zondvloed aan ongewenste informatie bevatten (allemaal in HTML-code) die niet nuttig is voor onze toepassing en die verwijderd kan worden. Hier normaliseren we het antwoord – verwijderen de tags JSON enzovoort zodat het op het TFT-display weergegeven kan worden:

 

StaticJsonDocument<1024> jsonResponse; 

    //parse the tags etc of the response string.

deserializeJson(jsonResponse, response);

    // and put in a simple stripped string & return

String assistantReply = jsonResponse

    ["choices"][0]["message"]["content"].

    as<String>(); 

    // select the first part which contains our reply

return assistantReply;

 

Software: setup en loop

In de setup-functie initialiseren we het TFT-display en het I2S-board, met het internet verbonden via onze WiFi-gegevens.

 

void setup() {

  delay(300);

  …

  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);

//I2S board initialised

  audio.setVolume(50);

 

Binnen de loop-functie sturen we vragen naar ChatGPT. Wanneer de sessie is voltooid, blijven we in de loop:

 

String response = makeApiRequest(msg);

    // sent to Chatgpt

...

if (l1>200) {

  response = response.substring(0, 200);

    // truncate first 200 characters

}

audio.connecttospeech(response.c_str(), "en");

    //speak up the 200 characters

 

Google TTS heeft een limiet van 200 tekens en voert geen tekst uit die deze limiet overschrijdt. Om dit te omzeilen, wordt de antwoordstring voor Google TTS ingekort tot 200 tekens. Dit zorgt ervoor dat, terwijl het volledige antwoord wordt weergegeven op het scherm, alleen de eerste 200 tekens worden uitgesproken. Voor langere antwoorden scrolt het scherm, maar dit kan worden aangepast door kleine wijzigingen aan te brengen in de sketch.

Test van het project

De delays die ik heb gebruikt in de softwarelussen zijn vrij specifiek. U kunt ze aanpassen, maar ik raad aan om te beginnen met de standaardwaarden die in de code worden gebruikt. Als de antwoorden u eenmaal bevallen, kunt u ze aanpassen. Ik begon met eenvoudige vragen zoals “Wie ben je?”. ChatGPT reageerde adequaat door zich op het display te introduceren, terwijl de tekst ook duidelijk werd uitgesproken.

Vervolgens testte ik het systeem met vragen als: “Schrijf 5 zinnen over het tijdschrift Elektor” (figuur 4) en vroeg het zelfs om blink-sketches te schrijven voor Arduino UNO, ESP32 en Raspberry Pi Pico.

Testing the system with prompts asking for blink sketches for Arduino UNO, ESP32, and Raspberry Pi Pico.
Figuur 4. Test van het systeem met vragen om blink-sketches voor Arduino UNO, ESP32 en Raspberry Pi Pico.

Telkens presteerde ChatGPT vlekkeloos, begreep de context perfect en gaf een accuraat antwoord, waarbij de luidspreker de spraakuitvoer luid en duidelijk liet horen.

Samenvattend

Alle bestanden die bij dit project horen, zijn te vinden op . Het internet en webbrowsers zoals Google hebben een revolutie teweeggebracht in onze toegang tot informatie en hebben de lijvige encyclopedieën vervangen die vroeger thuis in de boekenkast stonden. Nu zien we de opkomst van AI-software en -machines gebaseerd op ChatGPT API, TensorFlow Lite Micro, Edge Impulse, OpenMV en TinyML, die klaar staan om bestaande bedrijfsmodellen en meer traditionele methoden voor het oplossen van problemen overhoop te gooien. We leven in interessante tijden.


Vragen of opmerkingen?

Hebt u technische vragen of opmerkingen naar aanleiding van dit artikel? Stuur een e-mail naar de auteur via berasomnath@gmail.com of naar de redactie van Elektor via redactie@elektor.com.


Dit artikel (230536-03) verschijnt in de bonuseditie van AI 2024 van Elektor.


Inschrijven
Schrijf u in voor tag alert e-mails over Espressif!