UNPKG

@codixfy/gemini

Version:

An npm package for nodejs that makes easier working with Gemini AI API. Includes some useful methods solving common tasks, helping quick and stable development.

221 lines (218 loc) 6.75 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { Gemini: () => Gemini, GeminiUtils: () => GeminiUtils }); module.exports = __toCommonJS(index_exports); // src/providers/gemini.ts var { GoogleGenerativeAI, HarmBlockThreshold, HarmCategory } = require("@google/generative-ai"); var Base64 = require("base64-js"); var Gemini = class { genAI; model; currentModel; apiKey; constructor(apiKey, options) { var _a, _b, _c, _d; this.genAI = new GoogleGenerativeAI(apiKey); this.apiKey = apiKey; this.currentModel = "gemini-1.5-flash"; if (options == null ? void 0 : options.model) { this.currentModel = options.model; if (this.currentModel === "gemini-2.0-flash") { this.currentModel += "-exp"; } if (this.currentModel === "gemini-2.0-flash" && !(options == null ? void 0 : options.useLatestModel)) { this.currentModel += "-latest"; } } this.model = this.genAI.getGenerativeModel({ model: this.currentModel, safetySettings: [ { category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: ((_a = options == null ? void 0 : options.safetySettings) == null ? void 0 : _a.blockDangerousContent) === true ? HarmBlockThreshold.BLOCK_ONLY_HIGH : HarmBlockThreshold.BLOCK_NONE }, { category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: ((_b = options == null ? void 0 : options.safetySettings) == null ? void 0 : _b.blockExplicitContent) === true ? HarmBlockThreshold.BLOCK_ONLY_HIGH : HarmBlockThreshold.BLOCK_NONE }, { category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: ((_c = options == null ? void 0 : options.safetySettings) == null ? void 0 : _c.blockHarassmentContent) === true ? HarmBlockThreshold.BLOCK_ONLY_HIGH : HarmBlockThreshold.BLOCK_NONE }, { category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: ((_d = options == null ? void 0 : options.safetySettings) == null ? void 0 : _d.blockHateContent) === true ? HarmBlockThreshold.BLOCK_ONLY_HIGH : HarmBlockThreshold.BLOCK_NONE } ], systemInstruction: (options == null ? void 0 : options.instructions) || void 0 }); } // Used to send a message without any context async ask(message, extra) { const partsWithFiles = []; if ((extra == null ? void 0 : extra.files) && extra.files.length > 0) { if (this.currentModel === "gemini-pro-vision") { throw new Error( `This model does not support files. Current model: ${this.currentModel}` ); } for (const file of extra.files) { partsWithFiles.push( { text: "Link: " + file } ); } } const contents = [ { role: "user", parts: [ { text: message }, ...partsWithFiles ] } ]; const result = await this.model.generateContentStream({ contents }); const buffer = []; for await (const response of result.stream) { buffer.push(response.text()); if (extra == null ? void 0 : extra.stream) { extra.stream(response.text()); } } return buffer.join(" "); } createChat(chartContext) { return new GeminiChat( this.model, chartContext === null ? [] : chartContext, this.currentModel ); } }; var GeminiChat = class { model; chatContext; currentModel; constructor(model, chatContext, currentModel) { this.model = model; this.chatContext = chatContext; this.currentModel = currentModel; } async send(message, extra) { const partsWithFiles = []; if ((extra == null ? void 0 : extra.files) && extra.files.length > 0) { if (this.currentModel === "gemini-pro-vision") { throw new Error( `This model does not support images. Current model: ${this.currentModel}` ); } for (const file of extra.files) { partsWithFiles.push( { text: "Link: " + file } ); } } if (!this.chatContext) { this.chatContext = []; } this.chatContext.push({ role: "user", parts: [ { text: message }, ...partsWithFiles ] }); const contents = this.chatContext; const result = await this.model.generateContentStream({ contents }); const buffer = []; for await (const response of result.stream) { buffer.push(response.text()); if (extra == null ? void 0 : extra.stream) { extra.stream(response.text()); } } return buffer.join(" "); } async reset() { this.chatContext = []; } async save() { return this.chatContext; } async load(context) { this.chatContext = context; } }; var GeminiUtils = class { static async fileToGenerativePart(file) { const mimeType = await this.mimeTypeFromFile(file); const image64 = await fetch(file).then((r) => r.arrayBuffer()).then((a) => Base64.fromByteArray(new Uint8Array(a))); return { inline_data: { data: image64, mime_type: mimeType } }; } static async mimeTypeFromFile(file) { const extension = file.split(".")[file.split(".").length - 1]; switch (extension) { case "jpg": case "jpeg": return "image/jpeg"; case "png": return "image/png"; case "gif": return "image/gif"; case "webp": return "image/webp"; case "mp4": return "video/mp4"; case "wav": return "audio/wav"; case "mp3": return "audio/mp3"; case "aac": return "audio/aac"; default: throw new Error("Unsupported file type (${extension})"); } } }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Gemini, GeminiUtils });