diff --git a/README.md b/README.md index 80278a6..2d463f2 100644 --- a/README.md +++ b/README.md @@ -170,9 +170,12 @@ The value of `object` is as follows. {Array} object.history History for continuing chat. {Array} object.functions If you want to give the custom functions, please use this. {String} object.response_mime_type In the current stage, only "application/json" can be used. +{String} object.responseMimeType In the current stage, only "application/json" can be used. {Object} object.systemInstruction Ref: https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/gemini {Boolean} object.exportTotalTokens When this is true, the object `usageMetadata` including `promptTokenCount`, `candidatesTokenCount`, `totalTokenCount` is exported. At that time, the generated content and `usageMetadata` are returned as an object. {Boolean} object.exportRawData The default value is false. When this is true, the raw data returned from Gemini API is returned. +{Object} object.toolConfig The default is null. If you want to directly give the object of "toolConfig", please use this. +{Array} object.tools The default value is null. For example, when you want to use "codeExecution", please set `tools: [{ codeExecution: {}}]`. ``` - When you want to use `response_mime_type`, please give `jsonSchema` to generateContent method. In the current stage, only `"application/json"` can be used to `response_mime_type`. @@ -691,6 +694,7 @@ The sample scripts are as follows. - [Generate content with a movie file](#generatecontentwithamoviefile) - [Export total tokens](#exporttotaltokens) - [Use large file (over 50 MB)](#useover50mbdata) +- [Use codeExecution](#usecodeexecution) @@ -1351,6 +1355,51 @@ From v2.x.x, this can be achieved. This is from [Ref](https://github.com/tanaike The sample script can be seen at [here](#setfileidsorurlsWithresumableupload). + + +## Use codeExecution + +This prompt is from [this official document](https://ai.google.dev/gemini-api/docs/code-execution?lang=python). + +In order to use codeExecution, please use `tools: [{ codeExecution: {} }]` and `exportRawData: true` into the `geminiWithFiles` method as follows. + +```javascript +function myFunction() { + const apiKey = "###"; // Please set your API key. + + const g = GeminiWithFiles.geminiWithFiles({ apiKey, tools: [{ codeExecution: {} }], exportRawData: true }); + // const g = new GeminiWithFiles({ apiKey, tools: [{ codeExecution: {} }], exportRawData: true }); // This is for directly copying and pasting Class GeminiWithFiles into your Google Apps Script project. + + const res = g.generateContent({ q: 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.' }); + console.log(res.candidates[0].content.parts); +} +``` + +When this script is run, the following result is obtained. + +```json +[ + { + "text":"I will generate Python code to calculate the sum of the first 50 prime numbers.\n\n" + }, + { + "executableCode":{ + "language":"PYTHON", + "code":"\ndef is_prime(num):\n \"\"\"\n Checks if a number is prime.\n \"\"\"\n if num <= 1:\n return False\n for i in range(2, int(num**0.5) + 1):\n if num % i == 0:\n return False\n return True\n\nprimes = []\nn = 2\nwhile len(primes) < 50:\n if is_prime(n):\n primes.append(n)\n n += 1\n\nprint(f\\'The first 50 prime numbers are: {primes}\\')\nprint(f\\'The sum of the first 50 prime numbers is: {sum(primes)}\\')\n" + } + }, + { + "codeExecutionResult":{ + "outcome":"OUTCOME_OK", + "output":"The first 50 prime numbers are: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229]\nThe sum of the first 50 prime numbers is: 5117\n" + } + }, + { + "text":"The code first defines a function `is_prime(num)` to check if a number is prime. The function iterates through all numbers from 2 to the square root of the given number. If any of these numbers divide the given number, then the number is not prime. Otherwise, the number is prime.\n\nThen, the code initializes an empty list called `primes` to store the prime numbers. It also initializes a variable `n` to 2, which is the first prime number.\n\nThe code then enters a `while` loop that continues until 50 prime numbers are found. Inside the loop, the code checks if the current number `n` is prime using the `is_prime` function. If it is, the number is appended to the `primes` list.\n\nAfter the loop, the code prints the list of prime numbers and the sum of the prime numbers.\n\nThe output shows that the sum of the first 50 prime numbers is 5117." + } +] +``` + # IMPORTANT - If an error occurs, please try again after several minutes. @@ -1439,4 +1488,8 @@ I have already proposed the following future requests to the Google issue tracke - The export values with `exportTotalTokens` were changed. After v2.x.x, when this is true, the object `usageMetadata` including `promptTokenCount`, `candidatesTokenCount`, `totalTokenCount` is exported. At that time, the generated content and `usageMetadata` are returned as an object. - After v2.x.x, the large files can be uploaded to Gemini. This is from [this respository](https://github.com/tanaikech/UploadApp) and [this post](https://medium.com/google-cloud/uploading-large-files-to-gemini-with-google-apps-script-overcoming-50-mb-limit-6ea63204ee81). +- v2.0.1 (August 3, 2024) + + 1. From this version, `codeExecution` can be used. [Ref](#usecodeexecution) + [TOP](#top) diff --git a/classGeminiWithFiles.js b/classGeminiWithFiles.js index f9f2cd8..5994254 100644 --- a/classGeminiWithFiles.js +++ b/classGeminiWithFiles.js @@ -4,6 +4,9 @@ * GeminiWithFiles can upload files, generate content, and create descriptions * from multiple images at once. * This significantly reduces workload and expands possibilities for using Gemini. + * + * GeminiWithFiles v2.0.1 + * GitHub: https://github.com/tanaikech/GeminiWithFiles */ class GeminiWithFiles { @@ -22,9 +25,11 @@ class GeminiWithFiles { * @param {Object} object.systemInstruction Ref: https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/gemini. * @param {Boolean} object.exportTotalTokens When this is true, the total tokens are exported as the result value. At that time, the generated content and the total tokens are returned as an object. * @param {Boolean} object.exportRawData The default value is false. When this is true, the raw data returned from Gemini API is returned. + * @param {Object} object.toolConfig The default is null. If you want to directly give the object of "toolConfig", please use this. + * @param {Array} object.tools The default value is null. For example, when you want to use "codeExecution", please set `tools: [{ codeExecution: {}}]`. */ constructor(object = {}) { - const { apiKey, accessToken, model, version, doCountToken, history, functions, response_mime_type, responseMimeType, systemInstruction, exportTotalTokens, exportRawData } = object; + const { apiKey, accessToken, model, version, doCountToken, history, functions, response_mime_type, responseMimeType, systemInstruction, exportTotalTokens, exportRawData, toolConfig, tools } = object; /** @private */ this.model = model || "models/gemini-1.5-flash-latest"; // After v2.0.0, the model was changed from "models/gemini-1.5-pro-latest" to "models/gemini-1.5-flash-latest". @@ -104,10 +109,11 @@ class GeminiWithFiles { } /** @private */ - this.toolConfig = null; + this.toolConfig = toolConfig || {}; const keys = Object.keys(this.functions); if (keys.length > 0) { this.toolConfig = { + ...this.toolConfig, functionCallingConfig: { mode: "ANY", allowedFunctionNames: keys.filter(e => e != "params") @@ -121,6 +127,9 @@ class GeminiWithFiles { * @type {Array} */ this.history = history || []; + + /** @private */ + this.tools = tools || []; } /** @@ -393,6 +402,7 @@ class GeminiWithFiles { let check = true; let usageMetadataObj; const results = []; + let rawResult = {}; const url = this.addQueryParameters_(this.urlGenerateContent, this.queryParameters); do { retry--; @@ -403,9 +413,12 @@ class GeminiWithFiles { if (this.systemInstruction) { payload.systemInstruction = this.systemInstruction; } - if (this.toolConfig) { + if (Object.keys(this.toolConfig).length > 0) { payload.toolConfig = this.toolConfig; } + if (this.tools) { + payload.tools = this.tools; + } if (this.doCountToken) { const res = this.fetch_({ url: this.addQueryParameters_(this.urlCountToken, this.queryParameters), @@ -447,7 +460,7 @@ class GeminiWithFiles { } const raw = JSON.parse(res.getContentText()); if (this.exportRawData) { - results.push(raw); + rawResult = { ...raw }; break; } const { candidates, usageMetadata } = raw; @@ -492,7 +505,7 @@ class GeminiWithFiles { } } while (check && retry > 0); if (this.exportRawData) { - return results; + return rawResult; } const output = results.pop(); if (