
Teilen Sie:
Hamza ist ein Software-Ingenieur aus Chicago. Er arbeitet bei Webrtc.ventures, einem führenden Unternehmen, das WebRTC-Lösungen anbietet. Er arbeitet auch als Full-Stack-Entwickler bei Vonage und hilft bei der Video-Plattform, um die Bedürfnisse der Kunden besser zu erfüllen. Als stolzer Introvertierter verbringt er seine freie Zeit am liebsten mit seinen Katzen.
Verbessern Sie Videokonferenzen mit ChatGPT: Treffen Sie Ihren Live-KI-Assistenten
Lesedauer: 6 Minuten
Einführung
Die Technologie, insbesondere die künstliche Intelligenz, hat die Art und Weise verändert, wie wir online sprechen und arbeiten. Da sich die Welt zunehmend auf Online-Interaktionen über Webinare, Konferenzen und persönliche Treffen verlagert, besteht ein unbestreitbarer Bedarf an einem Tool, das die Produktivität dieser virtuellen Zusammenkünfte steigern kann.
Stellen Sie sich vor: ein KI-Assistent, der Ihnen bei diesen virtuellen Treffen zur Seite steht, um Fragen zu beantworten, Notizen zu Maßnahmen zu machen und wichtige Informationen in prägnanten Zusammenfassungen zusammenzufassen. Heute entwickeln wir einen solchen Assistenten, der sich in erster Linie auf Einzelgespräche konzentriert. Die Möglichkeiten sind jedoch grenzenlos, da dieses Konzept auf viele Szenarien anwendbar ist. Lassen Sie uns also ohne weiteres "Sushi" bauen!
Hier finden Sie ein Video-Demo:
Voraussetzungen
A Vonage API-Konto. Greifen Sie auf Ihr Vonage API Dashboard zu, um Ihren API-Schlüssel und Ihr API-Geheimnis zu finden.
Ein OpenAI Account und API-Geheimnis
Node 16.20.1+
npm
Um die Anwendung auf Ihrem Rechner einzurichten, klonen Sie zunächst das Repo.
git clone https://github.com/hamzanasir/vonage-openai-demoWechseln Sie nun in das Repository und installieren Sie die zugehörigen Pakete über:
npm installJetzt müssen wir unseren Vonage-API-Schlüssel und -Geheimnis einrichten. Beginnen wir mit dem Kopieren der .env-Vorlage:
cp .envcopy .envJetzt müssen Sie nur noch den API-Schlüssel und das Geheimnis in der .env-Datei durch Ihre Anmeldedaten ersetzen. Sie finden Ihren API-Schlüssel und Ihr Geheimnis auf der Projektseite Ihres Vonage Video API Accounts (https://tokbox.com/account). Ihre .env-Datei sollte wie folgt aussehen:
# enter your TokBox API key after the '=' sign below
TOKBOX_API_KEY=your_api_key
# enter your TokBox api secret after the '=' sign below
TOKBOX_SECRET=your_project_secretAußerdem müssen Sie ein OpenAI-Projekt erstellen. Dies können Sie tun, indem Sie zu https://platform.openai.com/signup. Sobald Sie sich angemeldet haben, können Sie im Abschnitt API-Schlüssel einen neuen geheimen Schlüssel erstellen.

Fügen Sie Ihren geheimen Schlüssel in die .env-Datei ein.
# enter your OpenAI Secret after the '=' sign below
OPENAI_SECRET=your_openai_secretWenn das erledigt ist, können Sie die App mit starten:
npm startGehen Sie jetzt auf http://localhost:8080/. Um das Gespräch mit Sushi zu beginnen, klicken Sie auf die Schaltflächen zum Starten der Untertitel unten links, um den Live Caption Service von Vonage zu starten. Stellen Sie sicher, dass Sie Kopfhörer tragen, damit die Stimme von Sushi nicht auf das Mikrofon des Herausgebers übertragen wird.
Der gesamte Code, über den wir in diesem Blog sprechen, findet sich in der public/js/app.js Datei. Wenn Sie wissen wollen, wie Live-Untertitel funktionieren, sollten Sie sich die Datei routes/index.js Datei, um zu sehen, wie der Untertitel-Dienst startet und stoppt.
Hochrangige Architektur
Um das Innenleben unseres virtuellen Assistenten zu verstehen, müssen wir uns mit seinem architektonischen Rahmen befassen.

Das Herzstück dieser Einrichtung ist die Verwaltung von Benutzergesprächen und Interaktionen mit der API von OpenAI. Wir haben uns für das GPT-3.5-Turbo-Modell von OpenAI entschieden, das sich hervorragend für die Verwaltung von Konversationen eignet. OpenAI bietet jedoch eine Vielzahl von Modellen an, um Ihren spezifischen Projektzielen gerecht zu werden.
Wenn wir eine Anfrage an GPT senden, braucht es einen Moment, um eine Antwort zu erstellen. Lassen Sie uns einen dynamischeren Ansatz wählen. Wir streamen die Daten, während sie generiert werden, und sorgen so für ein schnelleres und natürlicheres Gesprächserlebnis. Dieser Ansatz ermöglicht es den Nutzern auch, die Konversation zu unterbrechen und zu lenken, und ahmt so die Interaktion im echten Leben nach.
Während GPT seine Antwort formuliert, wandeln wir den generierten Text mithilfe eines Sprachsynthesizers in hörbare Sprache um. Zu diesem Zweck stehen verschiedene Optionen zur Verfügung, darunter auch kostenpflichtige Sprachsynthesizer von Drittanbietern, die eine natürlicher klingende Stimme liefern können. Für unser Projekt haben wir uns für das browserinterne Modul SpeechSynthesisUtterance entschieden. Um Unterbrechungen durch den sprechenden Benutzer zu verwalten, werden wir den AbortController des Browsers verwenden.
Veröffentlichen und Abonnieren von Beschriftungen
Lassen Sie uns einen Blick darauf werfen, wie wir unseren Untertitelungsdienst, eine zentrale Komponente unseres Systems, initiieren und verwalten.
Zu Beginn starten wir den Untertitelungsdienst, indem wir unseren Server per POST unter /captions/start aufrufen und ihm unsere Sitzungs-ID mitteilen. Damit sind wir bereit, Untertitel für alle Abonnenten in der Sitzung zu empfangen. Wir möchten jedoch auch unsere eigenen Beschriftungen als Herausgeber generieren. Um dies zu erreichen, abonnieren wir unseren eigenen Herausgeber mit einer Lautstärke von Null, um sicherzustellen, dass wir keine Wiederholung unserer eigenen Stimme erhalten.
Hier ist ein Ausschnitt aus dem Code, der dies ermöglicht:
const publisherOptions = {
insertMode: 'append',
width: '100%',
height: '100%',
publishCaptions: true,
};
publisher = OT.initPublisher('publisher', publisherOptions, (err) => {
if (err) {
handleError(err);
} else {
session.publish(publisher, () => {
if (error) {
console.error(error);
} else {
const captionOnlySub = session.subscribe(
publisher.stream,
document.createElement('div'),
{
audioVolume: 0
},
);
speakText(greetingMessage);
captionOnlySub.on('captionReceived', async (event) => {
if (event.isFinal) {
stopAiGenerator();
startAiGenerator(event.caption)
}
});
}
});
}
});
In diesem Code veröffentlichen wir unser Audio und Video in der Sitzung und abonnieren dann dieselbe Instanz, um unsere Untertitel zu empfangen. Damit dieser Prozess nahtlos funktioniert, fügen wir unserem Mock-Abonnenten einen Event-Handler "captionReceived" hinzu. Dieser Event-Handler erfasst die Transkription unserer Rede, während wir sprechen. Da dieses Ereignis in der Regel in regelmäßigen Abständen ausgelöst wird, wenn wir sprechen, verwenden wir den Booleschen Wert "isFinal", um zu erkennen, wann wir mit dem Sprechen fertig sind. Sobald unser generierter Text fertig ist, übergeben wir ihn an unseren startAiGenerator zur weiteren Verarbeitung.
Antworten generieren
Das Rückgrat unserer Logik liegt in der Funktion startAiGenerator. Da es sich um eine umfangreiche Funktion handelt, sollten wir sie in überschaubare Teile zerlegen. Schauen wir uns zunächst die Logik für API-Aufrufe genauer an:
async function startAiGenerator(message) {
let aiText = '';
let utterableText = ''
abortController = new AbortController();
const userMessage = {
'role': 'user',
'content': message
}
const reqBody = {
messages: [...messages, userMessage],
temperature: 1,
max_tokens: 256,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0,
model: 'gpt-3.5-turbo',
stream: true
};
try {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
headers: {
'Authorization': `Bearer ${openAISecret}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(reqBody),
method: 'POST',
signal: abortController.signal
});In diesem Schnipsel haben wir zwei Variablen, aiText und utterableText. aiText speichert die vollständige Antwort auf unsere Anfrage, während utterableText den letzten vollständigen Satz oder die letzte vollständige Phrase aus dem lesbaren Datenstrom von OpenAI erfasst. Wir richten auch eine AbortController-Instanz ein, um Benutzerunterbrechungen zu behandeln, während der Assistent spricht. Bevor wir den KI-Generator starten, wird eine separate Funktion, stopAiGenerator(), aufgerufen, um einen laufenden KI-Generierungsprozess anzuhalten.
function stopAiGenerator() {
if (abortController) {
abortController.abort();
abortController = null;
}
window.speechSynthesis.cancel();
}Schließlich rufen wir OpenAI mit dem Verlauf der Unterhaltungen auf, die im globalen Nachrichten-Array gespeichert sind. Werfen wir nun einen Blick darauf, wie wir Daten von OpenAI streamen:
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
while (true) {
const chunk = await reader.read();
const { done, value } = chunk;
if (done) {
break;
}
const decodedChunk = decoder.decode(value);
const lines = decodedChunk.split('\n');
const parsedLines = lines
.map(l => l.replace(/^data: /, '').trim())
.filter(l => l !== '' && l !== '[DONE]')
.map(l => JSON.parse(l));
for (const line of parsedLines) {
const textChunk = line?.choices[0]?.delta?.content;
if (textChunk) {
utterableText += textChunk
if (textChunk.match(/[.!?:,]$/)) {
speakText(utterableText);
utterableText = '';
}
aiText += textChunk;
}
}
}
In diesem Segment starten wir das Lesegerät aus dem Fetch-Objekt, das wir zur Anforderung von GPT verwendet haben. Wir verwenden eine while-Schleife, um kontinuierlich aus dem Stream zu lesen, bis er leer ist. Jedes Textstück wird an die beiden zuvor definierten Variablen angehängt. Wenn ein Textabschnitt ein Satzzeichen enthält, lösen wir die Funktion speakText() aus, die den zuletzt erzeugten Satz oder die zuletzt erzeugte Phrase vokalisiert und utterableText auf eine leere Zeichenfolge zurücksetzt. Denken Sie daran, dass dieser Prozess jederzeit durch ein Stop-Signal von unserem AbortController gestoppt werden kann.
Schließlich speichern wir sowohl die Eingaben des Benutzers als auch die Antwort von OpenAI wie folgt, unabhängig davon, ob wir den Stream beenden oder ihn zu Ende laufen lassen:
messages.push(userMessage);
messages.push({
content: aiText,
role: 'assistant'
}) Ein Wort zu Prompt Engineering
"Prompt-Engineering" bei der Verarbeitung natürlicher Sprache beinhaltet die Erstellung von Anweisungen oder Fragen zur Steuerung von KI-Modellen. Es geht darum, das richtige Gleichgewicht zwischen Klarheit und Zweideutigkeit zu finden, um bestimmte Ergebnisse zu erzielen. Mit dem richtigen Prompt-Engineering können Sie Sushi in einen fiktiven Rechtsberater, medizinischen Experten, frechen Freund usw. verwandeln. Für diese Demo verwenden wir diesen Prompt:
const messages = [
{
'role': 'system',
'content': "You are a participant called Sushi in a live call with someone. Speak concisely, as if you're having a one-on-one conversation with someone. " // Prompt engineering for AI assistant
}
];Versuchen Sie, den Inhalt dieses Codes zu ändern, um zu sehen, wie sich der Assistent verhält!
Sprachsynthese
Dieser Teil des Projekts bietet Raum für Flexibilität. Sie können sich für natürlichere, fortschrittlichere Lösungen für die Sprachsynthese entscheiden. Die meisten davon werden kostenpflichtig sein, daher entscheiden wir uns in dieser Demo für die Standardfunktionalität SpeechSynthesisUtterance des Browsers.
function speakText(text) {
let captions = '';
const utterThis = new SpeechSynthesisUtterance(text);
utterThis.voice = voices.find((v) => v.name.includes('Samantha'));
utterThis.onboundary = (event) => {
captions += `${event.utterance.text.substring(event.charIndex, event.charIndex + event.charLength)} `;
displayCaptions(captions, 'ai-assistant');
};
utterThis.onstart = () => {
animateVoiceSynthesis();
};
utterThis.onend = function() {
stopAnimateVoiceSynthesis();
};
window.speechSynthesis.speak(utterThis);
}
Zuerst initialisieren wir also das Modul SpeechSynthesisUtterance mit dem Text, den wir aussprechen wollen. Danach müssen wir eine vom Browser verfügbare Voice einstellen. Diese werden asynchron wie folgt geladen:
let voices = window.speechSynthesis.getVoices();
if (speechSynthesis.onvoiceschanged !== undefined)
speechSynthesis.onvoiceschanged = updateVoices;
function updateVoices() {
voices = window.speechSynthesis.getVoices();
}Wir verwenden die onstart und onend Ereignisse, um die Balken in der Mitte zu animieren, um zu zeigen, wann Sushi spricht. Außerdem wird das Ereignis onboundary verwendet, um Textbeschriftungen einzufügen, die anzeigen, welches Wort der Sprachsynthesizer gerade spricht.
Schlussfolgerung
Es ist wichtig zu beachten, dass dies nur ein Beispiel dafür ist, was Sie mit einer Integration mit GPT machen können. Der Zweck dieser Demo ist es zu zeigen, wie Sie die Pipeline zwischen Vonage Video Live-Untertiteln und OpenAI erstellen können, aber mit fachmännisch ausgearbeiteten Prompts sind der Fantasie keine Grenzen gesetzt.
Sehen Sie sich den Beispiel-Abschnitt von GPT um die unendlich vielen Anwendungen zu sehen. Wir können es kaum erwarten, zu sehen, was Sie kreieren werden!
Lassen Sie uns wissen, was Sie mit Vonage Video API entwickeln. Chatten Sie mit uns in unserer Vonage-Gemeinschaft Slack oder X, früher bekannt als Twitter, @VonageDev.
Teilen Sie:
Hamza ist ein Software-Ingenieur aus Chicago. Er arbeitet bei Webrtc.ventures, einem führenden Unternehmen, das WebRTC-Lösungen anbietet. Er arbeitet auch als Full-Stack-Entwickler bei Vonage und hilft bei der Video-Plattform, um die Bedürfnisse der Kunden besser zu erfüllen. Als stolzer Introvertierter verbringt er seine freie Zeit am liebsten mit seinen Katzen.