From 04972cd345b22f121c1af4c1ddeec791c1c03f9f Mon Sep 17 00:00:00 2001
From: Simonas <20096648+simjak@users.noreply.github.com>
Date: Mon, 18 Dec 2023 12:21:06 +0200
Subject: [PATCH] test fix, release 0.0.12

---
 coverage.xml                         |  22 +-
 docs/examples/function_calling.ipynb | 369 +++++++++++++++++++++------
 pyproject.toml                       |   2 +-
 3 files changed, 304 insertions(+), 89 deletions(-)

diff --git a/coverage.xml b/coverage.xml
index 3b0a9de9..9af9ebee 100644
--- a/coverage.xml
+++ b/coverage.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" ?>
-<coverage version="7.3.3" timestamp="1702893702032" lines-valid="345" lines-covered="345" line-rate="1" branches-covered="0" branches-valid="0" branch-rate="0" complexity="0">
+<coverage version="7.3.3" timestamp="1702894511196" lines-valid="345" lines-covered="345" line-rate="1" branches-covered="0" branches-valid="0" branch-rate="0" complexity="0">
 	<!-- Generated by coverage.py: https://coverage.readthedocs.io/en/7.3.3 -->
 	<!-- Based on https://raw.githubusercontent.com/cobertura/web/master/htdocs/xml/coverage-04.dtd -->
 	<sources>
@@ -349,12 +349,12 @@
 						<line number="2" hits="1"/>
 						<line number="4" hits="1"/>
 						<line number="5" hits="1"/>
-						<line number="7" hits="1"/>
+						<line number="6" hits="1"/>
 						<line number="8" hits="1"/>
-						<line number="11" hits="1"/>
+						<line number="9" hits="1"/>
 						<line number="12" hits="1"/>
-						<line number="14" hits="1"/>
-						<line number="19" hits="1"/>
+						<line number="13" hits="1"/>
+						<line number="15" hits="1"/>
 						<line number="20" hits="1"/>
 						<line number="21" hits="1"/>
 						<line number="22" hits="1"/>
@@ -362,12 +362,12 @@
 						<line number="24" hits="1"/>
 						<line number="25" hits="1"/>
 						<line number="26" hits="1"/>
-						<line number="28" hits="1"/>
+						<line number="27" hits="1"/>
 						<line number="29" hits="1"/>
 						<line number="30" hits="1"/>
 						<line number="31" hits="1"/>
 						<line number="32" hits="1"/>
-						<line number="35" hits="1"/>
+						<line number="33" hits="1"/>
 						<line number="36" hits="1"/>
 						<line number="37" hits="1"/>
 						<line number="38" hits="1"/>
@@ -380,11 +380,11 @@
 						<line number="45" hits="1"/>
 						<line number="46" hits="1"/>
 						<line number="47" hits="1"/>
-						<line number="49" hits="1"/>
+						<line number="48" hits="1"/>
 						<line number="50" hits="1"/>
-						<line number="51" hits="1"/>
-						<line number="53" hits="1"/>
-						<line number="54" hits="1"/>
+						<line number="55" hits="1"/>
+						<line number="57" hits="1"/>
+						<line number="58" hits="1"/>
 					</lines>
 				</class>
 			</classes>
diff --git a/docs/examples/function_calling.ipynb b/docs/examples/function_calling.ipynb
index 0966df1d..5d3be2fb 100644
--- a/docs/examples/function_calling.ipynb
+++ b/docs/examples/function_calling.ipynb
@@ -9,12 +9,11 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 12,
    "metadata": {},
    "outputs": [],
    "source": [
     "# OpenAI\n",
-    "import os\n",
     "import openai\n",
     "from semantic_router.utils.logger import logger\n",
     "\n",
@@ -40,7 +39,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 13,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -67,7 +66,9 @@
     "            \"inputs\": f\"You are a helpful assistant, user query: {prompt}\",\n",
     "            \"parameters\": {\n",
     "                \"max_new_tokens\": 200,\n",
-    "                \"temperature\": 0.1,\n",
+    "                \"temperature\": 0.01,\n",
+    "                \"num_beams\": 5,\n",
+    "                \"num_return_sequences\": 1,\n",
     "            },\n",
     "        },\n",
     "    )\n",
@@ -90,7 +91,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 14,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -112,7 +113,24 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 15,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import json\n",
+    "\n",
+    "\n",
+    "def is_valid_config(route_config_str: str) -> bool:\n",
+    "    try:\n",
+    "        output_json = json.loads(route_config_str)\n",
+    "        return all(key in output_json for key in [\"name\", \"utterances\"])\n",
+    "    except json.JSONDecodeError:\n",
+    "        return False"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -123,44 +141,57 @@
     "\n",
     "def generate_route(function) -> dict:\n",
     "    logger.info(\"Generating config...\")\n",
-    "    example_schema = {\n",
-    "        \"name\": \"get_weather\",\n",
-    "        \"description\": \"Useful to get the weather in a specific location\",\n",
-    "        \"signature\": \"(location: str) -> str\",\n",
-    "        \"output\": \"<class 'str'>\",\n",
-    "    }\n",
-    "\n",
-    "    example_config = {\n",
-    "        \"name\": \"get_weather\",\n",
-    "        \"utterances\": [\n",
-    "            \"What is the weather like in SF?\",\n",
-    "            \"What is the weather in Cyprus?\",\n",
-    "            \"weather in London?\",\n",
-    "            \"Tell me the weather in New York\",\n",
-    "            \"what is the current weather in Paris?\",\n",
-    "        ],\n",
-    "    }\n",
     "\n",
     "    function_schema = get_function_schema(function)\n",
     "\n",
     "    prompt = f\"\"\"\n",
-    "    You are a helpful assistant designed to output JSON.\n",
-    "    Given the following function schema\n",
-    "    {function_schema}\n",
-    "    generate a routing config with the format:\n",
-    "    {example_config}\n",
-    "\n",
-    "    For example:\n",
-    "    Input: {example_schema}\n",
-    "    Output: {example_config}\n",
+    "    You are tasked to generate a JSON configuration based on the provided\n",
+    "    function schema. Please follow the template below:\n",
     "\n",
-    "    Input: {function_schema}\n",
-    "    Output:\n",
+    "    {{\n",
+    "        \"name\": \"<function_name>\",\n",
+    "        \"utterances\": [\n",
+    "            \"<example_utterance_1>\",\n",
+    "            \"<example_utterance_2>\",\n",
+    "            \"<example_utterance_3>\",\n",
+    "            \"<example_utterance_4>\",\n",
+    "            \"<example_utterance_5>\"]\n",
+    "    }}\n",
+    "\n",
+    "    Only include the \"name\" and \"utterances\" keys in your answer.\n",
+    "    The \"name\" should match the function name and the \"utterances\"\n",
+    "    should comprise a list of 5 example phrases that could be used to invoke\n",
+    "    the function.\n",
+    "\n",
+    "    Input schema:\n",
+    "    {function_schema}\n",
     "    \"\"\"\n",
     "\n",
-    "    ai_message = llm_openai(prompt)\n",
+    "    try:\n",
+    "        ai_message = llm_mistral(prompt)\n",
+    "\n",
+    "        # Parse the response\n",
+    "        ai_message = ai_message[ai_message.find(\"{\") :]\n",
+    "        ai_message = (\n",
+    "            ai_message.replace(\"'\", '\"')\n",
+    "            .replace('\"s', \"'s\")\n",
+    "            .strip()\n",
+    "            .rstrip(\",\")\n",
+    "            .replace(\"}\", \"}\")\n",
+    "        )\n",
+    "\n",
+    "        valid_config = is_valid_config(ai_message)\n",
     "\n",
-    "    ai_message = ai_message.replace(\"CONFIG:\", \"\").replace(\"'\", '\"').strip().rstrip(\",\")\n",
+    "        if not valid_config:\n",
+    "            logger.warning(f\"Mistral failed with error, falling back to OpenAI\")\n",
+    "            ai_message = llm_openai(prompt)\n",
+    "            if not is_valid_config(ai_message):\n",
+    "                raise Exception(\"Invalid config generated\")\n",
+    "    except Exception as e:\n",
+    "        logger.error(f\"Fall back to OpenAI failed with error {e}\")\n",
+    "        ai_message = llm_openai(prompt)\n",
+    "        if not is_valid_config(ai_message):\n",
+    "            raise Exception(\"Failed to generate config\")\n",
     "\n",
     "    try:\n",
     "        route_config = json.loads(ai_message)\n",
@@ -181,7 +212,23 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 17,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def validate_parameters(function, parameters):\n",
+    "    sig = inspect.signature(function)\n",
+    "    for name, param in sig.parameters.items():\n",
+    "        if name not in parameters:\n",
+    "            return False, f\"Parameter {name} missing from query\"\n",
+    "        if not isinstance(parameters[name], param.annotation):\n",
+    "            return False, f\"Parameter {name} is not of type {param.annotation}\"\n",
+    "    return True, \"Parameters are valid\""
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 18,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -204,36 +251,52 @@
     "    prompt = f\"\"\"\n",
     "    You are a helpful assistant designed to output JSON.\n",
     "    Given the following function schema\n",
-    "    {get_function_schema(function)}\n",
+    "    << {get_function_schema(function)} >>\n",
     "    and query\n",
-    "    {query}\n",
+    "    << {query} >>\n",
     "    extract the parameters values from the query, in a valid JSON format.\n",
     "    Example:\n",
     "    Input:\n",
     "    query: {example_query}\n",
     "    schema: {example_schema}\n",
     "\n",
-    "    Output:\n",
-    "    parameters: {example_parameters}\n",
+    "    Result: {example_parameters}\n",
     "\n",
     "    Input:\n",
     "    query: {query}\n",
     "    schema: {get_function_schema(function)}\n",
-    "    Output:\n",
-    "    parameters:\n",
+    "    Result:\n",
     "    \"\"\"\n",
     "\n",
-    "    ai_message = llm_mistral(prompt)\n",
-    "\n",
-    "    ai_message = ai_message.replace(\"CONFIG:\", \"\").replace(\"'\", '\"').strip().rstrip(\",\")\n",
+    "    try:\n",
+    "        ai_message = llm_mistral(prompt)\n",
+    "        ai_message = (\n",
+    "            ai_message.replace(\"Output:\", \"\").replace(\"'\", '\"').strip().rstrip(\",\")\n",
+    "        )\n",
+    "    except Exception as e:\n",
+    "        logger.error(f\"Mistral failed with error {e}, falling back to OpenAI\")\n",
+    "        ai_message = llm_openai(prompt)\n",
     "\n",
     "    try:\n",
     "        parameters = json.loads(ai_message)\n",
+    "        valid, message = validate_parameters(function, parameters)\n",
+    "\n",
+    "        if not valid:\n",
+    "            logger.warning(\n",
+    "                f\"Invalid parameters from Mistral, falling back to OpenAI: {message}\"\n",
+    "            )\n",
+    "            # Fall back to OpenAI\n",
+    "            ai_message = llm_openai(prompt)\n",
+    "            parameters = json.loads(ai_message)\n",
+    "            valid, message = validate_parameters(function, parameters)\n",
+    "            if not valid:\n",
+    "                raise ValueError(message)\n",
+    "\n",
     "        logger.info(f\"Extracted parameters: {parameters}\")\n",
     "        return parameters\n",
-    "    except json.JSONDecodeError as json_error:\n",
-    "        logger.error(f\"JSON parsing error {json_error}\")\n",
-    "        return {\"error\": \"Failed to extract parameters\"}"
+    "    except ValueError as e:\n",
+    "        logger.error(f\"Parameter validation error: {str(e)}\")\n",
+    "        return {\"error\": \"Failed to validate parameters\"}"
    ]
   },
   {
@@ -245,24 +308,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "from semantic_router.schema import Route\n",
-    "from semantic_router.encoders import CohereEncoder, OpenAIEncoder\n",
-    "from semantic_router.layer import RouteLayer\n",
-    "from semantic_router.utils.logger import logger\n",
-    "\n",
-    "\n",
-    "def create_router(routes: list[dict]) -> RouteLayer:\n",
-    "    logger.info(\"Creating route layer...\")\n",
-    "    encoder = OpenAIEncoder"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 19,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -274,7 +320,7 @@
     "\n",
     "def create_router(routes: list[dict]) -> RouteLayer:\n",
     "    logger.info(\"Creating route layer...\")\n",
-    "    encoder = OpenAIEncoder()\n",
+    "    encoder = CohereEncoder()\n",
     "\n",
     "    route_list: list[Route] = []\n",
     "    for route in routes:\n",
@@ -296,11 +342,12 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 24,
    "metadata": {},
    "outputs": [],
    "source": [
     "from typing import Callable\n",
+    "from semantic_router.layer import RouteLayer\n",
     "\n",
     "\n",
     "def call_function(function: Callable, parameters: dict[str, str]):\n",
@@ -310,8 +357,14 @@
     "        logger.error(f\"Error calling function: {e}\")\n",
     "\n",
     "\n",
-    "def call_llm(query: str):\n",
-    "    return llm_mistral(query)\n",
+    "def call_llm(query: str) -> str:\n",
+    "    try:\n",
+    "        ai_message = llm_mistral(query)\n",
+    "    except Exception as e:\n",
+    "        logger.error(f\"Mistral failed with error {e}, falling back to OpenAI\")\n",
+    "        ai_message = llm_openai(query)\n",
+    "\n",
+    "    return ai_message\n",
     "\n",
     "\n",
     "def call(query: str, functions: list[Callable], router: RouteLayer):\n",
@@ -336,9 +389,55 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 21,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[32m2023-12-18 12:17:58 INFO semantic_router.utils.logger Generating config...\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:17:58 INFO semantic_router.utils.logger Calling Mistral model\u001b[0m\n",
+      "\u001b[31m2023-12-18 12:18:00 ERROR semantic_router.utils.logger Fall back to OpenAI failed with error ('Failed to call HuggingFace API', '{\"error\":\"Bad Gateway\"}')\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:18:00 INFO semantic_router.utils.logger Calling gpt-4 model\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:18:05 INFO semantic_router.utils.logger AI message: {\n",
+      "    \"name\": \"get_time\",\n",
+      "    \"utterances\": [\n",
+      "        \"what is the time in new york\",\n",
+      "        \"can you tell me the time in london\",\n",
+      "        \"get me the current time in tokyo\",\n",
+      "        \"i need to know the time in sydney\",\n",
+      "        \"please tell me the current time in paris\"\n",
+      "    ]\n",
+      "}\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:18:05 INFO semantic_router.utils.logger Generated config: {'name': 'get_time', 'utterances': ['what is the time in new york', 'can you tell me the time in london', 'get me the current time in tokyo', 'i need to know the time in sydney', 'please tell me the current time in paris']}\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:18:05 INFO semantic_router.utils.logger Generating config...\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:18:05 INFO semantic_router.utils.logger Calling Mistral model\u001b[0m\n",
+      "\u001b[31m2023-12-18 12:18:07 ERROR semantic_router.utils.logger Fall back to OpenAI failed with error ('Failed to call HuggingFace API', '{\"error\":\"Bad Gateway\"}')\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:18:07 INFO semantic_router.utils.logger Calling gpt-4 model\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:18:12 INFO semantic_router.utils.logger AI message: {\n",
+      "    \"name\": \"get_news\",\n",
+      "    \"utterances\": [\n",
+      "        \"Can I get the latest news in Canada?\",\n",
+      "        \"Show me the recent news in the US\",\n",
+      "        \"I would like to know about the sports news in England\",\n",
+      "        \"Let's check the technology news in Japan\",\n",
+      "        \"Show me the health related news in Germany\"\n",
+      "    ]\n",
+      "}\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:18:12 INFO semantic_router.utils.logger Generated config: {'name': 'get_news', 'utterances': ['Can I get the latest news in Canada?', 'Show me the recent news in the US', 'I would like to know about the sports news in England', \"Let's check the technology news in Japan\", 'Show me the health related news in Germany']}\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:18:12 INFO semantic_router.utils.logger Creating route layer...\u001b[0m\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Route: {'name': 'get_time', 'utterances': ['what is the time in new york', 'can you tell me the time in london', 'get me the current time in tokyo', 'i need to know the time in sydney', 'please tell me the current time in paris']}\n",
+      "Route: {'name': 'get_news', 'utterances': ['Can I get the latest news in Canada?', 'Show me the recent news in the US', 'I would like to know about the sports news in England', \"Let's check the technology news in Japan\", 'Show me the health related news in Germany']}\n"
+     ]
+    }
+   ],
    "source": [
     "def get_time(location: str) -> str:\n",
     "    \"\"\"Useful to get the time in a specific location\"\"\"\n",
@@ -367,9 +466,55 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 27,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[32m2023-12-18 12:20:12 INFO semantic_router.utils.logger Generating config...\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:12 INFO semantic_router.utils.logger Calling Mistral model\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:16 INFO semantic_router.utils.logger AI message: \n",
+      "    Example output:\n",
+      "    {\n",
+      "        \"name\": \"get_time\",\n",
+      "        \"utterances\": [\n",
+      "            \"What's the time in New York?\",\n",
+      "            \"Tell me the time in Tokyo.\",\n",
+      "            \"Can you give me the time in London?\",\n",
+      "            \"What's the current time in Sydney?\",\n",
+      "            \"Can you tell me the time in Berlin?\"\n",
+      "        ]\n",
+      "    }\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:16 INFO semantic_router.utils.logger Generated config: {'name': 'get_time', 'utterances': [\"What's the time in New York?\", 'Tell me the time in Tokyo.', 'Can you give me the time in London?', \"What's the current time in Sydney?\", 'Can you tell me the time in Berlin?']}\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:16 INFO semantic_router.utils.logger Generating config...\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:16 INFO semantic_router.utils.logger Calling Mistral model\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:20 INFO semantic_router.utils.logger AI message: \n",
+      "    Example output:\n",
+      "    {\n",
+      "        \"name\": \"get_news\",\n",
+      "        \"utterances\": [\n",
+      "            \"Tell me the latest news from the US\",\n",
+      "            \"What's happening in India today?\",\n",
+      "            \"Get me the top stories from Japan\",\n",
+      "            \"Can you give me the breaking news from Brazil?\",\n",
+      "            \"What's the latest news from Germany?\"\n",
+      "        ]\n",
+      "    }\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:20 INFO semantic_router.utils.logger Generated config: {'name': 'get_news', 'utterances': ['Tell me the latest news from the US', \"What's happening in India today?\", 'Get me the top stories from Japan', 'Can you give me the breaking news from Brazil?', \"What's the latest news from Germany?\"]}\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:20 INFO semantic_router.utils.logger Creating route layer...\u001b[0m\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Route: {'name': 'get_time', 'utterances': [\"What's the time in New York?\", 'Tell me the time in Tokyo.', 'Can you give me the time in London?', \"What's the current time in Sydney?\", 'Can you tell me the time in Berlin?']}\n",
+      "Route: {'name': 'get_news', 'utterances': ['Tell me the latest news from the US', \"What's happening in India today?\", 'Get me the top stories from Japan', 'Can you give me the breaking news from Brazil?', \"What's the latest news from Germany?\"]}\n"
+     ]
+    }
+   ],
    "source": [
     "def get_time(location: str) -> str:\n",
     "    \"\"\"Useful to get the time in a specific location\"\"\"\n",
@@ -398,14 +543,84 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 26,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[32m2023-12-18 12:20:02 INFO semantic_router.utils.logger Extracting parameters...\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:02 INFO semantic_router.utils.logger Calling Mistral model\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:04 INFO semantic_router.utils.logger AI message: \n",
+      "    {\n",
+      "        \"location\": \"Stockholm\"\n",
+      "    }\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:04 INFO semantic_router.utils.logger Extracted parameters: {'location': 'Stockholm'}\u001b[0m\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "parameters: {'location': 'Stockholm'}\n",
+      "Calling `get_time` function with location: Stockholm\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[32m2023-12-18 12:20:04 INFO semantic_router.utils.logger Extracting parameters...\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:04 INFO semantic_router.utils.logger Calling Mistral model\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:05 INFO semantic_router.utils.logger AI message: \n",
+      "    {\n",
+      "        \"category\": \"tech\",\n",
+      "        \"country\": \"Lithuania\"\n",
+      "    }\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:05 INFO semantic_router.utils.logger Extracted parameters: {'category': 'tech', 'country': 'Lithuania'}\u001b[0m\n"
+     ]
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "parameters: {'category': 'tech', 'country': 'Lithuania'}\n",
+      "Calling `get_news` function with category: tech and country: Lithuania\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[33m2023-12-18 12:20:05 WARNING semantic_router.utils.logger No function found\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:05 INFO semantic_router.utils.logger Calling Mistral model\u001b[0m\n",
+      "\u001b[32m2023-12-18 12:20:06 INFO semantic_router.utils.logger AI message:  How can I help you today?\u001b[0m\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": [
+       "' How can I help you today?'"
+      ]
+     },
+     "execution_count": 26,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
    "source": [
     "call(query=\"What is the time in Stockholm?\", functions=tools, router=router)\n",
     "call(query=\"What is the tech news in the Lithuania?\", functions=tools, router=router)\n",
     "call(query=\"Hi!\", functions=tools, router=router)"
    ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
   }
  ],
  "metadata": {
diff --git a/pyproject.toml b/pyproject.toml
index e45e5f17..5672d403 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "semantic-router"
-version = "0.0.11"
+version = "0.0.12"
 description = "Super fast semantic router for AI decision making"
 authors = [
     "James Briggs <james@aurelio.ai>",
-- 
GitLab