Skip to content
Snippets Groups Projects
Commit b7a3dd69 authored by Simonas's avatar Simonas
Browse files

RouteConfig tests

parent 393bf4b9
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Set up functions and routes ### Set up functions and routes
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def get_time(location: str) -> str: def get_time(location: str) -> str:
"""Useful to get the time in a specific location""" """Useful to get the time in a specific location"""
print(f"Result from: `get_time` function with location: `{location}`") print(f"Result from: `get_time` function with location: `{location}`")
return "get_time" return "get_time"
def get_news(category: str, country: str) -> str: def get_news(category: str, country: str) -> str:
"""Useful to get the news in a specific country""" """Useful to get the news in a specific country"""
print( print(
f"Result from: `get_news` function with category: `{category}` " f"Result from: `get_news` function with category: `{category}` "
f"and country: `{country}`" f"and country: `{country}`"
) )
return "get_news" return "get_news"
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Now generate a dynamic routing config for each function Now generate a dynamic routing config for each function
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
from semantic_router.route import Route, RouteConfig from semantic_router.route import Route, RouteConfig
functions = [get_time, get_news] functions = [get_time, get_news]
routes = [] routes = []
for function in functions: for function in functions:
route = await Route.from_dynamic_route(entity=function) route = await Route.from_dynamic_route(entity=function)
routes.append(route) routes.append(route)
route_config = RouteConfig(routes=routes) route_config = RouteConfig(routes=routes)
``` ```
%% Output %% Output
2023-12-19 17:46:30 INFO semantic_router.utils.logger Generating dynamic route... 2023-12-20 12:21:30 INFO semantic_router.utils.logger Generating dynamic route...
2023-12-19 17:46:40 INFO semantic_router.utils.logger Generated route config: 2023-12-20 12:21:33 INFO semantic_router.utils.logger Generated route config:
{ {
"name": "get_time", "name": "get_time",
"utterances": [ "utterances": [
"What's the time in New York?", "What's the time in New York?",
"Can you tell me the time in Tokyo?", "Can you tell me the time in Tokyo?",
"What's the current time in London?", "What's the current time in London?",
"Can you give me the time in Sydney?", "Can you give me the time in Sydney?",
"What's the time in Paris?" "What's the time in Paris?"
] ]
} }
2023-12-19 17:46:40 INFO semantic_router.utils.logger Generating dynamic route... 2023-12-20 12:21:33 INFO semantic_router.utils.logger Generating dynamic route...
2023-12-19 17:46:43 INFO semantic_router.utils.logger Generated route config: 2023-12-20 12:21:38 INFO semantic_router.utils.logger Generated route config:
{ {
"name": "get_news", "name": "get_news",
"utterances": [ "utterances": [
"Tell me the latest news from the United States", "Tell me the latest news from the United States",
"What's happening in India today?", "What's happening in India today?",
"Can you give me the top stories from Japan", "Can you give me the top stories from Japan",
"Get me the breaking news from the UK", "Get me the breaking news from the UK",
"What's the latest in Germany?" "What's the latest in Germany?"
] ]
} }
/var/folders/gf/cvm58m_x6pvghy227n5cmx5w0000gn/T/ipykernel_65737/1850296463.py:10: RuntimeWarning: coroutine 'Route.from_dynamic_route' was never awaited
route_config = RouteConfig(routes=routes)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# You can manually add or remove routes # You can manually add or remove routes
get_weather_route = Route( get_weather_route = Route(
name="get_weather", name="get_weather",
utterances=[ utterances=[
"what is the weather in SF", "what is the weather in SF",
"what is the current temperature in London?", "what is the current temperature in London?",
"tomorrow's weather in Paris?", "tomorrow's weather in Paris?",
], ],
) )
route_config.add(get_weather_route) route_config.add(get_weather_route)
route_config.remove("get_weather") route_config.remove("get_weather")
route_config.to_dict() route_config.to_dict()
``` ```
%% Output %% Output
2023-12-19 17:46:43 INFO semantic_router.utils.logger Added route `get_weather` 2023-12-19 17:46:43 INFO semantic_router.utils.logger Added route `get_weather`
2023-12-19 17:46:43 INFO semantic_router.utils.logger Removed route `get_weather` 2023-12-19 17:46:43 INFO semantic_router.utils.logger Removed route `get_weather`
[{'name': 'get_time', [{'name': 'get_time',
'utterances': ["What's the time in New York?", 'utterances': ["What's the time in New York?",
'Can you tell me the time in Tokyo?', 'Can you tell me the time in Tokyo?',
"What's the current time in London?", "What's the current time in London?",
'Can you give me the time in Sydney?', 'Can you give me the time in Sydney?',
"What's the time in Paris?"], "What's the time in Paris?"],
'description': None}, 'description': None},
{'name': 'get_news', {'name': 'get_news',
'utterances': ['Tell me the latest news from the United States', 'utterances': ['Tell me the latest news from the United States',
"What's happening in India today?", "What's happening in India today?",
'Can you give me the top stories from Japan', 'Can you give me the top stories from Japan',
'Get me the breaking news from the UK', 'Get me the breaking news from the UK',
"What's the latest in Germany?"], "What's the latest in Germany?"],
'description': None}] 'description': None}]
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# Get a route by name # Get a route by name
route_config.get("get_time") route_config.get("get_time")
``` ```
%% Output %% Output
Route(name='get_time', utterances=["What's the time in New York?", 'Can you tell me the time in Tokyo?', "What's the current time in London?", 'Can you give me the time in Sydney?', "What's the time in Paris?"], description=None) Route(name='get_time', utterances=["What's the time in New York?", 'Can you tell me the time in Tokyo?', "What's the current time in London?", 'Can you give me the time in Sydney?', "What's the time in Paris?"], description=None)
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Save config to a file (.json or .yaml) Save config to a file (.json or .yaml)
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
route_config.to_file("route_config.json") route_config.to_file("route_config.json")
``` ```
%% Output %% Output
2023-12-19 17:46:43 INFO semantic_router.utils.logger Saving route config to route_config.json 2023-12-19 17:46:43 INFO semantic_router.utils.logger Saving route config to route_config.json
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Define routing layer ### Define routing layer
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Load from local file Load from local file
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
from semantic_router.route import RouteConfig from semantic_router.route import RouteConfig
route_config = RouteConfig.from_file("route_config.json") route_config = RouteConfig.from_file("route_config.json")
``` ```
%% Output %% Output
2023-12-19 17:46:43 INFO semantic_router.utils.logger Loading route config from route_config.json 2023-12-19 17:46:43 INFO semantic_router.utils.logger Loading route config from route_config.json
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
from semantic_router import RouteLayer from semantic_router import RouteLayer
route_layer = RouteLayer(routes=route_config.routes) route_layer = RouteLayer(routes=route_config.routes)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Do a function call with functions as tool Do a function call with functions as tool
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
from semantic_router.utils.function_call import route_and_execute from semantic_router.utils.function_call import route_and_execute
tools = [get_time, get_news] tools = [get_time, get_news]
await route_and_execute( await route_and_execute(
query="What is the time in Stockholm?", functions=tools, route_layer=route_layer query="What is the time in Stockholm?", functions=tools, route_layer=route_layer
) )
await route_and_execute( await route_and_execute(
query="What is the tech news in the Lithuania?", query="What is the tech news in the Lithuania?",
functions=tools, functions=tools,
route_layer=route_layer, route_layer=route_layer,
) )
await route_and_execute(query="Hi!", functions=tools, route_layer=route_layer) await route_and_execute(query="Hi!", functions=tools, route_layer=route_layer)
``` ```
%% Output %% Output
2023-12-19 17:46:43 INFO semantic_router.utils.logger Extracting function input... 2023-12-19 17:46:43 INFO semantic_router.utils.logger Extracting function input...
Calling function: get_time Calling function: get_time
Result from: `get_time` function with location: `Stockholm` Result from: `get_time` function with location: `Stockholm`
2023-12-19 17:46:49 INFO semantic_router.utils.logger Extracting function input... 2023-12-19 17:46:49 INFO semantic_router.utils.logger Extracting function input...
Calling function: get_news Calling function: get_news
Result from: `get_news` function with category: `tech` and country: `Lithuania` Result from: `get_news` function with category: `tech` and country: `Lithuania`
2023-12-19 17:46:52 WARNING semantic_router.utils.logger No function found, calling LLM... 2023-12-19 17:46:52 WARNING semantic_router.utils.logger No function found, calling LLM...
'Hello! How can I assist you today?' 'Hello! How can I assist you today?'
......
...@@ -19,9 +19,8 @@ class RouteLayer: ...@@ -19,9 +19,8 @@ class RouteLayer:
categories = None categories = None
score_threshold = 0.82 score_threshold = 0.82
def __init__( def __init__(self, encoder: BaseEncoder | None = None, routes: list[Route] = []):
self, encoder: BaseEncoder = CohereEncoder(), routes: list[Route] = [] self.encoder = encoder if encoder is not None else CohereEncoder()
):
self.routes: list[Route] = routes self.routes: list[Route] = routes
self.encoder = encoder self.encoder = encoder
# decide on default threshold based on encoder # decide on default threshold based on encoder
......
...@@ -170,11 +170,12 @@ class RouteConfig: ...@@ -170,11 +170,12 @@ class RouteConfig:
self.routes.append(route) self.routes.append(route)
logger.info(f"Added route `{route.name}`") logger.info(f"Added route `{route.name}`")
def get(self, name: str): def get(self, name: str) -> Route | None:
for route in self.routes: for route in self.routes:
if route.name == name: if route.name == name:
return route return route
raise Exception(f"Route `{name}` not found") logger.error(f"Route `{name}` not found")
return None
def remove(self, name: str): def remove(self, name: str):
if name not in [route.name for route in self.routes]: if name not in [route.name for route in self.routes]:
......
[{"name": "test", "utterances": ["utterance"], "description": null}]
- description: null
name: test
utterances:
- utterance
import os
from unittest.mock import mock_open, patch
import pytest
from semantic_router.route import Route, RouteConfig
class TestRouteConfig:
def test_init(self):
route_config = RouteConfig()
assert route_config.routes == []
def test_to_file_json(self):
route = Route(name="test", utterances=["utterance"])
route_config = RouteConfig(routes=[route])
with patch("builtins.open", mock_open()) as mocked_open:
route_config.to_file("data/test_output.json")
mocked_open.assert_called_once_with("data/test_output.json", "w")
def test_to_file_yaml(self):
route = Route(name="test", utterances=["utterance"])
route_config = RouteConfig(routes=[route])
with patch("builtins.open", mock_open()) as mocked_open:
route_config.to_file("data/test_output.yaml")
mocked_open.assert_called_once_with("data/test_output.yaml", "w")
def test_to_file_invalid(self):
route = Route(name="test", utterances=["utterance"])
route_config = RouteConfig(routes=[route])
with pytest.raises(ValueError):
route_config.to_file("test_output.txt")
def test_from_file_json(self):
mock_json_data = '[{"name": "test", "utterances": ["utterance"]}]'
with patch("builtins.open", mock_open(read_data=mock_json_data)) as mocked_open:
route_config = RouteConfig.from_file("data/test.json")
mocked_open.assert_called_once_with("data/test.json", "r")
assert isinstance(route_config, RouteConfig)
def test_from_file_yaml(self):
mock_yaml_data = "- name: test\n utterances:\n - utterance"
with patch("builtins.open", mock_open(read_data=mock_yaml_data)) as mocked_open:
route_config = RouteConfig.from_file("data/test.yaml")
mocked_open.assert_called_once_with("data/test.yaml", "r")
assert isinstance(route_config, RouteConfig)
def test_from_file_invalid(self):
with open("test.txt", "w") as f:
f.write("dummy content")
with pytest.raises(ValueError):
RouteConfig.from_file("test.txt")
os.remove("test.txt")
def test_to_dict(self):
route = Route(name="test", utterances=["utterance"])
route_config = RouteConfig(routes=[route])
assert route_config.to_dict() == [route.to_dict()]
def test_add(self):
route = Route(name="test", utterances=["utterance"])
route_config = RouteConfig()
route_config.add(route)
assert route_config.routes == [route]
def test_get(self):
route = Route(name="test", utterances=["utterance"])
route_config = RouteConfig(routes=[route])
assert route_config.get("test") == route
def test_get_not_found(self):
route = Route(name="test", utterances=["utterance"])
route_config = RouteConfig(routes=[route])
assert route_config.get("not_found") is None
def test_remove(self):
route = Route(name="test", utterances=["utterance"])
route_config = RouteConfig(routes=[route])
route_config.remove("test")
assert route_config.routes == []
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment