@livekit/agents-plugin-openai 0.7.1 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/llm.cjs +4 -2
- package/dist/llm.cjs.map +1 -1
- package/dist/llm.d.ts +2 -1
- package/dist/llm.d.ts.map +1 -1
- package/dist/llm.js +4 -2
- package/dist/llm.js.map +1 -1
- package/dist/models.cjs.map +1 -1
- package/dist/models.d.ts +1 -1
- package/dist/models.d.ts.map +1 -1
- package/dist/realtime/realtime_model.cjs +61 -1
- package/dist/realtime/realtime_model.cjs.map +1 -1
- package/dist/realtime/realtime_model.d.ts +2 -0
- package/dist/realtime/realtime_model.d.ts.map +1 -1
- package/dist/realtime/realtime_model.js +62 -1
- package/dist/realtime/realtime_model.js.map +1 -1
- package/dist/stt.cjs +2 -1
- package/dist/stt.cjs.map +1 -1
- package/dist/stt.d.ts +2 -1
- package/dist/stt.d.ts.map +1 -1
- package/dist/stt.js +2 -1
- package/dist/stt.js.map +1 -1
- package/dist/tts.cjs +18 -8
- package/dist/tts.cjs.map +1 -1
- package/dist/tts.d.ts +3 -1
- package/dist/tts.d.ts.map +1 -1
- package/dist/tts.js +18 -8
- package/dist/tts.js.map +1 -1
- package/package.json +2 -2
- package/src/llm.ts +4 -1
- package/src/models.ts +1 -0
- package/src/realtime/realtime_model.ts +68 -0
- package/src/stt.ts +2 -1
- package/src/tts.ts +22 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/realtime/realtime_model.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport {\n AsyncIterableQueue,\n Future,\n Queue,\n llm,\n log,\n mergeFrames,\n multimodal,\n} from '@livekit/agents';\nimport { AudioFrame } from '@livekit/rtc-node';\nimport { once } from 'node:events';\nimport { WebSocket } from 'ws';\nimport * as api_proto from './api_proto.js';\n\ninterface ModelOptions {\n modalities: ['text', 'audio'] | ['text'];\n instructions: string;\n voice: api_proto.Voice;\n inputAudioFormat: api_proto.AudioFormat;\n outputAudioFormat: api_proto.AudioFormat;\n inputAudioTranscription: api_proto.InputAudioTranscription | null;\n turnDetection: api_proto.TurnDetectionType | null;\n temperature: number;\n maxResponseOutputTokens: number;\n model: api_proto.Model;\n apiKey?: string;\n baseURL: string;\n isAzure: boolean;\n entraToken?: string;\n apiVersion?: string;\n}\n\nexport interface RealtimeResponse {\n id: string;\n status: api_proto.ResponseStatus;\n statusDetails: api_proto.ResponseStatusDetails | null;\n usage: api_proto.ModelUsage | null;\n output: RealtimeOutput[];\n doneFut: Future;\n}\n\nexport interface RealtimeOutput {\n responseId: string;\n itemId: string;\n outputIndex: number;\n role: api_proto.Role;\n type: 'message' | 'function_call';\n content: RealtimeContent[];\n doneFut: Future;\n}\n\nexport interface RealtimeContent {\n responseId: string;\n itemId: string;\n outputIndex: number;\n contentIndex: number;\n text: string;\n audio: AudioFrame[];\n textStream: AsyncIterableQueue<string>;\n audioStream: AsyncIterableQueue<AudioFrame>;\n toolCalls: RealtimeToolCall[];\n}\n\nexport interface RealtimeToolCall {\n name: string;\n arguments: string;\n toolCallID: string;\n}\n\nexport interface InputSpeechTranscriptionCompleted {\n itemId: string;\n transcript: string;\n}\n\nexport interface InputSpeechTranscriptionFailed {\n itemId: string;\n message: string;\n}\n\nexport interface InputSpeechStarted {\n itemId: string;\n}\n\nexport interface InputSpeechCommitted {\n itemId: string;\n}\n\nclass InputAudioBuffer {\n #session: RealtimeSession;\n\n constructor(session: RealtimeSession) {\n this.#session = session;\n }\n\n append(frame: AudioFrame) {\n this.#session.queueMsg({\n type: 'input_audio_buffer.append',\n audio: Buffer.from(frame.data.buffer).toString('base64'),\n });\n }\n\n clear() {\n this.#session.queueMsg({\n type: 'input_audio_buffer.clear',\n });\n }\n\n commit() {\n this.#session.queueMsg({\n type: 'input_audio_buffer.commit',\n });\n }\n}\n\nclass ConversationItem {\n #session: RealtimeSession;\n #logger = log();\n\n constructor(session: RealtimeSession) {\n this.#session = session;\n }\n\n truncate(itemId: string, contentIndex: number, audioEnd: number) {\n this.#session.queueMsg({\n type: 'conversation.item.truncate',\n item_id: itemId,\n content_index: contentIndex,\n audio_end_ms: audioEnd,\n });\n }\n\n delete(itemId: string) {\n this.#session.queueMsg({\n type: 'conversation.item.delete',\n item_id: itemId,\n });\n }\n\n create(message: llm.ChatMessage, previousItemId?: string): void {\n if (!message.content) {\n return;\n }\n\n let event: api_proto.ConversationItemCreateEvent;\n\n if (message.toolCallId) {\n if (typeof message.content !== 'string') {\n throw new TypeError('message.content must be a string');\n }\n\n event = {\n type: 'conversation.item.create',\n previous_item_id: previousItemId,\n item: {\n type: 'function_call_output',\n call_id: message.toolCallId,\n output: message.content,\n },\n };\n } else {\n let content = message.content;\n if (!Array.isArray(content)) {\n content = [content];\n }\n\n if (message.role === llm.ChatRole.USER) {\n const contents: (api_proto.InputTextContent | api_proto.InputAudioContent)[] = [];\n for (const c of content) {\n if (typeof c === 'string') {\n contents.push({\n type: 'input_text',\n text: c,\n });\n } else if (\n // typescript type guard for determining ChatAudio vs ChatImage\n ((c: llm.ChatAudio | llm.ChatImage): c is llm.ChatAudio => {\n return (c as llm.ChatAudio).frame !== undefined;\n })(c)\n ) {\n contents.push({\n type: 'input_audio',\n audio: Buffer.from(mergeFrames(c.frame).data.buffer).toString('base64'),\n });\n }\n }\n\n event = {\n type: 'conversation.item.create',\n previous_item_id: previousItemId,\n item: {\n type: 'message',\n role: 'user',\n content: contents,\n },\n };\n } else if (message.role === llm.ChatRole.ASSISTANT) {\n const contents: api_proto.TextContent[] = [];\n for (const c of content) {\n if (typeof c === 'string') {\n contents.push({\n type: 'text',\n text: c,\n });\n } else if (\n // typescript type guard for determining ChatAudio vs ChatImage\n ((c: llm.ChatAudio | llm.ChatImage): c is llm.ChatAudio => {\n return (c as llm.ChatAudio).frame !== undefined;\n })(c)\n ) {\n this.#logger.warn('audio content in assistant message is not supported');\n }\n }\n\n event = {\n type: 'conversation.item.create',\n previous_item_id: previousItemId,\n item: {\n type: 'message',\n role: 'assistant',\n content: contents,\n },\n };\n } else if (message.role === llm.ChatRole.SYSTEM) {\n const contents: api_proto.InputTextContent[] = [];\n for (const c of content) {\n if (typeof c === 'string') {\n contents.push({\n type: 'input_text',\n text: c,\n });\n } else if (\n // typescript type guard for determining ChatAudio vs ChatImage\n ((c: llm.ChatAudio | llm.ChatImage): c is llm.ChatAudio => {\n return (c as llm.ChatAudio).frame !== undefined;\n })(c)\n ) {\n this.#logger.warn('audio content in system message is not supported');\n }\n }\n\n event = {\n type: 'conversation.item.create',\n previous_item_id: previousItemId,\n item: {\n type: 'message',\n role: 'system',\n content: contents,\n },\n };\n } else {\n this.#logger\n .child({ message })\n .warn('chat message is not supported inside the realtime API');\n return;\n }\n }\n\n this.#session.queueMsg(event);\n }\n}\n\nclass Conversation {\n #session: RealtimeSession;\n\n constructor(session: RealtimeSession) {\n this.#session = session;\n }\n\n get item(): ConversationItem {\n return new ConversationItem(this.#session);\n }\n}\n\nclass Response {\n #session: RealtimeSession;\n\n constructor(session: RealtimeSession) {\n this.#session = session;\n }\n\n create() {\n this.#session.queueMsg({\n type: 'response.create',\n });\n }\n\n cancel() {\n this.#session.queueMsg({\n type: 'response.cancel',\n });\n }\n}\n\ninterface ContentPtr {\n response_id: string;\n output_index: number;\n content_index: number;\n}\n\nexport class RealtimeModel extends multimodal.RealtimeModel {\n sampleRate = api_proto.SAMPLE_RATE;\n numChannels = api_proto.NUM_CHANNELS;\n inFrameSize = api_proto.IN_FRAME_SIZE;\n outFrameSize = api_proto.OUT_FRAME_SIZE;\n\n #defaultOpts: ModelOptions;\n #sessions: RealtimeSession[] = [];\n\n static withAzure({\n baseURL,\n azureDeployment,\n apiVersion = '2024-10-01-preview',\n apiKey = undefined,\n entraToken = undefined,\n instructions = '',\n modalities = ['text', 'audio'],\n voice = 'alloy',\n inputAudioFormat = 'pcm16',\n outputAudioFormat = 'pcm16',\n inputAudioTranscription = { model: 'whisper-1' },\n turnDetection = { type: 'server_vad' },\n temperature = 0.8,\n maxResponseOutputTokens = Infinity,\n }: {\n baseURL: string;\n azureDeployment: string;\n apiVersion?: string;\n apiKey?: string;\n entraToken?: string;\n instructions?: string;\n modalities?: ['text', 'audio'] | ['text'];\n voice?: api_proto.Voice;\n inputAudioFormat?: api_proto.AudioFormat;\n outputAudioFormat?: api_proto.AudioFormat;\n inputAudioTranscription?: api_proto.InputAudioTranscription;\n turnDetection?: api_proto.TurnDetectionType;\n temperature?: number;\n maxResponseOutputTokens?: number;\n }) {\n return new RealtimeModel({\n isAzure: true,\n baseURL: new URL('openai', baseURL).toString(),\n model: azureDeployment,\n apiVersion,\n apiKey,\n entraToken,\n instructions,\n modalities,\n voice,\n inputAudioFormat,\n outputAudioFormat,\n inputAudioTranscription,\n turnDetection,\n temperature,\n maxResponseOutputTokens,\n });\n }\n\n constructor({\n modalities = ['text', 'audio'],\n instructions = '',\n voice = 'alloy',\n inputAudioFormat = 'pcm16',\n outputAudioFormat = 'pcm16',\n inputAudioTranscription = { model: 'whisper-1' },\n turnDetection = { type: 'server_vad' },\n temperature = 0.8,\n maxResponseOutputTokens = Infinity,\n model = 'gpt-4o-realtime-preview-2024-10-01',\n apiKey = process.env.OPENAI_API_KEY || '',\n baseURL = api_proto.BASE_URL,\n // used for microsoft\n isAzure = false,\n apiVersion = undefined,\n entraToken = undefined,\n }: {\n modalities?: ['text', 'audio'] | ['text'];\n instructions?: string;\n voice?: api_proto.Voice;\n inputAudioFormat?: api_proto.AudioFormat;\n outputAudioFormat?: api_proto.AudioFormat;\n inputAudioTranscription?: api_proto.InputAudioTranscription;\n turnDetection?: api_proto.TurnDetectionType;\n temperature?: number;\n maxResponseOutputTokens?: number;\n model?: api_proto.Model;\n apiKey?: string;\n baseURL?: string;\n isAzure?: boolean;\n apiVersion?: string;\n entraToken?: string;\n }) {\n super();\n\n if (apiKey === '') {\n throw new Error(\n 'OpenAI API key is required, either using the argument or by setting the OPENAI_API_KEY environmental variable',\n );\n }\n\n this.#defaultOpts = {\n modalities,\n instructions,\n voice,\n inputAudioFormat,\n outputAudioFormat,\n inputAudioTranscription,\n turnDetection,\n temperature,\n maxResponseOutputTokens,\n model,\n apiKey,\n baseURL,\n isAzure,\n apiVersion,\n entraToken,\n };\n }\n\n get sessions(): RealtimeSession[] {\n return this.#sessions;\n }\n\n session({\n fncCtx,\n chatCtx,\n modalities = this.#defaultOpts.modalities,\n instructions = this.#defaultOpts.instructions,\n voice = this.#defaultOpts.voice,\n inputAudioFormat = this.#defaultOpts.inputAudioFormat,\n outputAudioFormat = this.#defaultOpts.outputAudioFormat,\n inputAudioTranscription = this.#defaultOpts.inputAudioTranscription,\n turnDetection = this.#defaultOpts.turnDetection,\n temperature = this.#defaultOpts.temperature,\n maxResponseOutputTokens = this.#defaultOpts.maxResponseOutputTokens,\n }: {\n fncCtx?: llm.FunctionContext;\n chatCtx?: llm.ChatContext;\n modalities?: ['text', 'audio'] | ['text'];\n instructions?: string;\n voice?: api_proto.Voice;\n inputAudioFormat?: api_proto.AudioFormat;\n outputAudioFormat?: api_proto.AudioFormat;\n inputAudioTranscription?: api_proto.InputAudioTranscription | null;\n turnDetection?: api_proto.TurnDetectionType | null;\n temperature?: number;\n maxResponseOutputTokens?: number;\n }): RealtimeSession {\n const opts: ModelOptions = {\n modalities,\n instructions,\n voice,\n inputAudioFormat,\n outputAudioFormat,\n inputAudioTranscription,\n turnDetection,\n temperature,\n maxResponseOutputTokens,\n model: this.#defaultOpts.model,\n apiKey: this.#defaultOpts.apiKey,\n baseURL: this.#defaultOpts.baseURL,\n isAzure: this.#defaultOpts.isAzure,\n apiVersion: this.#defaultOpts.apiVersion,\n entraToken: this.#defaultOpts.entraToken,\n };\n\n const newSession = new RealtimeSession(opts, {\n chatCtx: chatCtx || new llm.ChatContext(),\n fncCtx,\n });\n this.#sessions.push(newSession);\n return newSession;\n }\n\n async close() {\n await Promise.allSettled(this.#sessions.map((session) => session.close()));\n }\n}\n\nexport class RealtimeSession extends multimodal.RealtimeSession {\n #chatCtx: llm.ChatContext | undefined = undefined;\n #fncCtx: llm.FunctionContext | undefined = undefined;\n #opts: ModelOptions;\n #pendingResponses: { [id: string]: RealtimeResponse } = {};\n #sessionId = 'not-connected';\n #ws: WebSocket | null = null;\n #expiresAt: number | null = null;\n #logger = log();\n #task: Promise<void>;\n #closing = true;\n #sendQueue = new Queue<api_proto.ClientEvent>();\n\n constructor(\n opts: ModelOptions,\n { fncCtx, chatCtx }: { fncCtx?: llm.FunctionContext; chatCtx?: llm.ChatContext },\n ) {\n super();\n\n this.#opts = opts;\n this.#chatCtx = chatCtx;\n this.#fncCtx = fncCtx;\n\n this.#task = this.#start();\n\n this.sessionUpdate({\n modalities: this.#opts.modalities,\n instructions: this.#opts.instructions,\n voice: this.#opts.voice,\n inputAudioFormat: this.#opts.inputAudioFormat,\n outputAudioFormat: this.#opts.outputAudioFormat,\n inputAudioTranscription: this.#opts.inputAudioTranscription,\n turnDetection: this.#opts.turnDetection,\n temperature: this.#opts.temperature,\n maxResponseOutputTokens: this.#opts.maxResponseOutputTokens,\n toolChoice: 'auto',\n });\n }\n\n get chatCtx(): llm.ChatContext | undefined {\n return this.#chatCtx;\n }\n\n get fncCtx(): llm.FunctionContext | undefined {\n return this.#fncCtx;\n }\n\n set fncCtx(ctx: llm.FunctionContext | undefined) {\n this.#fncCtx = ctx;\n }\n\n get conversation(): Conversation {\n return new Conversation(this);\n }\n\n get inputAudioBuffer(): InputAudioBuffer {\n return new InputAudioBuffer(this);\n }\n\n get response(): Response {\n return new Response(this);\n }\n\n get expiration(): number {\n if (!this.#expiresAt) {\n throw new Error('session not started');\n }\n return this.#expiresAt * 1000;\n }\n\n queueMsg(command: api_proto.ClientEvent): void {\n this.#sendQueue.put(command);\n }\n\n /// Truncates the data field of the event to the specified maxLength to avoid overwhelming logs\n /// with large amounts of base64 audio data.\n #loggableEvent(\n event: api_proto.ClientEvent | api_proto.ServerEvent,\n maxLength: number = 30,\n ): Record<string, unknown> {\n const untypedEvent: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(event)) {\n if (value !== undefined) {\n untypedEvent[key] = value;\n }\n }\n\n if (untypedEvent.audio && typeof untypedEvent.audio === 'string') {\n const truncatedData =\n untypedEvent.audio.slice(0, maxLength) + (untypedEvent.audio.length > maxLength ? '…' : '');\n return { ...untypedEvent, audio: truncatedData };\n }\n if (\n untypedEvent.delta &&\n typeof untypedEvent.delta === 'string' &&\n event.type === 'response.audio.delta'\n ) {\n const truncatedDelta =\n untypedEvent.delta.slice(0, maxLength) + (untypedEvent.delta.length > maxLength ? '…' : '');\n return { ...untypedEvent, delta: truncatedDelta };\n }\n return untypedEvent;\n }\n\n sessionUpdate({\n modalities = this.#opts.modalities,\n instructions = this.#opts.instructions,\n voice = this.#opts.voice,\n inputAudioFormat = this.#opts.inputAudioFormat,\n outputAudioFormat = this.#opts.outputAudioFormat,\n inputAudioTranscription = this.#opts.inputAudioTranscription,\n turnDetection = this.#opts.turnDetection,\n temperature = this.#opts.temperature,\n maxResponseOutputTokens = this.#opts.maxResponseOutputTokens,\n toolChoice = 'auto',\n }: {\n modalities: ['text', 'audio'] | ['text'];\n instructions?: string;\n voice?: api_proto.Voice;\n inputAudioFormat?: api_proto.AudioFormat;\n outputAudioFormat?: api_proto.AudioFormat;\n inputAudioTranscription?: api_proto.InputAudioTranscription | null;\n turnDetection?: api_proto.TurnDetectionType | null;\n temperature?: number;\n maxResponseOutputTokens?: number;\n toolChoice?: api_proto.ToolChoice;\n }) {\n this.#opts = {\n modalities,\n instructions,\n voice,\n inputAudioFormat,\n outputAudioFormat,\n inputAudioTranscription,\n turnDetection,\n temperature,\n maxResponseOutputTokens,\n model: this.#opts.model,\n apiKey: this.#opts.apiKey,\n baseURL: this.#opts.baseURL,\n isAzure: this.#opts.isAzure,\n apiVersion: this.#opts.apiVersion,\n entraToken: this.#opts.entraToken,\n };\n\n const tools = this.#fncCtx\n ? Object.entries(this.#fncCtx).map(([name, func]) => ({\n type: 'function' as const,\n name,\n description: func.description,\n parameters:\n // don't format parameters if they are raw openai params\n func.parameters.type == ('object' as const)\n ? func.parameters\n : llm.oaiParams(func.parameters),\n }))\n : [];\n\n const sessionUpdateEvent: api_proto.SessionUpdateEvent = {\n type: 'session.update',\n session: {\n modalities: this.#opts.modalities,\n instructions: this.#opts.instructions,\n voice: this.#opts.voice,\n input_audio_format: this.#opts.inputAudioFormat,\n output_audio_format: this.#opts.outputAudioFormat,\n input_audio_transcription: this.#opts.inputAudioTranscription,\n turn_detection: this.#opts.turnDetection,\n temperature: this.#opts.temperature,\n max_response_output_tokens:\n this.#opts.maxResponseOutputTokens === Infinity\n ? 'inf'\n : this.#opts.maxResponseOutputTokens,\n tools,\n tool_choice: toolChoice,\n },\n };\n\n if (this.#opts.isAzure && this.#opts.maxResponseOutputTokens === Infinity) {\n // microsoft doesn't support inf for max_response_output_tokens, but accepts no args\n sessionUpdateEvent.session.max_response_output_tokens = undefined;\n }\n\n this.queueMsg(sessionUpdateEvent);\n }\n\n #start(): Promise<void> {\n return new Promise(async (resolve, reject) => {\n const headers: Record<string, string> = {\n 'User-Agent': 'LiveKit-Agents-JS',\n };\n if (this.#opts.isAzure) {\n // Microsoft API has two ways of authentication\n // 1. Entra token set as `Bearer` token\n // 2. API key set as `api_key` header (also accepts query string)\n if (this.#opts.entraToken) {\n headers.Authorization = `Bearer ${this.#opts.entraToken}`;\n } else if (this.#opts.apiKey) {\n headers['api-key'] = this.#opts.apiKey;\n } else {\n reject(new Error('Microsoft API key or entraToken is required'));\n return;\n }\n } else {\n headers.Authorization = `Bearer ${this.#opts.apiKey}`;\n headers['OpenAI-Beta'] = 'realtime=v1';\n }\n const url = new URL([this.#opts.baseURL, 'realtime'].join('/'));\n if (url.protocol === 'https:') {\n url.protocol = 'wss:';\n }\n\n // Construct query parameters\n const queryParams: Record<string, string> = {};\n if (this.#opts.isAzure) {\n queryParams['api-version'] = '2024-10-01-preview';\n queryParams['deployment'] = this.#opts.model;\n } else {\n queryParams['model'] = this.#opts.model;\n }\n\n for (const [key, value] of Object.entries(queryParams)) {\n url.searchParams.set(key, value);\n }\n\n console.debug('Connecting to OpenAI Realtime API at ', url.toString());\n this.#ws = new WebSocket(url.toString(), {\n headers: headers,\n });\n\n this.#ws.onerror = (error) => {\n reject(new Error('OpenAI Realtime WebSocket error: ' + error.message));\n };\n\n await once(this.#ws, 'open');\n this.#closing = false;\n\n this.#ws.onmessage = (message) => {\n const event: api_proto.ServerEvent = JSON.parse(message.data as string);\n this.#logger.debug(`<- ${JSON.stringify(this.#loggableEvent(event))}`);\n switch (event.type) {\n case 'error':\n this.#handleError(event);\n break;\n case 'session.created':\n this.#handleSessionCreated(event);\n break;\n case 'session.updated':\n this.#handleSessionUpdated(event);\n break;\n case 'conversation.created':\n this.#handleConversationCreated(event);\n break;\n case 'input_audio_buffer.committed':\n this.#handleInputAudioBufferCommitted(event);\n break;\n case 'input_audio_buffer.cleared':\n this.#handleInputAudioBufferCleared(event);\n break;\n case 'input_audio_buffer.speech_started':\n this.#handleInputAudioBufferSpeechStarted(event);\n break;\n case 'input_audio_buffer.speech_stopped':\n this.#handleInputAudioBufferSpeechStopped(event);\n break;\n case 'conversation.item.created':\n this.#handleConversationItemCreated(event);\n break;\n case 'conversation.item.input_audio_transcription.completed':\n this.#handleConversationItemInputAudioTranscriptionCompleted(event);\n break;\n case 'conversation.item.input_audio_transcription.failed':\n this.#handleConversationItemInputAudioTranscriptionFailed(event);\n break;\n case 'conversation.item.truncated':\n this.#handleConversationItemTruncated(event);\n break;\n case 'conversation.item.deleted':\n this.#handleConversationItemDeleted(event);\n break;\n case 'response.created':\n this.#handleResponseCreated(event);\n break;\n case 'response.done':\n this.#handleResponseDone(event);\n break;\n case 'response.output_item.added':\n this.#handleResponseOutputItemAdded(event);\n break;\n case 'response.output_item.done':\n this.#handleResponseOutputItemDone(event);\n break;\n case 'response.content_part.added':\n this.#handleResponseContentPartAdded(event);\n break;\n case 'response.content_part.done':\n this.#handleResponseContentPartDone(event);\n break;\n case 'response.text.delta':\n this.#handleResponseTextDelta(event);\n break;\n case 'response.text.done':\n this.#handleResponseTextDone(event);\n break;\n case 'response.audio_transcript.delta':\n this.#handleResponseAudioTranscriptDelta(event);\n break;\n case 'response.audio_transcript.done':\n this.#handleResponseAudioTranscriptDone(event);\n break;\n case 'response.audio.delta':\n this.#handleResponseAudioDelta(event);\n break;\n case 'response.audio.done':\n this.#handleResponseAudioDone(event);\n break;\n case 'response.function_call_arguments.delta':\n this.#handleResponseFunctionCallArgumentsDelta(event);\n break;\n case 'response.function_call_arguments.done':\n this.#handleResponseFunctionCallArgumentsDone(event);\n break;\n case 'rate_limits.updated':\n this.#handleRateLimitsUpdated(event);\n break;\n }\n };\n\n const sendTask = async () => {\n while (this.#ws && !this.#closing && this.#ws.readyState === WebSocket.OPEN) {\n try {\n const event = await this.#sendQueue.get();\n if (event.type !== 'input_audio_buffer.append') {\n this.#logger.debug(`-> ${JSON.stringify(this.#loggableEvent(event))}`);\n }\n this.#ws.send(JSON.stringify(event));\n } catch (error) {\n this.#logger.error('Error sending event:', error);\n }\n }\n };\n\n sendTask();\n\n this.#ws.onclose = () => {\n if (this.#expiresAt && Date.now() >= this.#expiresAt * 1000) {\n this.#closing = true;\n }\n if (!this.#closing) {\n reject(new Error('OpenAI Realtime connection closed unexpectedly'));\n }\n this.#ws = null;\n resolve();\n };\n });\n }\n\n async close() {\n if (!this.#ws) return;\n this.#closing = true;\n this.#ws.close();\n await this.#task;\n }\n\n #getContent(ptr: ContentPtr): RealtimeContent {\n const response = this.#pendingResponses[ptr.response_id];\n const output = response!.output[ptr.output_index];\n const content = output!.content[ptr.content_index]!;\n return content;\n }\n\n #handleError(event: api_proto.ErrorEvent): void {\n this.#logger.error(`OpenAI Realtime error ${JSON.stringify(event.error)}`);\n }\n\n #handleSessionCreated(event: api_proto.SessionCreatedEvent): void {\n this.#sessionId = event.session.id;\n this.#expiresAt = event.session.expires_at;\n this.#logger = this.#logger.child({ sessionId: this.#sessionId });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n #handleSessionUpdated(event: api_proto.SessionUpdatedEvent): void {}\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n #handleConversationCreated(event: api_proto.ConversationCreatedEvent): void {}\n\n #handleInputAudioBufferCommitted(event: api_proto.InputAudioBufferCommittedEvent): void {\n this.emit('input_speech_committed', {\n itemId: event.item_id,\n } as InputSpeechCommitted);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n #handleInputAudioBufferCleared(event: api_proto.InputAudioBufferClearedEvent): void {}\n\n #handleInputAudioBufferSpeechStarted(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n event: api_proto.InputAudioBufferSpeechStartedEvent,\n ): void {\n this.emit('input_speech_started', {\n itemId: event.item_id,\n } as InputSpeechStarted);\n }\n\n #handleInputAudioBufferSpeechStopped(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n event: api_proto.InputAudioBufferSpeechStoppedEvent,\n ): void {\n this.emit('input_speech_stopped');\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n #handleConversationItemCreated(event: api_proto.ConversationItemCreatedEvent): void {}\n\n #handleConversationItemInputAudioTranscriptionCompleted(\n event: api_proto.ConversationItemInputAudioTranscriptionCompletedEvent,\n ): void {\n const transcript = event.transcript;\n this.emit('input_speech_transcription_completed', {\n itemId: event.item_id,\n transcript: transcript,\n } as InputSpeechTranscriptionCompleted);\n }\n\n #handleConversationItemInputAudioTranscriptionFailed(\n event: api_proto.ConversationItemInputAudioTranscriptionFailedEvent,\n ): void {\n const error = event.error;\n this.#logger.error(`OpenAI Realtime failed to transcribe input audio: ${error.message}`);\n this.emit('input_speech_transcription_failed', {\n itemId: event.item_id,\n message: error.message,\n } as InputSpeechTranscriptionFailed);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n #handleConversationItemTruncated(event: api_proto.ConversationItemTruncatedEvent): void {}\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n #handleConversationItemDeleted(event: api_proto.ConversationItemDeletedEvent): void {}\n\n #handleResponseCreated(responseCreated: api_proto.ResponseCreatedEvent): void {\n const response = responseCreated.response;\n const doneFut = new Future();\n const newResponse: RealtimeResponse = {\n id: response.id,\n status: response.status,\n statusDetails: response.status_details,\n usage: null,\n output: [],\n doneFut: doneFut,\n };\n this.#pendingResponses[newResponse.id] = newResponse;\n this.emit('response_created', newResponse);\n }\n\n #handleResponseDone(event: api_proto.ResponseDoneEvent): void {\n const responseData = event.response;\n const responseId = responseData.id;\n const response = this.#pendingResponses[responseId]!;\n response.status = responseData.status;\n response.statusDetails = responseData.status_details;\n response.usage = responseData.usage ?? null;\n this.#pendingResponses[responseId] = response;\n response.doneFut.resolve();\n this.emit('response_done', response);\n }\n\n #handleResponseOutputItemAdded(event: api_proto.ResponseOutputItemAddedEvent): void {\n const responseId = event.response_id;\n const response = this.#pendingResponses[responseId];\n const itemData = event.item;\n\n if (itemData.type !== 'message' && itemData.type !== 'function_call') {\n throw new Error(`Unexpected item type: ${itemData.type}`);\n }\n\n let role: api_proto.Role;\n if (itemData.type === 'function_call') {\n role = 'assistant'; // function_call doesn't have a role field, defaulting it to assistant\n } else {\n role = itemData.role;\n }\n\n const newOutput: RealtimeOutput = {\n responseId: responseId,\n itemId: itemData.id,\n outputIndex: event.output_index,\n type: itemData.type,\n role: role,\n content: [],\n doneFut: new Future(),\n };\n response?.output.push(newOutput);\n this.emit('response_output_added', newOutput);\n }\n\n #handleResponseOutputItemDone(event: api_proto.ResponseOutputItemDoneEvent): void {\n const responseId = event.response_id;\n const response = this.#pendingResponses[responseId];\n const outputIndex = event.output_index;\n const output = response!.output[outputIndex];\n\n if (output?.type === 'function_call') {\n if (!this.#fncCtx) {\n this.#logger.error('function call received but no fncCtx is available');\n return;\n }\n\n // parse the arguments and call the function inside the fnc_ctx\n const item = event.item;\n if (item.type !== 'function_call') {\n throw new Error('Expected function_call item');\n }\n const func = this.#fncCtx[item.name];\n if (!func) {\n this.#logger.error(`no function with name ${item.name} in fncCtx`);\n return;\n }\n\n this.emit('function_call_started', {\n callId: item.call_id,\n });\n\n const parsedArgs = JSON.parse(item.arguments);\n\n this.#logger.debug(\n `[Function Call ${item.call_id}] Executing ${item.name} with arguments ${parsedArgs}`,\n );\n\n func.execute(parsedArgs).then(\n (content) => {\n this.#logger.debug(`[Function Call ${item.call_id}] ${item.name} returned ${content}`);\n this.emit('function_call_completed', {\n callId: item.call_id,\n });\n this.conversation.item.create(\n llm.ChatMessage.createToolFromFunctionResult({\n name: item.name,\n toolCallId: item.call_id,\n result: content,\n }),\n output.itemId,\n );\n this.response.create();\n },\n (error) => {\n this.#logger.error(`[Function Call ${item.call_id}] ${item.name} failed with ${error}`);\n // TODO: send it back up as failed?\n this.emit('function_call_failed', {\n callId: item.call_id,\n });\n },\n );\n }\n\n output?.doneFut.resolve();\n this.emit('response_output_done', output);\n }\n\n #handleResponseContentPartAdded(event: api_proto.ResponseContentPartAddedEvent): void {\n const responseId = event.response_id;\n const response = this.#pendingResponses[responseId];\n const outputIndex = event.output_index;\n const output = response!.output[outputIndex];\n\n const textStream = new AsyncIterableQueue<string>();\n const audioStream = new AsyncIterableQueue<AudioFrame>();\n\n const newContent: RealtimeContent = {\n responseId: responseId,\n itemId: event.item_id,\n outputIndex: outputIndex,\n contentIndex: event.content_index,\n text: '',\n audio: [],\n textStream: textStream,\n audioStream: audioStream,\n toolCalls: [],\n };\n output?.content.push(newContent);\n this.emit('response_content_added', newContent);\n }\n\n #handleResponseContentPartDone(event: api_proto.ResponseContentPartDoneEvent): void {\n const content = this.#getContent(event);\n this.emit('response_content_done', content);\n }\n\n #handleResponseTextDelta(event: api_proto.ResponseTextDeltaEvent): void {\n this.emit('response_text_delta', event);\n }\n\n #handleResponseTextDone(event: api_proto.ResponseTextDoneEvent): void {\n this.emit('response_text_done', event);\n }\n\n #handleResponseAudioTranscriptDelta(event: api_proto.ResponseAudioTranscriptDeltaEvent): void {\n const content = this.#getContent(event);\n const transcript = event.delta;\n content.text += transcript;\n\n content.textStream.put(transcript);\n }\n\n #handleResponseAudioTranscriptDone(event: api_proto.ResponseAudioTranscriptDoneEvent): void {\n const content = this.#getContent(event);\n content.textStream.close();\n }\n\n #handleResponseAudioDelta(event: api_proto.ResponseAudioDeltaEvent): void {\n const content = this.#getContent(event);\n const data = Buffer.from(event.delta, 'base64');\n const audio = new AudioFrame(\n new Int16Array(data.buffer),\n api_proto.SAMPLE_RATE,\n api_proto.NUM_CHANNELS,\n data.length / 2,\n );\n content.audio.push(audio);\n\n content.audioStream.put(audio);\n }\n\n #handleResponseAudioDone(event: api_proto.ResponseAudioDoneEvent): void {\n const content = this.#getContent(event);\n content.audioStream.close();\n }\n\n #handleResponseFunctionCallArgumentsDelta(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n event: api_proto.ResponseFunctionCallArgumentsDeltaEvent,\n ): void {}\n\n #handleResponseFunctionCallArgumentsDone(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n event: api_proto.ResponseFunctionCallArgumentsDoneEvent,\n ): void {}\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n #handleRateLimitsUpdated(event: api_proto.RateLimitsUpdatedEvent): void {}\n}\n"],"mappings":"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","names":["c"]}
|
|
1
|
+
{"version":3,"sources":["../../src/realtime/realtime_model.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport {\n AsyncIterableQueue,\n Future,\n Queue,\n llm,\n log,\n mergeFrames,\n metrics,\n multimodal,\n} from '@livekit/agents';\nimport { AudioFrame } from '@livekit/rtc-node';\nimport { once } from 'node:events';\nimport { WebSocket } from 'ws';\nimport * as api_proto from './api_proto.js';\n\ninterface ModelOptions {\n modalities: ['text', 'audio'] | ['text'];\n instructions: string;\n voice: api_proto.Voice;\n inputAudioFormat: api_proto.AudioFormat;\n outputAudioFormat: api_proto.AudioFormat;\n inputAudioTranscription: api_proto.InputAudioTranscription | null;\n turnDetection: api_proto.TurnDetectionType | null;\n temperature: number;\n maxResponseOutputTokens: number;\n model: api_proto.Model;\n apiKey?: string;\n baseURL: string;\n isAzure: boolean;\n entraToken?: string;\n apiVersion?: string;\n}\n\nexport interface RealtimeResponse {\n id: string;\n status: api_proto.ResponseStatus;\n statusDetails: api_proto.ResponseStatusDetails | null;\n usage: api_proto.ModelUsage | null;\n output: RealtimeOutput[];\n doneFut: Future;\n createdTimestamp: number;\n firstTokenTimestamp?: number;\n}\n\nexport interface RealtimeOutput {\n responseId: string;\n itemId: string;\n outputIndex: number;\n role: api_proto.Role;\n type: 'message' | 'function_call';\n content: RealtimeContent[];\n doneFut: Future;\n}\n\nexport interface RealtimeContent {\n responseId: string;\n itemId: string;\n outputIndex: number;\n contentIndex: number;\n text: string;\n audio: AudioFrame[];\n textStream: AsyncIterableQueue<string>;\n audioStream: AsyncIterableQueue<AudioFrame>;\n toolCalls: RealtimeToolCall[];\n}\n\nexport interface RealtimeToolCall {\n name: string;\n arguments: string;\n toolCallID: string;\n}\n\nexport interface InputSpeechTranscriptionCompleted {\n itemId: string;\n transcript: string;\n}\n\nexport interface InputSpeechTranscriptionFailed {\n itemId: string;\n message: string;\n}\n\nexport interface InputSpeechStarted {\n itemId: string;\n}\n\nexport interface InputSpeechCommitted {\n itemId: string;\n}\n\nclass InputAudioBuffer {\n #session: RealtimeSession;\n\n constructor(session: RealtimeSession) {\n this.#session = session;\n }\n\n append(frame: AudioFrame) {\n this.#session.queueMsg({\n type: 'input_audio_buffer.append',\n audio: Buffer.from(frame.data.buffer).toString('base64'),\n });\n }\n\n clear() {\n this.#session.queueMsg({\n type: 'input_audio_buffer.clear',\n });\n }\n\n commit() {\n this.#session.queueMsg({\n type: 'input_audio_buffer.commit',\n });\n }\n}\n\nclass ConversationItem {\n #session: RealtimeSession;\n #logger = log();\n\n constructor(session: RealtimeSession) {\n this.#session = session;\n }\n\n truncate(itemId: string, contentIndex: number, audioEnd: number) {\n this.#session.queueMsg({\n type: 'conversation.item.truncate',\n item_id: itemId,\n content_index: contentIndex,\n audio_end_ms: audioEnd,\n });\n }\n\n delete(itemId: string) {\n this.#session.queueMsg({\n type: 'conversation.item.delete',\n item_id: itemId,\n });\n }\n\n create(message: llm.ChatMessage, previousItemId?: string): void {\n if (!message.content) {\n return;\n }\n\n let event: api_proto.ConversationItemCreateEvent;\n\n if (message.toolCallId) {\n if (typeof message.content !== 'string') {\n throw new TypeError('message.content must be a string');\n }\n\n event = {\n type: 'conversation.item.create',\n previous_item_id: previousItemId,\n item: {\n type: 'function_call_output',\n call_id: message.toolCallId,\n output: message.content,\n },\n };\n } else {\n let content = message.content;\n if (!Array.isArray(content)) {\n content = [content];\n }\n\n if (message.role === llm.ChatRole.USER) {\n const contents: (api_proto.InputTextContent | api_proto.InputAudioContent)[] = [];\n for (const c of content) {\n if (typeof c === 'string') {\n contents.push({\n type: 'input_text',\n text: c,\n });\n } else if (\n // typescript type guard for determining ChatAudio vs ChatImage\n ((c: llm.ChatAudio | llm.ChatImage): c is llm.ChatAudio => {\n return (c as llm.ChatAudio).frame !== undefined;\n })(c)\n ) {\n contents.push({\n type: 'input_audio',\n audio: Buffer.from(mergeFrames(c.frame).data.buffer).toString('base64'),\n });\n }\n }\n\n event = {\n type: 'conversation.item.create',\n previous_item_id: previousItemId,\n item: {\n type: 'message',\n role: 'user',\n content: contents,\n },\n };\n } else if (message.role === llm.ChatRole.ASSISTANT) {\n const contents: api_proto.TextContent[] = [];\n for (const c of content) {\n if (typeof c === 'string') {\n contents.push({\n type: 'text',\n text: c,\n });\n } else if (\n // typescript type guard for determining ChatAudio vs ChatImage\n ((c: llm.ChatAudio | llm.ChatImage): c is llm.ChatAudio => {\n return (c as llm.ChatAudio).frame !== undefined;\n })(c)\n ) {\n this.#logger.warn('audio content in assistant message is not supported');\n }\n }\n\n event = {\n type: 'conversation.item.create',\n previous_item_id: previousItemId,\n item: {\n type: 'message',\n role: 'assistant',\n content: contents,\n },\n };\n } else if (message.role === llm.ChatRole.SYSTEM) {\n const contents: api_proto.InputTextContent[] = [];\n for (const c of content) {\n if (typeof c === 'string') {\n contents.push({\n type: 'input_text',\n text: c,\n });\n } else if (\n // typescript type guard for determining ChatAudio vs ChatImage\n ((c: llm.ChatAudio | llm.ChatImage): c is llm.ChatAudio => {\n return (c as llm.ChatAudio).frame !== undefined;\n })(c)\n ) {\n this.#logger.warn('audio content in system message is not supported');\n }\n }\n\n event = {\n type: 'conversation.item.create',\n previous_item_id: previousItemId,\n item: {\n type: 'message',\n role: 'system',\n content: contents,\n },\n };\n } else {\n this.#logger\n .child({ message })\n .warn('chat message is not supported inside the realtime API');\n return;\n }\n }\n\n this.#session.queueMsg(event);\n }\n}\n\nclass Conversation {\n #session: RealtimeSession;\n\n constructor(session: RealtimeSession) {\n this.#session = session;\n }\n\n get item(): ConversationItem {\n return new ConversationItem(this.#session);\n }\n}\n\nclass Response {\n #session: RealtimeSession;\n\n constructor(session: RealtimeSession) {\n this.#session = session;\n }\n\n create() {\n this.#session.queueMsg({\n type: 'response.create',\n });\n }\n\n cancel() {\n this.#session.queueMsg({\n type: 'response.cancel',\n });\n }\n}\n\ninterface ContentPtr {\n response_id: string;\n output_index: number;\n content_index: number;\n}\n\nexport class RealtimeModel extends multimodal.RealtimeModel {\n sampleRate = api_proto.SAMPLE_RATE;\n numChannels = api_proto.NUM_CHANNELS;\n inFrameSize = api_proto.IN_FRAME_SIZE;\n outFrameSize = api_proto.OUT_FRAME_SIZE;\n\n #defaultOpts: ModelOptions;\n #sessions: RealtimeSession[] = [];\n\n static withAzure({\n baseURL,\n azureDeployment,\n apiVersion = '2024-10-01-preview',\n apiKey = undefined,\n entraToken = undefined,\n instructions = '',\n modalities = ['text', 'audio'],\n voice = 'alloy',\n inputAudioFormat = 'pcm16',\n outputAudioFormat = 'pcm16',\n inputAudioTranscription = { model: 'whisper-1' },\n turnDetection = { type: 'server_vad' },\n temperature = 0.8,\n maxResponseOutputTokens = Infinity,\n }: {\n baseURL: string;\n azureDeployment: string;\n apiVersion?: string;\n apiKey?: string;\n entraToken?: string;\n instructions?: string;\n modalities?: ['text', 'audio'] | ['text'];\n voice?: api_proto.Voice;\n inputAudioFormat?: api_proto.AudioFormat;\n outputAudioFormat?: api_proto.AudioFormat;\n inputAudioTranscription?: api_proto.InputAudioTranscription;\n turnDetection?: api_proto.TurnDetectionType;\n temperature?: number;\n maxResponseOutputTokens?: number;\n }) {\n return new RealtimeModel({\n isAzure: true,\n baseURL: new URL('openai', baseURL).toString(),\n model: azureDeployment,\n apiVersion,\n apiKey,\n entraToken,\n instructions,\n modalities,\n voice,\n inputAudioFormat,\n outputAudioFormat,\n inputAudioTranscription,\n turnDetection,\n temperature,\n maxResponseOutputTokens,\n });\n }\n\n constructor({\n modalities = ['text', 'audio'],\n instructions = '',\n voice = 'alloy',\n inputAudioFormat = 'pcm16',\n outputAudioFormat = 'pcm16',\n inputAudioTranscription = { model: 'whisper-1' },\n turnDetection = { type: 'server_vad' },\n temperature = 0.8,\n maxResponseOutputTokens = Infinity,\n model = 'gpt-4o-realtime-preview-2024-10-01',\n apiKey = process.env.OPENAI_API_KEY || '',\n baseURL = api_proto.BASE_URL,\n // used for microsoft\n isAzure = false,\n apiVersion = undefined,\n entraToken = undefined,\n }: {\n modalities?: ['text', 'audio'] | ['text'];\n instructions?: string;\n voice?: api_proto.Voice;\n inputAudioFormat?: api_proto.AudioFormat;\n outputAudioFormat?: api_proto.AudioFormat;\n inputAudioTranscription?: api_proto.InputAudioTranscription;\n turnDetection?: api_proto.TurnDetectionType;\n temperature?: number;\n maxResponseOutputTokens?: number;\n model?: api_proto.Model;\n apiKey?: string;\n baseURL?: string;\n isAzure?: boolean;\n apiVersion?: string;\n entraToken?: string;\n }) {\n super();\n\n if (apiKey === '') {\n throw new Error(\n 'OpenAI API key is required, either using the argument or by setting the OPENAI_API_KEY environmental variable',\n );\n }\n\n this.#defaultOpts = {\n modalities,\n instructions,\n voice,\n inputAudioFormat,\n outputAudioFormat,\n inputAudioTranscription,\n turnDetection,\n temperature,\n maxResponseOutputTokens,\n model,\n apiKey,\n baseURL,\n isAzure,\n apiVersion,\n entraToken,\n };\n }\n\n get sessions(): RealtimeSession[] {\n return this.#sessions;\n }\n\n session({\n fncCtx,\n chatCtx,\n modalities = this.#defaultOpts.modalities,\n instructions = this.#defaultOpts.instructions,\n voice = this.#defaultOpts.voice,\n inputAudioFormat = this.#defaultOpts.inputAudioFormat,\n outputAudioFormat = this.#defaultOpts.outputAudioFormat,\n inputAudioTranscription = this.#defaultOpts.inputAudioTranscription,\n turnDetection = this.#defaultOpts.turnDetection,\n temperature = this.#defaultOpts.temperature,\n maxResponseOutputTokens = this.#defaultOpts.maxResponseOutputTokens,\n }: {\n fncCtx?: llm.FunctionContext;\n chatCtx?: llm.ChatContext;\n modalities?: ['text', 'audio'] | ['text'];\n instructions?: string;\n voice?: api_proto.Voice;\n inputAudioFormat?: api_proto.AudioFormat;\n outputAudioFormat?: api_proto.AudioFormat;\n inputAudioTranscription?: api_proto.InputAudioTranscription | null;\n turnDetection?: api_proto.TurnDetectionType | null;\n temperature?: number;\n maxResponseOutputTokens?: number;\n }): RealtimeSession {\n const opts: ModelOptions = {\n modalities,\n instructions,\n voice,\n inputAudioFormat,\n outputAudioFormat,\n inputAudioTranscription,\n turnDetection,\n temperature,\n maxResponseOutputTokens,\n model: this.#defaultOpts.model,\n apiKey: this.#defaultOpts.apiKey,\n baseURL: this.#defaultOpts.baseURL,\n isAzure: this.#defaultOpts.isAzure,\n apiVersion: this.#defaultOpts.apiVersion,\n entraToken: this.#defaultOpts.entraToken,\n };\n\n const newSession = new RealtimeSession(opts, {\n chatCtx: chatCtx || new llm.ChatContext(),\n fncCtx,\n });\n this.#sessions.push(newSession);\n return newSession;\n }\n\n async close() {\n await Promise.allSettled(this.#sessions.map((session) => session.close()));\n }\n}\n\nexport class RealtimeSession extends multimodal.RealtimeSession {\n #chatCtx: llm.ChatContext | undefined = undefined;\n #fncCtx: llm.FunctionContext | undefined = undefined;\n #opts: ModelOptions;\n #pendingResponses: { [id: string]: RealtimeResponse } = {};\n #sessionId = 'not-connected';\n #ws: WebSocket | null = null;\n #expiresAt: number | null = null;\n #logger = log();\n #task: Promise<void>;\n #closing = true;\n #sendQueue = new Queue<api_proto.ClientEvent>();\n\n constructor(\n opts: ModelOptions,\n { fncCtx, chatCtx }: { fncCtx?: llm.FunctionContext; chatCtx?: llm.ChatContext },\n ) {\n super();\n\n this.#opts = opts;\n this.#chatCtx = chatCtx;\n this.#fncCtx = fncCtx;\n\n this.#task = this.#start();\n\n this.sessionUpdate({\n modalities: this.#opts.modalities,\n instructions: this.#opts.instructions,\n voice: this.#opts.voice,\n inputAudioFormat: this.#opts.inputAudioFormat,\n outputAudioFormat: this.#opts.outputAudioFormat,\n inputAudioTranscription: this.#opts.inputAudioTranscription,\n turnDetection: this.#opts.turnDetection,\n temperature: this.#opts.temperature,\n maxResponseOutputTokens: this.#opts.maxResponseOutputTokens,\n toolChoice: 'auto',\n });\n }\n\n get chatCtx(): llm.ChatContext | undefined {\n return this.#chatCtx;\n }\n\n get fncCtx(): llm.FunctionContext | undefined {\n return this.#fncCtx;\n }\n\n set fncCtx(ctx: llm.FunctionContext | undefined) {\n this.#fncCtx = ctx;\n }\n\n get conversation(): Conversation {\n return new Conversation(this);\n }\n\n get inputAudioBuffer(): InputAudioBuffer {\n return new InputAudioBuffer(this);\n }\n\n get response(): Response {\n return new Response(this);\n }\n\n get expiration(): number {\n if (!this.#expiresAt) {\n throw new Error('session not started');\n }\n return this.#expiresAt * 1000;\n }\n\n queueMsg(command: api_proto.ClientEvent): void {\n this.#sendQueue.put(command);\n }\n\n /// Truncates the data field of the event to the specified maxLength to avoid overwhelming logs\n /// with large amounts of base64 audio data.\n #loggableEvent(\n event: api_proto.ClientEvent | api_proto.ServerEvent,\n maxLength: number = 30,\n ): Record<string, unknown> {\n const untypedEvent: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(event)) {\n if (value !== undefined) {\n untypedEvent[key] = value;\n }\n }\n\n if (untypedEvent.audio && typeof untypedEvent.audio === 'string') {\n const truncatedData =\n untypedEvent.audio.slice(0, maxLength) + (untypedEvent.audio.length > maxLength ? '…' : '');\n return { ...untypedEvent, audio: truncatedData };\n }\n if (\n untypedEvent.delta &&\n typeof untypedEvent.delta === 'string' &&\n event.type === 'response.audio.delta'\n ) {\n const truncatedDelta =\n untypedEvent.delta.slice(0, maxLength) + (untypedEvent.delta.length > maxLength ? '…' : '');\n return { ...untypedEvent, delta: truncatedDelta };\n }\n return untypedEvent;\n }\n\n sessionUpdate({\n modalities = this.#opts.modalities,\n instructions = this.#opts.instructions,\n voice = this.#opts.voice,\n inputAudioFormat = this.#opts.inputAudioFormat,\n outputAudioFormat = this.#opts.outputAudioFormat,\n inputAudioTranscription = this.#opts.inputAudioTranscription,\n turnDetection = this.#opts.turnDetection,\n temperature = this.#opts.temperature,\n maxResponseOutputTokens = this.#opts.maxResponseOutputTokens,\n toolChoice = 'auto',\n }: {\n modalities: ['text', 'audio'] | ['text'];\n instructions?: string;\n voice?: api_proto.Voice;\n inputAudioFormat?: api_proto.AudioFormat;\n outputAudioFormat?: api_proto.AudioFormat;\n inputAudioTranscription?: api_proto.InputAudioTranscription | null;\n turnDetection?: api_proto.TurnDetectionType | null;\n temperature?: number;\n maxResponseOutputTokens?: number;\n toolChoice?: api_proto.ToolChoice;\n }) {\n this.#opts = {\n modalities,\n instructions,\n voice,\n inputAudioFormat,\n outputAudioFormat,\n inputAudioTranscription,\n turnDetection,\n temperature,\n maxResponseOutputTokens,\n model: this.#opts.model,\n apiKey: this.#opts.apiKey,\n baseURL: this.#opts.baseURL,\n isAzure: this.#opts.isAzure,\n apiVersion: this.#opts.apiVersion,\n entraToken: this.#opts.entraToken,\n };\n\n const tools = this.#fncCtx\n ? Object.entries(this.#fncCtx).map(([name, func]) => ({\n type: 'function' as const,\n name,\n description: func.description,\n parameters:\n // don't format parameters if they are raw openai params\n func.parameters.type == ('object' as const)\n ? func.parameters\n : llm.oaiParams(func.parameters),\n }))\n : [];\n\n const sessionUpdateEvent: api_proto.SessionUpdateEvent = {\n type: 'session.update',\n session: {\n modalities: this.#opts.modalities,\n instructions: this.#opts.instructions,\n voice: this.#opts.voice,\n input_audio_format: this.#opts.inputAudioFormat,\n output_audio_format: this.#opts.outputAudioFormat,\n input_audio_transcription: this.#opts.inputAudioTranscription,\n turn_detection: this.#opts.turnDetection,\n temperature: this.#opts.temperature,\n max_response_output_tokens:\n this.#opts.maxResponseOutputTokens === Infinity\n ? 'inf'\n : this.#opts.maxResponseOutputTokens,\n tools,\n tool_choice: toolChoice,\n },\n };\n\n if (this.#opts.isAzure && this.#opts.maxResponseOutputTokens === Infinity) {\n // microsoft doesn't support inf for max_response_output_tokens, but accepts no args\n sessionUpdateEvent.session.max_response_output_tokens = undefined;\n }\n\n this.queueMsg(sessionUpdateEvent);\n }\n\n #start(): Promise<void> {\n return new Promise(async (resolve, reject) => {\n const headers: Record<string, string> = {\n 'User-Agent': 'LiveKit-Agents-JS',\n };\n if (this.#opts.isAzure) {\n // Microsoft API has two ways of authentication\n // 1. Entra token set as `Bearer` token\n // 2. API key set as `api_key` header (also accepts query string)\n if (this.#opts.entraToken) {\n headers.Authorization = `Bearer ${this.#opts.entraToken}`;\n } else if (this.#opts.apiKey) {\n headers['api-key'] = this.#opts.apiKey;\n } else {\n reject(new Error('Microsoft API key or entraToken is required'));\n return;\n }\n } else {\n headers.Authorization = `Bearer ${this.#opts.apiKey}`;\n headers['OpenAI-Beta'] = 'realtime=v1';\n }\n const url = new URL([this.#opts.baseURL, 'realtime'].join('/'));\n if (url.protocol === 'https:') {\n url.protocol = 'wss:';\n }\n\n // Construct query parameters\n const queryParams: Record<string, string> = {};\n if (this.#opts.isAzure) {\n queryParams['api-version'] = '2024-10-01-preview';\n queryParams['deployment'] = this.#opts.model;\n } else {\n queryParams['model'] = this.#opts.model;\n }\n\n for (const [key, value] of Object.entries(queryParams)) {\n url.searchParams.set(key, value);\n }\n\n console.debug('Connecting to OpenAI Realtime API at ', url.toString());\n this.#ws = new WebSocket(url.toString(), {\n headers: headers,\n });\n\n this.#ws.onerror = (error) => {\n reject(new Error('OpenAI Realtime WebSocket error: ' + error.message));\n };\n\n await once(this.#ws, 'open');\n this.#closing = false;\n\n this.#ws.onmessage = (message) => {\n const event: api_proto.ServerEvent = JSON.parse(message.data as string);\n this.#logger.debug(`<- ${JSON.stringify(this.#loggableEvent(event))}`);\n switch (event.type) {\n case 'error':\n this.#handleError(event);\n break;\n case 'session.created':\n this.#handleSessionCreated(event);\n break;\n case 'session.updated':\n this.#handleSessionUpdated(event);\n break;\n case 'conversation.created':\n this.#handleConversationCreated(event);\n break;\n case 'input_audio_buffer.committed':\n this.#handleInputAudioBufferCommitted(event);\n break;\n case 'input_audio_buffer.cleared':\n this.#handleInputAudioBufferCleared(event);\n break;\n case 'input_audio_buffer.speech_started':\n this.#handleInputAudioBufferSpeechStarted(event);\n break;\n case 'input_audio_buffer.speech_stopped':\n this.#handleInputAudioBufferSpeechStopped(event);\n break;\n case 'conversation.item.created':\n this.#handleConversationItemCreated(event);\n break;\n case 'conversation.item.input_audio_transcription.completed':\n this.#handleConversationItemInputAudioTranscriptionCompleted(event);\n break;\n case 'conversation.item.input_audio_transcription.failed':\n this.#handleConversationItemInputAudioTranscriptionFailed(event);\n break;\n case 'conversation.item.truncated':\n this.#handleConversationItemTruncated(event);\n break;\n case 'conversation.item.deleted':\n this.#handleConversationItemDeleted(event);\n break;\n case 'response.created':\n this.#handleResponseCreated(event);\n break;\n case 'response.done':\n this.#handleResponseDone(event);\n break;\n case 'response.output_item.added':\n this.#handleResponseOutputItemAdded(event);\n break;\n case 'response.output_item.done':\n this.#handleResponseOutputItemDone(event);\n break;\n case 'response.content_part.added':\n this.#handleResponseContentPartAdded(event);\n break;\n case 'response.content_part.done':\n this.#handleResponseContentPartDone(event);\n break;\n case 'response.text.delta':\n this.#handleResponseTextDelta(event);\n break;\n case 'response.text.done':\n this.#handleResponseTextDone(event);\n break;\n case 'response.audio_transcript.delta':\n this.#handleResponseAudioTranscriptDelta(event);\n break;\n case 'response.audio_transcript.done':\n this.#handleResponseAudioTranscriptDone(event);\n break;\n case 'response.audio.delta':\n this.#handleResponseAudioDelta(event);\n break;\n case 'response.audio.done':\n this.#handleResponseAudioDone(event);\n break;\n case 'response.function_call_arguments.delta':\n this.#handleResponseFunctionCallArgumentsDelta(event);\n break;\n case 'response.function_call_arguments.done':\n this.#handleResponseFunctionCallArgumentsDone(event);\n break;\n case 'rate_limits.updated':\n this.#handleRateLimitsUpdated(event);\n break;\n }\n };\n\n const sendTask = async () => {\n while (this.#ws && !this.#closing && this.#ws.readyState === WebSocket.OPEN) {\n try {\n const event = await this.#sendQueue.get();\n if (event.type !== 'input_audio_buffer.append') {\n this.#logger.debug(`-> ${JSON.stringify(this.#loggableEvent(event))}`);\n }\n this.#ws.send(JSON.stringify(event));\n } catch (error) {\n this.#logger.error('Error sending event:', error);\n }\n }\n };\n\n sendTask();\n\n this.#ws.onclose = () => {\n if (this.#expiresAt && Date.now() >= this.#expiresAt * 1000) {\n this.#closing = true;\n }\n if (!this.#closing) {\n reject(new Error('OpenAI Realtime connection closed unexpectedly'));\n }\n this.#ws = null;\n resolve();\n };\n });\n }\n\n async close() {\n if (!this.#ws) return;\n this.#closing = true;\n this.#ws.close();\n await this.#task;\n }\n\n #getContent(ptr: ContentPtr): RealtimeContent {\n const response = this.#pendingResponses[ptr.response_id];\n const output = response!.output[ptr.output_index];\n const content = output!.content[ptr.content_index]!;\n return content;\n }\n\n #handleError(event: api_proto.ErrorEvent): void {\n this.#logger.error(`OpenAI Realtime error ${JSON.stringify(event.error)}`);\n }\n\n #handleSessionCreated(event: api_proto.SessionCreatedEvent): void {\n this.#sessionId = event.session.id;\n this.#expiresAt = event.session.expires_at;\n this.#logger = this.#logger.child({ sessionId: this.#sessionId });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n #handleSessionUpdated(event: api_proto.SessionUpdatedEvent): void {}\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n #handleConversationCreated(event: api_proto.ConversationCreatedEvent): void {}\n\n #handleInputAudioBufferCommitted(event: api_proto.InputAudioBufferCommittedEvent): void {\n this.emit('input_speech_committed', {\n itemId: event.item_id,\n } as InputSpeechCommitted);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n #handleInputAudioBufferCleared(event: api_proto.InputAudioBufferClearedEvent): void {}\n\n #handleInputAudioBufferSpeechStarted(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n event: api_proto.InputAudioBufferSpeechStartedEvent,\n ): void {\n this.emit('input_speech_started', {\n itemId: event.item_id,\n } as InputSpeechStarted);\n }\n\n #handleInputAudioBufferSpeechStopped(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n event: api_proto.InputAudioBufferSpeechStoppedEvent,\n ): void {\n this.emit('input_speech_stopped');\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n #handleConversationItemCreated(event: api_proto.ConversationItemCreatedEvent): void {}\n\n #handleConversationItemInputAudioTranscriptionCompleted(\n event: api_proto.ConversationItemInputAudioTranscriptionCompletedEvent,\n ): void {\n const transcript = event.transcript;\n this.emit('input_speech_transcription_completed', {\n itemId: event.item_id,\n transcript: transcript,\n } as InputSpeechTranscriptionCompleted);\n }\n\n #handleConversationItemInputAudioTranscriptionFailed(\n event: api_proto.ConversationItemInputAudioTranscriptionFailedEvent,\n ): void {\n const error = event.error;\n this.#logger.error(`OpenAI Realtime failed to transcribe input audio: ${error.message}`);\n this.emit('input_speech_transcription_failed', {\n itemId: event.item_id,\n message: error.message,\n } as InputSpeechTranscriptionFailed);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n #handleConversationItemTruncated(event: api_proto.ConversationItemTruncatedEvent): void {}\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n #handleConversationItemDeleted(event: api_proto.ConversationItemDeletedEvent): void {}\n\n #handleResponseCreated(responseCreated: api_proto.ResponseCreatedEvent): void {\n const response = responseCreated.response;\n const doneFut = new Future();\n const newResponse: RealtimeResponse = {\n id: response.id,\n status: response.status,\n statusDetails: response.status_details,\n usage: null,\n output: [],\n doneFut: doneFut,\n createdTimestamp: Date.now(),\n };\n this.#pendingResponses[newResponse.id] = newResponse;\n this.emit('response_created', newResponse);\n }\n\n #handleResponseDone(event: api_proto.ResponseDoneEvent): void {\n const responseData = event.response;\n const responseId = responseData.id;\n const response = this.#pendingResponses[responseId]!;\n response.status = responseData.status;\n response.statusDetails = responseData.status_details;\n response.usage = responseData.usage ?? null;\n this.#pendingResponses[responseId] = response;\n response.doneFut.resolve();\n\n let metricsError: Error | undefined;\n let cancelled = false;\n switch (response.status) {\n case 'failed': {\n if (response.statusDetails.type !== 'failed') break;\n const err = response.statusDetails.error;\n metricsError = new metrics.MultimodalLLMError({\n type: response.statusDetails.type,\n code: err?.code,\n message: err?.message,\n });\n this.#logger\n .child({ code: err?.code, error: err?.message })\n .error('response generation failed');\n break;\n }\n case 'incomplete': {\n if (response.statusDetails.type !== 'incomplete') break;\n const reason = response.statusDetails.reason;\n metricsError = new metrics.MultimodalLLMError({\n type: response.statusDetails.type,\n reason,\n });\n this.#logger.child({ reason }).error('response generation incomplete');\n break;\n }\n case 'cancelled': {\n cancelled = true;\n break;\n }\n }\n this.emit('response_done', response);\n\n let ttft: number | undefined;\n if (response.firstTokenTimestamp) {\n ttft = response.firstTokenTimestamp - response.createdTimestamp;\n }\n const duration = Date.now() - response.createdTimestamp;\n\n const usage = response.usage;\n const metric: metrics.MultimodalLLMMetrics = {\n timestamp: response.createdTimestamp,\n requestId: response.id,\n ttft: ttft!,\n duration,\n cancelled,\n label: this.constructor.name,\n completionTokens: usage?.output_tokens || 0,\n promptTokens: usage?.input_tokens || 0,\n totalTokens: usage?.total_tokens || 0,\n tokensPerSecond: ((usage?.output_tokens || 0) / duration) * 1000,\n error: metricsError,\n inputTokenDetails: {\n cachedTokens: usage?.input_token_details.cached_tokens || 0,\n textTokens: usage?.input_token_details.text_tokens || 0,\n audioTokens: usage?.input_token_details.audio_tokens || 0,\n },\n outputTokenDetails: {\n textTokens: usage?.output_token_details.text_tokens || 0,\n audioTokens: usage?.output_token_details.audio_tokens || 0,\n },\n };\n this.emit('metrics_collected', metric);\n }\n\n #handleResponseOutputItemAdded(event: api_proto.ResponseOutputItemAddedEvent): void {\n const responseId = event.response_id;\n const response = this.#pendingResponses[responseId];\n const itemData = event.item;\n\n if (itemData.type !== 'message' && itemData.type !== 'function_call') {\n throw new Error(`Unexpected item type: ${itemData.type}`);\n }\n\n let role: api_proto.Role;\n if (itemData.type === 'function_call') {\n role = 'assistant'; // function_call doesn't have a role field, defaulting it to assistant\n } else {\n role = itemData.role;\n }\n\n const newOutput: RealtimeOutput = {\n responseId: responseId,\n itemId: itemData.id,\n outputIndex: event.output_index,\n type: itemData.type,\n role: role,\n content: [],\n doneFut: new Future(),\n };\n response?.output.push(newOutput);\n this.emit('response_output_added', newOutput);\n }\n\n #handleResponseOutputItemDone(event: api_proto.ResponseOutputItemDoneEvent): void {\n const responseId = event.response_id;\n const response = this.#pendingResponses[responseId];\n const outputIndex = event.output_index;\n const output = response!.output[outputIndex];\n\n if (output?.type === 'function_call') {\n if (!this.#fncCtx) {\n this.#logger.error('function call received but no fncCtx is available');\n return;\n }\n\n // parse the arguments and call the function inside the fnc_ctx\n const item = event.item;\n if (item.type !== 'function_call') {\n throw new Error('Expected function_call item');\n }\n const func = this.#fncCtx[item.name];\n if (!func) {\n this.#logger.error(`no function with name ${item.name} in fncCtx`);\n return;\n }\n\n this.emit('function_call_started', {\n callId: item.call_id,\n });\n\n const parsedArgs = JSON.parse(item.arguments);\n\n this.#logger.debug(\n `[Function Call ${item.call_id}] Executing ${item.name} with arguments ${parsedArgs}`,\n );\n\n func.execute(parsedArgs).then(\n (content) => {\n this.#logger.debug(`[Function Call ${item.call_id}] ${item.name} returned ${content}`);\n this.emit('function_call_completed', {\n callId: item.call_id,\n });\n this.conversation.item.create(\n llm.ChatMessage.createToolFromFunctionResult({\n name: item.name,\n toolCallId: item.call_id,\n result: content,\n }),\n output.itemId,\n );\n this.response.create();\n },\n (error) => {\n this.#logger.error(`[Function Call ${item.call_id}] ${item.name} failed with ${error}`);\n // TODO: send it back up as failed?\n this.emit('function_call_failed', {\n callId: item.call_id,\n });\n },\n );\n }\n\n output?.doneFut.resolve();\n this.emit('response_output_done', output);\n }\n\n #handleResponseContentPartAdded(event: api_proto.ResponseContentPartAddedEvent): void {\n const responseId = event.response_id;\n const response = this.#pendingResponses[responseId];\n const outputIndex = event.output_index;\n const output = response!.output[outputIndex];\n\n const textStream = new AsyncIterableQueue<string>();\n const audioStream = new AsyncIterableQueue<AudioFrame>();\n\n const newContent: RealtimeContent = {\n responseId: responseId,\n itemId: event.item_id,\n outputIndex: outputIndex,\n contentIndex: event.content_index,\n text: '',\n audio: [],\n textStream: textStream,\n audioStream: audioStream,\n toolCalls: [],\n };\n output?.content.push(newContent);\n response!.firstTokenTimestamp = Date.now();\n this.emit('response_content_added', newContent);\n }\n\n #handleResponseContentPartDone(event: api_proto.ResponseContentPartDoneEvent): void {\n const content = this.#getContent(event);\n this.emit('response_content_done', content);\n }\n\n #handleResponseTextDelta(event: api_proto.ResponseTextDeltaEvent): void {\n this.emit('response_text_delta', event);\n }\n\n #handleResponseTextDone(event: api_proto.ResponseTextDoneEvent): void {\n this.emit('response_text_done', event);\n }\n\n #handleResponseAudioTranscriptDelta(event: api_proto.ResponseAudioTranscriptDeltaEvent): void {\n const content = this.#getContent(event);\n const transcript = event.delta;\n content.text += transcript;\n\n content.textStream.put(transcript);\n }\n\n #handleResponseAudioTranscriptDone(event: api_proto.ResponseAudioTranscriptDoneEvent): void {\n const content = this.#getContent(event);\n content.textStream.close();\n }\n\n #handleResponseAudioDelta(event: api_proto.ResponseAudioDeltaEvent): void {\n const content = this.#getContent(event);\n const data = Buffer.from(event.delta, 'base64');\n const audio = new AudioFrame(\n new Int16Array(data.buffer),\n api_proto.SAMPLE_RATE,\n api_proto.NUM_CHANNELS,\n data.length / 2,\n );\n content.audio.push(audio);\n\n content.audioStream.put(audio);\n }\n\n #handleResponseAudioDone(event: api_proto.ResponseAudioDoneEvent): void {\n const content = this.#getContent(event);\n content.audioStream.close();\n }\n\n #handleResponseFunctionCallArgumentsDelta(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n event: api_proto.ResponseFunctionCallArgumentsDeltaEvent,\n ): void {}\n\n #handleResponseFunctionCallArgumentsDone(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n event: api_proto.ResponseFunctionCallArgumentsDoneEvent,\n ): void {}\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n #handleRateLimitsUpdated(event: api_proto.RateLimitsUpdatedEvent): void {}\n}\n"],"mappings":"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","names":["c"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime_model.d.ts","sourceRoot":"","sources":["../../src/realtime/realtime_model.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,kBAAkB,EAClB,MAAM,EAEN,GAAG,
|
|
1
|
+
{"version":3,"file":"realtime_model.d.ts","sourceRoot":"","sources":["../../src/realtime/realtime_model.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
llm,
|
|
6
6
|
log,
|
|
7
7
|
mergeFrames,
|
|
8
|
+
metrics,
|
|
8
9
|
multimodal
|
|
9
10
|
} from "@livekit/agents";
|
|
10
11
|
import { AudioFrame } from "@livekit/rtc-node";
|
|
@@ -685,7 +686,8 @@ class RealtimeSession extends multimodal.RealtimeSession {
|
|
|
685
686
|
statusDetails: response.status_details,
|
|
686
687
|
usage: null,
|
|
687
688
|
output: [],
|
|
688
|
-
doneFut
|
|
689
|
+
doneFut,
|
|
690
|
+
createdTimestamp: Date.now()
|
|
689
691
|
};
|
|
690
692
|
this.#pendingResponses[newResponse.id] = newResponse;
|
|
691
693
|
this.emit("response_created", newResponse);
|
|
@@ -699,7 +701,65 @@ class RealtimeSession extends multimodal.RealtimeSession {
|
|
|
699
701
|
response.usage = responseData.usage ?? null;
|
|
700
702
|
this.#pendingResponses[responseId] = response;
|
|
701
703
|
response.doneFut.resolve();
|
|
704
|
+
let metricsError;
|
|
705
|
+
let cancelled = false;
|
|
706
|
+
switch (response.status) {
|
|
707
|
+
case "failed": {
|
|
708
|
+
if (response.statusDetails.type !== "failed") break;
|
|
709
|
+
const err = response.statusDetails.error;
|
|
710
|
+
metricsError = new metrics.MultimodalLLMError({
|
|
711
|
+
type: response.statusDetails.type,
|
|
712
|
+
code: err == null ? void 0 : err.code,
|
|
713
|
+
message: err == null ? void 0 : err.message
|
|
714
|
+
});
|
|
715
|
+
this.#logger.child({ code: err == null ? void 0 : err.code, error: err == null ? void 0 : err.message }).error("response generation failed");
|
|
716
|
+
break;
|
|
717
|
+
}
|
|
718
|
+
case "incomplete": {
|
|
719
|
+
if (response.statusDetails.type !== "incomplete") break;
|
|
720
|
+
const reason = response.statusDetails.reason;
|
|
721
|
+
metricsError = new metrics.MultimodalLLMError({
|
|
722
|
+
type: response.statusDetails.type,
|
|
723
|
+
reason
|
|
724
|
+
});
|
|
725
|
+
this.#logger.child({ reason }).error("response generation incomplete");
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
728
|
+
case "cancelled": {
|
|
729
|
+
cancelled = true;
|
|
730
|
+
break;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
702
733
|
this.emit("response_done", response);
|
|
734
|
+
let ttft;
|
|
735
|
+
if (response.firstTokenTimestamp) {
|
|
736
|
+
ttft = response.firstTokenTimestamp - response.createdTimestamp;
|
|
737
|
+
}
|
|
738
|
+
const duration = Date.now() - response.createdTimestamp;
|
|
739
|
+
const usage = response.usage;
|
|
740
|
+
const metric = {
|
|
741
|
+
timestamp: response.createdTimestamp,
|
|
742
|
+
requestId: response.id,
|
|
743
|
+
ttft,
|
|
744
|
+
duration,
|
|
745
|
+
cancelled,
|
|
746
|
+
label: this.constructor.name,
|
|
747
|
+
completionTokens: (usage == null ? void 0 : usage.output_tokens) || 0,
|
|
748
|
+
promptTokens: (usage == null ? void 0 : usage.input_tokens) || 0,
|
|
749
|
+
totalTokens: (usage == null ? void 0 : usage.total_tokens) || 0,
|
|
750
|
+
tokensPerSecond: ((usage == null ? void 0 : usage.output_tokens) || 0) / duration * 1e3,
|
|
751
|
+
error: metricsError,
|
|
752
|
+
inputTokenDetails: {
|
|
753
|
+
cachedTokens: (usage == null ? void 0 : usage.input_token_details.cached_tokens) || 0,
|
|
754
|
+
textTokens: (usage == null ? void 0 : usage.input_token_details.text_tokens) || 0,
|
|
755
|
+
audioTokens: (usage == null ? void 0 : usage.input_token_details.audio_tokens) || 0
|
|
756
|
+
},
|
|
757
|
+
outputTokenDetails: {
|
|
758
|
+
textTokens: (usage == null ? void 0 : usage.output_token_details.text_tokens) || 0,
|
|
759
|
+
audioTokens: (usage == null ? void 0 : usage.output_token_details.audio_tokens) || 0
|
|
760
|
+
}
|
|
761
|
+
};
|
|
762
|
+
this.emit("metrics_collected", metric);
|
|
703
763
|
}
|
|
704
764
|
#handleResponseOutputItemAdded(event) {
|
|
705
765
|
const responseId = event.response_id;
|
|
@@ -798,6 +858,7 @@ class RealtimeSession extends multimodal.RealtimeSession {
|
|
|
798
858
|
toolCalls: []
|
|
799
859
|
};
|
|
800
860
|
output == null ? void 0 : output.content.push(newContent);
|
|
861
|
+
response.firstTokenTimestamp = Date.now();
|
|
801
862
|
this.emit("response_content_added", newContent);
|
|
802
863
|
}
|
|
803
864
|
#handleResponseContentPartDone(event) {
|