{
  "id": "semantic_router",
  "title": "Semantic Routing",
  "url": "https://redis.io/docs/latest/develop/ai/redisvl/0.9.1/user_guide/semantic_router/",
  "summary": "",
  "content": "\n\nRedisVL provides a `SemanticRouter` interface to utilize Redis' built-in search \u0026 aggregation in order to perform\nKNN-style classification over a set of `Route` references to determine the best match.\n\nThis notebook will go over how to use Redis as a Semantic Router for your applications\n\n## Define the Routes\n\nBelow we define 3 different routes. One for `technology`, one for `sports`, and\nanother for `entertainment`. Now for this example, the goal here is\nsurely topic \"classification\". But you can create routes and references for\nalmost anything.\n\nEach route has a set of references that cover the \"semantic surface area\" of the\nroute. The incoming query from a user needs to be semantically similar to one or\nmore of the references in order to \"match\" on the route.\n\nAdditionally, each route has a `distance_threshold` which determines the maximum distance between the query and the reference for the query to be routed to the route. This value is unique to each route.\n\n\n```python\nfrom redisvl.extensions.router import Route\n\n# Define routes for the semantic router\ntechnology = Route(\n    name=\"technology\",\n    references=[\n        \"what are the latest advancements in AI?\",\n        \"tell me about the newest gadgets\",\n        \"what's trending in tech?\"\n    ],\n    metadata={\"category\": \"tech\", \"priority\": 1},\n    distance_threshold=0.71\n)\n\nsports = Route(\n    name=\"sports\",\n    references=[\n        \"who won the game last night?\",\n        \"tell me about the upcoming sports events\",\n        \"what's the latest in the world of sports?\",\n        \"sports\",\n        \"basketball and football\"\n    ],\n    metadata={\"category\": \"sports\", \"priority\": 2},\n    distance_threshold=0.72\n)\n\nentertainment = Route(\n    name=\"entertainment\",\n    references=[\n        \"what are the top movies right now?\",\n        \"who won the best actor award?\",\n        \"what's new in the entertainment industry?\"\n    ],\n    metadata={\"category\": \"entertainment\", \"priority\": 3},\n    distance_threshold=0.7\n)\n\n```\n\n## Initialize the SemanticRouter\n\n``SemanticRouter`` will automatically create an index within Redis upon initialization for the route references. By default, it uses the `HFTextVectorizer` to \ngenerate embeddings for each route reference.\n\n\n```python\nimport os\nfrom redisvl.extensions.router import SemanticRouter\nfrom redisvl.utils.vectorize import HFTextVectorizer\n\nos.environ[\"TOKENIZERS_PARALLELISM\"] = \"false\"\n\n# Initialize the SemanticRouter\nrouter = SemanticRouter(\n    name=\"topic-router\",\n    vectorizer=HFTextVectorizer(),\n    routes=[technology, sports, entertainment],\n    redis_url=\"redis://localhost:6379\",\n    overwrite=True # Blow away any other routing index with this name\n)\n```\n\n    /Users/tyler.hutcherson/Documents/AppliedAI/redis-vl-python/.venv/lib/python3.13/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n      from .autonotebook import tqdm as notebook_tqdm\n\n\n    13:03:49 sentence_transformers.SentenceTransformer INFO   Use pytorch device_name: mps\n    13:03:49 sentence_transformers.SentenceTransformer INFO   Load pretrained SentenceTransformer: sentence-transformers/all-mpnet-base-v2\n\n\n    Batches: 100%|██████████| 1/1 [00:00\u003c00:00,  6.31it/s]\n    Batches: 100%|██████████| 1/1 [00:00\u003c00:00,  7.02it/s]\n    Batches: 100%|██████████| 1/1 [00:00\u003c00:00,  8.21it/s]\n    Batches: 100%|██████████| 1/1 [00:00\u003c00:00, 54.33it/s]\n\n\n\n```python\n# look at the index specification created for the semantic router\n!rvl index info -i topic-router\n```\n\n    \n    \n    Index Information:\n    ╭──────────────────┬──────────────────┬──────────────────┬──────────────────┬──────────────────╮\n    │ Index Name       │ Storage Type     │ Prefixes         │ Index Options    │ Indexing         │\n    ├──────────────────┼──────────────────┼──────────────────┼──────────────────┼──────────────────┤\n    | topic-router     | HASH             | ['topic-router'] | []               | 0                |\n    ╰──────────────────┴──────────────────┴──────────────────┴──────────────────┴──────────────────╯\n    Index Fields:\n    ╭─────────────────┬─────────────────┬─────────────────┬─────────────────┬─────────────────┬─────────────────┬─────────────────┬─────────────────┬─────────────────┬─────────────────┬─────────────────╮\n    │ Name            │ Attribute       │ Type            │ Field Option    │ Option Value    │ Field Option    │ Option Value    │ Field Option    │ Option Value    │ Field Option    │ Option Value    │\n    ├─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┼─────────────────┤\n    │ reference_id    │ reference_id    │ TAG             │ SEPARATOR       │ ,               │                 │                 │                 │                 │                 │                 │\n    │ route_name      │ route_name      │ TAG             │ SEPARATOR       │ ,               │                 │                 │                 │                 │                 │                 │\n    │ reference       │ reference       │ TEXT            │ WEIGHT          │ 1               │                 │                 │                 │                 │                 │                 │\n    │ vector          │ vector          │ VECTOR          │ algorithm       │ FLAT            │ data_type       │ FLOAT32         │ dim             │ 768             │ distance_metric │ COSINE          │\n    ╰─────────────────┴─────────────────┴─────────────────┴─────────────────┴─────────────────┴─────────────────┴─────────────────┴─────────────────┴─────────────────┴─────────────────┴─────────────────╯\n\n\n\n```python\nrouter._index.info()[\"num_docs\"]\n```\n\n\n\n\n    11\n\n\n\n## Simple routing\n\n\n```python\n# Query the router with a statement\nroute_match = router(\"Can you tell me about the latest in artificial intelligence?\")\nroute_match\n```\n\n    Batches: 100%|██████████| 1/1 [00:00\u003c00:00,  8.63it/s]\n\n\n\n\n\n    RouteMatch(name='technology', distance=0.419145941734)\n\n\n\n\n```python\n# Query the router with a statement and return a miss\nroute_match = router(\"are aliens real?\")\nroute_match\n```\n\n    Batches: 100%|██████████| 1/1 [00:00\u003c00:00, 11.71it/s]\n\n\n\n\n\n    RouteMatch(name=None, distance=None)\n\n\n\nWe can also route a statement to many routes and order them by distance:\n\n\n```python\n# Perform multi-class classification with route_many() -- toggle the max_k and the distance_threshold\nroute_matches = router.route_many(\"How is AI used in basketball?\", max_k=3)\nroute_matches\n```\n\n    Batches: 100%|██████████| 1/1 [00:00\u003c00:00, 12.12it/s]\n\n\n\n\n\n    [RouteMatch(name='technology', distance=0.556493639946),\n     RouteMatch(name='sports', distance=0.671060085297)]\n\n\n\n\n```python\n# Toggle the aggregation method -- note the different distances in the result\nfrom redisvl.extensions.router.schema import DistanceAggregationMethod\n\nroute_matches = router.route_many(\"How is AI used in basketball?\", aggregation_method=DistanceAggregationMethod.min, max_k=3)\nroute_matches\n```\n\n    Batches: 100%|██████████| 1/1 [00:00\u003c00:00, 56.69it/s]\n\n\n\n\n\n    [RouteMatch(name='technology', distance=0.556493639946),\n     RouteMatch(name='sports', distance=0.629264354706)]\n\n\n\nNote the different route match distances. This is because we used the `min` aggregation method instead of the default `avg` approach.\n\n## Update the routing config\n\n\n```python\nfrom redisvl.extensions.router import RoutingConfig\n\nrouter.update_routing_config(\n    RoutingConfig(aggregation_method=DistanceAggregationMethod.min, max_k=3)\n)\n```\n\n\n```python\nroute_matches = router.route_many(\"Lebron James\")\nroute_matches\n```\n\n    Batches: 100%|██████████| 1/1 [00:00\u003c00:00, 13.20it/s]\n\n\n\n\n\n    [RouteMatch(name='sports', distance=0.663253903389)]\n\n\n\n## Router serialization\n\n\n```python\nrouter.to_dict()\n```\n\n\n\n\n    {'name': 'topic-router',\n     'routes': [{'name': 'technology',\n       'references': ['what are the latest advancements in AI?',\n        'tell me about the newest gadgets',\n        \"what's trending in tech?\"],\n       'metadata': {'category': 'tech', 'priority': 1},\n       'distance_threshold': 0.71},\n      {'name': 'sports',\n       'references': ['who won the game last night?',\n        'tell me about the upcoming sports events',\n        \"what's the latest in the world of sports?\",\n        'sports',\n        'basketball and football'],\n       'metadata': {'category': 'sports', 'priority': 2},\n       'distance_threshold': 0.72},\n      {'name': 'entertainment',\n       'references': ['what are the top movies right now?',\n        'who won the best actor award?',\n        \"what's new in the entertainment industry?\"],\n       'metadata': {'category': 'entertainment', 'priority': 3},\n       'distance_threshold': 0.7}],\n     'vectorizer': {'type': 'hf',\n      'model': 'sentence-transformers/all-mpnet-base-v2'},\n     'routing_config': {'max_k': 3, 'aggregation_method': 'min'}}\n\n\n\n\n```python\nrouter2 = SemanticRouter.from_dict(router.to_dict(), redis_url=\"redis://localhost:6379\")\n\nassert router2.to_dict() == router.to_dict()\n```\n\n    13:03:54 sentence_transformers.SentenceTransformer INFO   Use pytorch device_name: mps\n    13:03:54 sentence_transformers.SentenceTransformer INFO   Load pretrained SentenceTransformer: sentence-transformers/all-mpnet-base-v2\n\n\n    Batches: 100%|██████████| 1/1 [00:00\u003c00:00, 53.91it/s]\n\n    13:03:54 redisvl.index.index INFO   Index already exists, not overwriting.\n\n\n    \n\n\n\n```python\nrouter.to_yaml(\"router.yaml\", overwrite=True)\n```\n\n\n```python\nrouter3 = SemanticRouter.from_yaml(\"router.yaml\", redis_url=\"redis://localhost:6379\")\n\nassert router3.to_dict() == router2.to_dict() == router.to_dict()\n```\n\n    13:03:54 sentence_transformers.SentenceTransformer INFO   Use pytorch device_name: mps\n    13:03:54 sentence_transformers.SentenceTransformer INFO   Load pretrained SentenceTransformer: sentence-transformers/all-mpnet-base-v2\n\n\n    Batches: 100%|██████████| 1/1 [00:00\u003c00:00, 51.94it/s]\n\n    13:03:55 redisvl.index.index INFO   Index already exists, not overwriting.\n\n\n    \n\n\n## Add route references\n\n\n```python\nrouter.add_route_references(route_name=\"technology\", references=[\"latest AI trends\", \"new tech gadgets\"])\n```\n\n    Batches: 100%|██████████| 1/1 [00:00\u003c00:00,  8.12it/s]\n\n\n\n\n\n    ['topic-router:technology:f243fb2d073774e81c7815247cb3013794e6225df3cbe3769cee8c6cefaca777',\n     'topic-router:technology:7e4bca5853c1c3298b4d001de13c3c7a79a6e0f134f81acc2e7cddbd6845961f']\n\n\n\n## Get route references\n\n\n```python\n# by route name\nrefs = router.get_route_references(route_name=\"technology\")\nrefs\n```\n\n\n\n\n    [{'id': 'topic-router:technology:85cc73a1437df27caa2f075a29c497e5a2e532023fbb75378aedbae80779ab37',\n      'reference_id': '85cc73a1437df27caa2f075a29c497e5a2e532023fbb75378aedbae80779ab37',\n      'route_name': 'technology',\n      'reference': 'tell me about the newest gadgets'},\n     {'id': 'topic-router:technology:851f51cce5a9ccfbbcb66993908be6b7871479af3e3a4b139ad292a1bf7e0676',\n      'reference_id': '851f51cce5a9ccfbbcb66993908be6b7871479af3e3a4b139ad292a1bf7e0676',\n      'route_name': 'technology',\n      'reference': 'what are the latest advancements in AI?'},\n     {'id': 'topic-router:technology:f243fb2d073774e81c7815247cb3013794e6225df3cbe3769cee8c6cefaca777',\n      'reference_id': 'f243fb2d073774e81c7815247cb3013794e6225df3cbe3769cee8c6cefaca777',\n      'route_name': 'technology',\n      'reference': 'latest AI trends'},\n     {'id': 'topic-router:technology:7e4bca5853c1c3298b4d001de13c3c7a79a6e0f134f81acc2e7cddbd6845961f',\n      'reference_id': '7e4bca5853c1c3298b4d001de13c3c7a79a6e0f134f81acc2e7cddbd6845961f',\n      'route_name': 'technology',\n      'reference': 'new tech gadgets'},\n     {'id': 'topic-router:technology:149a9c9919c58534aa0f369e85ad95ba7f00aa0513e0f81e2aff2ea4a717b0e0',\n      'reference_id': '149a9c9919c58534aa0f369e85ad95ba7f00aa0513e0f81e2aff2ea4a717b0e0',\n      'route_name': 'technology',\n      'reference': \"what's trending in tech?\"}]\n\n\n\n\n```python\n# by reference id\nrefs = router.get_route_references(reference_ids=[refs[0][\"reference_id\"]])\nrefs\n```\n\n\n\n\n    [{'id': 'topic-router:technology:85cc73a1437df27caa2f075a29c497e5a2e532023fbb75378aedbae80779ab37',\n      'reference_id': '85cc73a1437df27caa2f075a29c497e5a2e532023fbb75378aedbae80779ab37',\n      'route_name': 'technology',\n      'reference': 'tell me about the newest gadgets'}]\n\n\n\n## Delete route references\n\n\n```python\n# by route name\ndeleted_count = router.delete_route_references(route_name=\"sports\")\ndeleted_count\n```\n\n\n\n\n    5\n\n\n\n\n```python\n# by id\ndeleted_count = router.delete_route_references(reference_ids=[refs[0][\"reference_id\"]])\ndeleted_count\n```\n\n\n\n\n    1\n\n\n\n## Clean up the router\n\n\n```python\n# Use clear to flush all routes from the index\nrouter.clear()\n```\n\n\n```python\n# Use delete to clear the index and remove it completely\nrouter.delete()\n```\n",
  "tags": [],
  "last_updated": "2026-04-08T12:21:52-07:00"
}

