@axflow/models
Advanced tools
Comparing version 0.0.1-alpha.9 to 0.0.1-beta.0
@@ -0,1 +1,3 @@ | ||
import { JSONValueType } from '@axflow/models/shared'; | ||
declare class HttpError extends Error { | ||
@@ -12,6 +14,18 @@ readonly code: number; | ||
/** | ||
* Convert a ReadableStream<T> to an AsyncIterable<T>. | ||
* | ||
* ReadableStreams implement this natively in recent node versions. Unfortunately, older | ||
* node versions, most browsers, and the TypeScript type system do not support it yet. | ||
* | ||
* Example: | ||
* | ||
* for await (const chunk of StreamToIterable(stream)) { | ||
* // Do stuff with chunk | ||
* } | ||
* | ||
* @param stream A ReadableStream | ||
* @returns An AsyncIterable over the stream contents | ||
*/ | ||
declare function StreamToIterable<T>(stream: ReadableStream<T>): AsyncIterable<T>; | ||
type JSONValueType = null | string | number | boolean | { | ||
[x: string]: JSONValueType; | ||
} | Array<JSONValueType>; | ||
type NdJsonValueType = { | ||
@@ -25,6 +39,78 @@ type: 'chunk' | 'data'; | ||
}>; | ||
/** | ||
* Returns a streaming newline-delimited JSON `Response` object. | ||
* | ||
* Example: | ||
* | ||
* export async function POST(request: Request) { | ||
* const req = await request.json(); | ||
* const stream = await OpenAIChat.stream(req, { apiKey: process.env.OPENAI_API_KEY! }); | ||
* return NdJsonStream.response(stream, { | ||
* map: (chunk) => chunk.choices[0].delta.content ?? '', | ||
* }); | ||
* } | ||
* | ||
* @param stream A readable stream of chunks to encode as ndjson | ||
* @param options | ||
* @param options.status HTTP response status | ||
* @param options.statusText HTTP response status text | ||
* @param options.headers HTTP response headers | ||
* @param options.map A function to map input chunks to output chunks. The return value must be either a JSON-serializable object or a Promise that resolves to a JSON-serializable object. | ||
* @param options.data Additional data to prepend to the output stream | ||
* @returns A streaming newline-delimited JSON `Response` object | ||
*/ | ||
static response<T>(stream: ReadableStream<T>, options?: ResponseInit & { | ||
map?: (value: T) => JSONValueType | Promise<JSONValueType>; | ||
data?: JSONValueType[]; | ||
}): Response; | ||
/** | ||
* Transforms a stream of JSON-serializable objects to stream of newline-delimited JSON. | ||
* | ||
* Each object is wrapped with an object that specifies the `type` and references | ||
* the `value`. The `type` is one of `chunk` or `data`. A type of `chunk` means that | ||
* the `value` corresponds to chunks from the input stream. A type of `data` means | ||
* that the `value` corresponds to the additional data provided as the second argument | ||
* to this function. | ||
* | ||
* | ||
* Example WITHOUT additional data: | ||
* | ||
* const chunk = { key: 'value' }; | ||
* const stream = new ReadableStream({start(con) { con.enqueue(chunk); con.close() }}); | ||
* const ndJsonStream = NdJsonStream.encode(stream); | ||
* const entries = []; | ||
* for await (const chunk of stream) { | ||
* entry.push(new TextDecoder().decode(chunk)); | ||
* } | ||
* console.log(entries); // [ "{\"type\":\"chunk\",\"value\":{\"key\":\"value\"}}\n" ] | ||
* | ||
* | ||
* Example WITH additional data: | ||
* | ||
* const chunk = { key: 'value' }; | ||
* const stream = new ReadableStream({start(con) { con.enqueue(chunk); con.close() }}); | ||
* const ndJsonStream = NdJsonStream.encode(stream, { data: [{ extra: 'data' }] }); | ||
* const entries = []; | ||
* for await (const chunk of stream) { | ||
* entry.push(new TextDecoder().decode(chunk)); | ||
* } | ||
* console.log(entries); // [ "{\"type\":\"data\",\"value\":{\"extra\":\"data\"}}\n", "{\"type\":\"chunk\",\"value\":{\"key\":\"value\"}}\n" ] | ||
* | ||
* | ||
* @param stream A readable stream of chunks to encode as ndjson | ||
* @param options | ||
* @param options.map A function to map input chunks to output chunks. The return value must be either a JSON-serializable object or a Promise that resolves to a JSON-serializable object | ||
* @param options.data Additional data to prepend to the output stream | ||
* @returns A readable stream of newline-delimited JSON | ||
*/ | ||
static encode<T = any>(stream: ReadableStream<T>, options?: { | ||
map?: (value: T) => JSONValueType; | ||
data?: Record<string, JSONValueType>[]; | ||
map?: (value: T) => JSONValueType | Promise<JSONValueType>; | ||
data?: JSONValueType[]; | ||
}): ReadableStream<Uint8Array>; | ||
/** | ||
* Transforms a stream of newline-delimited JSON to a stream of objects. | ||
* | ||
* @param stream A readable stream of newline-delimited JSON objects | ||
* @returns A readable stream of objects | ||
*/ | ||
static decode(stream: ReadableStream<Uint8Array>): ReadableStream<NdJsonValueType>; | ||
@@ -31,0 +117,0 @@ } |
@@ -81,5 +81,36 @@ "use strict"; | ||
} | ||
var NdJsonStream = class { | ||
var NdJsonStream = class _NdJsonStream { | ||
static headers = Object.freeze({ "content-type": "application/x-ndjson; charset=utf-8" }); | ||
/** | ||
* Returns a streaming newline-delimited JSON `Response` object. | ||
* | ||
* Example: | ||
* | ||
* export async function POST(request: Request) { | ||
* const req = await request.json(); | ||
* const stream = await OpenAIChat.stream(req, { apiKey: process.env.OPENAI_API_KEY! }); | ||
* return NdJsonStream.response(stream, { | ||
* map: (chunk) => chunk.choices[0].delta.content ?? '', | ||
* }); | ||
* } | ||
* | ||
* @param stream A readable stream of chunks to encode as ndjson | ||
* @param options | ||
* @param options.status HTTP response status | ||
* @param options.statusText HTTP response status text | ||
* @param options.headers HTTP response headers | ||
* @param options.map A function to map input chunks to output chunks. The return value must be either a JSON-serializable object or a Promise that resolves to a JSON-serializable object. | ||
* @param options.data Additional data to prepend to the output stream | ||
* @returns A streaming newline-delimited JSON `Response` object | ||
*/ | ||
static response(stream, options) { | ||
options = options ?? {}; | ||
const ndjson = _NdJsonStream.encode(stream, { map: options.map, data: options.data }); | ||
return new Response(ndjson, { | ||
status: options.status, | ||
statusText: options.statusText, | ||
headers: { ...options.headers, ..._NdJsonStream.headers } | ||
}); | ||
} | ||
/** | ||
* Transforms a stream of JSON-serializable objects to stream of newline-delimited JSON. | ||
@@ -118,5 +149,5 @@ * | ||
* | ||
* @param stream A readable stream of JSON-serializable chunks to encode as ndjson | ||
* @param stream A readable stream of chunks to encode as ndjson | ||
* @param options | ||
* @param options.map A function to map stream chunks to desired, json-serializable outputs | ||
* @param options.map A function to map input chunks to output chunks. The return value must be either a JSON-serializable object or a Promise that resolves to a JSON-serializable object | ||
* @param options.data Additional data to prepend to the output stream | ||
@@ -141,4 +172,5 @@ * @returns A readable stream of newline-delimited JSON | ||
}, | ||
transform(value, controller) { | ||
controller.enqueue(serialize({ type: "chunk", value: map(value) })); | ||
async transform(chunk, controller) { | ||
const value = await Promise.resolve(map(chunk)); | ||
controller.enqueue(serialize({ type: "chunk", value })); | ||
} | ||
@@ -145,0 +177,0 @@ }); |
{ | ||
"name": "@axflow/models", | ||
"version": "0.0.1-alpha.9", | ||
"version": "0.0.1-beta.0", | ||
"description": "Zero-dependency module to run, stream, and render results across the most popular LLMs and embedding models", | ||
@@ -47,2 +47,4 @@ "author": "Axilla (https://axilla.io)", | ||
"@types/jest": "^29.5.3", | ||
"@types/react": "^18.2.21", | ||
"@types/react-dom": "^18.2.7", | ||
"jest": "^29.6.2", | ||
@@ -54,2 +56,10 @@ "prettier": "^3.0.2", | ||
}, | ||
"peerDependencies": { | ||
"react": "^18.2.0" | ||
}, | ||
"peerDependenciesMeta": { | ||
"react": { | ||
"optional": true | ||
} | ||
}, | ||
"typesVersions": { | ||
@@ -75,2 +85,8 @@ "*": { | ||
], | ||
"react": [ | ||
"./dist/react/index.d.ts" | ||
], | ||
"shared": [ | ||
"./dist/shared/index.d.ts" | ||
], | ||
"utils": [ | ||
@@ -119,2 +135,14 @@ "./dist/utils/index.d.ts" | ||
}, | ||
"./react": { | ||
"types": "./dist/react/index.d.ts", | ||
"import": "./dist/react/index.mjs", | ||
"module": "./dist/react/index.mjs", | ||
"require": "./dist/react/index.js" | ||
}, | ||
"./shared": { | ||
"types": "./dist/shared/index.d.ts", | ||
"import": "./dist/shared/index.mjs", | ||
"module": "./dist/shared/index.mjs", | ||
"require": "./dist/shared/index.js" | ||
}, | ||
"./utils": { | ||
@@ -127,3 +155,3 @@ "types": "./dist/utils/index.d.ts", | ||
}, | ||
"gitHead": "cb659f43473fce49cd3283e3a95d3b947dd683a4" | ||
"gitHead": "c5303f65b61cffb5ef0f85acb98a6291d515d6e7" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
99993
39
2161
1
8