Skip to content

Quickstart

Build your first semantic router in just a few lines of code.

1. Install StrataRouter

pip install stratarouter
pip install "stratarouter[openai]"
pip install "stratarouter[all]"

Note

See the Installation Guide for more options, virtual environments, and platform-specific instructions.


2. Create Your First Router

Create a Python file, e.g. my_router.py:

from stratarouter import Router, Route
import random

# 1. Create router
router = Router(dimension=384, threshold=0.5)

# 2. Define routes
billing = Route(
    id="billing",
    description="Billing and payment questions",
    keywords=["invoice", "payment", "refund", "charge", "bill"],
    examples=[
        "Where's my invoice?",
        "I need a refund",
        "Update my payment method"
    ]
)

support = Route(
    id="support",
    description="Technical support and bug reports",
    keywords=["bug", "crash", "error", "broken", "login"],
    examples=[
        "App is crashing",
        "Can't login",
        "Getting an error message"
    ]
)

# 3. Add routes to router
router.add_route(billing)
router.add_route(support)

# 4. Build the HNSW index with embeddings
# In production, use real embeddings from a model (see Step 3 below)
embeddings = [
    [random.random() for _ in range(384)],  # billing embedding
    [random.random() for _ in range(384)]   # support embedding
]
router.build_index(embeddings)

# 5. Route a query
query_embedding = [random.random() for _ in range(384)]
result = router.route("I need my invoice for last month", query_embedding)

print(f"Route:      {result.route_id}")          # "billing"
print(f"Confidence: {result.confidence:.3f}")    # e.g. 0.892
print(f"Latency:    {result.latency_ms:.2f}ms")  # e.g. 1.24ms

Run it:

python my_router.py

Success

You just routed a query in milliseconds. Step 3 shows how to use real embeddings for production accuracy.


3. Use Real Embeddings

For accurate routing, generate embeddings from an actual model:

from stratarouter import Router, Route
from sentence_transformers import SentenceTransformer

# Load a local embedding model (free, no API key needed)
model = SentenceTransformer("all-MiniLM-L6-v2")  # 384 dimensions

router = Router(dimension=384, threshold=0.7)

routes = [
    Route(
        id="billing",
        description="Billing, payments, invoices, and refunds",
        keywords=["invoice", "payment", "refund", "billing", "charge"],
        examples=["Where's my invoice?", "I need a refund", "Payment failed"]
    ),
    Route(
        id="support",
        description="Technical support, bugs, errors, and troubleshooting",
        keywords=["bug", "crash", "error", "broken", "login"],
        examples=["App is crashing", "Can't login", "Feature not working"]
    ),
    Route(
        id="sales",
        description="Pricing, plans, upgrades, and sales inquiries",
        keywords=["price", "cost", "upgrade", "plan", "buy"],
        examples=["What's your pricing?", "Can I upgrade?", "Enterprise plans?"]
    )
]

for route in routes:
    router.add_route(route)

# Generate embeddings from route descriptions
descriptions = [r.description for r in routes]
embeddings = model.encode(descriptions).tolist()
router.build_index(embeddings)

# Route with a real query embedding
test_queries = [
    "Where's my invoice?",
    "App is crashing",
    "What's your pricing?"
]

for query in test_queries:
    query_embedding = model.encode([query])[0].tolist()
    result = router.route(query, query_embedding)
    print(f"{query:30}{result.route_id:10} ({result.confidence:.3f})")

Output:

Where's my invoice?            → billing     (0.895)
App is crashing                → support     (0.876)
What's your pricing?           → sales       (0.912)

from stratarouter import Router, Route
from openai import OpenAI

client = OpenAI()

def embed(text: str) -> list[float]:
    resp = client.embeddings.create(
        model="text-embedding-3-small",  # 1536-dim
        input=text
    )
    return resp.data[0].embedding

router = Router(dimension=1536, threshold=0.7)

routes = [
    Route(
        id="billing",
        description="Billing, payments, invoices, and refunds",
        keywords=["invoice", "payment", "refund"]
    ),
    Route(
        id="support",
        description="Technical support, bugs, errors, and troubleshooting",
        keywords=["bug", "crash", "error"]
    )
]

for route in routes:
    router.add_route(route)

# Build index with OpenAI embeddings
embeddings = [embed(r.description) for r in routes]
router.build_index(embeddings)

# Route with real embedding
query = "Where can I download my invoice?"
result = router.route(query, embed(query))
print(f"→ {result.route_id} ({result.confidence:.3f})")  # billing (0.934)

4. Score Breakdown

Understand how StrataRouter calculates routing scores:

result = router.route(query, query_embedding)

# Primary decision
print(f"Route:      {result.route_id}")
print(f"Confidence: {result.confidence:.3f}")
print(f"Latency:    {result.latency_ms:.2f}ms")

# Detailed score breakdown
print(f"\nScore breakdown:")
print(f"  Semantic: {result.scores.semantic:.3f}")  # Dense embedding similarity
print(f"  Keyword:  {result.scores.keyword:.3f}")   # BM25 keyword matching
print(f"  Pattern:  {result.scores.pattern:.3f}")   # Rule-based patterns
print(f"  Total:    {result.scores.total:.3f}")     # Fused (64% sem + 29% kw + 7% rule)

# Alternative routes
for route_id, conf in result.alternatives:
    print(f"  Alt: {route_id} ({conf:.3f})")

Tip

StrataRouter uses hybrid scoring — semantic embeddings (64%) + BM25 keyword matching (29%) + rule-based patterns (7%). This combination outperforms embedding-only approaches, especially for domain-specific terms.


5. Handle Edge Cases

from stratarouter import Router, Route

router = Router(dimension=384, threshold=0.7)

# ... (add routes and build index) ...

def smart_route(query: str, query_embedding: list) -> str:
    """Route query with fallback for low confidence."""
    result = router.route(query, query_embedding)

    if result.confidence < 0.5:
        print(f"Low confidence ({result.confidence:.1%}) — using fallback")
        return "general_support"  # default fallback

    print(f"Routing to '{result.route_id}' with {result.confidence:.1%} confidence")
    return result.route_id

Common Patterns

from stratarouter import Router, Route

router = Router(dimension=384, threshold=0.6)
router.add_route(Route(id="billing",  description="Billing, invoices, payments"))
router.add_route(Route(id="support",  description="Technical issues, bugs"))
router.add_route(Route(id="sales",    description="Pricing, plans, upgrades"))
router.build_index(embeddings)

result = router.route("My payment failed", query_embedding)
print(result.route_id)  # "billing"
from stratarouter import Router, Route

router = Router(dimension=384)
router.add_route(Route(id="analyst",    description="Data analysis and reports"))
router.add_route(Route(id="researcher", description="Research and information"))
router.add_route(Route(id="coder",      description="Programming and code"))
router.build_index(embeddings)

result = router.route("Write Python code for ML", query_embedding)
agent = result.route_id  # "coder"
from stratarouter import Router, Route

router = Router(dimension=384)
router.add_route(Route(id="docs",  description="Product documentation"))
router.add_route(Route(id="faq",   description="Frequently asked questions"))
router.add_route(Route(id="blog",  description="Blog posts and tutorials"))
router.build_index(embeddings)

result = router.route("How do I get started?", query_embedding)
kb = result.route_id  # "docs"
from stratarouter import Router, Route

router = Router(dimension=384)
router.add_route(Route(id="gpt5",    description="Complex reasoning and analysis"))
router.add_route(Route(id="claude",  description="Long context and coding"))
router.add_route(Route(id="local",   description="Privacy-sensitive queries"))
router.build_index(embeddings)

result = router.route("Analyze this 50-page document", query_embedding)
model = result.route_id  # "claude"

Troubleshooting

ImportError: No module named 'stratarouter'

Make sure you installed it:

pip install stratarouter

Check the installation:

python -c "import stratarouter; print(stratarouter.__version__)"

If still failing, check you're in the correct virtual environment:

which python
pip list | grep stratarouter

DimensionMismatch error

Your embedding dimension doesn't match the router configuration. Always match them:

# If using all-MiniLM-L6-v2 (384 dimensions)
router = Router(dimension=384)
embeddings = model.encode(texts)  # returns 384-dim vectors ✓

# If using text-embedding-3-small (1536 dimensions)
router = Router(dimension=1536)
Routes not routing correctly
  1. Better descriptions: Make route descriptions specific and distinct
  2. Lower threshold: Try Router(threshold=0.5) instead of 0.7
  3. Add examples and keywords: Provide multiple examples per route
route = Route(
    id="billing",
    description="Invoice, payment, billing, subscription, cost, refund",
    keywords=["invoice", "payment", "refund", "charge"],
    examples=["Where's my invoice?", "I need a refund", "Payment failed"]
)
Slow routing (>10ms)
  1. Check the HNSW index is built: router.build_index(embeddings) before routing
  2. Enable SIMD: Router(dimension=384, enable_simd=True)
  3. Reduce hnsw_ef_search for fewer route counts

Debug latency:

result = router.route(query, embedding)
print(f"Latency: {result.latency_ms:.2f}ms")  # should be <10ms

Low confidence scores
  1. Improve descriptions: Be more specific
  2. Use a better model: Try all-mpnet-base-v2 (768d, higher quality)
  3. Lower threshold: Router(threshold=0.5)
# Higher quality model
model = SentenceTransformer("all-mpnet-base-v2")  # 768-dim
router = Router(dimension=768, threshold=0.5)

Next Steps


Need help? Check the FAQ or open an issue on GitHub.