@axflow/models
Version:
Zero-dependency, modular SDK for building robust natural language applications
129 lines (128 loc) • 3.82 kB
JavaScript
// src/google/generate-content.ts
import { HttpError, POST } from "@axflow/models/shared";
var GOOGLE_GENERATE_CONTENT_API_URL = "https://generativelanguage.googleapis.com/v1";
function constructUrl({
baseUrl,
model,
stream: stream2,
apiKey
}) {
const method = stream2 ? `streamGenerateContent` : "generateContent";
const search = new URLSearchParams();
if (apiKey) {
search.set("key", apiKey);
}
if (stream2) {
search.set("alt", "sse");
}
const query = search.size === 0 ? "" : `?${search}`;
return `${baseUrl}/models/${model}:${method}${query}`;
}
function headers(customHeaders) {
const headers2 = {
"content-type": "application/json",
...customHeaders
};
return headers2;
}
async function run(request, options) {
const { model, ...req } = request;
const url = constructUrl({
model,
stream: false,
apiKey: options.apiKey,
baseUrl: options.apiUrl || GOOGLE_GENERATE_CONTENT_API_URL
});
const response = await POST(url, {
headers: headers(options.headers),
body: JSON.stringify(req),
fetch: options.fetch,
signal: options.signal
});
return response.json();
}
async function streamBytes(request, options) {
const { model, ...req } = request;
const url = constructUrl({
model,
stream: true,
apiKey: options.apiKey,
baseUrl: options.apiUrl || GOOGLE_GENERATE_CONTENT_API_URL
});
const response = await POST(url, {
headers: headers(options.headers),
body: JSON.stringify(req),
fetch: options.fetch,
signal: options.signal
});
if (!response.body) {
throw new HttpError("Expected response body to be a ReadableStream", response);
}
return response.body;
}
function noop(chunk) {
return chunk;
}
async function stream(request, options) {
const byteStream = await streamBytes(request, options);
return byteStream.pipeThrough(new GoogleGenerateContentDecoderStream(noop));
}
function chunkToToken(chunk) {
return chunk.candidates[0].content.parts[0].text || "";
}
async function streamTokens(request, options) {
const byteStream = await streamBytes(request, options);
return byteStream.pipeThrough(new GoogleGenerateContentDecoderStream(chunkToToken));
}
var GoogleGenerateContent = class {
static run = run;
static streamBytes = streamBytes;
static stream = stream;
static streamTokens = streamTokens;
};
var GoogleGenerateContentDecoderStream = class _GoogleGenerateContentDecoderStream extends TransformStream {
static DATA_RE = /data:\s*(.+)/;
static parseChunk(chunk) {
chunk = chunk.trim();
if (chunk.length === 0) {
return null;
}
const match = chunk.match(_GoogleGenerateContentDecoderStream.DATA_RE);
try {
return JSON.parse(match[1]);
} catch (error) {
throw new Error(
`Encountered unexpected chunk while parsing Google generateContentStream response: ${JSON.stringify(
chunk
)}`
);
}
}
static streamTransformer(map) {
let buffer = [];
const decoder = new TextDecoder();
return (bytes, controller) => {
const chunk = decoder.decode(bytes);
for (let i = 0, len = chunk.length; i < len; ++i) {
const isChunkSeparator = chunk[i] === "\n" && buffer[buffer.length - 1] === "\r" && buffer[buffer.length - 2] === "\n" && buffer[buffer.length - 3] === "\r";
if (!isChunkSeparator) {
buffer.push(chunk[i]);
continue;
}
const parsedChunk = _GoogleGenerateContentDecoderStream.parseChunk(
buffer.join("")
);
if (parsedChunk) {
controller.enqueue(map(parsedChunk));
}
buffer = [];
}
};
}
constructor(map) {
super({ transform: _GoogleGenerateContentDecoderStream.streamTransformer(map) });
}
};
export {
GoogleGenerateContent
};