web 기본셋팅
This commit is contained in:
+894
@@ -0,0 +1,894 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* Harm categories that would cause prompts or candidates to be blocked.
|
||||
* @public
|
||||
*/
|
||||
var HarmCategory;
|
||||
(function (HarmCategory) {
|
||||
HarmCategory["HARM_CATEGORY_UNSPECIFIED"] = "HARM_CATEGORY_UNSPECIFIED";
|
||||
HarmCategory["HARM_CATEGORY_HATE_SPEECH"] = "HARM_CATEGORY_HATE_SPEECH";
|
||||
HarmCategory["HARM_CATEGORY_SEXUALLY_EXPLICIT"] = "HARM_CATEGORY_SEXUALLY_EXPLICIT";
|
||||
HarmCategory["HARM_CATEGORY_HARASSMENT"] = "HARM_CATEGORY_HARASSMENT";
|
||||
HarmCategory["HARM_CATEGORY_DANGEROUS_CONTENT"] = "HARM_CATEGORY_DANGEROUS_CONTENT";
|
||||
})(HarmCategory || (HarmCategory = {}));
|
||||
/**
|
||||
* Threshhold above which a prompt or candidate will be blocked.
|
||||
* @public
|
||||
*/
|
||||
var HarmBlockThreshold;
|
||||
(function (HarmBlockThreshold) {
|
||||
// Threshold is unspecified.
|
||||
HarmBlockThreshold["HARM_BLOCK_THRESHOLD_UNSPECIFIED"] = "HARM_BLOCK_THRESHOLD_UNSPECIFIED";
|
||||
// Content with NEGLIGIBLE will be allowed.
|
||||
HarmBlockThreshold["BLOCK_LOW_AND_ABOVE"] = "BLOCK_LOW_AND_ABOVE";
|
||||
// Content with NEGLIGIBLE and LOW will be allowed.
|
||||
HarmBlockThreshold["BLOCK_MEDIUM_AND_ABOVE"] = "BLOCK_MEDIUM_AND_ABOVE";
|
||||
// Content with NEGLIGIBLE, LOW, and MEDIUM will be allowed.
|
||||
HarmBlockThreshold["BLOCK_ONLY_HIGH"] = "BLOCK_ONLY_HIGH";
|
||||
// All content will be allowed.
|
||||
HarmBlockThreshold["BLOCK_NONE"] = "BLOCK_NONE";
|
||||
})(HarmBlockThreshold || (HarmBlockThreshold = {}));
|
||||
/**
|
||||
* Probability that a prompt or candidate matches a harm category.
|
||||
* @public
|
||||
*/
|
||||
var HarmProbability;
|
||||
(function (HarmProbability) {
|
||||
// Probability is unspecified.
|
||||
HarmProbability["HARM_PROBABILITY_UNSPECIFIED"] = "HARM_PROBABILITY_UNSPECIFIED";
|
||||
// Content has a negligible chance of being unsafe.
|
||||
HarmProbability["NEGLIGIBLE"] = "NEGLIGIBLE";
|
||||
// Content has a low chance of being unsafe.
|
||||
HarmProbability["LOW"] = "LOW";
|
||||
// Content has a medium chance of being unsafe.
|
||||
HarmProbability["MEDIUM"] = "MEDIUM";
|
||||
// Content has a high chance of being unsafe.
|
||||
HarmProbability["HIGH"] = "HIGH";
|
||||
})(HarmProbability || (HarmProbability = {}));
|
||||
/**
|
||||
* Reason that a prompt was blocked.
|
||||
* @public
|
||||
*/
|
||||
var BlockReason;
|
||||
(function (BlockReason) {
|
||||
// A blocked reason was not specified.
|
||||
BlockReason["BLOCKED_REASON_UNSPECIFIED"] = "BLOCKED_REASON_UNSPECIFIED";
|
||||
// Content was blocked by safety settings.
|
||||
BlockReason["SAFETY"] = "SAFETY";
|
||||
// Content was blocked, but the reason is uncategorized.
|
||||
BlockReason["OTHER"] = "OTHER";
|
||||
})(BlockReason || (BlockReason = {}));
|
||||
/**
|
||||
* Reason that a candidate finished.
|
||||
* @public
|
||||
*/
|
||||
var FinishReason;
|
||||
(function (FinishReason) {
|
||||
// Default value. This value is unused.
|
||||
FinishReason["FINISH_REASON_UNSPECIFIED"] = "FINISH_REASON_UNSPECIFIED";
|
||||
// Natural stop point of the model or provided stop sequence.
|
||||
FinishReason["STOP"] = "STOP";
|
||||
// The maximum number of tokens as specified in the request was reached.
|
||||
FinishReason["MAX_TOKENS"] = "MAX_TOKENS";
|
||||
// The candidate content was flagged for safety reasons.
|
||||
FinishReason["SAFETY"] = "SAFETY";
|
||||
// The candidate content was flagged for recitation reasons.
|
||||
FinishReason["RECITATION"] = "RECITATION";
|
||||
// Unknown reason.
|
||||
FinishReason["OTHER"] = "OTHER";
|
||||
})(FinishReason || (FinishReason = {}));
|
||||
/**
|
||||
* Task type for embedding content.
|
||||
* @public
|
||||
*/
|
||||
var TaskType;
|
||||
(function (TaskType) {
|
||||
TaskType["TASK_TYPE_UNSPECIFIED"] = "TASK_TYPE_UNSPECIFIED";
|
||||
TaskType["RETRIEVAL_QUERY"] = "RETRIEVAL_QUERY";
|
||||
TaskType["RETRIEVAL_DOCUMENT"] = "RETRIEVAL_DOCUMENT";
|
||||
TaskType["SEMANTIC_SIMILARITY"] = "SEMANTIC_SIMILARITY";
|
||||
TaskType["CLASSIFICATION"] = "CLASSIFICATION";
|
||||
TaskType["CLUSTERING"] = "CLUSTERING";
|
||||
})(TaskType || (TaskType = {}));
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
class GoogleGenerativeAIError extends Error {
|
||||
constructor(message) {
|
||||
super(`[GoogleGenerativeAI Error]: ${message}`);
|
||||
}
|
||||
}
|
||||
class GoogleGenerativeAIResponseError extends GoogleGenerativeAIError {
|
||||
constructor(message, response) {
|
||||
super(message);
|
||||
this.response = response;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
const BASE_URL = "https://generativelanguage.googleapis.com";
|
||||
const API_VERSION = "v1";
|
||||
/**
|
||||
* We can't `require` package.json if this runs on web. We will use rollup to
|
||||
* swap in the version number here at build time.
|
||||
*/
|
||||
const PACKAGE_VERSION = "0.1.3";
|
||||
const PACKAGE_LOG_HEADER = "genai-js";
|
||||
var Task;
|
||||
(function (Task) {
|
||||
Task["GENERATE_CONTENT"] = "generateContent";
|
||||
Task["STREAM_GENERATE_CONTENT"] = "streamGenerateContent";
|
||||
Task["COUNT_TOKENS"] = "countTokens";
|
||||
Task["EMBED_CONTENT"] = "embedContent";
|
||||
Task["BATCH_EMBED_CONTENTS"] = "batchEmbedContents";
|
||||
})(Task || (Task = {}));
|
||||
class RequestUrl {
|
||||
constructor(model, task, apiKey, stream) {
|
||||
this.model = model;
|
||||
this.task = task;
|
||||
this.apiKey = apiKey;
|
||||
this.stream = stream;
|
||||
}
|
||||
toString() {
|
||||
let url = `${BASE_URL}/${API_VERSION}/models/${this.model}:${this.task}`;
|
||||
if (this.stream) {
|
||||
url += "?alt=sse";
|
||||
}
|
||||
return url;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Simple, but may become more complex if we add more versions to log.
|
||||
*/
|
||||
function getClientHeaders() {
|
||||
return `${PACKAGE_LOG_HEADER}/${PACKAGE_VERSION}`;
|
||||
}
|
||||
async function makeRequest(url, body) {
|
||||
let response;
|
||||
try {
|
||||
response = await fetch(url.toString(), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"x-goog-api-client": getClientHeaders(),
|
||||
"x-goog-api-key": url.apiKey,
|
||||
},
|
||||
body,
|
||||
});
|
||||
if (!response.ok) {
|
||||
let message = "";
|
||||
try {
|
||||
const json = await response.json();
|
||||
message = json.error.message;
|
||||
if (json.error.details) {
|
||||
message += ` ${JSON.stringify(json.error.details)}`;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
// ignored
|
||||
}
|
||||
throw new Error(`[${response.status} ${response.statusText}] ${message}`);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
const err = new GoogleGenerativeAIError(`Error fetching from ${url.toString()}: ${e.message}`);
|
||||
err.stack = e.stack;
|
||||
throw err;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* Adds convenience helper methods to a response object, including stream
|
||||
* chunks (as long as each chunk is a complete GenerateContentResponse JSON).
|
||||
*/
|
||||
function addHelpers(response) {
|
||||
response.text = () => {
|
||||
if (response.candidates && response.candidates.length > 0) {
|
||||
if (response.candidates.length > 1) {
|
||||
console.warn(`This response had ${response.candidates.length} ` +
|
||||
`candidates. Returning text from the first candidate only. ` +
|
||||
`Access response.candidates directly to use the other candidates.`);
|
||||
}
|
||||
if (hadBadFinishReason(response.candidates[0])) {
|
||||
throw new GoogleGenerativeAIResponseError(`${formatBlockErrorMessage(response)}`, response);
|
||||
}
|
||||
return getText(response);
|
||||
}
|
||||
else if (response.promptFeedback) {
|
||||
throw new GoogleGenerativeAIResponseError(`Text not available. ${formatBlockErrorMessage(response)}`, response);
|
||||
}
|
||||
return "";
|
||||
};
|
||||
return response;
|
||||
}
|
||||
/**
|
||||
* Returns text of first candidate.
|
||||
*/
|
||||
function getText(response) {
|
||||
var _a, _b, _c, _d;
|
||||
if ((_d = (_c = (_b = (_a = response.candidates) === null || _a === void 0 ? void 0 : _a[0].content) === null || _b === void 0 ? void 0 : _b.parts) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.text) {
|
||||
return response.candidates[0].content.parts[0].text;
|
||||
}
|
||||
else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
const badFinishReasons = [FinishReason.RECITATION, FinishReason.SAFETY];
|
||||
function hadBadFinishReason(candidate) {
|
||||
return (!!candidate.finishReason &&
|
||||
badFinishReasons.includes(candidate.finishReason));
|
||||
}
|
||||
function formatBlockErrorMessage(response) {
|
||||
var _a, _b, _c;
|
||||
let message = "";
|
||||
if ((!response.candidates || response.candidates.length === 0) &&
|
||||
response.promptFeedback) {
|
||||
message += "Response was blocked";
|
||||
if ((_a = response.promptFeedback) === null || _a === void 0 ? void 0 : _a.blockReason) {
|
||||
message += ` due to ${response.promptFeedback.blockReason}`;
|
||||
}
|
||||
if ((_b = response.promptFeedback) === null || _b === void 0 ? void 0 : _b.blockReasonMessage) {
|
||||
message += `: ${response.promptFeedback.blockReasonMessage}`;
|
||||
}
|
||||
}
|
||||
else if ((_c = response.candidates) === null || _c === void 0 ? void 0 : _c[0]) {
|
||||
const firstCandidate = response.candidates[0];
|
||||
if (hadBadFinishReason(firstCandidate)) {
|
||||
message += `Candidate was blocked due to ${firstCandidate.finishReason}`;
|
||||
if (firstCandidate.finishMessage) {
|
||||
message += `: ${firstCandidate.finishMessage}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
***************************************************************************** */
|
||||
/* global Reflect, Promise, SuppressedError, Symbol */
|
||||
|
||||
|
||||
function __await(v) {
|
||||
return this instanceof __await ? (this.v = v, this) : new __await(v);
|
||||
}
|
||||
|
||||
function __asyncGenerator(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]); }
|
||||
}
|
||||
|
||||
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
||||
var e = new Error(message);
|
||||
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
||||
};
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
const responseLineRE = /^data\: (.*)(?:\n\n|\r\r|\r\n\r\n)/;
|
||||
/**
|
||||
* Process a response.body stream from the backend and return an
|
||||
* iterator that provides one complete GenerateContentResponse at a time
|
||||
* and a promise that resolves with a single aggregated
|
||||
* GenerateContentResponse.
|
||||
*
|
||||
* @param response - Response from a fetch call
|
||||
*/
|
||||
function processStream(response) {
|
||||
const inputStream = response.body.pipeThrough(new TextDecoderStream("utf8", { fatal: true }));
|
||||
const responseStream = getResponseStream(inputStream);
|
||||
const [stream1, stream2] = responseStream.tee();
|
||||
return {
|
||||
stream: generateResponseSequence(stream1),
|
||||
response: getResponsePromise(stream2),
|
||||
};
|
||||
}
|
||||
async function getResponsePromise(stream) {
|
||||
const allResponses = [];
|
||||
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 } = yield __await(reader.read());
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
yield yield __await(addHelpers(value));
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
function getResponseStream(inputStream) {
|
||||
const reader = inputStream.getReader();
|
||||
const stream = new ReadableStream({
|
||||
start(controller) {
|
||||
let currentText = "";
|
||||
return pump();
|
||||
function pump() {
|
||||
return reader.read().then(({ value, done }) => {
|
||||
if (done) {
|
||||
if (currentText.trim()) {
|
||||
controller.error(new GoogleGenerativeAIError("Failed to parse stream"));
|
||||
return;
|
||||
}
|
||||
controller.close();
|
||||
return;
|
||||
}
|
||||
currentText += value;
|
||||
let match = currentText.match(responseLineRE);
|
||||
let parsedResponse;
|
||||
while (match) {
|
||||
try {
|
||||
parsedResponse = JSON.parse(match[1]);
|
||||
}
|
||||
catch (e) {
|
||||
controller.error(new GoogleGenerativeAIError(`Error parsing JSON response: "${match[1]}"`));
|
||||
return;
|
||||
}
|
||||
controller.enqueue(parsedResponse);
|
||||
currentText = currentText.substring(match[0].length);
|
||||
match = currentText.match(responseLineRE);
|
||||
}
|
||||
return pump();
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
return stream;
|
||||
}
|
||||
/**
|
||||
* Aggregates an array of `GenerateContentResponse`s into a single
|
||||
* GenerateContentResponse.
|
||||
*/
|
||||
function aggregateResponses(responses) {
|
||||
const lastResponse = responses[responses.length - 1];
|
||||
const aggregatedResponse = {
|
||||
promptFeedback: lastResponse === null || lastResponse === void 0 ? void 0 : lastResponse.promptFeedback,
|
||||
};
|
||||
for (const response of responses) {
|
||||
if (response.candidates) {
|
||||
for (const candidate of response.candidates) {
|
||||
const i = candidate.index;
|
||||
if (!aggregatedResponse.candidates) {
|
||||
aggregatedResponse.candidates = [];
|
||||
}
|
||||
if (!aggregatedResponse.candidates[i]) {
|
||||
aggregatedResponse.candidates[i] = {
|
||||
index: candidate.index,
|
||||
};
|
||||
}
|
||||
// Keep overwriting, the last one will be final
|
||||
aggregatedResponse.candidates[i].citationMetadata =
|
||||
candidate.citationMetadata;
|
||||
aggregatedResponse.candidates[i].finishReason = candidate.finishReason;
|
||||
aggregatedResponse.candidates[i].finishMessage =
|
||||
candidate.finishMessage;
|
||||
aggregatedResponse.candidates[i].safetyRatings =
|
||||
candidate.safetyRatings;
|
||||
/**
|
||||
* Candidates should always have content and parts, but this handles
|
||||
* possible malformed responses.
|
||||
*/
|
||||
if (candidate.content && candidate.content.parts) {
|
||||
if (!aggregatedResponse.candidates[i].content) {
|
||||
aggregatedResponse.candidates[i].content = {
|
||||
role: candidate.content.role || "user",
|
||||
parts: [{ text: "" }],
|
||||
};
|
||||
}
|
||||
for (const part of candidate.content.parts) {
|
||||
if (part.text) {
|
||||
aggregatedResponse.candidates[i].content.parts[0].text +=
|
||||
part.text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return aggregatedResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
async function generateContentStream(apiKey, model, params) {
|
||||
const url = new RequestUrl(model, Task.STREAM_GENERATE_CONTENT, apiKey,
|
||||
/* stream */ true);
|
||||
const response = await makeRequest(url, JSON.stringify(params));
|
||||
return processStream(response);
|
||||
}
|
||||
async function generateContent(apiKey, model, params) {
|
||||
const url = new RequestUrl(model, Task.GENERATE_CONTENT, apiKey,
|
||||
/* stream */ false);
|
||||
const response = await makeRequest(url, JSON.stringify(params));
|
||||
const responseJson = await response.json();
|
||||
const enhancedResponse = addHelpers(responseJson);
|
||||
return {
|
||||
response: enhancedResponse,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
function formatNewContent(request, role) {
|
||||
let newParts = [];
|
||||
if (typeof request === "string") {
|
||||
newParts = [{ text: request }];
|
||||
}
|
||||
else {
|
||||
for (const partOrString of request) {
|
||||
if (typeof partOrString === "string") {
|
||||
newParts.push({ text: partOrString });
|
||||
}
|
||||
else {
|
||||
newParts.push(partOrString);
|
||||
}
|
||||
}
|
||||
}
|
||||
return { role, parts: newParts };
|
||||
}
|
||||
function formatGenerateContentInput(params) {
|
||||
if (params.contents) {
|
||||
return params;
|
||||
}
|
||||
else {
|
||||
const content = formatNewContent(params, "user");
|
||||
return { contents: [content] };
|
||||
}
|
||||
}
|
||||
function formatEmbedContentInput(params) {
|
||||
if (typeof params === "string" || Array.isArray(params)) {
|
||||
const content = formatNewContent(params, "user");
|
||||
return { content };
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* Do not log a message for this error.
|
||||
*/
|
||||
const SILENT_ERROR = "SILENT_ERROR";
|
||||
/**
|
||||
* ChatSession class that enables sending chat messages and stores
|
||||
* history of sent and received messages so far.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
class ChatSession {
|
||||
constructor(apiKey, model, params) {
|
||||
this.model = model;
|
||||
this.params = params;
|
||||
this._history = [];
|
||||
this._sendPromise = Promise.resolve();
|
||||
this._apiKey = apiKey;
|
||||
if (params === null || params === void 0 ? void 0 : params.history) {
|
||||
this._history = params.history.map((content) => {
|
||||
if (!content.role) {
|
||||
throw new Error("Missing role for history item: " + JSON.stringify(content));
|
||||
}
|
||||
return formatNewContent(content.parts, content.role);
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets the chat history so far. Blocked prompts are not added to history.
|
||||
* Blocked candidates are not added to history, nor are the prompts that
|
||||
* generated them.
|
||||
*/
|
||||
async getHistory() {
|
||||
await this._sendPromise;
|
||||
return this._history;
|
||||
}
|
||||
/**
|
||||
* Sends a chat message and receives a non-streaming
|
||||
* {@link GenerateContentResult}
|
||||
*/
|
||||
async sendMessage(request) {
|
||||
var _a, _b;
|
||||
await this._sendPromise;
|
||||
const newContent = formatNewContent(request, "user");
|
||||
const generateContentRequest = {
|
||||
safetySettings: (_a = this.params) === null || _a === void 0 ? void 0 : _a.safetySettings,
|
||||
generationConfig: (_b = this.params) === null || _b === void 0 ? void 0 : _b.generationConfig,
|
||||
contents: [...this._history, newContent],
|
||||
};
|
||||
let finalResult;
|
||||
// Add onto the chain.
|
||||
this._sendPromise = this._sendPromise
|
||||
.then(() => generateContent(this._apiKey, this.model, generateContentRequest))
|
||||
.then((result) => {
|
||||
var _a;
|
||||
if (result.response.candidates &&
|
||||
result.response.candidates.length > 0) {
|
||||
this._history.push(newContent);
|
||||
const responseContent = Object.assign({ parts: [],
|
||||
// Response seems to come back without a role set.
|
||||
role: "model" }, (_a = result.response.candidates) === null || _a === void 0 ? void 0 : _a[0].content);
|
||||
this._history.push(responseContent);
|
||||
}
|
||||
else {
|
||||
const blockErrorMessage = formatBlockErrorMessage(result.response);
|
||||
if (blockErrorMessage) {
|
||||
console.warn(`sendMessage() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.`);
|
||||
}
|
||||
}
|
||||
finalResult = result;
|
||||
});
|
||||
await this._sendPromise;
|
||||
return finalResult;
|
||||
}
|
||||
/**
|
||||
* Sends a chat message and receives the response as a
|
||||
* {@link GenerateContentStreamResult} containing an iterable stream
|
||||
* and a response promise.
|
||||
*/
|
||||
async sendMessageStream(request) {
|
||||
var _a, _b;
|
||||
await this._sendPromise;
|
||||
const newContent = formatNewContent(request, "user");
|
||||
const generateContentRequest = {
|
||||
safetySettings: (_a = this.params) === null || _a === void 0 ? void 0 : _a.safetySettings,
|
||||
generationConfig: (_b = this.params) === null || _b === void 0 ? void 0 : _b.generationConfig,
|
||||
contents: [...this._history, newContent],
|
||||
};
|
||||
const streamPromise = generateContentStream(this._apiKey, this.model, generateContentRequest);
|
||||
// Add onto the chain.
|
||||
this._sendPromise = this._sendPromise
|
||||
.then(() => streamPromise)
|
||||
// This must be handled to avoid unhandled rejection, but jump
|
||||
// to the final catch block with a label to not log this error.
|
||||
.catch((_ignored) => {
|
||||
throw new Error(SILENT_ERROR);
|
||||
})
|
||||
.then((streamResult) => streamResult.response)
|
||||
.then((response) => {
|
||||
if (response.candidates && response.candidates.length > 0) {
|
||||
this._history.push(newContent);
|
||||
const responseContent = Object.assign({}, response.candidates[0].content);
|
||||
// Response seems to come back without a role set.
|
||||
if (!responseContent.role) {
|
||||
responseContent.role = "model";
|
||||
}
|
||||
this._history.push(responseContent);
|
||||
}
|
||||
else {
|
||||
const blockErrorMessage = formatBlockErrorMessage(response);
|
||||
if (blockErrorMessage) {
|
||||
console.warn(`sendMessageStream() was unsuccessful. ${blockErrorMessage}. Inspect response object for details.`);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
// Errors in streamPromise are already catchable by the user as
|
||||
// streamPromise is returned.
|
||||
// Avoid duplicating the error message in logs.
|
||||
if (e.message !== SILENT_ERROR) {
|
||||
// Users do not have access to _sendPromise to catch errors
|
||||
// downstream from streamPromise, so they should not throw.
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
return streamPromise;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
async function countTokens(apiKey, model, params) {
|
||||
const url = new RequestUrl(model, Task.COUNT_TOKENS, apiKey, false);
|
||||
const response = await makeRequest(url, JSON.stringify(Object.assign(Object.assign({}, params), { model })));
|
||||
return response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
async function embedContent(apiKey, model, params) {
|
||||
const url = new RequestUrl(model, Task.EMBED_CONTENT, apiKey, false);
|
||||
const response = await makeRequest(url, JSON.stringify(params));
|
||||
return response.json();
|
||||
}
|
||||
async function batchEmbedContents(apiKey, model, params) {
|
||||
const url = new RequestUrl(model, Task.BATCH_EMBED_CONTENTS, apiKey, false);
|
||||
const requestsWithModel = params.requests.map((request) => {
|
||||
return Object.assign(Object.assign({}, request), { model: `models/${model}` });
|
||||
});
|
||||
const response = await makeRequest(url, JSON.stringify({ requests: requestsWithModel }));
|
||||
return response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* Class for generative model APIs.
|
||||
* @public
|
||||
*/
|
||||
class GenerativeModel {
|
||||
constructor(apiKey, modelParams) {
|
||||
var _a;
|
||||
this.apiKey = apiKey;
|
||||
if (modelParams.model.startsWith("models/")) {
|
||||
this.model = (_a = modelParams.model.split("models/")) === null || _a === void 0 ? void 0 : _a[1];
|
||||
}
|
||||
else {
|
||||
this.model = modelParams.model;
|
||||
}
|
||||
this.generationConfig = modelParams.generationConfig || {};
|
||||
this.safetySettings = modelParams.safetySettings || [];
|
||||
}
|
||||
/**
|
||||
* Makes a single non-streaming call to the model
|
||||
* and returns an object containing a single {@link GenerateContentResponse}.
|
||||
*/
|
||||
async generateContent(request) {
|
||||
const formattedParams = formatGenerateContentInput(request);
|
||||
return generateContent(this.apiKey, this.model, Object.assign({ generationConfig: this.generationConfig, safetySettings: this.safetySettings }, formattedParams));
|
||||
}
|
||||
/**
|
||||
* Makes a single streaming call to the model
|
||||
* and returns an object containing an iterable stream that iterates
|
||||
* over all chunks in the streaming response as well as
|
||||
* a promise that returns the final aggregated response.
|
||||
*/
|
||||
async generateContentStream(request) {
|
||||
const formattedParams = formatGenerateContentInput(request);
|
||||
return generateContentStream(this.apiKey, this.model, Object.assign({ generationConfig: this.generationConfig, safetySettings: this.safetySettings }, formattedParams));
|
||||
}
|
||||
/**
|
||||
* Gets a new {@link ChatSession} instance which can be used for
|
||||
* multi-turn chats.
|
||||
*/
|
||||
startChat(startChatParams) {
|
||||
return new ChatSession(this.apiKey, this.model, startChatParams);
|
||||
}
|
||||
/**
|
||||
* Counts the tokens in the provided request.
|
||||
*/
|
||||
async countTokens(request) {
|
||||
const formattedParams = formatGenerateContentInput(request);
|
||||
return countTokens(this.apiKey, this.model, formattedParams);
|
||||
}
|
||||
/**
|
||||
* Embeds the provided content.
|
||||
*/
|
||||
async embedContent(request) {
|
||||
const formattedParams = formatEmbedContentInput(request);
|
||||
return embedContent(this.apiKey, this.model, formattedParams);
|
||||
}
|
||||
/**
|
||||
* Embeds an array of {@link EmbedContentRequest}s.
|
||||
*/
|
||||
async batchEmbedContents(batchEmbedContentRequest) {
|
||||
return batchEmbedContents(this.apiKey, this.model, batchEmbedContentRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/**
|
||||
* Top-level class for this SDK
|
||||
* @public
|
||||
*/
|
||||
class GoogleGenerativeAI {
|
||||
constructor(apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
/**
|
||||
* Gets a {@link GenerativeModel} instance for the provided model name.
|
||||
*/
|
||||
getGenerativeModel(modelParams) {
|
||||
if (!modelParams.model) {
|
||||
throw new GoogleGenerativeAIError(`Must provide a model name. ` +
|
||||
`Example: genai.getGenerativeModel({ model: 'my-model-name' })`);
|
||||
}
|
||||
return new GenerativeModel(this.apiKey, modelParams);
|
||||
}
|
||||
}
|
||||
|
||||
export { BlockReason, ChatSession, FinishReason, GenerativeModel, GoogleGenerativeAI, HarmBlockThreshold, HarmCategory, HarmProbability, TaskType };
|
||||
//# sourceMappingURL=index.mjs.map
|
||||
Reference in New Issue
Block a user