ollama_openai_tools.ipynb
1 { 2 "cells": [ 3 { 4 "cell_type": "markdown", 5 "metadata": {}, 6 "source": [ 7 "## Function Calling with Ollama\n", 8 "\n", 9 "### Requirements\n", 10 "\n", 11 "#### 1. Ollama\n", 12 "\n", 13 "Ollama installation instructions per OS (macOS, Linux, Windows) can be found on [their website](https://ollama.com/download). For Linux simply (run cell below if not installed): " 14 ] 15 }, 16 { 17 "cell_type": "code", 18 "execution_count": null, 19 "metadata": {}, 20 "outputs": [], 21 "source": [ 22 "!curl -fsSL https://ollama.com/install.sh | sh" 23 ] 24 }, 25 { 26 "cell_type": "markdown", 27 "metadata": {}, 28 "source": [ 29 "#### 2. Python Ollama Library\n", 30 "\n", 31 "For that:" 32 ] 33 }, 34 { 35 "cell_type": "code", 36 "execution_count": 1, 37 "metadata": {}, 38 "outputs": [ 39 { 40 "name": "stdout", 41 "output_type": "stream", 42 "text": [ 43 "Collecting ollama\n", 44 " Downloading ollama-0.3.0-py3-none-any.whl.metadata (3.8 kB)\n", 45 "Requirement already satisfied: httpx<0.28.0,>=0.27.0 in /opt/homebrew/anaconda3/envs/func-call-demo/lib/python3.12/site-packages (from ollama) (0.27.0)\n", 46 "Requirement already satisfied: anyio in /opt/homebrew/anaconda3/envs/func-call-demo/lib/python3.12/site-packages (from httpx<0.28.0,>=0.27.0->ollama) (4.3.0)\n", 47 "Requirement already satisfied: certifi in /opt/homebrew/anaconda3/envs/func-call-demo/lib/python3.12/site-packages (from httpx<0.28.0,>=0.27.0->ollama) (2024.2.2)\n", 48 "Requirement already satisfied: httpcore==1.* in /opt/homebrew/anaconda3/envs/func-call-demo/lib/python3.12/site-packages (from httpx<0.28.0,>=0.27.0->ollama) (1.0.5)\n", 49 "Requirement already satisfied: idna in /opt/homebrew/anaconda3/envs/func-call-demo/lib/python3.12/site-packages (from httpx<0.28.0,>=0.27.0->ollama) (3.6)\n", 50 "Requirement already satisfied: sniffio in /opt/homebrew/anaconda3/envs/func-call-demo/lib/python3.12/site-packages (from httpx<0.28.0,>=0.27.0->ollama) (1.3.0)\n", 51 "Requirement already satisfied: h11<0.15,>=0.13 in /opt/homebrew/anaconda3/envs/func-call-demo/lib/python3.12/site-packages (from httpcore==1.*->httpx<0.28.0,>=0.27.0->ollama) (0.14.0)\n", 52 "Downloading ollama-0.3.0-py3-none-any.whl (10 kB)\n", 53 "Installing collected packages: ollama\n", 54 "Successfully installed ollama-0.3.0\n", 55 "Note: you may need to restart the kernel to use updated packages.\n" 56 ] 57 } 58 ], 59 "source": [ 60 "%pip install ollama" 61 ] 62 }, 63 { 64 "cell_type": "markdown", 65 "metadata": {}, 66 "source": [ 67 "#### 3. Pull the model from Ollama\n", 68 "\n", 69 "Download the q8 quantized NousHermes-2-Pro-Mistral-7B from Ollama (uploaded by adrienbrault):" 70 ] 71 }, 72 { 73 "cell_type": "code", 74 "execution_count": null, 75 "metadata": {}, 76 "outputs": [], 77 "source": [ 78 "!ollama pull adrienbrault/nous-hermes2pro:Q8_0" 79 ] 80 }, 81 { 82 "cell_type": "markdown", 83 "metadata": {}, 84 "source": [ 85 "### Usage\n", 86 "\n", 87 "#### 1. Define Tools" 88 ] 89 }, 90 { 91 "cell_type": "code", 92 "execution_count": 31, 93 "metadata": {}, 94 "outputs": [], 95 "source": [ 96 "import requests\n", 97 "import random\n", 98 "from datetime import datetime\n", 99 "import pytz\n", 100 "\n", 101 "def get_weather_forecast(location: str) -> dict[str, str]:\n", 102 " \"\"\"Retrieves a simple weather forecast for a given location\"\"\"\n", 103 " url = f\"https://wttr.in/{location}?format=%C,%t\"\n", 104 " response = requests.get(url)\n", 105 " if response.status_code == 200:\n", 106 " condition, temperature = response.text.strip().split(',')\n", 107 " return {\n", 108 " \"location\": location,\n", 109 " \"forecast\": condition,\n", 110 " \"temperature\": temperature\n", 111 " }\n", 112 " else:\n", 113 " return {\"error\": \"Unable to fetch weather data\"}\n", 114 "\n", 115 "\n", 116 "def get_stock_price(symbol: str) -> float:\n", 117 " \"\"\"Retrieves the stock price for a given symbol\"\"\"\n", 118 " api_key = \"your_stock_api_key\"\n", 119 " url = f\"https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol={symbol}&apikey={api_key}\"\n", 120 " response = requests.get(url)\n", 121 " data = response.json()\n", 122 " return float(data[\"Global Quote\"][\"05. price\"])\n", 123 "\n", 124 "def get_random_number(min_value: int, max_value: int) -> int:\n", 125 " \"\"\"Returns a random number between min_value and max_value\"\"\"\n", 126 " return random.randint(min_value, max_value)\n", 127 "\n", 128 "def get_current_time(time_zone: str, format: str) -> str:\n", 129 " \"\"\"Returns the current time in the specified time zone and format\"\"\"\n", 130 " tz = pytz.timezone(time_zone)\n", 131 " current_time = datetime.now(tz)\n", 132 " return current_time.strftime(format)\n", 133 "\n", 134 "def get_user_location(ip_address: str, accuracy: int) -> str:\n", 135 " \"\"\"Returns the user's location based on the provided IP address and accuracy level\"\"\"\n", 136 " url = f\"http://ip-api.com/json/{ip_address}\"\n", 137 " response = requests.get(url)\n", 138 " data = response.json()\n", 139 " if accuracy == 1:\n", 140 " return data[\"country\"]\n", 141 " elif accuracy == 2:\n", 142 " return f\"{data['city']}, {data['country']}\"\n", 143 " else:\n", 144 " return f\"{data['city']}, {data['region']}, {data['country']}\"" 145 ] 146 }, 147 { 148 "cell_type": "code", 149 "execution_count": 32, 150 "metadata": {}, 151 "outputs": [], 152 "source": [ 153 "def test_functions():\n", 154 " print(\"Testing get_weather_forecast:\")\n", 155 " try:\n", 156 " weather = get_weather_forecast(\"London\")\n", 157 " print(f\"Weather in London: {weather}\")\n", 158 " except Exception as e:\n", 159 " print(f\"Error in get_weather_forecast: {str(e)}\")\n", 160 "\n", 161 " print(\"\\nTesting get_stock_price:\")\n", 162 " try:\n", 163 " price = get_stock_price(\"AAPL\")\n", 164 " print(f\"Current price of AAPL: ${price:.2f}\")\n", 165 " except Exception as e:\n", 166 " print(f\"Error in get_stock_price: {str(e)}\")\n", 167 "\n", 168 " print(\"\\nTesting get_random_number:\")\n", 169 " try:\n", 170 " number = get_random_number(2, 42)\n", 171 " print(f\"Random number between 1 and 100: {number}\")\n", 172 " except Exception as e:\n", 173 " print(f\"Error in get_random_number: {str(e)}\")\n", 174 "\n", 175 " print(\"\\nTesting get_current_time:\")\n", 176 " try:\n", 177 " time = get_current_time(\"America/New_York\", \"%Y-%m-%d %H:%M:%S\")\n", 178 " print(f\"Current time in New York: {time}\")\n", 179 " except Exception as e:\n", 180 " print(f\"Error in get_current_time: {str(e)}\")\n", 181 "\n", 182 " print(\"\\nTesting get_user_location:\")\n", 183 " try:\n", 184 " location = get_user_location(\"8.8.8.8\", 2)\n", 185 " print(f\"Location for IP 8.8.8.8: {location}\")\n", 186 " except Exception as e:\n", 187 " print(f\"Error in get_user_location: {str(e)}\")" 188 ] 189 }, 190 { 191 "cell_type": "code", 192 "execution_count": 33, 193 "metadata": {}, 194 "outputs": [ 195 { 196 "name": "stdout", 197 "output_type": "stream", 198 "text": [ 199 "Testing get_weather_forecast:\n", 200 "Weather in London: {'location': 'London', 'forecast': 'Partly cloudy', 'temperature': '+22°C'}\n", 201 "\n", 202 "Testing get_stock_price:\n", 203 "Current price of AAPL: $224.31\n", 204 "\n", 205 "Testing get_random_number:\n", 206 "Random number between 1 and 100: 13\n", 207 "\n", 208 "Testing get_current_time:\n", 209 "Current time in New York: 2024-07-20 13:19:54\n", 210 "\n", 211 "Testing get_user_location:\n", 212 "Location for IP 8.8.8.8: Ashburn, United States\n" 213 ] 214 } 215 ], 216 "source": [ 217 "test_functions()" 218 ] 219 }, 220 { 221 "cell_type": "code", 222 "execution_count": 41, 223 "metadata": {}, 224 "outputs": [], 225 "source": [ 226 "from langchain_core.utils.function_calling import convert_to_openai_function\n", 227 "\n", 228 "functions = [\n", 229 " get_weather_forecast,\n", 230 " get_stock_price,\n", 231 " get_random_number,\n", 232 " get_current_time,\n", 233 " get_user_location\n", 234 "]\n", 235 "\n", 236 "tools = [convert_to_openai_function(t) for t in tools]" 237 ] 238 }, 239 { 240 "cell_type": "code", 241 "execution_count": 43, 242 "metadata": {}, 243 "outputs": [ 244 { 245 "name": "stdout", 246 "output_type": "stream", 247 "text": [ 248 "[\n", 249 " {\n", 250 " \"name\": \"get_weather_forecast\",\n", 251 " \"description\": \"Retrieves a simple weather forecast for a given location\",\n", 252 " \"parameters\": {\n", 253 " \"type\": \"object\",\n", 254 " \"properties\": {\n", 255 " \"location\": {\n", 256 " \"type\": \"string\"\n", 257 " }\n", 258 " },\n", 259 " \"required\": [\n", 260 " \"location\"\n", 261 " ]\n", 262 " }\n", 263 " },\n", 264 " {\n", 265 " \"name\": \"get_stock_price\",\n", 266 " \"description\": \"Retrieves the stock price for a given symbol\",\n", 267 " \"parameters\": {\n", 268 " \"type\": \"object\",\n", 269 " \"properties\": {\n", 270 " \"symbol\": {\n", 271 " \"type\": \"string\"\n", 272 " }\n", 273 " },\n", 274 " \"required\": [\n", 275 " \"symbol\"\n", 276 " ]\n", 277 " }\n", 278 " },\n", 279 " {\n", 280 " \"name\": \"get_random_number\",\n", 281 " \"description\": \"Returns a random number between min_value and max_value\",\n", 282 " \"parameters\": {\n", 283 " \"type\": \"object\",\n", 284 " \"properties\": {\n", 285 " \"min_value\": {\n", 286 " \"type\": \"integer\"\n", 287 " },\n", 288 " \"max_value\": {\n", 289 " \"type\": \"integer\"\n", 290 " }\n", 291 " },\n", 292 " \"required\": [\n", 293 " \"min_value\",\n", 294 " \"max_value\"\n", 295 " ]\n", 296 " }\n", 297 " },\n", 298 " {\n", 299 " \"name\": \"get_current_time\",\n", 300 " \"description\": \"Returns the current time in the specified time zone and format\",\n", 301 " \"parameters\": {\n", 302 " \"type\": \"object\",\n", 303 " \"properties\": {\n", 304 " \"time_zone\": {\n", 305 " \"type\": \"string\"\n", 306 " },\n", 307 " \"format\": {\n", 308 " \"type\": \"string\"\n", 309 " }\n", 310 " },\n", 311 " \"required\": [\n", 312 " \"time_zone\",\n", 313 " \"format\"\n", 314 " ]\n", 315 " }\n", 316 " },\n", 317 " {\n", 318 " \"name\": \"get_user_location\",\n", 319 " \"description\": \"Returns the user's location based on the provided IP address and accuracy level\",\n", 320 " \"parameters\": {\n", 321 " \"type\": \"object\",\n", 322 " \"properties\": {\n", 323 " \"ip_address\": {\n", 324 " \"type\": \"string\"\n", 325 " },\n", 326 " \"accuracy\": {\n", 327 " \"type\": \"integer\"\n", 328 " }\n", 329 " },\n", 330 " \"required\": [\n", 331 " \"ip_address\",\n", 332 " \"accuracy\"\n", 333 " ]\n", 334 " }\n", 335 " }\n", 336 "]\n" 337 ] 338 } 339 ], 340 "source": [ 341 "import json\n", 342 "\n", 343 "\n", 344 "print(json.dumps(tools, indent=2))" 345 ] 346 }, 347 { 348 "cell_type": "code", 349 "execution_count": 40, 350 "metadata": {}, 351 "outputs": [], 352 "source": [ 353 "from openai import OpenAI\n", 354 "\n", 355 "client = OpenAI(\n", 356 " base_url = 'http://localhost:11434/v1',\n", 357 " api_key='ollama', # required, but unused\n", 358 ")" 359 ] 360 }, 361 { 362 "cell_type": "code", 363 "execution_count": null, 364 "metadata": {}, 365 "outputs": [], 366 "source": [ 367 "response = client.chat.completions.create(\n", 368 " model=\"interstellarninja/hermes-2-theta-llama-3-8b:latest\",\n", 369 " messages = [\n", 370 " {\"role\": \"user\", \"content\": \"what's the weather like today in Paris?\"}\n", 371 " ],\n", 372 " tools=tools\n", 373 ")" 374 ] 375 }, 376 { 377 "cell_type": "code", 378 "execution_count": null, 379 "metadata": {}, 380 "outputs": [], 381 "source": [ 382 "print(response)" 383 ] 384 } 385 ], 386 "metadata": { 387 "kernelspec": { 388 "display_name": "Python 3", 389 "language": "python", 390 "name": "python3" 391 }, 392 "language_info": { 393 "codemirror_mode": { 394 "name": "ipython", 395 "version": 3 396 }, 397 "file_extension": ".py", 398 "mimetype": "text/x-python", 399 "name": "python", 400 "nbconvert_exporter": "python", 401 "pygments_lexer": "ipython3", 402 "version": "3.12.2" 403 } 404 }, 405 "nbformat": 4, 406 "nbformat_minor": 2 407 }