UNPKG

remix-nlux

Version:

Remix IDE NLUX integration. Remix IDE is the leading IDE for building and deploying smart contracts on Ethereum. NLUX is a JavaScript and React library for building conversational AI experiences.

101 lines (90 loc) 3.81 kB
import {ChatAdapterExtras, StreamingAdapterObserver} from '@nlux/core'; import {NluxError, NluxUsageError} from '@shared/types/error'; import {warn} from '@shared/utils/warn'; import {parseChunk} from '../parser/parseChunk'; import {ChatAdapterOptions} from '../types/adapterOptions'; import {adapterErrorToExceptionId} from '../utils/adapterErrorToExceptionId'; import {LangServeAbstractAdapter} from './adapter'; export class LangServeStreamAdapter<AiMsg> extends LangServeAbstractAdapter<AiMsg> { constructor(options: ChatAdapterOptions<AiMsg>) { super(options); } async batchText(message: string, extras: ChatAdapterExtras<AiMsg>): Promise<string | object | undefined> { throw new NluxUsageError({ source: this.constructor.name, message: 'Cannot fetch text using the stream adapter!', }); } streamText( message: string, observer: StreamingAdapterObserver<string | object | undefined>, extras: ChatAdapterExtras<AiMsg>, ): void { const body = this.getRequestBody( message, this.config, extras.conversationHistory, ); fetch(this.endpointUrl, { method: 'POST', headers: { ...this.headers, 'Content-Type': 'application/json', }, body, }) .then(async (response) => { if (!response.ok) { throw new NluxError({ source: this.constructor.name, message: `LangServe runnable returned status code: ${response.status}`, }); } if (!response.body) { throw new NluxError({ source: this.constructor.name, message: `LangServe runnable returned status code: ${response.status}`, }); } // Read a stream of server-sent events // and feed them to the observer as they are being generated const reader = response.body.getReader(); const textDecoder = new TextDecoder(); let doneReading = false; while (!doneReading) { const {value, done} = await reader.read(); if (done) { doneReading = true; break; } const chunk = textDecoder.decode(value); const chunkContent = parseChunk(chunk); if (Array.isArray(chunkContent)) { for (const aiEvent of chunkContent) { if (aiEvent.event === 'data' && aiEvent.data !== undefined) { observer.next(aiEvent.data as string | object | undefined); } if (aiEvent.event === 'end') { observer.complete(); doneReading = true; break; } } } if (chunkContent instanceof Error) { warn(chunkContent); observer.error(chunkContent); doneReading = true; } } }) .catch((error) => { warn(error); observer.error(new NluxUsageError({ source: this.constructor.name, message: error.message, exceptionId: adapterErrorToExceptionId(error) ?? undefined, })); }); } }