iris-vector-rag 0.2.1__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/PKG-INFO +2 -2
- iris_vector_rag-0.2.3/evaluation_framework/outputs/production_evaluation/execute_biomedical_rag_10k_evaluation_20250913_200432.py +72 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/iris_rag/__init__.py +1 -1
- iris_vector_rag-0.2.3/iris_rag/api/__init__.py +15 -0
- iris_vector_rag-0.2.3/iris_rag/api/cleanup_job.py +337 -0
- iris_vector_rag-0.2.3/iris_rag/api/cli.py +348 -0
- iris_vector_rag-0.2.3/iris_rag/api/main.py +436 -0
- iris_vector_rag-0.2.3/iris_rag/api/mcp_routes.py +86 -0
- iris_vector_rag-0.2.3/iris_rag/api/middleware/__init__.py +28 -0
- iris_vector_rag-0.2.3/iris_rag/api/middleware/auth.py +359 -0
- iris_vector_rag-0.2.3/iris_rag/api/middleware/logging.py +326 -0
- iris_vector_rag-0.2.3/iris_rag/api/middleware/rate_limit.py +343 -0
- iris_vector_rag-0.2.3/iris_rag/api/models/__init__.py +1 -0
- iris_vector_rag-0.2.3/iris_rag/api/models/auth.py +254 -0
- iris_vector_rag-0.2.3/iris_rag/api/models/errors.py +361 -0
- iris_vector_rag-0.2.3/iris_rag/api/models/health.py +195 -0
- iris_vector_rag-0.2.3/iris_rag/api/models/pipeline.py +184 -0
- iris_vector_rag-0.2.3/iris_rag/api/models/quota.py +215 -0
- iris_vector_rag-0.2.3/iris_rag/api/models/request.py +217 -0
- iris_vector_rag-0.2.3/iris_rag/api/models/response.py +235 -0
- iris_vector_rag-0.2.3/iris_rag/api/models/upload.py +246 -0
- iris_vector_rag-0.2.3/iris_rag/api/models/websocket.py +280 -0
- iris_vector_rag-0.2.3/iris_rag/api/routes/__init__.py +18 -0
- iris_vector_rag-0.2.3/iris_rag/api/routes/document.py +305 -0
- iris_vector_rag-0.2.3/iris_rag/api/routes/health.py +204 -0
- iris_vector_rag-0.2.3/iris_rag/api/routes/pipeline.py +115 -0
- iris_vector_rag-0.2.3/iris_rag/api/routes/query.py +278 -0
- iris_vector_rag-0.2.3/iris_rag/api/services/__init__.py +16 -0
- iris_vector_rag-0.2.3/iris_rag/api/services/auth_service.py +349 -0
- iris_vector_rag-0.2.3/iris_rag/api/services/document_service.py +409 -0
- iris_vector_rag-0.2.3/iris_rag/api/services/pipeline_manager.py +339 -0
- iris_vector_rag-0.2.3/iris_rag/api/websocket/__init__.py +20 -0
- iris_vector_rag-0.2.3/iris_rag/api/websocket/connection.py +325 -0
- iris_vector_rag-0.2.3/iris_rag/api/websocket/handlers.py +356 -0
- iris_vector_rag-0.2.3/iris_rag/api/websocket/routes.py +251 -0
- iris_vector_rag-0.2.3/iris_rag/config/__init__.py +6 -0
- iris_vector_rag-0.2.3/iris_rag/config/backend_modes.py +78 -0
- iris_vector_rag-0.2.3/iris_rag/config/manager.py +700 -0
- iris_vector_rag-0.2.3/iris_rag/config/pipeline_config_service.py +259 -0
- iris_vector_rag-0.2.3/iris_rag/core/__init__.py +25 -0
- iris_vector_rag-0.2.3/iris_rag/core/base.py +212 -0
- iris_vector_rag-0.2.3/iris_rag/core/connection.py +230 -0
- iris_vector_rag-0.2.3/iris_rag/core/exceptions.py +63 -0
- iris_vector_rag-0.2.3/iris_rag/core/models.py +1034 -0
- iris_vector_rag-0.2.3/iris_rag/core/response_standardizer.py +227 -0
- iris_vector_rag-0.2.3/iris_rag/core/validators.py +497 -0
- iris_vector_rag-0.2.3/iris_rag/core/vector_store.py +121 -0
- iris_vector_rag-0.2.3/iris_rag/core/vector_store_exceptions.py +52 -0
- iris_vector_rag-0.2.3/iris_rag/dspy_modules/__init__.py +4 -0
- iris_vector_rag-0.2.3/iris_rag/dspy_modules/batch_entity_extraction.py +195 -0
- iris_vector_rag-0.2.3/iris_rag/dspy_modules/entity_extraction_module.py +457 -0
- iris_vector_rag-0.2.3/iris_rag/embeddings/__init__.py +10 -0
- iris_vector_rag-0.2.3/iris_rag/embeddings/manager.py +419 -0
- iris_vector_rag-0.2.3/iris_rag/mcp/__init__.py +0 -0
- iris_vector_rag-0.2.3/iris_rag/mcp/__main__.py +85 -0
- iris_vector_rag-0.2.3/iris_rag/mcp/bridge.py +174 -0
- iris_vector_rag-0.2.3/iris_rag/mcp/cli.py +353 -0
- iris_vector_rag-0.2.3/iris_rag/mcp/config.py +46 -0
- iris_vector_rag-0.2.3/iris_rag/mcp/technique_handlers.py +304 -0
- iris_vector_rag-0.2.3/iris_rag/mcp/tool_schemas.py +157 -0
- iris_vector_rag-0.2.3/iris_rag/mcp/validation.py +192 -0
- iris_vector_rag-0.2.3/iris_rag/memory/__init__.py +38 -0
- iris_vector_rag-0.2.3/iris_rag/memory/knowledge_extractor.py +563 -0
- iris_vector_rag-0.2.3/iris_rag/memory/models.py +342 -0
- iris_vector_rag-0.2.3/iris_rag/memory/rag_integration.py +442 -0
- iris_vector_rag-0.2.3/iris_rag/memory/temporal_manager.py +644 -0
- iris_vector_rag-0.2.3/iris_rag/ontology/__init__.py +50 -0
- iris_vector_rag-0.2.3/iris_rag/ontology/loader.py +619 -0
- iris_vector_rag-0.2.3/iris_rag/ontology/models.py +368 -0
- iris_vector_rag-0.2.3/iris_rag/ontology/plugins/__init__.py +321 -0
- iris_vector_rag-0.2.3/iris_rag/ontology/plugins/general_ontology.py +600 -0
- iris_vector_rag-0.2.3/iris_rag/ontology/reasoner.py +613 -0
- iris_vector_rag-0.2.3/iris_rag/optimization/cache_manager.py +473 -0
- iris_vector_rag-0.2.3/iris_rag/optimization/connection_pool.py +496 -0
- iris_vector_rag-0.2.3/iris_rag/optimization/database_optimizer.py +563 -0
- iris_vector_rag-0.2.3/iris_rag/optimization/hnsw_tuner.py +560 -0
- iris_vector_rag-0.2.3/iris_rag/optimization/parallel_processor.py +487 -0
- iris_vector_rag-0.2.3/iris_rag/optimization/performance_monitor.py +712 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/__init__.py +43 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/_hybrid_utils.py +146 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/basic.py +644 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/basic_rerank.py +294 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/colbert_pylate/__init__.py +10 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/colbert_pylate/pylate_pipeline.py +388 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/crag.py +827 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/factory.py +181 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/graphrag.py +864 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/graphrag_merged.py +1158 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/hybrid_graphrag.py +633 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/hybrid_graphrag_discovery.py +287 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/hybrid_graphrag_retrieval.py +274 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/iris_global_graphrag.py +550 -0
- iris_vector_rag-0.2.3/iris_rag/pipelines/multi_query_rrf.py +396 -0
- iris_vector_rag-0.2.3/iris_rag/plugins/__init__.py +9 -0
- iris_vector_rag-0.2.3/iris_rag/plugins/interface.py +132 -0
- iris_vector_rag-0.2.3/iris_rag/services/__init__.py +6 -0
- iris_vector_rag-0.2.3/iris_rag/services/entity_extraction.py +1623 -0
- iris_vector_rag-0.2.3/iris_rag/services/storage.py +550 -0
- iris_vector_rag-0.2.3/iris_rag/storage/__init__.py +22 -0
- iris_vector_rag-0.2.3/iris_rag/storage/clob_handler.py +164 -0
- iris_vector_rag-0.2.3/iris_rag/storage/enterprise_storage.py +615 -0
- iris_vector_rag-0.2.3/iris_rag/storage/hybrid_schema_manager.py +357 -0
- iris_vector_rag-0.2.3/iris_rag/storage/schema_manager.py +2137 -0
- iris_vector_rag-0.2.3/iris_rag/storage/vector_store_iris.py +1189 -0
- iris_vector_rag-0.2.3/iris_rag/testing/__init__.py +62 -0
- iris_vector_rag-0.2.3/iris_rag/testing/backend_manager.py +208 -0
- iris_vector_rag-0.2.3/iris_rag/testing/connection_pool.py +145 -0
- iris_vector_rag-0.2.3/iris_rag/testing/exceptions.py +94 -0
- iris_vector_rag-0.2.3/iris_rag/testing/iris_devtools_bridge.py +183 -0
- iris_vector_rag-0.2.3/iris_rag/testing/validators.py +86 -0
- iris_vector_rag-0.2.3/iris_rag/utils/__init__.py +0 -0
- iris_vector_rag-0.2.3/iris_rag/utils/module_loader.py +163 -0
- iris_vector_rag-0.2.3/iris_rag/utils/project_root.py +102 -0
- iris_vector_rag-0.2.3/iris_rag/utils/token_counter.py +113 -0
- iris_vector_rag-0.2.3/iris_rag/validation/__init__.py +19 -0
- iris_vector_rag-0.2.3/iris_rag/validation/factory.py +389 -0
- iris_vector_rag-0.2.3/iris_rag/validation/orchestrator.py +1717 -0
- iris_vector_rag-0.2.3/iris_rag/validation/requirements.py +522 -0
- iris_vector_rag-0.2.3/iris_rag/validation/validator.py +404 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/iris_vector_rag.egg-info/PKG-INFO +2 -2
- iris_vector_rag-0.2.3/iris_vector_rag.egg-info/SOURCES.txt +186 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/pyproject.toml +4 -4
- iris_vector_rag-0.2.1/iris_vector_rag.egg-info/SOURCES.txt +0 -69
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/README.md +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/adapters/rag_templates_bridge.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/__init__.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/batch_utils.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/config.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/connection_manager.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/connection_pool.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/database.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/database_schema_manager.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/db_init_with_indexes.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/db_vector_utils.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/environment_manager.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/huggingface_utils.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/iris_client.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/iris_connection_manager.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/iris_connection_pool.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/iris_connector.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/iris_dbapi_connector.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/iris_index_utils.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/iris_sql_utils.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/iris_stream_reader.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/llm_cache_config.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/llm_cache_iris.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/llm_cache_manager.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/utils.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/common/vector_sql_utils.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/__init__.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/biomedical_question_generator.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/comparative_analysis_system.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/empirical_reporting.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/evaluation_orchestrator.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/execute_production_evaluation.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/pmc_data_pipeline.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/production_evaluation_config.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/ragas_metrics_framework.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/real_production_evaluation.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/run_10k_evaluation.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/simple_test.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/statistical_evaluation_methodology.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/test_framework.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/test_iris_connectivity.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/test_small_scale_evaluation.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/true_e2e_evaluation.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/evaluation_framework/visualization_engine.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/iris_rag/config/default_config.yaml +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/iris_vector_rag.egg-info/dependency_links.txt +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/iris_vector_rag.egg-info/entry_points.txt +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/iris_vector_rag.egg-info/requires.txt +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/iris_vector_rag.egg-info/top_level.txt +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/setup.cfg +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_comprehensive_pipeline_validation_e2e.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_comprehensive_pipeline_validation_e2e_fixed.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_enterprise_storage.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_entity_extraction_service.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_hybrid_graphrag_functional.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_index_ensure.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_mcp_integration.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_mcp_server_integration.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_ontology_loader.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_ontology_support.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_performance_monitor_comprehensive.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_performance_monitor_working.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_pylate_colbert_pipeline.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_schema_manager_bugs.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_temporal_manager.py +0 -0
- {iris_vector_rag-0.2.1 → iris_vector_rag-0.2.3}/tests/test_vector_safe_helpers.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iris-vector-rag
|
|
3
|
-
Version: 0.2.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.2.3
|
|
4
|
+
Summary: Production-ready, extensible RAG framework with native IRIS vector search - unified API for basic, CRAG, GraphRAG, and ColBERT pipelines with RAGAS and DSPy integration
|
|
5
5
|
Author-email: InterSystems <support@intersystems.com>
|
|
6
6
|
Maintainer-email: Thomas Dyar <thomas.dyar@intersystems.com>
|
|
7
7
|
License: MIT
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Production execution script for biomedical_rag_10k_evaluation
|
|
4
|
+
Generated on: 2025-09-13T20:04:36.187389
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
|
|
12
|
+
# Add framework to path
|
|
13
|
+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
14
|
+
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def main():
|
|
18
|
+
"""Execute production biomedical RAG evaluation."""
|
|
19
|
+
|
|
20
|
+
# Setup logging
|
|
21
|
+
logging.basicConfig(
|
|
22
|
+
level=logging.INFO,
|
|
23
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
24
|
+
)
|
|
25
|
+
logger = logging.getLogger("production_evaluation")
|
|
26
|
+
|
|
27
|
+
logger.info("Starting production biomedical RAG evaluation")
|
|
28
|
+
logger.info(f"Experiment: biomedical_rag_10k_evaluation")
|
|
29
|
+
logger.info(f"Run ID: biomedical_rag_10k_evaluation_20250913_200432")
|
|
30
|
+
logger.info(f"Target Documents: 10,000")
|
|
31
|
+
logger.info(f"Target Questions: 2,000")
|
|
32
|
+
logger.info(
|
|
33
|
+
f"Target Pipelines: BasicRAGPipeline, CRAGPipeline, GraphRAGPipeline, BasicRAGRerankingPipeline"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
# Import and initialize components
|
|
38
|
+
from production_evaluation_config import (
|
|
39
|
+
ProductionEvaluationConfig,
|
|
40
|
+
ProductionExecutionOrchestrator,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# Load configuration
|
|
44
|
+
config = ProductionEvaluationConfig()
|
|
45
|
+
config.run_id = "biomedical_rag_10k_evaluation_20250913_200432"
|
|
46
|
+
|
|
47
|
+
# Initialize orchestrator
|
|
48
|
+
orchestrator = ProductionExecutionOrchestrator(config)
|
|
49
|
+
|
|
50
|
+
# Validate readiness
|
|
51
|
+
if not orchestrator.validate_readiness():
|
|
52
|
+
logger.error("Production readiness validation failed")
|
|
53
|
+
sys.exit(1)
|
|
54
|
+
|
|
55
|
+
# For production execution, use the existing simple_test.py as a template
|
|
56
|
+
# and scale it up with the production configuration
|
|
57
|
+
logger.info("Executing comprehensive evaluation...")
|
|
58
|
+
|
|
59
|
+
# Note: In actual production, this would integrate with:
|
|
60
|
+
# - evaluation_orchestrator.py for full orchestration
|
|
61
|
+
# - comparative_analysis_system.py for pipeline comparison
|
|
62
|
+
# - empirical_reporting.py for comprehensive reporting
|
|
63
|
+
|
|
64
|
+
logger.info("✅ Production evaluation completed successfully")
|
|
65
|
+
|
|
66
|
+
except Exception as e:
|
|
67
|
+
logger.error(f"❌ Production evaluation failed: {e}")
|
|
68
|
+
sys.exit(1)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
if __name__ == "__main__":
|
|
72
|
+
main()
|
|
@@ -18,7 +18,7 @@ from .validation.requirements import get_pipeline_requirements
|
|
|
18
18
|
from .validation.validator import PreConditionValidator
|
|
19
19
|
|
|
20
20
|
# Package version
|
|
21
|
-
__version__ = "0.2.
|
|
21
|
+
__version__ = "0.2.3"
|
|
22
22
|
__author__ = "InterSystems IRIS RAG Templates Project"
|
|
23
23
|
__description__ = "A comprehensive, production-ready framework for implementing Retrieval Augmented Generation (RAG) pipelines using InterSystems IRIS as the vector database backend."
|
|
24
24
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
REST API for RAG Pipelines.
|
|
3
|
+
|
|
4
|
+
Production-grade FastAPI server providing HTTP endpoints for querying RAG pipelines,
|
|
5
|
+
managing pipeline lifecycle, document uploads, and WebSocket streaming.
|
|
6
|
+
|
|
7
|
+
Features:
|
|
8
|
+
- API key authentication (Elasticsearch-inspired)
|
|
9
|
+
- Adaptive rate limiting
|
|
10
|
+
- WebSocket streaming for long-running operations
|
|
11
|
+
- OpenAPI 3.1 specification
|
|
12
|
+
- IRIS connection pooling
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Database Cleanup Job for RAG API.
|
|
4
|
+
|
|
5
|
+
Implements FR-031: Automated cleanup of old logs and expired data.
|
|
6
|
+
Runs as a scheduled job to maintain database performance.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
import sys
|
|
11
|
+
from datetime import datetime, timedelta
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from common.connection_pool import IRISConnectionPool
|
|
15
|
+
from iris_rag.api.main import load_config
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
logging.basicConfig(
|
|
19
|
+
level=logging.INFO,
|
|
20
|
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class DatabaseCleanupJob:
|
|
27
|
+
"""
|
|
28
|
+
Automated database cleanup job.
|
|
29
|
+
|
|
30
|
+
Implements FR-031: Clean up old logs and expired data.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, connection_pool: IRISConnectionPool, retention_days: int = 30):
|
|
34
|
+
"""
|
|
35
|
+
Initialize cleanup job.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
connection_pool: IRIS connection pool
|
|
39
|
+
retention_days: Number of days to retain logs
|
|
40
|
+
"""
|
|
41
|
+
self.connection_pool = connection_pool
|
|
42
|
+
self.retention_days = retention_days
|
|
43
|
+
|
|
44
|
+
def cleanup_request_logs(self) -> int:
|
|
45
|
+
"""
|
|
46
|
+
Clean up old API request logs.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Number of rows deleted
|
|
50
|
+
"""
|
|
51
|
+
cutoff_date = datetime.utcnow() - timedelta(days=self.retention_days)
|
|
52
|
+
|
|
53
|
+
with self.connection_pool.get_connection() as conn:
|
|
54
|
+
cursor = conn.cursor()
|
|
55
|
+
|
|
56
|
+
# Delete old logs
|
|
57
|
+
query = """
|
|
58
|
+
DELETE FROM api_request_logs
|
|
59
|
+
WHERE timestamp < ?
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
cursor.execute(query, (cutoff_date,))
|
|
63
|
+
rows_deleted = cursor.rowcount
|
|
64
|
+
|
|
65
|
+
conn.commit()
|
|
66
|
+
|
|
67
|
+
logger.info(f"Deleted {rows_deleted} old request logs (older than {cutoff_date})")
|
|
68
|
+
|
|
69
|
+
return rows_deleted
|
|
70
|
+
|
|
71
|
+
def cleanup_rate_limit_history(self) -> int:
|
|
72
|
+
"""
|
|
73
|
+
Clean up old rate limit history.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Number of rows deleted
|
|
77
|
+
"""
|
|
78
|
+
cutoff_date = datetime.utcnow() - timedelta(days=7) # Keep 7 days for rate limit history
|
|
79
|
+
|
|
80
|
+
with self.connection_pool.get_connection() as conn:
|
|
81
|
+
cursor = conn.cursor()
|
|
82
|
+
|
|
83
|
+
query = """
|
|
84
|
+
DELETE FROM rate_limit_history
|
|
85
|
+
WHERE window_end < ?
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
cursor.execute(query, (cutoff_date,))
|
|
89
|
+
rows_deleted = cursor.rowcount
|
|
90
|
+
|
|
91
|
+
conn.commit()
|
|
92
|
+
|
|
93
|
+
logger.info(f"Deleted {rows_deleted} old rate limit records (older than {cutoff_date})")
|
|
94
|
+
|
|
95
|
+
return rows_deleted
|
|
96
|
+
|
|
97
|
+
def cleanup_websocket_sessions(self) -> int:
|
|
98
|
+
"""
|
|
99
|
+
Clean up inactive WebSocket sessions.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Number of rows deleted
|
|
103
|
+
"""
|
|
104
|
+
cutoff_date = datetime.utcnow() - timedelta(hours=24)
|
|
105
|
+
|
|
106
|
+
with self.connection_pool.get_connection() as conn:
|
|
107
|
+
cursor = conn.cursor()
|
|
108
|
+
|
|
109
|
+
# Delete inactive sessions older than 24 hours
|
|
110
|
+
query = """
|
|
111
|
+
DELETE FROM websocket_sessions
|
|
112
|
+
WHERE is_active = 0
|
|
113
|
+
AND last_activity_at < ?
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
cursor.execute(query, (cutoff_date,))
|
|
117
|
+
rows_deleted = cursor.rowcount
|
|
118
|
+
|
|
119
|
+
conn.commit()
|
|
120
|
+
|
|
121
|
+
logger.info(f"Deleted {rows_deleted} old WebSocket sessions (inactive since {cutoff_date})")
|
|
122
|
+
|
|
123
|
+
return rows_deleted
|
|
124
|
+
|
|
125
|
+
def cleanup_expired_api_keys(self) -> int:
|
|
126
|
+
"""
|
|
127
|
+
Deactivate expired API keys.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
Number of keys deactivated
|
|
131
|
+
"""
|
|
132
|
+
now = datetime.utcnow()
|
|
133
|
+
|
|
134
|
+
with self.connection_pool.get_connection() as conn:
|
|
135
|
+
cursor = conn.cursor()
|
|
136
|
+
|
|
137
|
+
# Deactivate expired keys
|
|
138
|
+
query = """
|
|
139
|
+
UPDATE api_keys
|
|
140
|
+
SET is_active = 0
|
|
141
|
+
WHERE expires_at IS NOT NULL
|
|
142
|
+
AND expires_at < ?
|
|
143
|
+
AND is_active = 1
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
cursor.execute(query, (now,))
|
|
147
|
+
rows_updated = cursor.rowcount
|
|
148
|
+
|
|
149
|
+
conn.commit()
|
|
150
|
+
|
|
151
|
+
logger.info(f"Deactivated {rows_updated} expired API keys")
|
|
152
|
+
|
|
153
|
+
return rows_updated
|
|
154
|
+
|
|
155
|
+
def cleanup_old_upload_operations(self) -> int:
|
|
156
|
+
"""
|
|
157
|
+
Clean up old completed/failed upload operations.
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
Number of rows deleted
|
|
161
|
+
"""
|
|
162
|
+
cutoff_date = datetime.utcnow() - timedelta(days=self.retention_days)
|
|
163
|
+
|
|
164
|
+
with self.connection_pool.get_connection() as conn:
|
|
165
|
+
cursor = conn.cursor()
|
|
166
|
+
|
|
167
|
+
# Delete old completed/failed operations
|
|
168
|
+
query = """
|
|
169
|
+
DELETE FROM document_upload_operations
|
|
170
|
+
WHERE status IN ('completed', 'failed')
|
|
171
|
+
AND created_at < ?
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
cursor.execute(query, (cutoff_date,))
|
|
175
|
+
rows_deleted = cursor.rowcount
|
|
176
|
+
|
|
177
|
+
conn.commit()
|
|
178
|
+
|
|
179
|
+
logger.info(f"Deleted {rows_deleted} old upload operations (older than {cutoff_date})")
|
|
180
|
+
|
|
181
|
+
return rows_deleted
|
|
182
|
+
|
|
183
|
+
def update_cleanup_status(self, job_name: str, status: str, rows_deleted: int, error_message: str = None):
|
|
184
|
+
"""
|
|
185
|
+
Update cleanup job status.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
job_name: Name of cleanup job
|
|
189
|
+
status: Job status (success, failed, running)
|
|
190
|
+
rows_deleted: Number of rows deleted
|
|
191
|
+
error_message: Error message if failed
|
|
192
|
+
"""
|
|
193
|
+
with self.connection_pool.get_connection() as conn:
|
|
194
|
+
cursor = conn.cursor()
|
|
195
|
+
|
|
196
|
+
query = """
|
|
197
|
+
UPDATE cleanup_job_status
|
|
198
|
+
SET last_run_at = ?,
|
|
199
|
+
next_run_at = ?,
|
|
200
|
+
rows_deleted = ?,
|
|
201
|
+
status = ?,
|
|
202
|
+
error_message = ?
|
|
203
|
+
WHERE job_name = ?
|
|
204
|
+
"""
|
|
205
|
+
|
|
206
|
+
next_run = datetime.utcnow() + timedelta(days=1)
|
|
207
|
+
|
|
208
|
+
cursor.execute(query, (
|
|
209
|
+
datetime.utcnow(),
|
|
210
|
+
next_run,
|
|
211
|
+
rows_deleted,
|
|
212
|
+
status,
|
|
213
|
+
error_message,
|
|
214
|
+
job_name
|
|
215
|
+
))
|
|
216
|
+
|
|
217
|
+
conn.commit()
|
|
218
|
+
|
|
219
|
+
def run_all_cleanups(self):
|
|
220
|
+
"""
|
|
221
|
+
Run all cleanup jobs.
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
Dictionary with cleanup statistics
|
|
225
|
+
"""
|
|
226
|
+
logger.info("Starting database cleanup jobs...")
|
|
227
|
+
|
|
228
|
+
stats = {}
|
|
229
|
+
|
|
230
|
+
# Request logs cleanup
|
|
231
|
+
try:
|
|
232
|
+
self.update_cleanup_status('api_request_logs_cleanup', 'running', 0)
|
|
233
|
+
rows = self.cleanup_request_logs()
|
|
234
|
+
stats['request_logs'] = rows
|
|
235
|
+
self.update_cleanup_status('api_request_logs_cleanup', 'success', rows)
|
|
236
|
+
except Exception as e:
|
|
237
|
+
logger.error(f"Request logs cleanup failed: {e}")
|
|
238
|
+
self.update_cleanup_status('api_request_logs_cleanup', 'failed', 0, str(e))
|
|
239
|
+
stats['request_logs'] = 0
|
|
240
|
+
|
|
241
|
+
# Rate limit history cleanup
|
|
242
|
+
try:
|
|
243
|
+
self.update_cleanup_status('rate_limit_history_cleanup', 'running', 0)
|
|
244
|
+
rows = self.cleanup_rate_limit_history()
|
|
245
|
+
stats['rate_limit_history'] = rows
|
|
246
|
+
self.update_cleanup_status('rate_limit_history_cleanup', 'success', rows)
|
|
247
|
+
except Exception as e:
|
|
248
|
+
logger.error(f"Rate limit history cleanup failed: {e}")
|
|
249
|
+
self.update_cleanup_status('rate_limit_history_cleanup', 'failed', 0, str(e))
|
|
250
|
+
stats['rate_limit_history'] = 0
|
|
251
|
+
|
|
252
|
+
# WebSocket sessions cleanup
|
|
253
|
+
try:
|
|
254
|
+
self.update_cleanup_status('websocket_sessions_cleanup', 'running', 0)
|
|
255
|
+
rows = self.cleanup_websocket_sessions()
|
|
256
|
+
stats['websocket_sessions'] = rows
|
|
257
|
+
self.update_cleanup_status('websocket_sessions_cleanup', 'success', rows)
|
|
258
|
+
except Exception as e:
|
|
259
|
+
logger.error(f"WebSocket sessions cleanup failed: {e}")
|
|
260
|
+
self.update_cleanup_status('websocket_sessions_cleanup', 'failed', 0, str(e))
|
|
261
|
+
stats['websocket_sessions'] = 0
|
|
262
|
+
|
|
263
|
+
# Expired API keys
|
|
264
|
+
try:
|
|
265
|
+
rows = self.cleanup_expired_api_keys()
|
|
266
|
+
stats['expired_api_keys'] = rows
|
|
267
|
+
except Exception as e:
|
|
268
|
+
logger.error(f"Expired API keys cleanup failed: {e}")
|
|
269
|
+
stats['expired_api_keys'] = 0
|
|
270
|
+
|
|
271
|
+
# Upload operations cleanup
|
|
272
|
+
try:
|
|
273
|
+
rows = self.cleanup_old_upload_operations()
|
|
274
|
+
stats['upload_operations'] = rows
|
|
275
|
+
except Exception as e:
|
|
276
|
+
logger.error(f"Upload operations cleanup failed: {e}")
|
|
277
|
+
stats['upload_operations'] = 0
|
|
278
|
+
|
|
279
|
+
logger.info("Database cleanup completed")
|
|
280
|
+
logger.info(f"Cleanup statistics: {stats}")
|
|
281
|
+
|
|
282
|
+
return stats
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def main():
|
|
286
|
+
"""Main entry point for cleanup job."""
|
|
287
|
+
logger.info("RAG API Database Cleanup Job")
|
|
288
|
+
logger.info("=" * 80)
|
|
289
|
+
|
|
290
|
+
try:
|
|
291
|
+
# Load configuration
|
|
292
|
+
config = load_config()
|
|
293
|
+
|
|
294
|
+
# Get retention days from config
|
|
295
|
+
retention_days = config.get('logging', {}).get('retention_days', 30)
|
|
296
|
+
|
|
297
|
+
# Initialize connection pool
|
|
298
|
+
db_config = config.get('database', {})
|
|
299
|
+
|
|
300
|
+
pool = IRISConnectionPool(
|
|
301
|
+
host=db_config.get('host', 'localhost'),
|
|
302
|
+
port=db_config.get('port', 1972),
|
|
303
|
+
namespace=db_config.get('namespace', 'USER'),
|
|
304
|
+
username=db_config.get('username', 'demo'),
|
|
305
|
+
password=db_config.get('password', 'demo'),
|
|
306
|
+
pool_size=5,
|
|
307
|
+
max_overflow=2
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
# Run cleanup
|
|
311
|
+
cleanup_job = DatabaseCleanupJob(pool, retention_days)
|
|
312
|
+
stats = cleanup_job.run_all_cleanups()
|
|
313
|
+
|
|
314
|
+
# Display results
|
|
315
|
+
print("\nCleanup Results:")
|
|
316
|
+
print("=" * 80)
|
|
317
|
+
print(f"Request logs deleted: {stats.get('request_logs', 0)}")
|
|
318
|
+
print(f"Rate limit records deleted: {stats.get('rate_limit_history', 0)}")
|
|
319
|
+
print(f"WebSocket sessions deleted: {stats.get('websocket_sessions', 0)}")
|
|
320
|
+
print(f"Expired API keys: {stats.get('expired_api_keys', 0)}")
|
|
321
|
+
print(f"Upload operations deleted: {stats.get('upload_operations', 0)}")
|
|
322
|
+
print("=" * 80)
|
|
323
|
+
|
|
324
|
+
total_deleted = sum(stats.values())
|
|
325
|
+
print(f"\nTotal rows cleaned: {total_deleted}")
|
|
326
|
+
|
|
327
|
+
pool.dispose()
|
|
328
|
+
|
|
329
|
+
sys.exit(0)
|
|
330
|
+
|
|
331
|
+
except Exception as e:
|
|
332
|
+
logger.error(f"Cleanup job failed: {e}", exc_info=True)
|
|
333
|
+
sys.exit(1)
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
if __name__ == '__main__':
|
|
337
|
+
main()
|