avatarBalazs Kocsis

Summary

The undefined website content discusses the integration of function calling in the Ollama 0.3.0 framework, which enhances AI capabilities by allowing interaction with external tools and APIs to solve complex problems.

Abstract

The Ollama framework's latest version, 0.3.0, introduces function calling that enables AI systems to interact with external tools and data sources, such as APIs and databases, to provide more accurate and contextually relevant responses. This feature is exemplified through the use of two custom functions for retrieving weather data and comparing numbers, demonstrating how AI can now perform tasks beyond traditional conversational boundaries. The article details the code structure, including the definition of tools and their parameters, and explains how the AI model can invoke these functions based on user queries. It also emphasizes the importance of fallback mechanisms to ensure a seamless conversation when function calls are not necessary, maintaining the natural flow of dialogue.

Opinions

  • The author believes that function calling significantly bridges the gap between language models and real-world applications.
  • The ability to interact with external tools is seen as a major enhancement to the problem-solving abilities of AI systems.
  • It is highlighted that the Ollama framework's function calling gracefully coexists with traditional conversational AI workflows.
  • The article suggests that defining function environments within the Ollama framework can be arbitrarily numerous, indicating scalability and flexibility.
  • The author seems to value the accuracy and reliability of information provided by function calls over the AI's own data processing, avoiding guesswork or "hallucinating" responses.
  • The inclusion of a fallback to the default language model response is considered crucial for handling a wide range of user queries and maintaining dialogue flow.

Function calling in Ollama 0.3.0

Tool use with any model privately with LLama3.1

Image from https://ollama.com/blog/tool-support

Function calling is bridging the gap between language models and real-world applications. It allows an AI system to seamlessly interact with external tools (for example API-s, databases, calculators), dramatically expanding its problem-solving abilities. In this article we will explore the newly introduced function calling in Ollama framework, give an example of defining two function environments, and how it gracefully coexists with traditional conversational AI workflows.

Photo by Jakob Owens on Unsplash

Requirements: ollama>=0.3.0 llama3.1 and compatible models

Code walk-through

The following code block is an example of using ollama (0.3.0) with the `tools` block in the ollama.chat object. Here we are defining two function, one for the weather, and one for number comparison. This list of functions can be arbitrarily numerous.

import ollama
import requests


def get_current_weather(city):
    base_url = f"https://wttr.in/{city}?format=j1"
    response = requests.get(base_url)
    data = response.json()
    return f"Temp in {city}: {data['current_condition'][0]['temp_C']}"


def what_is_bigger(n, m):
    if n > m:
        return f"{n} is bigger"
    elif m > n:
        return f"{m} is bigger"
    else:
        return f"{n} and {m} are equal"


def chat_with_ollama_no_functions(user_question):
    response = ollama.chat(
        model='llama3.1:8b-instruct-fp16',
        messages=[
            {'role': 'user', 'content': user_question}
        ]
    )
    return response


def chat_with_ollama(user_question):
    response = ollama.chat(
        model='llama3.1:8b-instruct-fp16',
        messages=[
            {'role': 'user', 'content': user_question}
        ],
        tools=[
            {
                'type': 'function',
                'function': {
                    'name': "get_current_weather",
                    'description': "Get the current weather for a city",
                    'parameters': {
                        'type': "object",
                        'properties': {
                            'city': {
                                'type': "string",
                                "description": "City",
                            },
                        },
                        'required': ['city'],
                    },
                },
            },
            {
                'type': "function",
                'function': {
                    "name": "which_is_bigger",
                    'parameters': {
                        'type': 'object',
                        'properties': {
                            'n': {
                                'type': "float",
                            },
                            "m": {
                                'type': "float"
                            },
                        },
                        'required': ['n', 'm'],
                    },
                },
            },
        ],
    )
    return response


def main():
    while True:
        user_input = input("Enter your question (or 'quit' to exit): ")
        if user_input.lower() == 'quit':
            break

        response = chat_with_ollama(user_input)

        if 'tool_calls' in response['message'] and response['message']['tool_calls']:
            tools_calls = response['message']['tool_calls']
            for tool_call in tools_calls:
                tool_name = tool_call['function']['name']
                arguments = tool_call['function']['arguments']

                if tool_name == 'get_current_weather' and 'city' in arguments:
                    result = get_current_weather(arguments['city'])
                    print("Weather function result:", result)
                elif tool_name == 'which_is_bigger' and 'n' in arguments and 'm' in arguments:
                    n, m = float(arguments['n']), float(arguments['m'])
                    result = what_is_bigger(n, m)
                    print("Comparison function result:", result)
                else:
                    print(f"No valid arguments found for function: {tool_name}")
        else:
            # If no tool calls or no valid arguments, use the LLM's response
            response = chat_with_ollama_no_functions(user_input)
            print("AI response:", response['message']['content'])


if __name__ == "__main__":
    main()

The most important part here is the definition of the `tools` argument with its parameters, i.e. the extraction of the relevant values from the user prompt and defining them as arguments to the functions (`get_current_weather`, `what_is_bigger`, respectively).

The main function just handles the chat and channels the extracted arguments to the corresponding functions. Also, in case that during the chat flow, there are no keywords (arguments for the functions) have been detected, the chat uses the default response of the LLM.

The “tools” field in detail

The `chat_with_ollama` function is a crucial component of this code, responsible for interacting with the Ollama language model and setting up the function-calling capabilities.

def chat_with_ollama(user_question):
    response = ollama.chat(
        model='llama3.1:8b-instruct-fp16',
        messages=[
            {'role': 'user', 'content': user_question}
        ],
        tools=[
            # Tool definitions here
        ]
    )
    return response

Ollama Chat Configuration The function uses `ollama.chat()` to interact with the Ollama API. Next to the model and messages sections, it now has the `tools` section.

Tools Section The `tools` array is where the function-calling capabilities are defined. Each tool is an object with the following structure:

{
    'type': 'function',
    'function': {
        'name': "function_name",
        'description': "Function description",
        'parameters': {
            'type': "object",
            'properties': {
                # Parameter definitions
            },
            'required': ['param1', 'param2'],
        },
    },
}

Two tools are defined in this function: `get_current_weather` with only the `city` as argument, and the `which_is_bigger`with the floats as parameters.

These tool definitions inform the Ollama model about the available functions it can call. When the model determines that a function call is necessary to answer a user’s question, it will include a `tool_calls` object in its response, specifying which function to call and with what arguments.

The main program then interprets these `tool_calls` and executes the appropriate functions, integrating their results into the conversation flow.

Function calling in general

In this implementation, the model can recognize when a user’s query requires specific data or computations that it can’t directly provide. Instead of guessing or hallucinating, it can “call” predefined functions to retrieve accurate information or perform calculations. This is achieved by providing the model with a list of available functions and their parameters. When the model determines a function call is necessary, it generates a structured request specifying the function name and required arguments, allowing the application to execute the appropriate function and incorporate the result into the conversation.

The chat_with_ollama function defines these tools, each with its own set of parameters and descriptions. During execution, the application checks for tool_calls in the model's response. If present, it iterates through each call, matches it to the corresponding function, and executes it with the provided arguments. By simply adding new functions to the tools list and implementing their corresponding logic in the main loop, the capabilities of the app will be more specific to the needs of the user.

Fallback to default LLM response

The case when a chat context does not execute functions: The code also handles scenarios where function calls are not necessary or applicable. In cases where the model’s response doesn’t include tool_calls, or when the arguments for a function call are invalid, the application falls back to a standard chat interaction. This is implemented through the chat_with_ollama_no_functions function, which processes the user's input without any function-calling capabilities. This fallback ensures that the conversation can continue smoothly even when the user's query doesn't require external data or computations, maintaining a natural dialogue flow. It's a crucial feature that allows the AI to handle a wide range of queries, from those requiring specific data to open-ended conversations.

Conclusion

This code example shows a simple implementation of multiple functions in a chat application using ollama. While running simple chats with the code, one can see that when the pattern is defined in a user prompt, the corresponding functions are executed as expected and return a response as defined in the function. When no tool calling patterns were detected, the app uses the LLM’s response (no function calling). In this simplistic example we used only two functions. This can be more complex, in case when several similar functions are defined, with similar arguments. This behavior of such a case should also be tested.

In Plain English 🚀

Thank you for being a part of the In Plain English community! Before you go:

Ollama
Llm Function Calling
Python
Recommended from ReadMedium