Noch immer wird darüber diskutiert, ob KI-Lösungen wie ChatGPT den Turing-Test bestehen können. Turing stellte sich einen menschlichen Operator vor, der die Antworten auf Fragen bewertet, die mit einem elektromechanischen Fernschreiber gesendet und empfangen werden. Hier bauen wir eine Version von Turings ursprünglichem experimentellem Konzept für das 21. Jahrhundert, indem wir ein ESP32-Board mit Tastatur und TFT-Bildschirm ausstatten, um ausschließlich mit ChatGPT über das Internet zu kommunizieren. Zusätzlich ermöglicht Google Text-to-Speech in Verbindung mit einem winzigen I2S-Verstärkermodul und einem Lautsprecher das Mithören der Konversation. In unserem Fall ist es natürlich von Anfang an klar, dass wir mit einer Maschine kommunizieren. Oder?

Es besteht kein Zweifel daran, dass KI-Tools wie ChatGPT von OpenAI und Gemini von Google in vielen Situationen echte Killerapplikationen sein können. Ich habe zum Beispiel mit ChatGPT ziemlich komplexe Steuerungslösungen entwickelt, wobei ich die anfängliche Idee lieferte, und wenn ich weitere Eingaben machte, verfeinerte ChatGPT den Code und machte ihn mit jeder Iteration besser. ChatGPT kann sogar Python-Code in MicroPython oder einen Arduino-Sketch umwandeln. Der Knackpunkt liegt darin, den Prozess sorgfältig zu steuern, damit er nicht zu weit vom Kurs abweicht. Manchmal kommt dies vor und ChatGPT wiederholt dieselben Fehler, aber es macht mir Spaß, diese Fehler zu finden und die Ausgabe von ChatGPT so zu steuern, dass sie meinem Ziel näher kommt.

KI-Terminal

Hardware

Herzstück dieses Projekts ist das ESP32-Entwicklungsmodul von Espressif. Seine Dual-Core-Architektur ist leistungsfähig genug, um die WLAN-Kommunikation zu übernehmen, die serielle Eingabe einer PS2-Tastatur zu verarbeiten, Daten an das 3,5-Zoll-TFT-Display zu senden und digitale Audiodaten an das I2S-Modul auszugeben. Der vollständige Schaltplan des ChatGPT-Terminals ist in Bild 1 dargestellt.

Bild 1. Schema des sprechenden ChatGPT-Terminals.

Sie werden sich vielleicht über die alte PS2-Tastatur wundern; der einzige Grund dafür ist, dass es mir nicht gelungen ist, für diesen Zweck einen USB-Anschluss auf dem ESP32 zu implementieren. In der begrenzten Zeit, die mir zur Verfügung stand, habe ich mich für die einfachere PS2-Schnittstelle entschieden, die weit weniger Ressourcen verbraucht. Einen PS2-Adapter für eine USB-Tastatur kann man problemlos im nächsten Elektronikladen kaufen. Die PS2-Pinbelegung lässt sich dem Schaltplan entnehmen. Sicherlich wird es Entwickler geben, die das System auf USB aufrüsten wollen und werden und ich freue mich über deren Beiträge.

Das verwendete 3,5-Zoll-TFT-Touch-Display hat statt eines SPI-Anschlusses eine parallele Schnittstelle. Dadurch werden zwar zwangsläufig mehr Verbindungen benötigt, aber in dieser Anwendung haben wir genügend freie GPIOs und eine parallele Schnittstelle bietet eine deutlich schnellere Reaktionszeit. Die Touchscreen-Funktionen des Displays werden in dieser Anwendung nicht genutzt.

Bild 2. Das 3-W-Audioverstärkermodul wandelt das digitales I2S- in ein kräftiges analoges Audiosignal um.

Ein I2S-Verstärkermodul MAX98357A (Bild 2) verwandelt das vom ESP32 erzeugte digitale I2S-Audiosignal in analoges Audio. Der integrierte Klasse-D-Verstärker verstärkt das Signal auf einen ausreichenden Pegel von 3 W, um einen 4-Ω-Lautsprecher ansteuern. Der GAIN-Eingang des Verstärkermoduls ist mit Masse verbunden, so dass die maximale Verstärkung (= Lautstärke) erreicht wird.

Abonnieren
Tag-Benachrichtigung zu Embedded & AI jetzt abonnieren!

Verlieren Sie den Schlüssel nicht!

ChatGPT von OpenAI erzeugt textbasierte Antworten auf Aufforderungen oder Fragen, die vom Benutzer eingegeben werden. Normalerweise funktioniert dies über eine Browserschnittstelle. Für Entwickler und Unternehmen wurde die OpenAI-API entwickelt, damit die KI-Funktionen in eigene Anwendungen, Software oder Websites integriert werden können. Es handelt sich nicht nur um eine Chatbot-Schnittstelle, sondern um eine flexible Programmierschnittstelle, die es Unternehmen ermöglicht, die Fähigkeiten von ChatGPT in ihre Produkte einzubinden. Entwickler senden programmgesteuert Daten an die API und erhalten Antworten zurück. Um die OpenAI-API zu nutzen, benötigt man einen eindeutigen Schlüssel, der für Ihr Konto generiert wird und mit dem Sie sich anmelden. Rufen Sie dazu die OpenAI-Website auf und klicken Sie auf Sign up.

Füllen Sie das Anmeldeformular mit Ihrer E-Mail-Adresse, Ihrem Passwort und anderen erforderlichen Informationen aus. Sobald Sie diese Informationen eingegeben haben, navigieren Sie zum Dashboard Ihres OpenAI-Kontos und klicken Sie auf die New Project. Geben Sie Ihrem Projekt einen Namen und (optional) eine Beschreibung. Klicken Sie in Ihren Projekteinstellungen auf den Tab API Keys. Es wird eine Liste der vorhandenen geheimen Schlüssel angezeigt (Bild 3). Klicken Sie auf die Schaltfläche Create new secret key, um einen neuen Schlüssel zu erzeugen. Erstellen Sie eine Kopie dieses API-Schlüssels und speichern Sie ihn sicher (ganz altmodisch auch auf einem Zettel), da Sie ihn aus Sicherheitsgründen nicht wieder abrufen können. Sie benötigen diesen Schlüssel, um Ihre Anwendungen bei den Diensten von OpenAI zu authentifizieren. Auf der Website von OpenAI gibt es ein Schnellstart-Tutorial für Entwickler, das Sie durch den Prozess der Generierung einer Antwort über die API unter Verwendung des generierten Schlüssels zur Autorisierung Ihres Zugangs führt.

Bild 3. Die OpenAI-Webseite zur Registrierung für die OpenAI-API.

Als dieser Artikel geschrieben wurde, stellte OpenAI bei der ersten Anmeldung kostenlose „Credits“ zur Verfügung, mit denen Sie die API ausprobieren können. Wenn diese Credits aufgebraucht sind, müssen Sie für die Nutzung bezahlen. Wenn Sie noch keine Zahlungsmethode eingerichtet haben, müssen Sie dies tun. Lesen Sie dazu die OpenAI-Nutzungsrichtlinien und -bedingungen.

Text to Speech

Eine Text-to-Speech-API (TTS) wird verwendet, um die Textantwort von OpenAI in einen digitalen Audiodatenstrom zu konvertieren. Es gibt eine Reihe von Text-to-Speech-APIs, die wir dafür verwenden können. OpenAI verfügt über eine eigene TTS-API, die eine Reihe verschiedener Sprachalternativen bietet, die recht natürlich klingen. Um auf diese API zuzugreifen, verwenden Sie denselben Schlüssel, den Sie für die Nutzung der OpenAI-API erhalten haben.

Für dieses Projekt nutzen wir die Text-to-Speech-API der Google Cloud. Sie bietet eine breite Palette von Stimmen in verschiedenen Sprachen und Dialekten. Im Vergleich zu OpenAI-TTS klingen die Stimmen zwar ein wenig mechanischer, und bei langen Textstrings bricht die Ausgabe ab, aber die Nutzung dieser API ist zur Zeit kostenlos, ganz im Gegensatz zur API von OpenAI.

Um Google-TTS zu verwenden, müssen wir zunächst ein Projekt auf Google Cloud erstellen und die Google-TTS-API aktivieren, um einen API-Schlüssel zu erhalten. Die Textstrings können nun mit einer HTTP-POST-Anfrage zusammen mit dem Schlüssel an die API gesendet werden. Der resultierende digitale I2S-Audiostream wird dann gespeichert und wiedergegeben, um über den MAX98357A ein analoges Audiosignal zu erzeugen.

Abonnieren
Tag-Benachrichtigung zu OpenAI jetzt abonnieren!

Software: Bibliotheken

Der Arduino-Sketch ist unter abrufbar. Überprüfen Sie, ob alle Bibliotheken in Ihrer Entwicklungsumgebung installiert sind, auf die im Header des Sketches verwiesen wird. Falls dies nicht der Fall sein sollte, installieren Sie sie jetzt mit dem Bibliotheksmanager der Arduino-IDE. Mit den Methoden der Bibliothek Audio.h war es eine einfache Aufgabe, die Audioausgabe zu erzeugen, die die Textausgabe auf dem TFT-Display begleitet. Es war nur notwendig, ein paar Zeilen in der Schleife hinzuzufügen, um den Ton zu erzeugen. Schauen Sie sich das im Arduino-Sketch an:

#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 parst die JSON-formatierten Antwortdaten der OpenAI-API in ein Format, das vom Arduino-Code verwendet werden kann.

Software: ChatGPT-API-Anfrage

Die Interaktion mit der OpenAI-API ist in der Funktion makeApiRequest(String prompt1) enthalten:

1. Zuerst richten wir einen HTTP client ein:

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. Als Nächstes bereiten wir die Nutzdaten (Payload) im JSON-Format vor:

 

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. Bereiten Sie die Nachricht (ein verschachteltes Array von Nachrichten) vor, serialisieren Sie sie im JSON-Format und senden Sie die Anfrage:

 

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. Senden Sie die Anfrage und empfangen Sie die Antwort:

 

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. Die Webseite enthält in der Regel einen Dschungel von überflüssigen Informationen (im HTML-Code), die für unsere Anwendung nicht nützlich sind und entfernt werden können. Wir normalisieren die Antwort, indem wir JSON-Tags und Ähnliches entfernen, damit sie auf dem TFT-Display gelesen werden kann:

 

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: Einrichtung und Schleife

In der setup-Funktion werden das TFT-Display, das I2S-Board und die WLAN-Anmeldedaten (Verbindung mit dem Internet) initialisiert.

 

void setup() {

  delay(300);

  …

  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);

//I2S board initialised

  audio.setVolume(50);

 

In der loop-Funktion haben wir Fragen an ChatGPT gesendet. Wenn die Sitzung beendet ist, bleiben wir in der 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 hat ein Limit von 200 Zeichen und gibt, wenn dieses Limit überschritten wird, gar keinen Text mehr aus. Um dieses Problem zu umgehen, wird der Antwortstring für Google-TTS auf 200 Zeichen gekürzt. So wird stets die vollständige Antwort auf dem Bildschirm angezeigt, aber nur die ersten 200 Zeichen gesprochen. Bei längeren Antworten scrollt der Bildschirm, was aber durch kleine Änderungen im Sketch geändert werden kann.

Projekt-Tests

Die Verzögerungen, die ich in den Software-Schleifen verwendet habe, sind ziemlich spezifisch. Sie können sie anpassen, aber ich empfehle, mit den im Code verwendeten Standardwerten zu beginnen. Wenn Sie mit den Antworten zufrieden sind, können Sie sie ändern. Ich habe mit einfachen Fragen wie „Who r u?“ begonnen. ChatGPT reagierte angemessen, indem es die Einleitung auf dem Bildschirm anzeigte, während der Sprecher sie deutlich artikulierte.

Dann testete ich das System mit Fragen wie „Write 5 sentences about Elektor magazine“ (Bild 4) und beauftragte ChatGPT anschließend, Blink-Sketches für Arduino UNO, ESP32 und Raspberry Pi Pico zu schreiben.

Bild 4. Testen des Systems mit Aufforderungen zur Eingabe von Blink-Sketches für Arduino UNO, ESP32 und Raspberry Pi Pico.

In jedem Fall funktionierte ChatGPT einwandfrei, verstand den Kontext perfekt und antwortete präzise, wobei die Sprache laut und deutlich wiedergegeben wurde.

Zum Abschluss

Alle Dateien zu diesem Projekt finden Sie unter . Das Internet und Webbrowser wie Google haben unseren Zugang zu Informationen völlig revolutioniert und die sperrigen Enzyklopädien und Lexika ersetzt, die früher unsere Bücherregale zu Hause füllten. Jetzt erleben wir den Aufstieg von KI-Software und Maschinen auf der Grundlage von ChatGPT-API, TensorFlow Lite Micro, Edge Impulse, OpenMV, TinyML, die sich anschicken, bestehende Geschäftsmodelle und traditionellere Methoden der Problemlösung abzulösen. Wir leben in spannenden Zeiten!


Sie haben Fragen oder Kommentare?

Wenn Sie technische Fragen oder Anmerkungen zu diesem Artikel haben, wenden Sie sich bitte per E-Mail an den Autor unter berasomnath@gmail.com oder an die Elektor-Redaktion unter redaktion@elektor.de.


Dieser Artikel (230536-02) erscheint in der als Gast herausgegebenen AI 2024 Bonusausgabe von Elektor.


Abonnieren
Tag-Benachrichtigung zu Espressif jetzt abonnieren!