@google/generative-ai
Advanced tools
Comparing version 0.1.2 to 0.1.3
@@ -161,3 +161,3 @@ 'use strict'; | ||
*/ | ||
const PACKAGE_VERSION = "0.1.1"; | ||
const PACKAGE_VERSION = "0.1.3"; | ||
const PACKAGE_LOG_HEADER = "genai-js"; | ||
@@ -172,8 +172,16 @@ var Task; | ||
})(Task || (Task = {})); | ||
function getUrl(model, task, apiKey, stream) { | ||
let url = `${BASE_URL}/${API_VERSION}/models/${model}:${task}?key=${apiKey}`; | ||
if (stream) { | ||
url += "&alt=sse"; | ||
class RequestUrl { | ||
constructor(model, task, apiKey, stream) { | ||
this.model = model; | ||
this.task = task; | ||
this.apiKey = apiKey; | ||
this.stream = stream; | ||
} | ||
return url; | ||
toString() { | ||
let url = `${BASE_URL}/${API_VERSION}/models/${this.model}:${this.task}`; | ||
if (this.stream) { | ||
url += "?alt=sse"; | ||
} | ||
return url; | ||
} | ||
} | ||
@@ -189,3 +197,3 @@ /** | ||
try { | ||
response = await fetch(url, { | ||
response = await fetch(url.toString(), { | ||
method: "POST", | ||
@@ -195,2 +203,3 @@ headers: { | ||
"x-goog-api-client": getClientHeaders(), | ||
"x-goog-api-key": url.apiKey, | ||
}, | ||
@@ -215,3 +224,3 @@ body, | ||
catch (e) { | ||
const err = new GoogleGenerativeAIError(`Error fetching from ${url}: ${e.message}`); | ||
const err = new GoogleGenerativeAIError(`Error fetching from ${url.toString()}: ${e.message}`); | ||
err.stack = e.stack; | ||
@@ -359,3 +368,3 @@ throw err; | ||
*/ | ||
const responseLineRE = /^data\: (.*)\r\n/; | ||
const responseLineRE = /^data\: (.*)(?:\n\n|\r\r|\r\n\r\n)/; | ||
/** | ||
@@ -370,34 +379,32 @@ * Process a response.body stream from the backend and return an | ||
function processStream(response) { | ||
const reader = response.body.getReader(); | ||
const responseStream = readFromReader(reader); | ||
const inputStream = response.body.pipeThrough(new TextDecoderStream("utf8", { fatal: true })); | ||
const responseStream = getResponseStream(inputStream); | ||
const [stream1, stream2] = responseStream.tee(); | ||
const reader1 = stream1.getReader(); | ||
const reader2 = stream2.getReader(); | ||
return { | ||
stream: generateResponseSequence(stream1), | ||
response: getResponsePromise(stream2), | ||
}; | ||
} | ||
async function getResponsePromise(stream) { | ||
const allResponses = []; | ||
const responsePromise = new Promise(async (resolve) => { | ||
const reader = stream.getReader(); | ||
while (true) { | ||
const { done, value } = await reader.read(); | ||
if (done) { | ||
return addHelpers(aggregateResponses(allResponses)); | ||
} | ||
allResponses.push(value); | ||
} | ||
} | ||
function generateResponseSequence(stream) { | ||
return __asyncGenerator(this, arguments, function* generateResponseSequence_1() { | ||
const reader = stream.getReader(); | ||
while (true) { | ||
const { value, done } = await reader1.read(); | ||
const { value, done } = yield __await(reader.read()); | ||
if (done) { | ||
const aggregatedResponse = aggregateResponses(allResponses); | ||
resolve(addHelpers(aggregatedResponse)); | ||
return; | ||
break; | ||
} | ||
allResponses.push(value); | ||
yield yield __await(addHelpers(value)); | ||
} | ||
}); | ||
function generateResponseSequence() { | ||
return __asyncGenerator(this, arguments, function* generateResponseSequence_1() { | ||
while (true) { | ||
const { value, done } = yield __await(reader2.read()); | ||
if (done) { | ||
break; | ||
} | ||
yield yield __await(addHelpers(value)); | ||
} | ||
}); | ||
} | ||
return { | ||
stream: generateResponseSequence(), | ||
response: responsePromise, | ||
}; | ||
} | ||
@@ -409,6 +416,7 @@ /** | ||
*/ | ||
function readFromReader(reader) { | ||
let currentText = ""; | ||
function getResponseStream(inputStream) { | ||
const reader = inputStream.getReader(); | ||
const stream = new ReadableStream({ | ||
start(controller) { | ||
let currentText = ""; | ||
return pump(); | ||
@@ -418,10 +426,13 @@ function pump() { | ||
if (done) { | ||
if (currentText.trim()) { | ||
controller.error(new GoogleGenerativeAIError("Failed to parse stream")); | ||
return; | ||
} | ||
controller.close(); | ||
return; | ||
} | ||
const chunk = new TextDecoder().decode(value); | ||
currentText += chunk; | ||
const match = currentText.match(responseLineRE); | ||
if (match) { | ||
let parsedResponse; | ||
currentText += value; | ||
let match = currentText.match(responseLineRE); | ||
let parsedResponse; | ||
while (match) { | ||
try { | ||
@@ -431,6 +442,8 @@ parsedResponse = JSON.parse(match[1]); | ||
catch (e) { | ||
throw new GoogleGenerativeAIError(`Error parsing JSON response: "${match[1]}"`); | ||
controller.error(new GoogleGenerativeAIError(`Error parsing JSON response: "${match[1]}"`)); | ||
return; | ||
} | ||
currentText = ""; | ||
controller.enqueue(parsedResponse); | ||
currentText = currentText.substring(match[0].length); | ||
match = currentText.match(responseLineRE); | ||
} | ||
@@ -514,3 +527,3 @@ return pump(); | ||
async function generateContentStream(apiKey, model, params) { | ||
const url = getUrl(model, Task.STREAM_GENERATE_CONTENT, apiKey, | ||
const url = new RequestUrl(model, Task.STREAM_GENERATE_CONTENT, apiKey, | ||
/* stream */ true); | ||
@@ -521,3 +534,4 @@ const response = await makeRequest(url, JSON.stringify(params)); | ||
async function generateContent(apiKey, model, params) { | ||
const url = getUrl(model, Task.GENERATE_CONTENT, apiKey, /* stream */ false); | ||
const url = new RequestUrl(model, Task.GENERATE_CONTENT, apiKey, | ||
/* stream */ false); | ||
const response = await makeRequest(url, JSON.stringify(params)); | ||
@@ -742,3 +756,3 @@ const responseJson = await response.json(); | ||
async function countTokens(apiKey, model, params) { | ||
const url = getUrl(model, Task.COUNT_TOKENS, apiKey, false); | ||
const url = new RequestUrl(model, Task.COUNT_TOKENS, apiKey, false); | ||
const response = await makeRequest(url, JSON.stringify(Object.assign(Object.assign({}, params), { model }))); | ||
@@ -765,3 +779,3 @@ return response.json(); | ||
async function embedContent(apiKey, model, params) { | ||
const url = getUrl(model, Task.EMBED_CONTENT, apiKey, false); | ||
const url = new RequestUrl(model, Task.EMBED_CONTENT, apiKey, false); | ||
const response = await makeRequest(url, JSON.stringify(params)); | ||
@@ -771,3 +785,3 @@ return response.json(); | ||
async function batchEmbedContents(apiKey, model, params) { | ||
const url = getUrl(model, Task.BATCH_EMBED_CONTENTS, apiKey, false); | ||
const url = new RequestUrl(model, Task.BATCH_EMBED_CONTENTS, apiKey, false); | ||
const requestsWithModel = params.requests.map((request) => { | ||
@@ -774,0 +788,0 @@ return Object.assign(Object.assign({}, request), { model: `models/${model}` }); |
@@ -24,3 +24,10 @@ /** | ||
} | ||
export declare function getUrl(model: string, task: Task, apiKey: string, stream: boolean): string; | ||
export declare function makeRequest(url: string, body: string): Promise<Response>; | ||
export declare class RequestUrl { | ||
model: string; | ||
task: Task; | ||
apiKey: string; | ||
stream: boolean; | ||
constructor(model: string, task: Task, apiKey: string, stream: boolean); | ||
toString(): string; | ||
} | ||
export declare function makeRequest(url: RequestUrl, body: string): Promise<Response>; |
@@ -28,2 +28,8 @@ /** | ||
/** | ||
* Reads a raw stream from the fetch response and join incomplete | ||
* chunks, returning a new stream that provides a single complete | ||
* GenerateContentResponse in each iteration. | ||
*/ | ||
export declare function getResponseStream<T>(inputStream: ReadableStream<string>): ReadableStream<T>; | ||
/** | ||
* Aggregates an array of `GenerateContentResponse`s into a single | ||
@@ -30,0 +36,0 @@ * GenerateContentResponse. |
{ | ||
"name": "@google/generative-ai", | ||
"version": "0.1.2", | ||
"version": "0.1.3", | ||
"description": "Google AI JavaScript SDK", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
Sorry, the diff of this file is not supported yet
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
114707
25
2926