Semantic Routing

The routing layer determines which data source can best answer a user's question. It uses a combination of keyword matching, embedding similarity, and metadata lookup.

Routing Decision Tree
"Show PMPM by region"
    โ”‚
    โ”œโ”€ Does a PBI measure named "PMPM" exist?
    โ”‚  โ†’ YES โ†’ Route to Power BI
    โ”‚
    โ”œโ”€ Is the question about detail-level data?
    โ”‚  โ†’ Route to Snowflake
    โ”‚
    โ””โ”€ Ambiguous?
       โ†’ Check embedding similarity against known query patterns
       โ†’ Route to highest-confidence match

Routing rules (in priority order):

#RuleRoutes To
1Question references a known PBI measurePower BI
2Question asks for a report or dashboardPower BI
3Question asks for detail rows or raw dataSnowflake
4Question matches a few-shot examplePer example
5Fallback: embedding similarityHighest match

Metadata Service

A central service that provides schema, measure, and relationship information from both data sources.

๐Ÿ“Š

Power BI Metadata

Tables, columns, measures, relationships, descriptions โ€” extracted via the PBI REST API or TMDL.

โ„๏ธ

Snowflake Metadata

Databases, schemas, tables, columns, data types โ€” extracted from INFORMATION_SCHEMA.

๐Ÿ”—

Cross-Source Mapping

Map PBI measures to Snowflake tables so the system knows which Snowflake tables back which PBI models.

โšก

Metadata Cache

Metadata refreshed on schedule (e.g., every 6 hours). Cached in-memory for sub-millisecond lookups.

The metadata service ensures prompts only include relevant context โ€” not the entire schema. For a question about "PMPM by region," the prompt includes only the PMPM measure, region dimension, and their relationship.

Business Glossary

Domain-specific terms resolved to exact column/measure references before they reach the LLM:

Business TermResolves ToSource
PMPM[Fact Claims].[PMPM] measurePower BI
member months[Fact Eligibility].[Member Months] measurePower BI
LOB[Dim LOB].[Line of Business] columnBoth
region[Dim Region].[Region Name] columnBoth
denied claimsclaims WHERE status = 'DENIED'Snowflake
high-cost claimantclaims WHERE amount > 50000Snowflake

The glossary is maintained as a JSON file and can be updated by business users without code changes.

Few-Shot Examples

Curated questionโ†’query pairs injected into prompts. These dramatically improve LLM accuracy for domain-specific patterns:

Few-Shot Example SetDAX
// Example 1
Q: "What is the current PMPM by line of business?"
A: EVALUATE
   SUMMARIZECOLUMNS(
     'Dim LOB'[Line of Business],
     "PMPM", [PMPM]
   )

// Example 2
Q: "Show top 10 clients by total claims amount"
A: EVALUATE
   TOPN(
     10,
     SUMMARIZECOLUMNS(
       'Dim Client'[Client Name],
       "Total Claims", [Total Claims Amount]
     ),
     [Total Claims Amount], DESC
   )

Best practices for few-shot examples:

  • โœ“Include 3โ€“5 examples per query pattern (KPI, trend, comparison, etc.)
  • โœ“Only inject examples that match the detected intent type
  • โœ“Keep examples verified โ€” wrong examples poison all future queries
  • โœ“Version-control examples alongside the metadata configuration

Caching Strategy

Metadata Cache

Schema, measures, glossary. Refreshed every 6 hours or on demand. Stored in-memory. TTL-based eviction.

Query Cache

Recent query results keyed by normalized query string + user role. TTL: 15 minutes. Invalidated on data refresh.

Cache hits return in under 50ms. Cache misses fall through to the full pipeline.