UNPKG

@llumiverse/core

Version:

Provide an universal API to LLMs. Support for existing LLMs can be added by writing a driver.

131 lines 4.16 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EventStream = void 0; exports.asyncMap = asyncMap; exports.oneAsyncIterator = oneAsyncIterator; exports.transformSSEStream = transformSSEStream; exports.transformAsyncIterator = transformAsyncIterator; async function* asyncMap(asyncIterable, callback) { let i = 0; for await (const val of asyncIterable) yield callback(val, i++); } function oneAsyncIterator(value) { return { async *[Symbol.asyncIterator]() { yield value; } }; } /** * Given a ReadableStream of server sent events, tran */ function transformSSEStream(stream, transform) { // on node and bun the ReadableStream is an async iterable return stream.pipeThrough(new TransformStream({ transform(event, controller) { if (event.type === 'event' && event.data && event.data !== '[DONE]') { try { const result = transform(event.data) ?? ''; controller.enqueue(result); } catch (err) { // double check for the last event which is not a JSON - at this time togetherai and mistralai returns the string [DONE] // do nothing - happens if data is not a JSON - the last event data is the [DONE] string } } } })); } class EventStream { queue = []; pending; done = false; push(event) { if (this.done) { throw new Error('Cannot push to a closed stream'); } if (this.pending) { this.pending.resolve({ value: event }); this.pending = undefined; } else { this.queue.push(event); } } /** * Close the stream. This means the stream cannot be fed anymore. * But the consumer can still consume the remaining events. */ close(value) { this.done = true; if (this.pending) { this.pending.resolve({ done: true, value }); this.pending = undefined; } } [Symbol.asyncIterator]() { const self = this; return { next() { const next = self.queue.shift(); if (next !== undefined) { return Promise.resolve({ value: next }); } else if (self.done) { return Promise.resolve({ done: true, value: undefined }); } else { return new Promise((resolve, reject) => { self.pending = { resolve, reject }; }); } }, async return(value) { self.done = true; self.queue = []; if (value === undefined) { return { done: true, value: undefined }; } const _value = await value; return { done: true, value: _value }; } }; } } exports.EventStream = EventStream; /** * Transform an async iterator by applying a function to each value. * @param originalGenerator * @param transform **/ async function* transformAsyncIterator(originalGenerator, transform, initCallback) { if (initCallback) { yield initCallback(); } for await (const value of originalGenerator) { yield transform(value); } } //TODO move in a test file // const max = 10; let cnt = 0; // function feedStream(stream: EventStream<string>) { // setTimeout(() => { // cnt++; // console.log('push: ', cnt, max); // stream.push('event ' + cnt); // if (cnt < max) { // console.log('next: ', cnt, max); // setTimeout(() => feedStream(stream), 1000); // } else { // console.log('end of stream'); // stream.close(); // } // }, 1000); // } // const stream = new EventStream<string>(); // feedStream(stream); // for await (const chunk of stream) { // console.log('++++chunk:', chunk); // } //# sourceMappingURL=async.js.map