Skip to content

Instantly share code, notes, and snippets.

@gsans
Created February 9, 2025 21:38
Show Gist options
  • Save gsans/612b51fa347c0f94bb9065e0673b9d2d to your computer and use it in GitHub Desktop.
Save gsans/612b51fa347c0f94bb9065e0673b9d2d to your computer and use it in GitHub Desktop.

Revisions

  1. gsans created this gist Feb 9, 2025.
    131 changes: 131 additions & 0 deletions code-snippet.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,131 @@
    async TestGeminiProFunctionCallingCalculator() {
    // Gemini Client
    const genAI = new GoogleGenerativeAI(environment.API_KEY);

    // Define the function to be called.
    // Following the specificication at https://spec.openapis.org/oas/v3.0.3
    const evalMathFunction = {
    name: "evalMath",
    description: "Get a result of a math expression as a string using the specified runtime",
    parameters: {
    type: SchemaType.OBJECT,
    properties: {
    expression: {
    type: SchemaType.STRING,
    description: "A valid math expression to evaluate.",
    },
    runtime: {
    type: SchemaType.STRING,
    enum: ["javascript"],
    description: "The runtime to use for the evaluation.",
    }
    },
    required: ["expression", "runtime"],
    },
    };

    // Executable function code.
    interface EvaluationExpressionParams {
    expression: string;
    runtime: string;
    }

    const functions = {
    evalMath: ({ expression, runtime }: EvaluationExpressionParams) => {
    console.log("Evaluating expression:", expression);
    try {
    let evaluationMessage = "";
    const result = eval(expression);
    console.log("Result:", result);
    return {
    result,
    runtime,
    evaluationMessage: "Success: The result is " + result,
    };
    } catch (error) {
    console.error("Error evaluating expression:", error);
    return {
    result: null,
    runtime,
    evaluationMessage: "Error: Invalid mathematical expression."
    };
    }
    }
    };

    const toolConfig = {
    tools: [
    {
    functionDeclarations: [
    evalMathFunction,
    ],
    },
    ],
    toolConfig: {
    functionCallingConfig: {
    // (⌘ + /) Toggle line comments to test different function calling modes.

    // (default) Generates an unstructured output or a single function call as defined in "functionDeclarations".
    mode: FunctionCallingMode.AUTO,

    // // Generates a single function call as defined in "tools.functionDeclarations".
    // // The function must be whitelisted below.
    // // Warning: unstructured outputs are not possible using this option.
    // mode: FunctionCallingMode.ANY,
    // allowedFunctionNames: ["getCurrentWeather"],

    // // Effectively disables the "tools.functionDeclarations".
    // mode: FunctionCallingMode.NONE,
    },
    }
    }

    const generationConfig = {
    safetySettings: [
    {
    category: HarmCategory.HARM_CATEGORY_HARASSMENT,
    threshold: HarmBlockThreshold.BLOCK_ONLY_HIGH,
    },
    ],
    maxOutputTokens: 100,

    ...toolConfig,
    };

    const model = genAI.getGenerativeModel({
    model: GoogleAI.Model.Gemini20ProExp,
    ...generationConfig,
    });
    const chat = model.startChat();

    // Initial request from user
    const prompt = "Calculate the root square of 25.";
    const result = await chat.sendMessage(prompt);
    console.log(`User prompt: ${prompt}`);
    console.log(result.response);

    // Extract function call generated by the model
    const call = result.response.functionCalls()?.[0];
    if (call) {
    // Call the actual function
    if (call.name === "evalMath") {
    // Remeber to add aditional checks for the function name and parameters
    const callResponse = functions[call.name](call.args as EvaluationExpressionParams);

    // (Optional) Send the API response back to the model
    // You can skip this step if you only need the raw API response but not as part of a chatbot conversation.
    const finalResponse = await chat.sendMessage([{
    functionResponse: {
    name: 'evalMath',
    response: callResponse,
    }
    }]);
    // Answer from the model
    console.log(`Gemini: ${finalResponse.response.text()}`);
    // Answer from API response (as if we skipped the finalResponse step)
    console.log(`Raw API: Total is (${callResponse.result}). Runtime (${callResponse?.runtime}). Evaluation Message (${callResponse.evaluationMessage})`);
    }
    } else {
    console.error(result.response.text());
    }
    }