{
  "schema_version": 2,
  "id": "develop/ai/redisvl/api/router",
  "title": "Semantic Router",
  "url": "https://redis.io/docs/latest/develop/ai/redisvl/0.29.0/api/router/",
  "summary": "",
  "content": "\n\n\u003ca id=\"semantic-router-api\"\u003e\u003c/a\u003e\n\n## Semantic Router\n\n### `class SemanticRouter(name, routes, vectorizer=None, routing_config=None, redis_client=None, redis_url='redis://localhost:6379', overwrite=False, connection_kwargs=None, create_index=True)`\n\nSemantic Router for managing and querying route vectors.\n\nInitialize the SemanticRouter.\n\n* **Parameters:**\n  * **name** (*str*) – The name of the semantic router.\n  * **routes** (*List* *[*[Route](#route) *]*) – List of Route objects.\n  * **vectorizer** (*BaseVectorizer* *,* *optional*) – The vectorizer used to embed route references. Defaults to default HFTextVectorizer.\n  * **routing_config** ([RoutingConfig](#routingconfig) *,* *optional*) – Configuration for routing behavior. Defaults to the default RoutingConfig.\n  * **redis_client** (*Optional* *[* *SyncRedisClient* *]* *,* *optional*) – Redis client for connection. Defaults to None.\n  * **redis_url** (*str* *,* *optional*) – The redis url. Defaults to redis://localhost:6379.\n  * **overwrite** (*bool* *,* *optional*) – Whether to overwrite existing index. Defaults to False.\n  * **connection_kwargs** (*Dict* *[* *str* *,* *Any* *]*) – The connection arguments\n    for the redis client. Defaults to empty {}.\n  * **create_index** (*bool* *,* *optional*) – Whether RedisVL creates and validates\n    the index. When False the constructor issues no index command at\n    all and writes nothing: the index must already exist, already\n    hold the reference vectors for `routes`, and already have its\n    stored config, since none of that is written or verified.\n    `routes` must match what is indexed, because each route’s\n    distance threshold is applied from this local list – and\n    [add_route](#add_route) rewrites the stored config from that same list,\n    so attaching with a partial set and then adding a route\n    truncates the config every other client reads. See\n    [`SemanticCache`](https://redis.io/docs/latest/cache/#semanticcache) for a worked\n    example of the flag, and [Install RedisVL](https://redis.io/docs/latest/../user_guide/installation) for the\n    ACL details. Defaults to True.\n* **Raises:**\n  **ValueError** – If both create_index is False and overwrite is True.\n\n#### `add_route(route)`\n\nAdd a new route to the SemanticRouter.\n\nNote that this replaces the router’s stored config with this instance’s\nroute list, so a router constructed with a subset of the indexed routes\nwill drop the rest from the config that [from_existing](#from_existing) reads.\n\nEmbeds the route’s references, writes them to the Redis index,\nappends the route to `self.routes`, and persists the updated router\nconfig so the route survives [from_existing](#from_existing).\n\n* **Parameters:**\n  **route** ([Route](#route)) – A fully-formed Route (name, references,\n  distance_threshold, optional metadata).\n* **Returns:**\n  The added route’s name.\n* **Return type:**\n  str\n* **Raises:**\n  **ValueError** – If a route with this name already exists on the router.\n      Use [add_route_references](#add_route_references) to extend an existing route.\n\n#### `add_route_references(route_name, references)`\n\nAdd a reference(s) to an existing route.\n\n* **Parameters:**\n  * **router_name** (*str*) – The name of the router.\n  * **references** (*Union* *[* *str* *,* *List* *[* *str* *]* *]*) – The reference or list of references to add.\n  * **route_name** (*str*)\n* **Returns:**\n  The list of added references keys.\n* **Return type:**\n  List[str]\n\n#### `clear()`\n\nDelete every route reference, leaving the index in place.\n\nClears by index membership. Available under `create_index=False`;\ndropping the index is [delete](#delete).\n\n\u003e [!WARNING]\n\u003e The stored `route_config` is left as it was, here and on the\n\u003e default path. A separate process calling [from_existing](#from_existing)\n\u003e afterwards will report routes whose reference vectors are gone.\n\u003e [remove_route](#remove_route) keeps the two in step.\n\n* **Return type:**\n  None\n\n#### `delete()`\n\nDelete the semantic router index and its persisted route config.\n\n* **Raises:**\n  **ValueError** – If `create_index=False`. Use [clear](#clear) to\n      remove the route references and leave the index standing.\n* **Return type:**\n  None\n\n#### `delete_route_references(route_name='', reference_ids=None, keys=None)`\n\nGet references for an existing semantic router route.\n\n* **Parameters:**\n  * **Optional** (*keys*) – The name of the router.\n  * **Optional** – The reference or list of references to delete.\n  * **Optional** – List of fully qualified keys (prefix:router:reference_id) to delete.\n  * **route_name** (*str*)\n  * **reference_ids** (*list* *[* *str* *]*  *|* *None*)\n  * **keys** (*list* *[* *str* *]*  *|* *None*)\n* **Returns:**\n  Number of objects deleted\n* **Return type:**\n  int\n* **Raises:**\n  * **ValueError** – If no references match the given route/ids/keys.\n  * [**PartialDeletionError**](https://redis.io/docs/latest/exceptions/#partialdeletionerror) – If some keys could not be unlinked. Raised only\n        after the surviving references have been reconciled and persisted,\n        so a retry picks up exactly what is left.\n\n\u003e [!NOTE]\n\u003e Deleting every reference of a route removes the route itself, matching\n\u003e [remove_route](#remove_route). A route with no references cannot match anything,\n\u003e and [Route](#route) rejects an empty\n\u003e reference list, so persisting one would produce a config that\n\u003e [from_existing](#from_existing) can no longer load.\n\n\u003e [!NOTE]\n\u003e On Redis Cluster keys are unlinked one at a time and a per-key failure\n\u003e is logged rather than raised. References whose key failed to unlink are\n\u003e deliberately *kept* in the persisted route config: the hash is still in\n\u003e the index and the router would keep matching it, so dropping it from\n\u003e the config would leave the router claiming a reference is gone while\n\u003e still routing to it.\n\n#### `classmethod from_dict(data, **kwargs)`\n\nCreate a SemanticRouter from a dictionary.\n\n* **Parameters:**\n  **data** (*Dict* *[* *str* *,* *Any* *]*) – The dictionary containing the semantic router data.\n* **Returns:**\n  The semantic router instance.\n* **Return type:**\n  [SemanticRouter](#semanticrouter)\n* **Raises:**\n  **ValueError** – If required data is missing or invalid.\n\n```python\nfrom redisvl.extensions.router import SemanticRouter\nrouter_data = {\n    \"name\": \"example_router\",\n    \"routes\": [{\"name\": \"route1\", \"references\": [\"ref1\"], \"distance_threshold\": 0.5}],\n    \"vectorizer\": {\"type\": \"openai\", \"model\": \"text-embedding-ada-002\"},\n}\nrouter = SemanticRouter.from_dict(router_data)\n```\n\n#### `classmethod from_existing(name, redis_client=None, redis_url='redis://localhost:6379', **kwargs)`\n\nReturn SemanticRouter instance from existing index.\n\nReads the stored route config with `JSON.GET`, so unlike\n`SearchIndex.from_existing()` this needs no `FT.INFO`. Pass\n`create_index=False` to keep it that way through construction, which\nmakes this the way to attach to a router with a credential that cannot\nrun index-metadata commands.\n\n* **Parameters:**\n  * **name** (*str*)\n  * **redis_client** (*Redis* *|* *RedisCluster* *|* *None*)\n  * **redis_url** (*str*)\n* **Return type:**\n  [SemanticRouter](#semanticrouter)\n\n#### `classmethod from_yaml(file_path, **kwargs)`\n\nCreate a SemanticRouter from a YAML file.\n\n* **Parameters:**\n  **file_path** (*str*) – The path to the YAML file.\n* **Returns:**\n  The semantic router instance.\n* **Return type:**\n  [SemanticRouter](#semanticrouter)\n* **Raises:**\n  * **ValueError** – If the file path is invalid.\n  * **FileNotFoundError** – If the file does not exist.\n\n```python\nfrom redisvl.extensions.router import SemanticRouter\nrouter = SemanticRouter.from_yaml(\"router.yaml\", redis_url=\"redis://localhost:6379\")\n```\n\n#### `get(route_name)`\n\nGet a route by its name.\n\n* **Parameters:**\n  **route_name** (*str*) – Name of the route.\n* **Returns:**\n  The selected Route object or None if not found.\n* **Return type:**\n  Optional[[Route](#route)]\n\n#### `get_route_references(route_name='', reference_ids=None, keys=None)`\n\nGet references for an existing route route.\n\n* **Parameters:**\n  * **router_name** (*str*) – The name of the router.\n  * **references** (*Union* *[* *str* *,* *List* *[* *str* *]* *]*) – The reference or list of references to add.\n  * **route_name** (*str*)\n  * **reference_ids** (*list* *[* *str* *]*  *|* *None*)\n  * **keys** (*list* *[* *str* *]*  *|* *None*)\n* **Returns:**\n  Reference objects stored\n* **Return type:**\n  List[Dict[str, Any]]]\n\n#### `model_post_init(context, /)`\n\nThis function is meant to behave like a BaseModel method to initialise private attributes.\n\nIt takes context as an argument since that’s what pydantic-core passes when calling it.\n\n* **Parameters:**\n  * **self** (*BaseModel*) – The BaseModel instance.\n  * **context** (*Any*) – The context.\n* **Return type:**\n  None\n\n#### `remove_route(route_name)`\n\nRemove a route and all references from the semantic router.\n\nLike [add_route](#add_route), this replaces the router’s stored config with\nthis instance’s route list, so removing one route from a router holding\nonly a subset drops the rest from the config [from_existing](#from_existing)\nreads.\n\n* **Parameters:**\n  **route_name** (*str*) – Name of the route to remove.\n* **Raises:**\n  [**PartialDeletionError**](https://redis.io/docs/latest/exceptions/#partialdeletionerror) – If some of the route’s reference keys could not\n      be unlinked. The route is then kept with exactly those references\n      and the config persisted before raising, so the router keeps\n      describing what the index can still match and a retry removes the\n      remainder.\n* **Return type:**\n  None\n\n#### `route_many(statement=None, vector=None, max_k=None, distance_threshold=None, aggregation_method=None)`\n\nQuery the semantic router with a given statement or vector for multiple matches.\n\n* **Parameters:**\n  * **statement** (*Optional* *[* *str* *]*) – The input statement to be queried.\n  * **vector** (*Optional* *[* *List* *[* *float* *]* *]*) – The input vector to be queried.\n  * **max_k** (*Optional* *[* *int* *]*) – The maximum number of top matches to return.\n  * **distance_threshold** (*Optional* *[* *float* *]*) – The threshold for semantic distance.\n  * **aggregation_method** (*Optional* *[*[DistanceAggregationMethod](#distanceaggregationmethod) *]*) – The aggregation method used for vector distances.\n* **Returns:**\n  The matching routes and their details.\n* **Return type:**\n  List[[RouteMatch](#routematch)]\n\n#### `to_dict()`\n\nConvert the SemanticRouter instance to a dictionary.\n\n* **Returns:**\n  The dictionary representation of the SemanticRouter.\n* **Return type:**\n  Dict[str, Any]\n\n```python\nfrom redisvl.extensions.router import SemanticRouter\nrouter = SemanticRouter(name=\"example_router\", routes=[], redis_url=\"redis://localhost:6379\")\nrouter_dict = router.to_dict()\n```\n\n#### `to_yaml(file_path, overwrite=True)`\n\nWrite the semantic router to a YAML file.\n\n* **Parameters:**\n  * **file_path** (*str*) – The path to the YAML file.\n  * **overwrite** (*bool*) – Whether to overwrite the file if it already exists.\n* **Raises:**\n  **FileExistsError** – If the file already exists and overwrite is False.\n* **Return type:**\n  None\n\n```python\nfrom redisvl.extensions.router import SemanticRouter\nrouter = SemanticRouter(\n    name=\"example_router\",\n    routes=[],\n    redis_url=\"redis://localhost:6379\"\n)\nrouter.to_yaml(\"router.yaml\")\n```\n\n#### `update_route_thresholds(route_thresholds)`\n\nUpdate the distance thresholds for each route.\n\n* **Parameters:**\n  **route_thresholds** (*Dict* *[* *str* *,* *float* *]*) – Dictionary of route names and their distance thresholds.\n\n#### `update_routing_config(routing_config)`\n\nUpdate the routing configuration.\n\n* **Parameters:**\n  **routing_config** ([RoutingConfig](#routingconfig)) – The new routing configuration.\n\n#### `model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}`\n\nConfiguration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].\n\n#### `name: str`\n\nThe name of the semantic router.\n\n#### `property route_names: list[str]`\n\nGet the list of route names.\n\n* **Returns:**\n  List of route names.\n* **Return type:**\n  List[str]\n\n#### `property route_thresholds: dict[str, float | None]`\n\nGet the distance thresholds for each route.\n\n* **Returns:**\n  Dictionary of route names and their distance thresholds.\n* **Return type:**\n  Dict[str, float]\n\n#### `routes: `list[[Route](#route)]\n\nList of Route objects.\n\n#### `routing_config: `[RoutingConfig](#routingconfig)\n\nConfiguration for routing behavior.\n\n#### `vectorizer: BaseVectorizer`\n\nThe vectorizer used to embed route references.\n\n## Routing Config\n\n### `class RoutingConfig(*, max_k=1, aggregation_method=DistanceAggregationMethod.avg)`\n\nConfiguration for routing behavior.\n\nCreate a new model by parsing and validating input data from keyword arguments.\n\nRaises [ValidationError][pydantic_core.ValidationError] if the input data cannot be\nvalidated to form a valid model.\n\nself is explicitly positional-only to allow self as a field name.\n\n* **Parameters:**\n  * **max_k** (*Annotated* *[* *int* *,* *FieldInfo* *(* *annotation=NoneType* *,* *required=True* *,* *metadata=* *[* *Strict* *(* *strict=True* *)* *,* *Gt* *(* *gt=0* *)* *]* *)* *]*)\n  * **aggregation_method** ([DistanceAggregationMethod](#distanceaggregationmethod))\n\n#### `max_k: Annotated[int, FieldInfo(annotation=NoneType, required=True, metadata=[Strict(strict=True), Gt(gt=0)])]`\n\nAggregation method to use to classify queries.\n\n#### `model_config: ClassVar[ConfigDict] = {'extra': 'ignore'}`\n\nConfiguration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].\n\n## Route\n\n### `class Route(*, name, references, metadata={}, distance_threshold=0.5)`\n\nModel representing a routing path with associated metadata and thresholds.\n\nCreate a new model by parsing and validating input data from keyword arguments.\n\nRaises [ValidationError][pydantic_core.ValidationError] if the input data cannot be\nvalidated to form a valid model.\n\nself is explicitly positional-only to allow self as a field name.\n\n* **Parameters:**\n  * **name** (*str*)\n  * **references** (*list* *[* *str* *]*)\n  * **metadata** (*dict* *[* *str* *,* *Any* *]*)\n  * **distance_threshold** (*Annotated* *[* *float* *,* *FieldInfo* *(* *annotation=NoneType* *,* *required=True* *,* *metadata=* *[* *Strict* *(* *strict=True* *)* *,* *Gt* *(* *gt=0* *)* *,* *Le* *(* *le=2* *)* *]* *)* *]*)\n\n#### `distance_threshold: Annotated[float, FieldInfo(annotation=NoneType, required=True, metadata=[Strict(strict=True), Gt(gt=0), Le(le=2)])]`\n\nMaximum distance for matching the route, inclusive.\n\n#### `metadata: dict[str, Any]`\n\nMetadata associated with the route.\n\n#### `model_config: ClassVar[ConfigDict] = {}`\n\nConfiguration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].\n\n#### `name: str`\n\nThe name of the route.\n\n#### `references: list[str]`\n\nList of reference phrases for the route.\n\n## Route Match\n\n### `class RouteMatch(*, name=None, distance=None)`\n\nModel representing a matched route with distance information.\n\nCreate a new model by parsing and validating input data from keyword arguments.\n\nRaises [ValidationError][pydantic_core.ValidationError] if the input data cannot be\nvalidated to form a valid model.\n\nself is explicitly positional-only to allow self as a field name.\n\n* **Parameters:**\n  * **name** (*str* *|* *None*)\n  * **distance** (*float* *|* *None*)\n\n#### `distance: float | None`\n\nThe vector distance between the statement and the matched route.\n\n#### `model_config: ClassVar[ConfigDict] = {}`\n\nConfiguration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].\n\n#### `name: str | None`\n\nThe matched route name.\n\n## Distance Aggregation Method\n\n### `class DistanceAggregationMethod(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)`\n\nEnumeration for distance aggregation methods.\n\n#### `avg = 'avg'`\n\nCompute the average of the vector distances.\n\n#### `min = 'min'`\n\nCompute the minimum of the vector distances.\n\n#### `sum = 'sum'`\n\nCompute the sum of the vector distances.\n",
  "tags": [],
  "last_updated": "2026-11-02T13:23:15+02:00"
}
