Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-rag/src/lexigram/ai/rag/routing/types.py: 84%
79 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
1"""Core types for query routing."""
3from __future__ import annotations
5from dataclasses import dataclass, field
6from enum import StrEnum
7from typing import Any
9from lexigram.ai.rag.multimodal.types import Modality
12class QueryIntent(StrEnum):
13 """Intent classification for queries.
15 Attributes:
16 FACTUAL: Questions seeking factual information.
17 CONVERSATIONAL: Casual conversation or greetings.
18 ANALYTICAL: Queries requiring comparison or analysis.
19 CREATIVE: Requests for creative content generation.
20 PROCEDURAL: How-to questions or instructions.
21 NAVIGATIONAL: Queries seeking specific pages or resources.
22 """
24 FACTUAL = "factual"
25 CONVERSATIONAL = "conversational"
26 ANALYTICAL = "analytical"
27 CREATIVE = "creative"
28 PROCEDURAL = "procedural"
29 NAVIGATIONAL = "navigational"
32class DataSourceType(StrEnum):
33 """Types of data sources for routing.
35 Attributes:
36 VECTOR_STORE: Dense vector embeddings store.
37 KEYWORD_INDEX: Sparse keyword-based index (BM25, TF-IDF).
38 KNOWLEDGE_GRAPH: Graph database for structured knowledge.
39 SQL_DATABASE: Relational database for structured queries.
40 EXTERNAL_API: External API or web service.
41 MULTIMODAL_STORE: Multi-modal content store (images, audio, video).
42 """
44 VECTOR_STORE = "vector_store"
45 KEYWORD_INDEX = "keyword_index"
46 KNOWLEDGE_GRAPH = "knowledge_graph"
47 SQL_DATABASE = "sql_database"
48 EXTERNAL_API = "external_api"
49 MULTIMODAL_STORE = "multimodal_store"
52@dataclass
53class QueryFeatures:
54 """Features extracted from a query for routing decisions.
56 Attributes:
57 text: Original query text.
58 length: Character count of the query.
59 intent: Classified intent of the query.
60 language: Detected language code (e.g., 'en', 'es').
61 domain: Optional domain classification (e.g., 'technical', 'medical').
62 keywords: Extracted keywords from the query.
63 has_entities: Whether named entities were detected.
64 modalities: Detected modalities (text, image, audio, video).
65 complexity: Query complexity score (0-1).
66 metadata: Additional metadata for routing decisions.
67 """
69 text: str
70 length: int
71 intent: QueryIntent
72 language: str = "en"
73 domain: str | None = None
74 keywords: list[str] = field(default_factory=list)
75 has_entities: bool = False
76 modalities: list[Modality] = field(default_factory=lambda: [Modality.TEXT])
77 complexity: float = 0.5
78 metadata: dict[str, Any] = field(default_factory=dict)
80 @property
81 def is_simple(self) -> bool:
82 """Check if query is simple (low complexity)."""
83 return self.complexity < 0.3
85 @property
86 def is_complex(self) -> bool:
87 """Check if query is complex (high complexity)."""
88 return self.complexity > 0.7
90 @property
91 def is_multimodal(self) -> bool:
92 """Check if query involves multiple modalities."""
93 return len(self.modalities) > 1 or Modality.TEXT not in self.modalities
95 @property
96 def is_long(self) -> bool:
97 """Check if query is long (>200 chars)."""
98 return self.length > 200
101@dataclass
102class DataSource:
103 """Represents a data source for query routing.
105 Attributes:
106 name: Unique identifier for the data source.
107 type: Type of data source (vector store, keyword index, etc.).
108 description: Human-readable description.
109 capabilities: List of supported capabilities.
110 priority: Priority for routing (higher = more preferred).
111 metadata: Additional metadata about the data source.
112 """
114 name: str
115 type: DataSourceType
116 description: str
117 capabilities: list[str] = field(default_factory=list)
118 priority: int = 0
119 metadata: dict[str, Any] = field(default_factory=dict)
121 def supports(self, capability: str) -> bool:
122 """Check if data source supports a capability.
124 Args:
125 capability: Capability to check (e.g., 'dense_search').
127 Returns:
128 True if capability is supported, False otherwise.
129 """
130 return capability in self.capabilities
132 def __hash__(self) -> int:
133 """Make DataSourceProtocol hashable for use in sets/dicts."""
134 return hash(self.name)
136 def __eq__(self, other: object) -> bool:
137 """Check equality based on name."""
138 if not isinstance(other, DataSource):
139 return NotImplemented
140 return self.name == other.name
143@dataclass
144class RoutingDecision:
145 """Result of a routing decision.
147 Attributes:
148 query: Original query text.
149 data_sources: Selected data sources for the query.
150 strategy: Retrieval strategy to use.
151 confidence: Confidence score (0-1) in the routing decision.
152 reasoning: Human-readable explanation of the decision.
153 features: Query features used for routing.
154 metadata: Additional metadata about the routing decision.
155 """
157 query: str
158 data_sources: list[DataSource]
159 strategy: str
160 confidence: float
161 reasoning: str
162 features: QueryFeatures | None = None
163 metadata: dict[str, Any] = field(default_factory=dict)
165 @property
166 def primary_source(self) -> DataSource | None:
167 """Get the primary (first) data source."""
168 return self.data_sources[0] if self.data_sources else None
170 @property
171 def is_confident(self) -> bool:
172 """Check if routing decision is confident (>0.7)."""
173 return self.confidence > 0.7
175 @property
176 def is_multimodal(self) -> bool:
177 """Check if routing involves multimodal sources."""
178 return any(
179 source.type == DataSourceType.MULTIMODAL_STORE
180 for source in self.data_sources
181 )
183 def to_dict(self) -> dict[str, Any]:
184 """Convert routing decision to dictionary.
186 Returns:
187 Dictionary representation of the routing decision.
188 """
189 return {
190 "query": self.query,
191 "data_sources": [
192 {
193 "name": source.name,
194 "type": source.type.value,
195 "description": source.description,
196 }
197 for source in self.data_sources
198 ],
199 "strategy": self.strategy,
200 "confidence": self.confidence,
201 "reasoning": self.reasoning,
202 "features": (
203 {
204 "intent": self.features.intent.value,
205 "language": self.features.language,
206 "domain": self.features.domain,
207 "modalities": [m.value for m in self.features.modalities],
208 }
209 if self.features
210 else None
211 ),
212 "metadata": self.metadata,
213 }