iris-vector-rag 0.6.0__tar.gz → 0.7.0__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.
Files changed (202) hide show
  1. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/PKG-INFO +1 -1
  2. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/__init__.py +1 -1
  3. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/hybrid_graphrag.py +145 -5
  4. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag.egg-info/PKG-INFO +1 -1
  5. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag.egg-info/SOURCES.txt +1 -0
  6. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/pyproject.toml +1 -1
  7. iris_vector_rag-0.7.0/tests/test_attach_corpus.py +362 -0
  8. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/LICENSE +0 -0
  9. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/README.md +0 -0
  10. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/adapters/rag_templates_bridge.py +0 -0
  11. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/__init__.py +0 -0
  12. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/cleanup_job.py +0 -0
  13. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/cli.py +0 -0
  14. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/main.py +0 -0
  15. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/mcp_routes.py +0 -0
  16. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/middleware/__init__.py +0 -0
  17. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/middleware/auth.py +0 -0
  18. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/middleware/logging.py +0 -0
  19. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/middleware/rate_limit.py +0 -0
  20. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/models/__init__.py +0 -0
  21. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/models/auth.py +0 -0
  22. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/models/errors.py +0 -0
  23. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/models/health.py +0 -0
  24. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/models/pipeline.py +0 -0
  25. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/models/quota.py +0 -0
  26. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/models/request.py +0 -0
  27. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/models/response.py +0 -0
  28. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/models/upload.py +0 -0
  29. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/models/websocket.py +0 -0
  30. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/routes/__init__.py +0 -0
  31. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/routes/document.py +0 -0
  32. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/routes/health.py +0 -0
  33. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/routes/pipeline.py +0 -0
  34. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/routes/query.py +0 -0
  35. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/services/__init__.py +0 -0
  36. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/services/auth_service.py +0 -0
  37. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/services/document_service.py +0 -0
  38. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/services/pipeline_manager.py +0 -0
  39. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/websocket/__init__.py +0 -0
  40. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/websocket/connection.py +0 -0
  41. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/websocket/handlers.py +0 -0
  42. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/api/websocket/routes.py +0 -0
  43. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/__init__.py +0 -0
  44. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/batch_utils.py +0 -0
  45. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/config.py +0 -0
  46. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/connection_manager.py +0 -0
  47. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/connection_pool.py +0 -0
  48. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/database.py +0 -0
  49. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/database_schema_manager.py +0 -0
  50. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/db_init_with_indexes.py +0 -0
  51. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/db_vector_utils.py +0 -0
  52. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/environment_manager.py +0 -0
  53. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/exceptions.py +0 -0
  54. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/huggingface_utils.py +0 -0
  55. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/iris_client.py +0 -0
  56. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/iris_connection.py +0 -0
  57. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/iris_connection_manager.py +0 -0
  58. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/iris_connection_pool.py +0 -0
  59. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/iris_connector.py +0 -0
  60. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/iris_dbapi_connector.py +0 -0
  61. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/iris_globals.py +0 -0
  62. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/iris_index_utils.py +0 -0
  63. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/iris_sql_utils.py +0 -0
  64. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/iris_stream_reader.py +0 -0
  65. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/llm_cache_config.py +0 -0
  66. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/llm_cache_disk.py +0 -0
  67. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/llm_cache_iris.py +0 -0
  68. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/llm_cache_manager.py +0 -0
  69. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/utils.py +0 -0
  70. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/common/vector_sql_utils.py +0 -0
  71. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/config/__init__.py +0 -0
  72. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/config/backend_modes.py +0 -0
  73. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/config/config_manager.py +0 -0
  74. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/config/default_config.yaml +0 -0
  75. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/config/embedding_config.py +0 -0
  76. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/config/entities.py +0 -0
  77. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/config/manager.py +0 -0
  78. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/config/pipeline_config_service.py +0 -0
  79. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/config/validators.py +0 -0
  80. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/core/__init__.py +0 -0
  81. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/core/base.py +0 -0
  82. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/core/connection.py +0 -0
  83. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/core/exceptions.py +0 -0
  84. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/core/models.py +0 -0
  85. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/core/response_standardizer.py +0 -0
  86. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/core/validators.py +0 -0
  87. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/core/vector_store.py +0 -0
  88. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/core/vector_store_exceptions.py +0 -0
  89. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/dspy_modules/__init__.py +0 -0
  90. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/dspy_modules/batch_entity_extraction.py +0 -0
  91. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/dspy_modules/entity_extraction_module.py +0 -0
  92. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/dspy_modules/iris_llm_lm.py +0 -0
  93. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/embeddings/__init__.py +0 -0
  94. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/embeddings/entity_extractor.py +0 -0
  95. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/embeddings/iris_embedding.py +0 -0
  96. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/embeddings/manager.py +0 -0
  97. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/evaluation/__init__.py +0 -0
  98. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/evaluation/datasets.py +0 -0
  99. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/evaluation/metrics.py +0 -0
  100. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/exceptions.py +0 -0
  101. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/executor.py +0 -0
  102. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/mcp/__init__.py +0 -0
  103. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/mcp/__main__.py +0 -0
  104. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/mcp/bridge.py +0 -0
  105. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/mcp/cli.py +0 -0
  106. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/mcp/config.py +0 -0
  107. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/mcp/iris_llm_handler.py +0 -0
  108. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/mcp/technique_handlers.py +0 -0
  109. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/mcp/tool_schemas.py +0 -0
  110. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/mcp/validation.py +0 -0
  111. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/memory/__init__.py +0 -0
  112. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/memory/knowledge_extractor.py +0 -0
  113. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/memory/models.py +0 -0
  114. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/memory/rag_integration.py +0 -0
  115. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/memory/temporal_manager.py +0 -0
  116. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/monitoring/__init__.py +0 -0
  117. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/ontology/__init__.py +0 -0
  118. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/ontology/loader.py +0 -0
  119. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/ontology/models.py +0 -0
  120. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/ontology/plugins/__init__.py +0 -0
  121. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/ontology/plugins/general_ontology.py +0 -0
  122. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/ontology/reasoner.py +0 -0
  123. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/optimization/cache_manager.py +0 -0
  124. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/optimization/connection_pool.py +0 -0
  125. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/optimization/database_optimizer.py +0 -0
  126. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/optimization/hnsw_tuner.py +0 -0
  127. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/optimization/parallel_processor.py +0 -0
  128. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/optimization/performance_monitor.py +0 -0
  129. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/__init__.py +0 -0
  130. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/_hybrid_utils.py +0 -0
  131. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/basic.py +0 -0
  132. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/basic_rerank.py +0 -0
  133. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/colbert_iris/__init__.py +0 -0
  134. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/colbert_iris/ingest.py +0 -0
  135. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/colbert_iris/maxsim_indb.py +0 -0
  136. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/colbert_iris/pipeline.py +0 -0
  137. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/colbert_iris/plaid.py +0 -0
  138. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/colbert_iris/schema.py +0 -0
  139. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/colbert_iris/vecindex_phase2.py +0 -0
  140. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/colbert_pylate/__init__.py +0 -0
  141. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/colbert_pylate/pylate_pipeline.py +0 -0
  142. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/crag.py +0 -0
  143. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/factory.py +0 -0
  144. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/graphrag.py +0 -0
  145. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/graphrag_merged.py +0 -0
  146. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/hybrid_graphrag_discovery.py +0 -0
  147. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/hybrid_graphrag_retrieval.py +0 -0
  148. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/iris_global_graphrag.py +0 -0
  149. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/pipelines/multi_query_rrf.py +0 -0
  150. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/plugins/__init__.py +0 -0
  151. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/plugins/interface.py +0 -0
  152. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/security/__init__.py +0 -0
  153. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/services/__init__.py +0 -0
  154. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/services/batch_entity_processor.py +0 -0
  155. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/services/entity_extraction.py +0 -0
  156. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/services/storage.py +0 -0
  157. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/storage/__init__.py +0 -0
  158. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/storage/clob_handler.py +0 -0
  159. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/storage/constants.py +0 -0
  160. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/storage/enterprise_storage.py +0 -0
  161. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/storage/hybrid_schema_manager.py +0 -0
  162. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/storage/iris_embedding_ops.py +0 -0
  163. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/storage/metadata_filter_manager.py +0 -0
  164. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/storage/schema_manager.py +0 -0
  165. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/storage/vector_store_iris.py +0 -0
  166. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/testing/__init__.py +0 -0
  167. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/testing/backend_manager.py +0 -0
  168. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/testing/connection_pool.py +0 -0
  169. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/testing/exceptions.py +0 -0
  170. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/testing/iris_devtools_bridge.py +0 -0
  171. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/testing/validators.py +0 -0
  172. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/tools/__init__.py +0 -0
  173. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/tools/graphrag.py +0 -0
  174. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/utils/__init__.py +0 -0
  175. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/utils/module_loader.py +0 -0
  176. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/utils/project_root.py +0 -0
  177. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/utils/token_counter.py +0 -0
  178. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/validation/__init__.py +0 -0
  179. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/validation/factory.py +0 -0
  180. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/validation/orchestrator.py +0 -0
  181. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/validation/requirements.py +0 -0
  182. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag/validation/validator.py +0 -0
  183. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag.egg-info/dependency_links.txt +0 -0
  184. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag.egg-info/entry_points.txt +0 -0
  185. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag.egg-info/requires.txt +0 -0
  186. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/iris_vector_rag.egg-info/top_level.txt +0 -0
  187. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/setup.cfg +0 -0
  188. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_comprehensive_pipeline_validation_e2e.py +0 -0
  189. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_comprehensive_pipeline_validation_e2e_fixed.py +0 -0
  190. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_enterprise_storage.py +0 -0
  191. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_entity_extraction_service.py +0 -0
  192. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_fuzzy_search_quick.py +0 -0
  193. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_hybrid_graphrag_functional.py +0 -0
  194. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_index_ensure.py +0 -0
  195. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_ontology_loader.py +0 -0
  196. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_ontology_support.py +0 -0
  197. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_performance_monitor_comprehensive.py +0 -0
  198. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_performance_monitor_working.py +0 -0
  199. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_pylate_colbert_pipeline.py +0 -0
  200. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_schema_manager_bugs.py +0 -0
  201. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_temporal_manager.py +0 -0
  202. {iris_vector_rag-0.6.0 → iris_vector_rag-0.7.0}/tests/test_vector_safe_helpers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iris-vector-rag
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: Enterprise RAG pipelines with native IRIS vector search. 6 production implementations with RAGAS evaluation, LangChain, AWS/Azure configs. No external VectorDB required.
5
5
  Author-email: Thomas Dyar <thomas.dyar@intersystems.com>
6
6
  Maintainer-email: Thomas Dyar <thomas.dyar@intersystems.com>
@@ -19,7 +19,7 @@ from .validation.requirements import get_pipeline_requirements
19
19
  from .validation.validator import PreConditionValidator
20
20
 
21
21
  # Package version
22
- __version__ = "0.5.19"
22
+ __version__ = "0.7.0"
23
23
  __author__ = "InterSystems IRIS RAG Templates Project"
24
24
  __description__ = "A comprehensive, production-ready framework for implementing Retrieval Augmented Generation (RAG) pipelines using InterSystems IRIS as the vector database backend."
25
25
 
@@ -10,7 +10,7 @@ robust error handling, and modular architecture.
10
10
 
11
11
  import logging
12
12
  import time
13
- from typing import Any, Callable, Dict, List, Optional
13
+ from typing import Any, Callable, Dict, List, Optional, TypedDict
14
14
 
15
15
  from ..config.manager import ConfigurationManager
16
16
  from ..core.connection import ConnectionManager
@@ -22,6 +22,20 @@ from .hybrid_graphrag_retrieval import HybridRetrievalMethods
22
22
  logger = logging.getLogger(__name__)
23
23
 
24
24
 
25
+ class AttachResult(TypedDict):
26
+ table: str
27
+ label: str
28
+ id_col: str
29
+ embedding_col: str
30
+ dimension: int
31
+ row_count: int
32
+ has_hnsw_index: Optional[bool]
33
+
34
+
35
+ class DimensionMismatchError(ValueError):
36
+ pass
37
+
38
+
25
39
  class HybridGraphRAGPipeline(GraphRAGPipeline):
26
40
  """
27
41
  Enhanced GraphRAG pipeline with hybrid search capabilities.
@@ -48,7 +62,13 @@ class HybridGraphRAGPipeline(GraphRAGPipeline):
48
62
  embedding_config: Optional[str] = None,
49
63
  executor=None,
50
64
  ):
51
- super().__init__(connection_manager, config_manager, llm_func, vector_store, executor=executor)
65
+ super().__init__(
66
+ connection_manager,
67
+ config_manager,
68
+ llm_func,
69
+ vector_store,
70
+ executor=executor,
71
+ )
52
72
 
53
73
  # Store schema manager for iris_vector_graph table management
54
74
  self.schema_manager = schema_manager
@@ -73,6 +93,8 @@ class HybridGraphRAGPipeline(GraphRAGPipeline):
73
93
  self.text_engine = None
74
94
  self.vector_optimizer = None
75
95
 
96
+ self._attached_corpora: Dict[str, AttachResult] = {}
97
+
76
98
  # Initialize graph core integration
77
99
  self._initialize_graph_core()
78
100
 
@@ -147,6 +169,116 @@ class HybridGraphRAGPipeline(GraphRAGPipeline):
147
169
  logger.error(f"Failed to initialize iris_vector_graph components: {e}")
148
170
  raise
149
171
 
172
+ def _detect_hnsw_index(
173
+ self, source_table: str, embedding_col: str
174
+ ) -> Optional[bool]:
175
+ try:
176
+ schema, tbl = (
177
+ source_table.split(".", 1)
178
+ if "." in source_table
179
+ else ("", source_table)
180
+ )
181
+ conn = self.iris_engine.conn if self.iris_engine else None
182
+ if conn is None:
183
+ return None
184
+ cur = conn.cursor()
185
+ try:
186
+ cur.execute(
187
+ "SELECT COUNT(*) FROM INFORMATION_SCHEMA.INDEXES "
188
+ "WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND COLUMN_NAME = ?",
189
+ [schema or "USER", tbl, embedding_col],
190
+ )
191
+ row = cur.fetchone()
192
+ return row is not None and int(row[0]) > 0
193
+ finally:
194
+ cur.close()
195
+ except Exception:
196
+ return None
197
+
198
+ def attach_existing_corpus(
199
+ self,
200
+ source_table: str,
201
+ id_col: str,
202
+ text_col: str,
203
+ embedding_col: str,
204
+ graph_label: str,
205
+ ) -> AttachResult:
206
+ if self.iris_engine is None:
207
+ raise RuntimeError(
208
+ "iris_vector_graph engine not initialized. "
209
+ "Call _initialize_graph_core() first."
210
+ )
211
+
212
+ validation = self.iris_engine.validate_vector_table(source_table, embedding_col)
213
+ dimension = validation.get("dimension")
214
+ row_count = validation.get("row_count", 0)
215
+
216
+ if dimension is None and row_count > 0:
217
+ cur = self.iris_engine.conn.cursor()
218
+ try:
219
+ cur.execute(
220
+ f"SELECT TOP 1 {embedding_col} "
221
+ f"FROM {source_table} WHERE {embedding_col} IS NOT NULL"
222
+ )
223
+ row = cur.fetchone()
224
+ if row and row[0]:
225
+ raw = row[0]
226
+ if isinstance(raw, str):
227
+ dimension = raw.count(",") + 1
228
+ elif isinstance(raw, (list, tuple)):
229
+ dimension = len(raw)
230
+ elif isinstance(raw, bytes):
231
+ dimension = len(raw) // 8
232
+ except Exception:
233
+ pass
234
+ finally:
235
+ cur.close()
236
+
237
+ if dimension is None or dimension == 0:
238
+ logger.warning(
239
+ f"No non-NULL embeddings found in {source_table}.{embedding_col} — "
240
+ f"vector search will return no results until embeddings are populated."
241
+ )
242
+
243
+ self.iris_engine.map_sql_table(
244
+ source_table,
245
+ id_col,
246
+ graph_label,
247
+ property_columns=[text_col],
248
+ )
249
+
250
+ has_hnsw = self._detect_hnsw_index(source_table, embedding_col)
251
+ if has_hnsw is False:
252
+ logger.warning(
253
+ f"No HNSW index found on {source_table}.{embedding_col} — "
254
+ f"vector search will use brute force. "
255
+ f"Consider running BUILD INDEX for better performance."
256
+ )
257
+
258
+ result: AttachResult = {
259
+ "table": source_table,
260
+ "label": graph_label,
261
+ "id_col": id_col,
262
+ "embedding_col": embedding_col,
263
+ "dimension": dimension if dimension else 0,
264
+ "row_count": row_count,
265
+ "has_hnsw_index": has_hnsw,
266
+ }
267
+ self._attached_corpora[graph_label] = result
268
+ return result
269
+
270
+ def _validate_query_dimension(self, graph_label: str, query_vec) -> None:
271
+ if graph_label not in self._attached_corpora:
272
+ return
273
+ expected_dim = self._attached_corpora[graph_label].get("dimension", 0)
274
+ if expected_dim and expected_dim > 0:
275
+ actual_dim = len(query_vec) if hasattr(query_vec, "__len__") else 0
276
+ if actual_dim > 0 and actual_dim != expected_dim:
277
+ raise DimensionMismatchError(
278
+ f"Query vector dimension ({actual_dim}) does not match "
279
+ f"table embedding dimension ({expected_dim})"
280
+ )
281
+
150
282
  def query(
151
283
  self,
152
284
  query_text: Optional[str] = None,
@@ -282,7 +414,11 @@ class HybridGraphRAGPipeline(GraphRAGPipeline):
282
414
  normalized: List[Document] = []
283
415
  for doc in documents:
284
416
  if isinstance(doc, Document):
285
- score = doc.metadata.get("similarity_score") if hasattr(doc, "metadata") else None
417
+ score = (
418
+ doc.metadata.get("similarity_score")
419
+ if hasattr(doc, "metadata")
420
+ else None
421
+ )
286
422
  score_value = float(score) if score is not None else 1.0
287
423
  normalized.append(
288
424
  Document(
@@ -354,7 +490,9 @@ class HybridGraphRAGPipeline(GraphRAGPipeline):
354
490
  )
355
491
  # If text search returns 0 results, fall back to vector search
356
492
  if not documents:
357
- logger.warning("Text search returned 0 results. Falling back to vector search.")
493
+ logger.warning(
494
+ "Text search returned 0 results. Falling back to vector search."
495
+ )
358
496
  fallback_docs = self._fallback_to_vector_search(query_text, top_k)
359
497
  return fallback_docs, "vector_fallback"
360
498
  return documents, method
@@ -374,7 +512,9 @@ class HybridGraphRAGPipeline(GraphRAGPipeline):
374
512
  )
375
513
  # If HNSW returns 0 results, fall back to IRISVectorStore
376
514
  if not documents:
377
- logger.warning("HNSW vector search returned 0 results. Falling back to IRISVectorStore.")
515
+ logger.warning(
516
+ "HNSW vector search returned 0 results. Falling back to IRISVectorStore."
517
+ )
378
518
  fallback_docs = self._fallback_to_vector_search(query_text, top_k)
379
519
  return fallback_docs, "vector_fallback"
380
520
  return documents, method
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iris-vector-rag
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: Enterprise RAG pipelines with native IRIS vector search. 6 production implementations with RAGAS evaluation, LangChain, AWS/Azure configs. No external VectorDB required.
5
5
  Author-email: Thomas Dyar <thomas.dyar@intersystems.com>
6
6
  Maintainer-email: Thomas Dyar <thomas.dyar@intersystems.com>
@@ -182,6 +182,7 @@ iris_vector_rag/validation/factory.py
182
182
  iris_vector_rag/validation/orchestrator.py
183
183
  iris_vector_rag/validation/requirements.py
184
184
  iris_vector_rag/validation/validator.py
185
+ tests/test_attach_corpus.py
185
186
  tests/test_comprehensive_pipeline_validation_e2e.py
186
187
  tests/test_comprehensive_pipeline_validation_e2e_fixed.py
187
188
  tests/test_enterprise_storage.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "iris-vector-rag"
7
- version = "0.6.0"
7
+ version = "0.7.0"
8
8
  description = "Enterprise RAG pipelines with native IRIS vector search. 6 production implementations with RAGAS evaluation, LangChain, AWS/Azure configs. No external VectorDB required."
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -0,0 +1,362 @@
1
+ import logging
2
+ import os
3
+
4
+ import numpy as np
5
+ import pytest
6
+
7
+ IRIS_HOST = os.environ.get("IRIS_HOSTNAME", "localhost")
8
+ IRIS_PORT = int(os.environ.get("IRIS_PORT", "1972"))
9
+ TOKEN_DIM = 384
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ def _get_conn():
15
+ import iris.dbapi as dbapi
16
+
17
+ return dbapi.connect(
18
+ hostname=IRIS_HOST,
19
+ port=IRIS_PORT,
20
+ namespace="USER",
21
+ username="_SYSTEM",
22
+ password="SYS",
23
+ )
24
+
25
+
26
+ def _get_engine(conn):
27
+ import intersystems_iris
28
+ from iris_vector_graph import IRISGraphEngine
29
+
30
+ native = intersystems_iris.createConnection(
31
+ hostname=IRIS_HOST,
32
+ port=IRIS_PORT,
33
+ namespace="USER",
34
+ username="_SYSTEM",
35
+ password="SYS",
36
+ )
37
+ return IRISGraphEngine(native)
38
+
39
+
40
+ def _create_test_table(conn, table_name, n_rows, dim=TOKEN_DIM):
41
+ cur = conn.cursor()
42
+ try:
43
+ cur.execute(f"DROP TABLE IF EXISTS {table_name}")
44
+ conn.commit()
45
+ cur.execute(
46
+ f"CREATE TABLE {table_name} ("
47
+ f"doc_id VARCHAR(50) PRIMARY KEY, "
48
+ f"text_content VARCHAR(2000), "
49
+ f"embedding VECTOR(DOUBLE, {dim}))"
50
+ )
51
+ conn.commit()
52
+ rng = np.random.default_rng(42)
53
+ for i in range(n_rows):
54
+ vec = rng.random(dim).astype(np.float32)
55
+ vec /= np.linalg.norm(vec)
56
+ vec_str = ",".join(str(float(v)) for v in vec)
57
+ cur.execute(
58
+ f"INSERT INTO {table_name} (doc_id, text_content, embedding) "
59
+ f"VALUES (?, ?, TO_VECTOR(?, DOUBLE, {dim}))",
60
+ [f"doc_{i:04d}", f"Test document {i} about topic {i % 10}.", vec_str],
61
+ )
62
+ conn.commit()
63
+ finally:
64
+ cur.close()
65
+ return n_rows
66
+
67
+
68
+ def _drop_test_table(conn, table_name):
69
+ cur = conn.cursor()
70
+ try:
71
+ cur.execute(f"DROP TABLE IF EXISTS {table_name}")
72
+ conn.commit()
73
+ except Exception:
74
+ pass
75
+ finally:
76
+ cur.close()
77
+
78
+
79
+ def _make_pipeline(conn, engine):
80
+ from unittest.mock import MagicMock
81
+
82
+ from iris_vector_rag.pipelines.hybrid_graphrag import HybridGraphRAGPipeline
83
+
84
+ pipeline = HybridGraphRAGPipeline.__new__(HybridGraphRAGPipeline)
85
+ pipeline.iris_engine = engine
86
+ pipeline._attached_corpora = {}
87
+ pipeline.connection_manager = MagicMock()
88
+ pipeline.config_manager = MagicMock()
89
+ return pipeline
90
+
91
+
92
+ @pytest.fixture(scope="module")
93
+ def conn():
94
+ c = _get_conn()
95
+ yield c
96
+ c.close()
97
+
98
+
99
+ @pytest.fixture(scope="module")
100
+ def engine(conn):
101
+ import intersystems_iris
102
+
103
+ native = intersystems_iris.createConnection(
104
+ hostname=IRIS_HOST,
105
+ port=IRIS_PORT,
106
+ namespace="USER",
107
+ username="_SYSTEM",
108
+ password="SYS",
109
+ )
110
+ from iris_vector_graph import IRISGraphEngine
111
+
112
+ e = IRISGraphEngine(native, embedding_dimension=TOKEN_DIM)
113
+ e.initialize_schema(auto_deploy_objectscript=False)
114
+ return e
115
+
116
+
117
+ @pytest.fixture(scope="module")
118
+ def pipeline(conn, engine):
119
+ return _make_pipeline(conn, engine)
120
+
121
+
122
+ @pytest.fixture(scope="module")
123
+ def test_table(conn):
124
+ table = "Test069.CorpusA"
125
+ _create_test_table(conn, table, 100)
126
+ yield table
127
+ _drop_test_table(conn, table)
128
+
129
+
130
+ # --- US1: Attach RAG corpus ---
131
+
132
+
133
+ @pytest.mark.integration
134
+ class TestAttachCorpusBasic:
135
+ def test_attach_returns_result(self, pipeline, test_table):
136
+ result = pipeline.attach_existing_corpus(
137
+ source_table=test_table,
138
+ id_col="doc_id",
139
+ text_col="text_content",
140
+ embedding_col="embedding",
141
+ graph_label="TestDoc",
142
+ )
143
+ assert result["table"] == test_table
144
+ assert result["label"] == "TestDoc"
145
+ assert result["dimension"] == TOKEN_DIM
146
+ assert result["row_count"] == 100
147
+ assert isinstance(result["has_hnsw_index"], (bool, type(None)))
148
+
149
+ def test_graph_query_returns_rows(self, pipeline, engine, test_table):
150
+ pipeline.attach_existing_corpus(
151
+ source_table=test_table,
152
+ id_col="doc_id",
153
+ text_col="text_content",
154
+ embedding_col="embedding",
155
+ graph_label="TestDoc2",
156
+ )
157
+ results = engine.execute_cypher("MATCH (d:TestDoc2) RETURN d.doc_id LIMIT 5")
158
+ assert len(results) > 0
159
+
160
+ def test_vector_search_returns_results(self, pipeline, engine, test_table):
161
+ pipeline.attach_existing_corpus(
162
+ source_table=test_table,
163
+ id_col="doc_id",
164
+ text_col="text_content",
165
+ embedding_col="embedding",
166
+ graph_label="TestDocVS",
167
+ )
168
+ rng = np.random.default_rng(99)
169
+ q = rng.random(TOKEN_DIM).astype(np.float32)
170
+ q /= np.linalg.norm(q)
171
+ results = engine.vector_search(
172
+ test_table, "embedding", q.tolist(), top_k=5, id_col="doc_id"
173
+ )
174
+ assert len(results) > 0
175
+
176
+
177
+ @pytest.mark.integration
178
+ class TestAttachCorpusIdempotent:
179
+ def test_double_attach_no_error(self, pipeline, test_table):
180
+ r1 = pipeline.attach_existing_corpus(
181
+ source_table=test_table,
182
+ id_col="doc_id",
183
+ text_col="text_content",
184
+ embedding_col="embedding",
185
+ graph_label="IdempotentLabel",
186
+ )
187
+ r2 = pipeline.attach_existing_corpus(
188
+ source_table=test_table,
189
+ id_col="doc_id",
190
+ text_col="text_content",
191
+ embedding_col="embedding",
192
+ graph_label="IdempotentLabel",
193
+ )
194
+ assert r1["dimension"] == r2["dimension"]
195
+ assert r1["label"] == r2["label"]
196
+
197
+
198
+ @pytest.mark.integration
199
+ class TestNewRowsVisible:
200
+ def test_new_row_in_graph_after_insert(self, pipeline, conn, engine, test_table):
201
+ pipeline.attach_existing_corpus(
202
+ source_table=test_table,
203
+ id_col="doc_id",
204
+ text_col="text_content",
205
+ embedding_col="embedding",
206
+ graph_label="NewRowLabel",
207
+ )
208
+ cur = conn.cursor()
209
+ rng = np.random.default_rng(777)
210
+ vec = rng.random(TOKEN_DIM).astype(np.float32)
211
+ vec /= np.linalg.norm(vec)
212
+ vec_str = ",".join(str(float(v)) for v in vec)
213
+ try:
214
+ cur.execute(
215
+ f"INSERT INTO {test_table} (doc_id, text_content, embedding) "
216
+ f"VALUES (?, ?, TO_VECTOR(?, FLOAT, {TOKEN_DIM}))",
217
+ ["doc_new_0001", "Newly inserted document.", vec_str],
218
+ )
219
+ conn.commit()
220
+ finally:
221
+ cur.close()
222
+ results = engine.execute_cypher(
223
+ "MATCH (d:NewRowLabel) WHERE d.doc_id = 'doc_new_0001' RETURN d.doc_id"
224
+ )
225
+ assert len(results) > 0
226
+
227
+
228
+ # --- US2: Custom IRIS table ---
229
+
230
+
231
+ @pytest.mark.integration
232
+ class TestAttachCustomTable:
233
+ def test_custom_schema_table(self, conn, engine):
234
+ p = _make_pipeline(conn, engine)
235
+ table = "Test069.ClinicalNotes"
236
+ _create_test_table(conn, table, 50, dim=384)
237
+ try:
238
+ result = p.attach_existing_corpus(
239
+ source_table=table,
240
+ id_col="doc_id",
241
+ text_col="text_content",
242
+ embedding_col="embedding",
243
+ graph_label="ClinNote",
244
+ )
245
+ assert result["label"] == "ClinNote"
246
+ assert result["row_count"] == 50
247
+ results = engine.execute_cypher(
248
+ "MATCH (n:ClinNote) RETURN n.doc_id LIMIT 3"
249
+ )
250
+ assert len(results) > 0
251
+ finally:
252
+ _drop_test_table(conn, table)
253
+
254
+
255
+ # --- US3: Dimension mismatch ---
256
+
257
+
258
+ @pytest.mark.integration
259
+ class TestDimensionMismatch:
260
+ def test_mismatch_raises_error(self, pipeline, test_table):
261
+ from iris_vector_rag.pipelines.hybrid_graphrag import DimensionMismatchError
262
+
263
+ pipeline.attach_existing_corpus(
264
+ source_table=test_table,
265
+ id_col="doc_id",
266
+ text_col="text_content",
267
+ embedding_col="embedding",
268
+ graph_label="DimTest",
269
+ )
270
+ wrong_dim_vec = np.random.default_rng(0).random(768).tolist()
271
+ with pytest.raises(DimensionMismatchError):
272
+ pipeline._validate_query_dimension("DimTest", wrong_dim_vec)
273
+
274
+ def test_all_null_embeddings_warns(self, conn, engine, caplog):
275
+ p = _make_pipeline(conn, engine)
276
+ table = "Test069.NullEmb"
277
+ cur = conn.cursor()
278
+ try:
279
+ cur.execute(f"DROP TABLE IF EXISTS {table}")
280
+ conn.commit()
281
+ cur.execute(
282
+ f"CREATE TABLE {table} ("
283
+ f"doc_id VARCHAR(50) PRIMARY KEY, "
284
+ f"text_content VARCHAR(200), "
285
+ f"embedding VECTOR(DOUBLE, 384))"
286
+ )
287
+ conn.commit()
288
+ cur.execute(
289
+ f"INSERT INTO {table} (doc_id, text_content) VALUES ('n1', 'No embedding')"
290
+ )
291
+ conn.commit()
292
+ finally:
293
+ cur.close()
294
+ try:
295
+ with caplog.at_level(logging.WARNING):
296
+ result = p.attach_existing_corpus(
297
+ source_table=table,
298
+ id_col="doc_id",
299
+ text_col="text_content",
300
+ embedding_col="embedding",
301
+ graph_label="NullLabel",
302
+ )
303
+ assert result["dimension"] is None or result["dimension"] == 0
304
+ assert any(
305
+ "non-NULL" in r.message or "NULL" in r.message for r in caplog.records
306
+ )
307
+ finally:
308
+ _drop_test_table(conn, table)
309
+
310
+
311
+ # --- Polish: Edge cases ---
312
+
313
+
314
+ @pytest.mark.integration
315
+ class TestEdgeCases:
316
+ def test_nonexistent_table_raises(self, pipeline):
317
+ with pytest.raises(ValueError, match="not found"):
318
+ pipeline.attach_existing_corpus(
319
+ source_table="NoSuch.Table",
320
+ id_col="id",
321
+ text_col="txt",
322
+ embedding_col="emb",
323
+ graph_label="Ghost",
324
+ )
325
+
326
+ def test_nonexistent_column_raises(self, pipeline, test_table):
327
+ with pytest.raises(ValueError, match="not found"):
328
+ pipeline.attach_existing_corpus(
329
+ source_table=test_table,
330
+ id_col="doc_id",
331
+ text_col="text_content",
332
+ embedding_col="no_such_column",
333
+ graph_label="BadCol",
334
+ )
335
+
336
+ def test_upsert_repoint_label(self, conn, engine):
337
+ p = _make_pipeline(conn, engine)
338
+ table_a = "Test069.TableA"
339
+ table_b = "Test069.TableB"
340
+ _create_test_table(conn, table_a, 10)
341
+ _create_test_table(conn, table_b, 20)
342
+ try:
343
+ r1 = p.attach_existing_corpus(
344
+ source_table=table_a,
345
+ id_col="doc_id",
346
+ text_col="text_content",
347
+ embedding_col="embedding",
348
+ graph_label="Repoint",
349
+ )
350
+ assert r1["row_count"] == 10
351
+ r2 = p.attach_existing_corpus(
352
+ source_table=table_b,
353
+ id_col="doc_id",
354
+ text_col="text_content",
355
+ embedding_col="embedding",
356
+ graph_label="Repoint",
357
+ )
358
+ assert r2["row_count"] == 20
359
+ assert r2["table"] == table_b
360
+ finally:
361
+ _drop_test_table(conn, table_a)
362
+ _drop_test_table(conn, table_b)
File without changes