Newer
Older
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "UxqB7_Ieur0s"
},
"source": [
"[](https://colab.research.google.com/github/aurelio-labs/semantic-router/blob/main/docs/02-dynamic-routes.ipynb) [](https://nbviewer.org/github/aurelio-labs/semantic-router/blob/main/docs/02-dynamic-routes.ipynb)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "EduhQaNAur0u"
},
"source": [
"# Dynamic Routes"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "_4JgNeX4ur0v"
},
"source": [
"In semantic-router there are two types of routes that can be chosen. Both routes belong to the `Route` object, the only difference between them is that _static_ routes return a `Route.name` when chosen, whereas _dynamic_ routes use an LLM call to produce parameter input values.\n",
"\n",
"For example, a _static_ route will tell us if a query is talking about mathematics by returning the route name (which could be `\"math\"` for example). A _dynamic_ route does the same thing, but it also extracts key information from the input utterance to be used in a function associated with that route.\n",
"\n",
"For example we could provide a dynamic route with associated utterances:\n",
"\n",
"```\n",
"\"what is x to the power of y?\"\n",
"\"what is 9 to the power of 4?\"\n",
"\"calculate the result of base x and exponent y\"\n",
"\"calculate the result of base 10 and exponent 3\"\n",
"\"return x to the power of y\"\n",
"```\n",
"\n",
"and we could also provide the route with a schema outlining key features of the function:\n",
"\n",
"```\n",
"def power(base: float, exponent: float) -> float:\n",
" \"\"\"Raise base to the power of exponent.\n",
"\n",
" Args:\n",
" base (float): The base number.\n",
" exponent (float): The exponent to which the base is raised.\n",
"\n",
" Returns:\n",
" float: The result of base raised to the power of exponent.\n",
" \"\"\"\n",
" return base ** exponent\n",
"```\n",
"\n",
"Then, if the users input utterance is \"What is 2 to the power of 3?\", the route will be triggered, as the input utterance is semantically similar to the route utterances. Furthermore, the route utilizes an LLM to identify that `base=2` and `exponent=3`. These values are returned in such a way that they can be used in the above `power` function. That is, the dynamic router automates the process of calling relevant functions from natural language inputs.\n",
"\n",
"***⚠️ Note: We have a fully local version of dynamic routes available at [docs/05-local-execution.ipynb](https://github.com/aurelio-labs/semantic-router/blob/main/docs/05-local-execution.ipynb). The local 05 version tends to outperform the OpenAI version we demo in this notebook, so we'd recommend trying [05](https://github.com/aurelio-labs/semantic-router/blob/main/docs/05-local-execution.ipynb)!***"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "bbmw8CO4ur0v"
},
"source": [
"## Installing the Library"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "dLElfRhgur0v",
"outputId": "da0e506e-24cf-43da-9243-894a7c4955db"
},
"outputs": [
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: tzdata in c:\\users\\siraj\\documents\\personal\\work\\aurelio\\virtual environments\\semantic_router_3\\lib\\site-packages (2024.1)\n"
]
"name": "stderr",
"output_type": "stream",
"text": [
"\n",
"[notice] A new release of pip is available: 23.1.2 -> 24.0\n",
"[notice] To update, run: python.exe -m pip install --upgrade pip\n"
]
}
],
"source": [
"!pip install tzdata\n",
"!pip install -qU \"semantic-router==0.1.0.dev3\""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "BixZd6Eour0w"
},
"source": [
"## Initializing Routes and RouteLayer"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "PxnW9qBvur0x"
},
"source": [
"Dynamic routes are treated in the same way as static routes, let's begin by initializing a `RouteLayer` consisting of static routes."
]
},
{
"cell_type": "code",
"metadata": {
"id": "kc9Ty6Lgur0x",
"outputId": "f32e3a25-c073-4802-ced3-d7a5663670c1"
},
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
"source": [
"from semantic_router import Route\n",
"\n",
"politics = Route(\n",
" name=\"politics\",\n",
" utterances=[\n",
" \"isn't politics the best thing ever\",\n",
" \"why don't you tell me about your political opinions\",\n",
" \"don't you just love the president\" \"don't you just hate the president\",\n",
" \"they're going to destroy this country!\",\n",
" \"they will save the country!\",\n",
" ],\n",
")\n",
"chitchat = Route(\n",
" name=\"chitchat\",\n",
" utterances=[\n",
" \"how's the weather today?\",\n",
" \"how are things going?\",\n",
" \"lovely weather today\",\n",
" \"the weather is horrendous\",\n",
" \"let's go to the chippy\",\n",
" ],\n",
")\n",
"\n",
"routes = [politics, chitchat]"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "voWyqmffur0x"
},
"source": [
"We initialize our `RouteLayer` with our `encoder` and `routes`. We can use popular encoder APIs like `CohereEncoder` and `OpenAIEncoder`, or local alternatives like `FastEmbedEncoder`."
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
"id": "BI9AiDspur0y",
"outputId": "27329a54-3f16-44a5-ac20-13a6b26afb97"
},
"outputs": [
"2025-01-06 12:09:04 - semantic_router.utils.logger - WARNING - base.py:356 - _get_index() - No index provided. Using default LocalIndex.\n",
"2025-01-06 12:09:04 - httpx - INFO - _client.py:1025 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n",
"2025-01-06 12:09:05 - httpx - INFO - _client.py:1025 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n",
"2025-01-06 12:09:05 - semantic_router.utils.logger - WARNING - local.py:148 - _write_config() - No config is written for LocalIndex.\n"
]
}
],
"source": [
"import os\n",
"from getpass import getpass\n",
"from semantic_router.encoders import CohereEncoder, OpenAIEncoder\n",
"from semantic_router.routers import SemanticRouter\n",
"\n",
"# dashboard.cohere.ai\n",
"# os.environ[\"COHERE_API_KEY\"] = os.getenv(\"COHERE_API_KEY\") or getpass(\n",
"# \"Enter Cohere API Key: \"\n",
"# )\n",
"# platform.openai.com\n",
"os.environ[\"OPENAI_API_KEY\"] = os.getenv(\"OPENAI_API_KEY\") or getpass(\n",
" \"Enter OpenAI API Key: \"\n",
")\n",
"\n",
"# encoder = CohereEncoder()\n",
"encoder = OpenAIEncoder()\n",
"\n",
"rl = SemanticRouter(encoder=encoder, routes=routes, auto_sync=\"local\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "GuLCeIS5ur0y"
},
"source": [
"We run the solely static routes layer:"
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
"id": "_rNREh7gur0y",
"outputId": "f3a1dc0b-d760-4efb-b634-d3547011dcb7"
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"2025-01-06 12:09:08 - httpx - INFO - _client.py:1025 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n"
]
},
"data": {
"text/plain": [
"RouteChoice(name='chitchat', function_call=None, similarity_score=None)"
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rl(\"how's the weather today?\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "McbLKO26ur0y"
},
"source": [
"## Creating a Dynamic Route"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ANAoEjxYur0y"
},
"source": [
"As with static routes, we must create a dynamic route before adding it to our route layer. To make a route dynamic, we need to provide the `function_schemas` as a list. Each function schema provides instructions on what a function is, so that an LLM can decide how to use it correctly."
]
},
{
"cell_type": "code",
"metadata": {
"id": "5jaF1Xa5ur0y"
},
"outputs": [],
"source": [
"from datetime import datetime\n",
"from zoneinfo import ZoneInfo\n",
"\n",
"\n",
"def get_time(timezone: str) -> str:\n",
" \"\"\"Finds the current time in a specific timezone.\n",
"\n",
" :param timezone: The timezone to find the current time in, should\n",
" be a valid timezone from the IANA Time Zone Database like\n",
" \"America/New_York\" or \"Europe/London\". Do NOT put the place\n",
" name itself like \"rome\", or \"new york\", you must provide\n",
" the IANA format.\n",
" :type timezone: str\n",
" :return: The current time in the specified timezone.\"\"\"\n",
" now = datetime.now(ZoneInfo(timezone))\n",
" return now.strftime(\"%H:%M\")"
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 35
"id": "YyFKV8jMur0z",
"outputId": "29cf80f4-552c-47bb-fbf9-019f5dfdf00a"
},
"outputs": [
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"get_time(\"America/New_York\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "4qyaRuNXur0z"
},
"source": [
"To get the function schema we can use the `get_schema` function from the `function_call` module."
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
"id": "tOjuhp5Xur0z",
"outputId": "ca88a3ea-d70a-4950-be9a-63fab699de3b"
},
"outputs": [
"data": {
"text/plain": [
"[{'type': 'function',\n",
" 'function': {'name': 'get_time',\n",
" 'description': 'Finds the current time in a specific timezone.\\n\\n:param timezone: The timezone to find the current time in, should\\n be a valid timezone from the IANA Time Zone Database like\\n \"America/New_York\" or \"Europe/London\". Do NOT put the place\\n name itself like \"rome\", or \"new york\", you must provide\\n the IANA format.\\n:type timezone: str\\n:return: The current time in the specified timezone.',\n",
" 'parameters': {'type': 'object',\n",
" 'properties': {'timezone': {'type': 'string',\n",
" 'description': 'The timezone to find the current time in, should\\n be a valid timezone from the IANA Time Zone Database like\\n \"America/New_York\" or \"Europe/London\". Do NOT put the place\\n name itself like \"rome\", or \"new york\", you must provide\\n the IANA format.'}},\n",
" 'required': ['timezone']}}}]"
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from semantic_router.llms.openai import get_schemas_openai\n",
"\n",
"schemas = get_schemas_openai([get_time])\n",
"schemas"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "HcF7jGjAur0z"
},
"source": [
"We use this to define our dynamic route:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "iesBG9P3ur0z"
},
"outputs": [],
"source": [
"time_route = Route(\n",
" name=\"get_time\",\n",
" utterances=[\n",
" \"what is the time in new york city?\",\n",
" \"what is the time in london?\",\n",
" \"I live in Rome, what time is it?\",\n",
" ],\n",
" function_schemas=schemas,\n",
")"
]
},
{
"cell_type": "code",
"metadata": {
"id": "jmVwEWEIg9hq"
},
"outputs": [],
"source": [
"time_route.llm"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ZiUs3ovpur0z"
},
"source": [
"Add the new route to our `layer`:"
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
"id": "-0vY8PRXur0z",
"outputId": "db01e14c-eab3-4f93-f4c2-e30f508c8b5d"
},
"outputs": [
"2025-01-06 12:09:28 - semantic_router.utils.logger - WARNING - base.py:172 - _read_config() - This method should be implemented by subclasses.\n",
"2025-01-06 12:09:28 - httpx - INFO - _client.py:1025 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n",
"2025-01-06 12:09:29 - semantic_router.utils.logger - WARNING - local.py:148 - _write_config() - No config is written for LocalIndex.\n"
]
}
],
"source": [
"rl.add(time_route)"
]
},
{
"cell_type": "code",
"metadata": {
"id": "mbccVdy5g9hr"
},
"outputs": [],
"source": [
"time_route.llm"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "7yoE0IrNur0z"
},
"source": [
"Now we can ask our layer a time related question to trigger our new dynamic route."
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 53
"id": "Wfb68M0-ur0z",
"outputId": "79923883-2a4d-4744-f8ce-e818cb5f14c3"
},
"outputs": [
"2025-01-06 12:09:32 - httpx - INFO - _client.py:1025 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n",
"2025-01-06 12:09:32 - semantic_router.utils.logger - WARNING - base.py:441 - __call__() - No LLM provided for dynamic route, will use OpenAI LLM default. Ensure API key is set in OPENAI_API_KEY environment variable.\n",
"2025-01-06 12:09:34 - httpx - INFO - _client.py:1025 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/chat/completions \"HTTP/1.1 200 OK\"\n"
"data": {
"text/plain": [
"RouteChoice(name='get_time', function_call=[{'function_name': 'get_time', 'arguments': {'timezone': 'America/New_York'}}], similarity_score=None)"
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"response = rl(\"what is the time in new york city?\")\n",
"response"
]
},
{
"cell_type": "code",
"metadata": {
"id": "92x96x1Og9hr",
"outputId": "c1e46a81-b681-4a10-fff6-71e03342a88e"
},
"outputs": [
"name": "stdout",
"output_type": "stream",
"text": [
"[{'function_name': 'get_time', 'arguments': {'timezone': 'America/New_York'}}]\n"
]
}
],
"source": [
"print(response.function_call)"
]
},
{
"cell_type": "code",
"metadata": {
"id": "xvdyUPKqg9hr",
"outputId": "4161e7e0-ab6d-4e76-f068-2d66728305ff"
},
"outputs": [
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
]
}
],
"source": [
"import json\n",
"\n",
"for call in response.function_call:\n",
" if call[\"function_name\"] == \"get_time\":\n",
" args = call[\"arguments\"]\n",
" result = get_time(**args)\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Qt0vkq2Xur00"
},
"source": [
"Our dynamic route provides both the route itself _and_ the input parameters required to use the route."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "jToYBo8Ug9hr"
},
"source": [
"## Dynamic Routes with Multiple Functions"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "J0oD1dxIur00"
},
"source": [
"---"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "vEkTpoVAg9hr"
},
"source": [
"Routes can be assigned multiple functions. Then, when that particular Route is selected by the Route Layer, a number of those functions might be invoked due to the users utterance containing relevant information that fits their arguments."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "BHUlB3org9hs"
},
"source": [
"Let's define a Route that has multiple functions."
]
},
{
"cell_type": "code",
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
"metadata": {
"id": "dtrksov0g9hs"
},
"outputs": [],
"source": [
"from datetime import datetime, timedelta\n",
"from zoneinfo import ZoneInfo\n",
"\n",
"\n",
"# Function with one argument\n",
"def get_time(timezone: str) -> str:\n",
" \"\"\"Finds the current time in a specific timezone.\n",
"\n",
" :param timezone: The timezone to find the current time in, should\n",
" be a valid timezone from the IANA Time Zone Database like\n",
" \"America/New_York\" or \"Europe/London\". Do NOT put the place\n",
" name itself like \"rome\", or \"new york\", you must provide\n",
" the IANA format.\n",
" :type timezone: str\n",
" :return: The current time in the specified timezone.\"\"\"\n",
" now = datetime.now(ZoneInfo(timezone))\n",
" return now.strftime(\"%H:%M\")\n",
"\n",
"\n",
"def get_time_difference(timezone1: str, timezone2: str) -> str:\n",
" \"\"\"Calculates the time difference between two timezones.\n",
" :param timezone1: The first timezone, should be a valid timezone from the IANA Time Zone Database like \"America/New_York\" or \"Europe/London\".\n",
" :param timezone2: The second timezone, should be a valid timezone from the IANA Time Zone Database like \"America/New_York\" or \"Europe/London\".\n",
" :type timezone1: str\n",
" :type timezone2: str\n",
" :return: The time difference in hours between the two timezones.\"\"\"\n",
" # Get the current time in UTC\n",
" now_utc = datetime.utcnow().replace(tzinfo=ZoneInfo(\"UTC\"))\n",
"\n",
" # Convert the UTC time to the specified timezones\n",
" tz1_time = now_utc.astimezone(ZoneInfo(timezone1))\n",
" tz2_time = now_utc.astimezone(ZoneInfo(timezone2))\n",
"\n",
" # Calculate the difference in offsets from UTC\n",
" tz1_offset = tz1_time.utcoffset().total_seconds()\n",
" tz2_offset = tz2_time.utcoffset().total_seconds()\n",
"\n",
" # Calculate the difference in hours\n",
" hours_difference = (tz2_offset - tz1_offset) / 3600\n",
"\n",
" return f\"The time difference between {timezone1} and {timezone2} is {hours_difference} hours.\"\n",
"\n",
"\n",
"# Function with three arguments\n",
"def convert_time(time: str, from_timezone: str, to_timezone: str) -> str:\n",
" \"\"\"Converts a specific time from one timezone to another.\n",
" :param time: The time to convert in HH:MM format.\n",
" :param from_timezone: The original timezone of the time, should be a valid IANA timezone.\n",
" :param to_timezone: The target timezone for the time, should be a valid IANA timezone.\n",
" :type time: str\n",
" :type from_timezone: str\n",
" :type to_timezone: str\n",
" :return: The converted time in the target timezone.\n",
" :raises ValueError: If the time format or timezone strings are invalid.\n",
"\n",
" Example:\n",
" convert_time(\"12:30\", \"America/New_York\", \"Asia/Tokyo\") -> \"03:30\"\n",
" \"\"\"\n",
" try:\n",
" # Use today's date to avoid historical timezone issues\n",
" today = datetime.now().date()\n",
" datetime_string = f\"{today} {time}\"\n",
" time_obj = datetime.strptime(datetime_string, \"%Y-%m-%d %H:%M\").replace(\n",
" tzinfo=ZoneInfo(from_timezone)\n",
" )\n",
"\n",
" converted_time = time_obj.astimezone(ZoneInfo(to_timezone))\n",
"\n",
" formatted_time = converted_time.strftime(\"%H:%M\")\n",
" return formatted_time\n",
" except Exception as e:\n",
" raise ValueError(f\"Error converting time: {e}\")"
]
},
{
"cell_type": "code",
"metadata": {
"id": "AjoYy7mFg9hs"
},
"outputs": [],
"source": [
"functions = [get_time, get_time_difference, convert_time]"
]
},
{
"cell_type": "code",
"metadata": {
"id": "DoOkXV2Tg9hs",
"outputId": "f1e0fe08-b6ed-4f50-d845-5c54832ca677"
},
"outputs": [
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
"data": {
"text/plain": [
"[{'type': 'function',\n",
" 'function': {'name': 'get_time',\n",
" 'description': 'Finds the current time in a specific timezone.\\n\\n:param timezone: The timezone to find the current time in, should\\n be a valid timezone from the IANA Time Zone Database like\\n \"America/New_York\" or \"Europe/London\". Do NOT put the place\\n name itself like \"rome\", or \"new york\", you must provide\\n the IANA format.\\n:type timezone: str\\n:return: The current time in the specified timezone.',\n",
" 'parameters': {'type': 'object',\n",
" 'properties': {'timezone': {'type': 'string',\n",
" 'description': 'The timezone to find the current time in, should\\n be a valid timezone from the IANA Time Zone Database like\\n \"America/New_York\" or \"Europe/London\". Do NOT put the place\\n name itself like \"rome\", or \"new york\", you must provide\\n the IANA format.'}},\n",
" 'required': ['timezone']}}},\n",
" {'type': 'function',\n",
" 'function': {'name': 'get_time_difference',\n",
" 'description': 'Calculates the time difference between two timezones.\\n:param timezone1: The first timezone, should be a valid timezone from the IANA Time Zone Database like \"America/New_York\" or \"Europe/London\".\\n:param timezone2: The second timezone, should be a valid timezone from the IANA Time Zone Database like \"America/New_York\" or \"Europe/London\".\\n:type timezone1: str\\n:type timezone2: str\\n:return: The time difference in hours between the two timezones.',\n",
" 'parameters': {'type': 'object',\n",
" 'properties': {'timezone1': {'type': 'string',\n",
" 'description': 'The first timezone, should be a valid timezone from the IANA Time Zone Database like \"America/New_York\" or \"Europe/London\".'},\n",
" 'timezone2': {'type': 'string',\n",
" 'description': 'The second timezone, should be a valid timezone from the IANA Time Zone Database like \"America/New_York\" or \"Europe/London\".'}},\n",
" 'required': ['timezone1', 'timezone2']}}},\n",
" {'type': 'function',\n",
" 'function': {'name': 'convert_time',\n",
" 'description': 'Converts a specific time from one timezone to another.\\n:param time: The time to convert in HH:MM format.\\n:param from_timezone: The original timezone of the time, should be a valid IANA timezone.\\n:param to_timezone: The target timezone for the time, should be a valid IANA timezone.\\n:type time: str\\n:type from_timezone: str\\n:type to_timezone: str\\n:return: The converted time in the target timezone.\\n:raises ValueError: If the time format or timezone strings are invalid.\\n\\nExample:\\n convert_time(\"12:30\", \"America/New_York\", \"Asia/Tokyo\") -> \"03:30\"',\n",
" 'parameters': {'type': 'object',\n",
" 'properties': {'time': {'type': 'string',\n",
" 'description': 'The time to convert in HH:MM format.'},\n",
" 'from_timezone': {'type': 'string',\n",
" 'description': 'The original timezone of the time, should be a valid IANA timezone.'},\n",
" 'to_timezone': {'type': 'string',\n",
" 'description': 'The target timezone for the time, should be a valid IANA timezone.'}},\n",
" 'required': ['time', 'from_timezone', 'to_timezone']}}}]"
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Generate schemas for all functions\n",
"from semantic_router.llms.openai import get_schemas_openai\n",
"\n",
"schemas = get_schemas_openai(functions)\n",
"schemas"
]
},
{
"cell_type": "code",
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
"metadata": {
"id": "YBRHxhnkg9hs"
},
"outputs": [],
"source": [
"# Define the dynamic route with multiple functions\n",
"multi_function_route = Route(\n",
" name=\"timezone_management\",\n",
" utterances=[\n",
" # Utterances for get_time function\n",
" \"what is the time in New York?\",\n",
" \"current time in Berlin?\",\n",
" \"tell me the time in Moscow right now\",\n",
" \"can you show me the current time in Tokyo?\",\n",
" \"please provide the current time in London\",\n",
" # Utterances for get_time_difference function\n",
" \"how many hours ahead is Tokyo from London?\",\n",
" \"time difference between Sydney and Cairo\",\n",
" \"what's the time gap between Los Angeles and New York?\",\n",
" \"how much time difference is there between Paris and Sydney?\",\n",
" \"calculate the time difference between Dubai and Toronto\",\n",
" # Utterances for convert_time function\n",
" \"convert 15:00 from New York time to Berlin time\",\n",
" \"change 09:00 from Paris time to Moscow time\",\n",
" \"adjust 20:00 from Rome time to London time\",\n",
" \"convert 12:00 from Madrid time to Chicago time\",\n",
" \"change 18:00 from Beijing time to Los Angeles time\"\n",
" # All three functions\n",
" \"What is the time in Seattle? What is the time difference between Mumbai and Tokyo? What is 5:53 Toronto time in Sydney time?\",\n",
" ],\n",
" function_schemas=schemas,\n",
")"
]
},
{
"cell_type": "code",
"metadata": {
"id": "yEbQadQbg9ht"
},
"outputs": [],
"source": [
"routes = [politics, chitchat, multi_function_route]"
]
},
{
"cell_type": "code",
"metadata": {
"id": "C0aYIXaog9ht",
"outputId": "74114a86-4a6f-49c5-8e2e-600f577d63f5"
},
"outputs": [
"2025-01-06 12:10:35 - semantic_router.utils.logger - WARNING - base.py:356 - _get_index() - No index provided. Using default LocalIndex.\n",
"2025-01-06 12:10:36 - httpx - INFO - _client.py:1025 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n",
"2025-01-06 12:10:36 - httpx - INFO - _client.py:1025 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n",
"2025-01-06 12:10:37 - semantic_router.utils.logger - WARNING - local.py:148 - _write_config() - No config is written for LocalIndex.\n"
"rl2 = SemanticRouter(encoder=encoder, routes=routes, auto_sync=\"local\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cG98YLZ5g9ht"
},
"source": [
"### Function to Parse Route Layer Responses"
]
},
{
"cell_type": "code",
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
"metadata": {
"id": "PJR97klVg9ht"
},
"outputs": [],
"source": [
"def parse_response(response: str):\n",
" for call in response.function_call:\n",
" args = call[\"arguments\"]\n",
" if call[\"function_name\"] == \"get_time\":\n",
" result = get_time(**args)\n",
" print(result)\n",
" if call[\"function_name\"] == \"get_time_difference\":\n",
" result = get_time_difference(**args)\n",
" print(result)\n",
" if call[\"function_name\"] == \"convert_time\":\n",
" result = convert_time(**args)\n",
" print(result)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "OUbPbxZKg9ht"
},
"source": [
"### Checking that Politics Non-Dynamic Route Still Works"
]
},
{
"cell_type": "code",
"metadata": {
"id": "D2kXFv9Xg9ht",
"outputId": "569cf17f-2091-4aea-9cba-11bb0af2ebd4"
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"2025-01-06 12:10:40 - httpx - INFO - _client.py:1025 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n"
]
},
"data": {
"text/plain": [
"RouteChoice(name='politics', function_call=None, similarity_score=None)"
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"response = rl2(\"What is your political leaning?\")\n",
"response"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ZHgw8QoWg9ht"
},
"source": [
"### Checking that Chitchat Non-Dynamic Route Still Works"
]
},
{
"cell_type": "code",
"metadata": {
"id": "YsI5O_bHg9ht",
"outputId": "a6e3814b-97e0-4406-ec9a-17b1c7103e40"
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"2025-01-06 12:10:45 - httpx - INFO - _client.py:1025 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n"
]
},
"data": {
"text/plain": [
"RouteChoice(name='chitchat', function_call=None, similarity_score=None)"
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"response = rl2(\"Hello bot, how are you today?\")\n",
"response"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "uZDiY787g9hu"
},
"source": [
"### Testing the `multi_function_route` - The `get_time` Function"
]
},
{
"cell_type": "code",
"metadata": {
"id": "BdOfLx-wg9hu",
"outputId": "ef55a34c-7c34-4acc-918d-a173fac95171"
},
"outputs": [
"2025-01-06 12:10:47 - httpx - INFO - _client.py:1025 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n",
"2025-01-06 12:10:47 - semantic_router.utils.logger - WARNING - base.py:441 - __call__() - No LLM provided for dynamic route, will use OpenAI LLM default. Ensure API key is set in OPENAI_API_KEY environment variable.\n",
"2025-01-06 12:10:48 - httpx - INFO - _client.py:1025 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/chat/completions \"HTTP/1.1 200 OK\"\n"
"data": {
"text/plain": [
"RouteChoice(name='timezone_management', function_call=[{'function_name': 'get_time', 'arguments': {'timezone': 'America/New_York'}}], similarity_score=None)"
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"response = rl2(\"what is the time in New York?\")\n",
"response"
]
},
{
"cell_type": "code",
"metadata": {
"id": "QrpF_JcHg9hu",
"outputId": "242d645f-43c3-4e9f-9a46-d3aa3105f02a"
},
"outputs": [
]
}
],
"source": [
"parse_response(response)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "wcjQ4Dbpg9hu"
},
"source": [
"### Testing the `multi_function_route` - The `get_time_difference` Function"
]
},
{
"cell_type": "code",
"metadata": {
"id": "W85287lAg9hu",
"outputId": "4f247f13-046b-4a5c-f119-de17df29131f"
},
"outputs": [
"2025-01-06 12:10:52 - httpx - INFO - _client.py:1025 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings \"HTTP/1.1 200 OK\"\n",
"2025-01-06 12:10:52 - httpx - INFO - _client.py:1025 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/chat/completions \"HTTP/1.1 200 OK\"\n"