Skip to content

Day 7 — Tool calling + local models with Ollama

Why / क्यों

English: An LLM alone only writes text — it can't know today's weather or touch your database. Tool calling hands it your Python functions, and the LLM decides when to use them. This is the foundation of agents. Ollama lets you run models on your own laptop.

Hindi: अकेला LLM सिर्फ़ text बनाता है — आज का weather या आपका database नहीं जानता। Tool calling में आप उसे Python functions देते हो, और LLM खुद तय करता है कब use करना है। यही agents की नींव है। Ollama से model आपके laptop पर चलता है।

How tool calling works / tool calling कैसे चलता है

sequenceDiagram
    participant U as User
    participant C as Your code
    participant L as LLM
    participant T as get_weather()
    U->>C: Is it hot in Delhi?
    C->>L: question + tool description
    L-->>C: call get_weather(city="Delhi")
    C->>T: run the function
    T-->>C: {"temperature_c": 24}
    C->>L: tool result
    L-->>U: It's 24 °C — pleasant, not hot.

Key idea

The LLM never runs the tool itself. It returns the function name + arguments; your code runs it and sends the result back.

1. Tool calling with Gemini

import os
import requests
from dotenv import load_dotenv
from google import genai
from google.genai import types

load_dotenv()
client = genai.Client(
    api_key=os.getenv("GEMINI_API_KEY"),
    http_options=types.HttpOptions(timeout=60000),
)

CITIES = {"delhi": (28.61, 77.21), "mumbai": (19.07, 72.88)}

def get_weather(city: str) -> dict:
    """Returns the current temperature and wind speed for an Indian city.

    Args:
        city: Name of the city, for example Delhi or Mumbai.
    """
    print(f"   [TOOL CALLED] get_weather(city='{city}')")
    coords = CITIES.get(city.lower())
    if coords is None:
        return {"error": f"{city} not supported"}
    lat, lon = coords
    url = "https://api.open-meteo.com/v1/forecast"
    params = {"latitude": lat, "longitude": lon, "current_weather": True}
    data = requests.get(url, params=params).json()["current_weather"]
    return {"city": city, "temperature_c": data["temperature"], "wind_kmh": data["windspeed"]}

config = types.GenerateContentConfig(tools=[get_weather], temperature=0)

for question in ["Is it hot in Delhi right now?", "What is Python, in one line?"]:
    print("You:", question)
    response = client.models.generate_content(
        model="gemini-3.5-flash-lite", contents=question, config=config
    )
    print("Bot:", response.text, "\n")

The weather question triggers the tool; the Python question does not — the LLM decided.

Write clear docstrings

The LLM reads the function's docstring to decide when to use the tool.

2. Ollama — run an LLM on your laptop

winget install Ollama.Ollama
ollama pull qwen3.5:4b
ollama run qwen3.5:4b

Inside the chat, turn off slow "thinking" and exit with:

/set nothink
/bye

From Python:

pip install ollama
import time
import ollama

start = time.time()
response = ollama.chat(
    model="qwen3.5:4b",
    messages=[{"role": "user", "content": "What is RAG? Answer in 2 lines."}],
    think=False,
)
print(response["message"]["content"])
print(f"Time: {time.time() - start:.1f} seconds — no internet, no API key")
Local / open models (Ollama, Qwen, Llama) Closed APIs (Gemini, Claude, GPT)
Strength Privacy, no per-token cost, full control Best quality, no hardware needed
Use when Private data (banks, hospitals) You need top quality fast

Quiz / अपने आप को test करो

1. Does the LLM run the tool function itself?

No. It returns the function name and arguments; your code runs it and sends back the result.

2. How does the LLM know when to use a tool?

From the tool's name and docstring description.

3. What turns tool calling into an agent?

Repeating the loop — think, call tool, observe result — until the task is done.

4. Why run models locally with Ollama?

Privacy, no internet, and no per-token cost.

5. Why turn thinking off for simple questions?

Thinking models are slower; simple tasks don't need extra reasoning (latency vs quality trade-off).