/ examples / ollama_openai_tools.ipynb
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  }