Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-rag/src/lexigram/ai/rag/config.py: 98%
150 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
1from __future__ import annotations
3from dataclasses import dataclass
4from enum import StrEnum
5from typing import Any, ClassVar, cast
7from lexigram.ai.rag.constants import ENV_NESTED_DELIMITER, ENV_PREFIX
8from lexigram.ai.rag.synthesis.types import SynthesisConfig
9from lexigram.config.base import BaseConfig
10from lexigram.domain.models import DomainModel
11from lexigram.validation import ConfigDict, Field
14@dataclass(init=False)
15class RAGTenancyConfig(DomainModel):
16 """Optional tenant-aware RAG pipeline configuration.
18 When enabled, the RAG provider wraps the ``RAGPipelineProtocol`` binding
19 in a ``TenantScopedRAGPipeline`` that resolves the ``collection_name``
20 from the current tenant context at request time, with per-tenant
21 pipeline instance caching.
23 Note:
24 Requires ``lexigram-tenancy`` in the module graph when ``enabled``
25 is ``True`` — the provider resolves ``Context`` at boot.
26 """
28 enabled: bool = Field(
29 default=False,
30 description="Enable tenant-aware collection resolution in RAG pipeline",
31 )
34class RAGConfig(BaseConfig):
35 """Configuration for RAG (Retrieval Augmented Generation) pipeline.
37 Example:
38 >>> config = RAGConfig(
39 ... vector_store_type="chroma",
40 ... collection_name="pet_knowledge",
41 ... top_k=5,
42 ... enable_citations=True
43 ... )
44 """
46 config_section: ClassVar[str] = "ai_rag"
48 def with_collection(self, name: str) -> RAGConfig:
49 """Return a copy of this config with a different *collection_name*.
51 Usage::
53 tenant_config = base_config.with_collection("canon_t_tenant42")
54 """
55 return self.model_copy(update={"collection_name": name})
57 model_config: ClassVar[ConfigDict] = cast(
58 "ConfigDict",
59 {
60 "env_prefix": ENV_PREFIX,
61 "env_nested_delimiter": ENV_NESTED_DELIMITER,
62 "extra": "ignore",
63 },
64 )
66 # Feature toggle
67 enabled: bool = Field(
68 default=True,
69 description="Enable the RAG pipeline",
70 )
72 # Local persistence (for Chroma and similar file-based stores)
73 persist_directory: str | None = Field(
74 default=None,
75 description="Local directory path for vector store persistence (e.g. Chroma)",
76 )
78 # Vector Store
79 vector_store_type: str = Field(
80 default="pgvector",
81 description="Vector store backend (pgvector, chroma, qdrant, mock)",
82 )
83 vector_dimension: int = Field(
84 default=1536,
85 ge=1,
86 description="Embedding vector dimension (1536 for OpenAI ada-002)",
87 )
88 collection_name: str = Field(
89 default="default",
90 description="Collection/index name for vector store",
91 )
93 # Retrieval
94 top_k: int = Field(
95 default=5,
96 ge=1,
97 description="Number of documents to retrieve",
98 )
99 similarity_threshold: float = Field(
100 default=0.7,
101 ge=0.0,
102 le=1.0,
103 description="Minimum similarity score threshold",
104 )
105 use_hybrid_search: bool = Field(
106 default=True,
107 description="Enable hybrid search (semantic + keyword)",
108 )
110 # Embedding Model
111 embedding_provider: str = Field(
112 default="openai",
113 description="Embedding provider (openai, cohere, etc.)",
114 )
115 embedding_model: str | None = Field(
116 default=None,
117 description="Embedding model identifier. Must be set explicitly — no vendor-specific default.",
118 )
120 # Citations
121 enable_citations: bool = Field(
122 default=True,
123 description="Include source citations in responses",
124 )
125 citation_style: str = Field(
126 default="inline",
127 description="Citation style (inline, footnote, numbered)",
128 )
129 min_citation_confidence: float = Field(
130 default=0.6,
131 ge=0.0,
132 le=1.0,
133 description="Minimum confidence for citation inclusion",
134 )
136 # Chunking
137 chunk_size: int = Field(
138 default=512,
139 ge=1,
140 description="Text chunk size in tokens",
141 )
142 chunk_overlap: int = Field(
143 default=50,
144 ge=0,
145 description="Overlap between consecutive chunks",
146 )
147 chunking_strategy: str = Field(
148 default="recursive",
149 description="Chunking strategy (recursive, semantic, token)",
150 )
152 # Query Enhancement
153 enable_query_expansion: bool = Field(
154 default=True,
155 description="Enable query expansion techniques",
156 )
157 enable_hyde: bool = Field(
158 default=False,
159 description="Enable HyDE (Hypothetical Document Embeddings)",
160 )
162 # Response Synthesis
163 synthesis_strategy: str = Field(
164 default="hybrid",
165 description="Synthesis strategy (direct, extractive, abstractive, hybrid)",
166 )
167 enable_hallucination_detection: bool = Field(
168 default=True,
169 description="Enable hallucination detection for AI responses",
170 )
172 # Cache
173 enable_caching: bool = Field(
174 default=True,
175 description="Enable caching for RAG queries",
176 )
177 cache_ttl: int = Field(
178 default=3600,
179 ge=0,
180 description="Cache TTL in seconds (default: 1 hour)",
181 )
183 # Tenancy
184 tenancy: RAGTenancyConfig = Field(
185 default_factory=RAGTenancyConfig,
186 description="Optional tenant-aware RAG pipeline configuration",
187 )
190class PipelineStageType(StrEnum):
191 """Types of stages in a RAG pipeline."""
193 INGESTION = "ingestion"
194 QUERY_PROCESSING = "query_processing"
195 RETRIEVAL = "retrieval"
196 CONTEXT_OPTIMIZATION = "context_optimization"
197 SYNTHESIS = "synthesis"
198 QUALITY_ASSURANCE = "quality_assurance"
199 POST_PROCESSING = "post_processing"
202class DocumentFormat(StrEnum):
203 """Supported document formats for ingestion."""
205 TEXT = "text"
206 PDF = "pdf"
207 MARKDOWN = "markdown"
208 HTML = "html"
211class RoutingStrategyType(StrEnum):
212 """Routing strategy types."""
214 RULE_BASED = "rule_based"
215 SEMANTIC = "semantic"
216 LLM = "llm"
217 HYBRID = "hybrid"
220class IngestionConfig(BaseConfig):
221 """Configuration for document ingestion stage."""
223 model_config: ClassVar[ConfigDict] = ConfigDict(extra="ignore")
225 enabled: bool = Field(default=True)
226 document_formats: list[DocumentFormat] = Field(
227 default_factory=lambda: [
228 DocumentFormat.TEXT,
229 DocumentFormat.PDF,
230 DocumentFormat.MARKDOWN,
231 ],
232 )
233 preprocessing_enabled: bool = Field(default=False)
234 ocr_enabled: bool = Field(default=False)
235 table_extraction_enabled: bool = Field(default=False)
236 metadata_enrichment_enabled: bool = Field(default=False)
237 chunking_strategy: str = Field(default="recursive")
238 chunk_size: int = Field(default=1000)
239 chunk_overlap: int = Field(default=200)
240 min_chunk_size: int = Field(default=100)
241 error_strategy: str = Field(default="graceful")
242 fail_fast: bool = Field(default=False)
245class QueryProcessingConfig(BaseConfig):
246 """Configuration for query processing stage."""
248 model_config: ClassVar[ConfigDict] = ConfigDict(extra="ignore")
250 enabled: bool = Field(default=True)
251 transformation_enabled: bool = Field(default=False)
252 transformation_strategies: list[str] = Field(default_factory=lambda: ["expansion"])
253 hyde_enabled: bool = Field(default=False)
254 hyde_num_documents: int = Field(default=1)
255 routing_enabled: bool = Field(default=False)
256 routing_strategy: RoutingStrategyType = Field(
257 default=RoutingStrategyType.RULE_BASED
258 )
259 error_strategy: str = Field(default="graceful")
262class RetrievalConfig(BaseConfig):
263 """Configuration for retrieval stage."""
265 model_config: ClassVar[ConfigDict] = ConfigDict(extra="ignore")
267 enabled: bool = Field(default=True)
268 strategy: str = Field(default="hybrid")
269 vector_search_enabled: bool = Field(default=True)
270 top_k: int = Field(default=10)
271 similarity_threshold: float = Field(default=0.0)
272 knowledge_graph_enabled: bool = Field(default=False)
273 max_graph_depth: int = Field(default=2)
274 multi_hop_enabled: bool = Field(default=False)
275 max_hops: int = Field(default=3)
276 error_strategy: str = Field(default="fail_fast")
279class ContextOptimizationConfig(BaseConfig):
280 """Configuration for context optimization stage."""
282 model_config: ClassVar[ConfigDict] = ConfigDict(extra="ignore")
284 enabled: bool = Field(default=True)
285 strategy: str = Field(default="cross-encoder")
286 top_k: int = Field(default=5)
287 ranking_enabled: bool = Field(default=True)
288 compression_enabled: bool = Field(default=False)
289 compression_strategy: str = Field(default="hybrid")
290 max_context_tokens: int = Field(default=4000)
291 deduplication_enabled: bool = Field(default=True)
292 deduplication_threshold: float = Field(default=0.9)
293 citations_enabled: bool = Field(default=True)
294 error_strategy: str = Field(default="graceful")
297class QualityAssuranceConfig(BaseConfig):
298 """Configuration for quality assurance stage."""
300 model_config: ClassVar[ConfigDict] = ConfigDict(extra="ignore")
302 enabled: bool = Field(default=True)
303 min_faithfulness: float = Field(default=0.7)
304 min_relevance: float = Field(default=0.6)
305 min_confidence: float = Field(default=0.5)
306 hallucination_detection_enabled: bool = Field(default=True)
307 hallucination_strict_mode: bool = Field(default=False)
308 reject_low_quality: bool = Field(default=False)
309 warn_low_quality: bool = Field(default=True)
310 error_strategy: str = Field(default="graceful")
313class PostProcessingConfig(BaseConfig):
314 """Configuration for post-processing stage."""
316 model_config: ClassVar[ConfigDict] = ConfigDict(extra="ignore")
318 enabled: bool = Field(default=True)
319 cache_enabled: bool = Field(default=True)
320 cache_results: bool = Field(default=True)
321 collect_metrics: bool = Field(default=True)
322 detailed_logging: bool = Field(default=False)
323 error_strategy: str = Field(default="skip")
326class PipelineConfig(BaseConfig):
327 """Complete pipeline configuration."""
329 model_config: ClassVar[ConfigDict] = ConfigDict(extra="ignore")
331 name: str = Field(default="default-rag-pipeline")
332 description: str = Field(default="")
333 ingestion: IngestionConfig = Field(default_factory=IngestionConfig)
334 query_processing: QueryProcessingConfig = Field(
335 default_factory=QueryProcessingConfig
336 )
337 retrieval: RetrievalConfig = Field(default_factory=RetrievalConfig)
338 context_optimization: ContextOptimizationConfig = Field(
339 default_factory=ContextOptimizationConfig
340 )
341 synthesis: SynthesisConfig = Field(default_factory=SynthesisConfig)
342 quality_assurance: QualityAssuranceConfig = Field(
343 default_factory=QualityAssuranceConfig
344 )
345 post_processing: PostProcessingConfig = Field(default_factory=PostProcessingConfig)
347 stages: list[PipelineStageType] = Field(
348 default_factory=lambda: [
349 PipelineStageType.RETRIEVAL,
350 PipelineStageType.SYNTHESIS,
351 PipelineStageType.QUALITY_ASSURANCE,
352 ],
353 description="Ordered list of pipeline stages to execute",
354 )
356 max_retries: int = Field(default=3)
357 retry_delay: float = Field(default=1.0)
358 default_error_strategy: str = Field(default="graceful")
359 metadata: dict[str, Any] = Field(default_factory=dict)
361 # Auto-evaluation hook (P7.1)
362 auto_evaluate_every_n: int | None = Field(
363 default=None,
364 description="Run automatic evaluation every N pipeline requests. None disables auto-evaluation.",
365 )
367 # Citation enforcement (P7.2)
368 require_citations: bool = Field(
369 default=False,
370 description="Raise MissingCitationsError when the synthesis result contains no citations.",
371 )
373 @classmethod
374 def from_dict(cls, config_dict: dict[str, Any]) -> PipelineConfig:
375 """Create configuration from dictionary."""
376 return cls(**config_dict)
378 def to_dict(self) -> dict[str, Any]:
379 """Convert configuration to dictionary."""
380 return {
381 "name": self.name,
382 "description": self.description,
383 "max_retries": self.max_retries,
384 "retry_delay": self.retry_delay,
385 "default_error_strategy": self.default_error_strategy,
386 "metadata": self.metadata,
387 }
390__all__ = [
391 "ContextOptimizationConfig",
392 "DocumentFormat",
393 "IngestionConfig",
394 "PipelineConfig",
395 "PipelineStageType",
396 "PostProcessingConfig",
397 "QualityAssuranceConfig",
398 "QueryProcessingConfig",
399 "RAGConfig",
400 "RAGTenancyConfig",
401 "RetrievalConfig",
402 "RoutingStrategyType",
403 "SynthesisConfig",
404]