@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
JavaScript
;
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