Skip to content

Commit

Permalink
initial code for OpenAI Realtime API
Browse files Browse the repository at this point in the history
  • Loading branch information
OvidijusParsiunas committed Jan 12, 2025
1 parent 256424c commit c8962ce
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 1 deletion.
3 changes: 2 additions & 1 deletion component/src/services/openAI/openAIChatIO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,5 +180,6 @@ export class OpenAIChatIO extends DirectServiceIO {
throw e;
}
}
throw Error(OpenAIUtils.FUNCTION_TOOL_RESP_ERROR);}
throw Error(OpenAIUtils.FUNCTION_TOOL_RESP_ERROR);
}
}
75 changes: 75 additions & 0 deletions component/src/services/openAI/openAIRealtimeIO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {DirectConnection} from '../../types/directConnection';
import {DirectServiceIO} from '../utils/directServiceIO';
import {ChatFunctionHandler} from '../../types/openAI';
import {OpenAIUtils} from './utils/openAIUtils';
import {DeepChat} from '../../deepChat';

export class OpenAIRealtimeIO extends DirectServiceIO {
override insertKeyPlaceholderText = 'OpenAI API Key';
override keyHelpUrl = 'https://platform.openai.com/account/api-keys';
url = 'https://api.openai.com/v1/chat/completions';
permittedErrorPrefixes = ['Incorrect'];
_functionHandler?: ChatFunctionHandler;
asyncCallInProgress = false; // used when streaming tools

constructor(deepChat: DeepChat) {
const directConnectionCopy = JSON.parse(JSON.stringify(deepChat.directConnection)) as DirectConnection;
const apiKey = directConnectionCopy.openAI;
super(deepChat, OpenAIUtils.buildKeyVerificationDetails(), OpenAIUtils.buildHeaders, apiKey);
this.maxMessages ??= -1;
this.rawBody.model ??= 'gpt-4o';
this.init();
}

private async init() {
// Get an ephemeral key from your server - see server code below
// const tokenResponse = await fetch('/session');
// const data = await tokenResponse.json();
const EPHEMERAL_KEY = 'key';

// Create a peer connection
const pc = new RTCPeerConnection();

// Set up to play remote audio from the model
const audioEl = document.createElement('audio');
audioEl.autoplay = true;
pc.ontrack = (e) => (audioEl.srcObject = e.streams[0]);

// Add local audio track for microphone input in the browser
const ms = await navigator.mediaDevices.getUserMedia({
audio: true,
});
pc.addTrack(ms.getTracks()[0]);

// Set up data channel for sending and receiving events
const dc = pc.createDataChannel('oai-events');
dc.addEventListener('message', (e) => {
// Realtime server events appear here!
const response = JSON.parse(e.data);
if (response.type === 'response.audio_transcript.delta') {
console.log(response.delta);
}
});

// Start the session using the Session Description Protocol (SDP)
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

const baseUrl = 'https://api.openai.com/v1/realtime';
const model = 'gpt-4o-realtime-preview-2024-12-17';
const sdpResponse = await fetch(`${baseUrl}?model=${model}`, {
method: 'POST',
body: offer.sdp,
headers: {
Authorization: `Bearer ${EPHEMERAL_KEY}`,
'Content-Type': 'application/sdp',
},
});

const answer: RTCSessionDescriptionInit = {
type: 'answer',
sdp: await sdpResponse.text(),
};
await pc.setRemoteDescription(answer);
}
}
4 changes: 4 additions & 0 deletions component/src/services/serviceIOFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {AzureTextToSpeechIO} from './azure/azureTextToSpeechIO';
import {AzureSpeechToTextIO} from './azure/azureSpeechToTextIO';
import {AzureTranslationIO} from './azure/azureTranslationIO';
import {AzureOpenAIChatIO} from './azure/azureOpenAIChatIO';
import {OpenAIRealtimeIO} from './openAI/openAIRealtimeIO';
import {OpenAIImagesIO} from './openAI/openAIImagesIO';
import {BaseServiceIO} from './utils/baseServiceIO';
import {OpenAIChatIO} from './openAI/openAIChatIO';
Expand Down Expand Up @@ -54,6 +55,9 @@ export class ServiceIOFactory {
if (directConnection.openAI.assistant) {
return new OpenAIAssistantIO(deepChat);
}
if (directConnection.openAI.realtime) {
return new OpenAIRealtimeIO(deepChat);
}
return new OpenAIChatIO(deepChat);
}
if (directConnection.assemblyAI) {
Expand Down
1 change: 1 addition & 0 deletions component/src/types/openAI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export type OpenAIChat = {
export interface OpenAI {
chat?: true | OpenAIChat;
assistant?: true | OpenAIAssistant;
realtime?: true;
images?: true | OpenAIImagesDalle2 | OpenAIImagesDalle3;
textToSpeech?: true | OpenAITextToSpeech;
speechToText?: true | OpenAISpeechToText;
Expand Down

0 comments on commit c8962ce

Please sign in to comment.