Comparing version 0.0.20 to 0.0.21
@@ -26,3 +26,3 @@ "use strict"; | ||
constructor(config) { | ||
const { accessKey, url = "https://api.fxn.ai/graph" } = config; | ||
const { accessKey, url = "https://api.fxn.ai" } = config; | ||
this.url = url; | ||
@@ -39,3 +39,3 @@ this.auth = accessKey ? `Bearer ${accessKey}` : null; | ||
// Request | ||
const response = yield fetch(this.url, { | ||
const response = yield fetch(`${this.url}/graph`, { | ||
method: "POST", | ||
@@ -42,0 +42,0 @@ headers: { Accept: "application/json", "Content-Type": "application/json", Authorization: this.auth }, |
@@ -15,2 +15,14 @@ "use strict"; | ||
}; | ||
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } | ||
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { | ||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); | ||
var g = generator.apply(thisArg, _arguments || []), i, q = []; | ||
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; | ||
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } | ||
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } | ||
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } | ||
function fulfill(value) { resume("next", value); } | ||
function reject(value) { resume("throw", value); } | ||
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } | ||
}; | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
@@ -54,3 +66,3 @@ var t = {}; | ||
* Create a prediction. | ||
* @param input Input arguments. | ||
* @param input Prediction input. | ||
* @returns Prediction. | ||
@@ -61,22 +73,84 @@ */ | ||
const { tag, inputs: rawInputs, rawOutputs, dataUrlLimit } = input; | ||
const minUploadSize = 4096; | ||
const key = Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2); // this doesn't have to be good | ||
const inputs = rawInputs ? | ||
yield Promise.all(Object.entries(rawInputs) | ||
.map(([name, value]) => (0, value_1.toFunctionValue)({ storage: this.storage, value, name, minUploadSize, key }) | ||
.then(f => (Object.assign(Object.assign({}, f), { name }))))) : null; | ||
const _a = (yield this.client.query(`mutation ($input: CreatePredictionInput!) { | ||
// Serialize inputs | ||
const inputObject = yield serializePredictionInputs(rawInputs, this.storage); | ||
const inputs = inputObject ? Object.entries(inputObject).map(([name, value]) => (Object.assign(Object.assign({}, value), { name }))) : null; | ||
// Query | ||
const { data: { prediction } } = yield this.client.query(`mutation ($input: CreatePredictionInput!) { | ||
prediction: createPrediction (input: $input) { | ||
${exports.PREDICTION_FIELDS} | ||
} | ||
}`, { input: { tag, inputs, client, dataUrlLimit } })).data.prediction, { results: rawResults } = _a, others = __rest(_a, ["results"]); | ||
const results = rawResults && !rawOutputs ? | ||
yield Promise.all(rawResults.map(value => (0, value_1.toPlainValue)({ value: value }))) : | ||
rawResults; | ||
const prediction = rawResults !== undefined ? Object.assign(Object.assign({}, others), { results }) : others; | ||
return prediction; | ||
}`, { input: { tag, inputs, client, dataUrlLimit } }); | ||
// Parse | ||
const result = yield deserializePredictionOutputs(prediction, rawOutputs); | ||
// Return | ||
return result; | ||
}); | ||
} | ||
/** | ||
* Create a streaming prediction. | ||
* NOTE: This feature is currently experimental. | ||
* @param input Prediction input. | ||
* @returns Generator which asynchronously returns prediction results as they are streamed from the predictor. | ||
*/ | ||
stream(input) { | ||
return __asyncGenerator(this, arguments, function* stream_1() { | ||
const { tag, inputs: rawInputs, rawOutputs, dataUrlLimit } = input; | ||
// Serialize inputs | ||
const inputs = yield __await(serializePredictionInputs(rawInputs, this.storage)); | ||
// Request | ||
const url = new URL(`/predict/${tag}`, this.client.url); | ||
url.searchParams.append("rawOutputs", "true"); | ||
url.searchParams.append("stream", "true"); | ||
url.searchParams.append("dataUrlLimit", dataUrlLimit === null || dataUrlLimit === void 0 ? void 0 : dataUrlLimit.toString()); | ||
const response = yield __await(fetch(url, { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
"Authorization": this.client.auth, | ||
"fxn-client": client | ||
}, | ||
body: JSON.stringify(inputs) | ||
})); | ||
// Stream | ||
const decoder = new TextDecoderStream(); | ||
const reader = response.body.pipeThrough(decoder).getReader(); | ||
let done, value; | ||
while (!done) { | ||
({ value, done } = yield __await(reader.read())); | ||
if (done) | ||
break; | ||
const payload = JSON.parse(value); | ||
if (response.status >= 400) | ||
throw new Error(payload.error); | ||
const prediction = yield __await(deserializePredictionOutputs(payload, rawOutputs)); | ||
yield yield __await(prediction); | ||
} | ||
}); | ||
} | ||
} | ||
exports.PredictionService = PredictionService; | ||
function serializePredictionInputs(inputs, storage, minUploadSize = 4096) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (!inputs) | ||
return null; | ||
const key = Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2); // this doesn't have to be robust | ||
const entries = yield Promise.all(Object.entries(inputs) | ||
.map(([name, value]) => (0, value_1.toFunctionValue)({ storage, value, name, minUploadSize, key }) | ||
.then(f => (Object.assign(Object.assign({}, f), { name }))))); | ||
const result = Object.fromEntries(entries.map((_a) => { | ||
var { name } = _a, value = __rest(_a, ["name"]); | ||
return [name, value]; | ||
})); | ||
return result; | ||
}); | ||
} | ||
function deserializePredictionOutputs(prediction, rawOutputs) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const { results: rawResults } = prediction, others = __rest(prediction, ["results"]); | ||
const results = rawResults && !rawOutputs ? | ||
yield Promise.all(rawResults.map(value => (0, value_1.toPlainValue)({ value: value }))) : | ||
rawResults; | ||
return rawResults !== undefined ? Object.assign(Object.assign({}, others), { results }) : others; | ||
}); | ||
} | ||
const client = !browser_or_node_1.isBrowser ? !browser_or_node_1.isDeno ? !browser_or_node_1.isNode ? !browser_or_node_1.isWebWorker ? | ||
@@ -83,0 +157,0 @@ "edge" : // we get this in e.g. Vercel Serverless Functions with edge runtime |
@@ -16,4 +16,4 @@ import { FunctionConfig } from "../client"; | ||
export declare class GraphClient { | ||
private readonly url; | ||
private readonly auth; | ||
readonly url: string; | ||
readonly auth: string; | ||
/** | ||
@@ -20,0 +20,0 @@ * Create a Function graph API client. |
import { GraphClient } from "../graph"; | ||
import { CloudPrediction, EdgePrediction, PlainValue, Value } from "../types"; | ||
import { CloudPrediction, PlainValue, Value } from "../types"; | ||
import { StorageService } from "./storage"; | ||
@@ -30,6 +30,13 @@ export declare const PREDICTION_FIELDS = "\nid\ntag\ntype\ncreated\n... on CloudPrediction {\n results {\n data\n type\n shape\n }\n latency\n error\n logs\n}\n"; | ||
* Create a prediction. | ||
* @param input Input arguments. | ||
* @param input Prediction input. | ||
* @returns Prediction. | ||
*/ | ||
create(input: CreatePredictionInput): Promise<CloudPrediction | EdgePrediction>; | ||
create(input: CreatePredictionInput): Promise<CloudPrediction>; | ||
/** | ||
* Create a streaming prediction. | ||
* NOTE: This feature is currently experimental. | ||
* @param input Prediction input. | ||
* @returns Generator which asynchronously returns prediction results as they are streamed from the predictor. | ||
*/ | ||
stream(input: CreatePredictionInput): AsyncGenerator<CloudPrediction>; | ||
} |
{ | ||
"name": "fxnjs", | ||
"version": "0.0.20", | ||
"version": "0.0.21", | ||
"description": "Run AI prediction functions in your JavaScript and Node.js apps.", | ||
@@ -5,0 +5,0 @@ "scripts": { |
Sorry, the diff of this file is too big to display
632284
54379
10