fennec-rag 0.1.1__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 (207) hide show
  1. fennec_rag-0.1.1/LICENSE +21 -0
  2. fennec_rag-0.1.1/MANIFEST.in +10 -0
  3. fennec_rag-0.1.1/PKG-INFO +222 -0
  4. fennec_rag-0.1.1/README.md +99 -0
  5. fennec_rag-0.1.1/fennec/__init__.py +0 -0
  6. fennec_rag-0.1.1/fennec/cache/__init__.py +6 -0
  7. fennec_rag-0.1.1/fennec/cache/cache_entry.py +117 -0
  8. fennec_rag-0.1.1/fennec/cache/cache_metrics.py +146 -0
  9. fennec_rag-0.1.1/fennec/cache/cache_strategies.py +10 -0
  10. fennec_rag-0.1.1/fennec/cache/config_cache.py +116 -0
  11. fennec_rag-0.1.1/fennec/cache/multi_level_cache.py +961 -0
  12. fennec_rag-0.1.1/fennec/chunks/__init__.py +35 -0
  13. fennec_rag-0.1.1/fennec/chunks/arabic_chunker.py +831 -0
  14. fennec_rag-0.1.1/fennec/chunks/base.py +118 -0
  15. fennec_rag-0.1.1/fennec/chunks/chunk_config.py +54 -0
  16. fennec_rag-0.1.1/fennec/chunks/doc_model.py +32 -0
  17. fennec_rag-0.1.1/fennec/chunks/multi_chunker.py +860 -0
  18. fennec_rag-0.1.1/fennec/chunks/text_splitter.py +250 -0
  19. fennec_rag-0.1.1/fennec/context/__init__.py +12 -0
  20. fennec_rag-0.1.1/fennec/context/allocations.py +39 -0
  21. fennec_rag-0.1.1/fennec/context/context_config.py +24 -0
  22. fennec_rag-0.1.1/fennec/context/context_manager.py +525 -0
  23. fennec_rag-0.1.1/fennec/context/stratgey.py +40 -0
  24. fennec_rag-0.1.1/fennec/document_loaders/__init__.py +74 -0
  25. fennec_rag-0.1.1/fennec/document_loaders/auto_loader.py +202 -0
  26. fennec_rag-0.1.1/fennec/document_loaders/base_loader.py +211 -0
  27. fennec_rag-0.1.1/fennec/document_loaders/config_loader.py +156 -0
  28. fennec_rag-0.1.1/fennec/document_loaders/csv_loader.py +302 -0
  29. fennec_rag-0.1.1/fennec/document_loaders/directory_loader.py +302 -0
  30. fennec_rag-0.1.1/fennec/document_loaders/docx_loader.py +188 -0
  31. fennec_rag-0.1.1/fennec/document_loaders/html_loader.py +241 -0
  32. fennec_rag-0.1.1/fennec/document_loaders/json_loader.py +271 -0
  33. fennec_rag-0.1.1/fennec/document_loaders/pdf_loader.py +255 -0
  34. fennec_rag-0.1.1/fennec/document_loaders/text_loader.py +233 -0
  35. fennec_rag-0.1.1/fennec/document_loaders/web_loader.py +235 -0
  36. fennec_rag-0.1.1/fennec/embeddings/__init__.py +99 -0
  37. fennec_rag-0.1.1/fennec/embeddings/arabic_embedder.py +903 -0
  38. fennec_rag-0.1.1/fennec/embeddings/base_embedder.py +512 -0
  39. fennec_rag-0.1.1/fennec/embeddings/config_embedder.py +54 -0
  40. fennec_rag-0.1.1/fennec/embeddings/gemini_embedder.py +788 -0
  41. fennec_rag-0.1.1/fennec/embeddings/hugginface_embedder.py +484 -0
  42. fennec_rag-0.1.1/fennec/embeddings/mistral_embedder.py +604 -0
  43. fennec_rag-0.1.1/fennec/embeddings/ollama_embedder.py +681 -0
  44. fennec_rag-0.1.1/fennec/embeddings/openai_embedder.py +743 -0
  45. fennec_rag-0.1.1/fennec/evaluator/__init__.py +17 -0
  46. fennec_rag-0.1.1/fennec/evaluator/dashboard.py +426 -0
  47. fennec_rag-0.1.1/fennec/evaluator/eval_report.py +83 -0
  48. fennec_rag-0.1.1/fennec/evaluator/eval_result.py +47 -0
  49. fennec_rag-0.1.1/fennec/evaluator/evaluator.py +349 -0
  50. fennec_rag-0.1.1/fennec/evaluator/generation_metrics.py +38 -0
  51. fennec_rag-0.1.1/fennec/evaluator/retrieval_metrics.py +22 -0
  52. fennec_rag-0.1.1/fennec/llm/__init__.py +60 -0
  53. fennec_rag-0.1.1/fennec/llm/anthropic_interface.py +134 -0
  54. fennec_rag-0.1.1/fennec/llm/base_llm_interface.py +163 -0
  55. fennec_rag-0.1.1/fennec/llm/config_llm.py +22 -0
  56. fennec_rag-0.1.1/fennec/llm/gemini_interface.py +227 -0
  57. fennec_rag-0.1.1/fennec/llm/hallucination/__init__.py +40 -0
  58. fennec_rag-0.1.1/fennec/llm/hallucination/config.py +419 -0
  59. fennec_rag-0.1.1/fennec/llm/hallucination/hallucination_guard.py +567 -0
  60. fennec_rag-0.1.1/fennec/llm/hallucination/hallucination_pattern.py +57 -0
  61. fennec_rag-0.1.1/fennec/llm/hallucination/protected_llm_interface.py +473 -0
  62. fennec_rag-0.1.1/fennec/llm/hugginface_interface.py +275 -0
  63. fennec_rag-0.1.1/fennec/llm/mistral_interface.py +135 -0
  64. fennec_rag-0.1.1/fennec/llm/ollama_interface.py +282 -0
  65. fennec_rag-0.1.1/fennec/llm/openai_interface.py +134 -0
  66. fennec_rag-0.1.1/fennec/memory/__init__.py +42 -0
  67. fennec_rag-0.1.1/fennec/memory/core/__init__.py +22 -0
  68. fennec_rag-0.1.1/fennec/memory/core/base.py +103 -0
  69. fennec_rag-0.1.1/fennec/memory/core/config.py +147 -0
  70. fennec_rag-0.1.1/fennec/memory/core/memory_entry.py +231 -0
  71. fennec_rag-0.1.1/fennec/memory/core/memory_type.py +122 -0
  72. fennec_rag-0.1.1/fennec/memory/core/models.py +62 -0
  73. fennec_rag-0.1.1/fennec/memory/memories/__init__.py +14 -0
  74. fennec_rag-0.1.1/fennec/memory/memories/buffer_memory.py +116 -0
  75. fennec_rag-0.1.1/fennec/memory/memories/entity_memory.py +228 -0
  76. fennec_rag-0.1.1/fennec/memory/memories/summary_memory.py +206 -0
  77. fennec_rag-0.1.1/fennec/memory/memories/window_memory.py +66 -0
  78. fennec_rag-0.1.1/fennec/monitor/__init__.py +30 -0
  79. fennec_rag-0.1.1/fennec/monitor/metrics_point.py +38 -0
  80. fennec_rag-0.1.1/fennec/monitor/monitor.py +415 -0
  81. fennec_rag-0.1.1/fennec/monitor/timer_context.py +60 -0
  82. fennec_rag-0.1.1/fennec/observability/__init__.py +104 -0
  83. fennec_rag-0.1.1/fennec/observability/anomaly.py +288 -0
  84. fennec_rag-0.1.1/fennec/observability/api.py +327 -0
  85. fennec_rag-0.1.1/fennec/observability/config.py +73 -0
  86. fennec_rag-0.1.1/fennec/observability/dashboard.py +732 -0
  87. fennec_rag-0.1.1/fennec/observability/export.py +330 -0
  88. fennec_rag-0.1.1/fennec/observability/observability.py +611 -0
  89. fennec_rag-0.1.1/fennec/observability/storage.py +494 -0
  90. fennec_rag-0.1.1/fennec/observability/tracer.py +511 -0
  91. fennec_rag-0.1.1/fennec/output_parser/__init__.py +26 -0
  92. fennec_rag-0.1.1/fennec/output_parser/base_parser.py +255 -0
  93. fennec_rag-0.1.1/fennec/output_parser/csv_parser.py +175 -0
  94. fennec_rag-0.1.1/fennec/output_parser/json_parser.py +180 -0
  95. fennec_rag-0.1.1/fennec/output_parser/list_parser.py +182 -0
  96. fennec_rag-0.1.1/fennec/output_parser/pydantic_parser.py +172 -0
  97. fennec_rag-0.1.1/fennec/output_parser/structured_parser.py +250 -0
  98. fennec_rag-0.1.1/fennec/output_parser/yaml_parser.py +260 -0
  99. fennec_rag-0.1.1/fennec/persistence/__init__.py +33 -0
  100. fennec_rag-0.1.1/fennec/persistence/backup.py +166 -0
  101. fennec_rag-0.1.1/fennec/persistence/cache.py +156 -0
  102. fennec_rag-0.1.1/fennec/persistence/enums.py +60 -0
  103. fennec_rag-0.1.1/fennec/persistence/manager.py +578 -0
  104. fennec_rag-0.1.1/fennec/persistence/metadata.py +129 -0
  105. fennec_rag-0.1.1/fennec/persistence/serializers.py +243 -0
  106. fennec_rag-0.1.1/fennec/plugins/__init__.py +17 -0
  107. fennec_rag-0.1.1/fennec/plugins/base.py +163 -0
  108. fennec_rag-0.1.1/fennec/plugins/manager.py +905 -0
  109. fennec_rag-0.1.1/fennec/plugins/plugin.py +280 -0
  110. fennec_rag-0.1.1/fennec/prompt/__init__.py +43 -0
  111. fennec_rag-0.1.1/fennec/prompt/core/__init__.py +10 -0
  112. fennec_rag-0.1.1/fennec/prompt/core/base_template.py +111 -0
  113. fennec_rag-0.1.1/fennec/prompt/core/chat_template.py +201 -0
  114. fennec_rag-0.1.1/fennec/prompt/core/few_shot_template.py +194 -0
  115. fennec_rag-0.1.1/fennec/prompt/core/prompt_template.py +275 -0
  116. fennec_rag-0.1.1/fennec/prompt/templates/__init__.py +17 -0
  117. fennec_rag-0.1.1/fennec/prompt/templates/arabic_prompts.py +281 -0
  118. fennec_rag-0.1.1/fennec/prompt/templates/system_prompts.py +221 -0
  119. fennec_rag-0.1.1/fennec/prompt/templates/task_prompts.py +327 -0
  120. fennec_rag-0.1.1/fennec/prompt/utils/__init__.py +17 -0
  121. fennec_rag-0.1.1/fennec/prompt/utils/formatters.py +354 -0
  122. fennec_rag-0.1.1/fennec/prompt/utils/validators.py +323 -0
  123. fennec_rag-0.1.1/fennec/prompt/utils/variable_extractor.py +267 -0
  124. fennec_rag-0.1.1/fennec/rag/agentic_rag/__init__.py +4 -0
  125. fennec_rag-0.1.1/fennec/rag/agentic_rag/action_step.py +15 -0
  126. fennec_rag-0.1.1/fennec/rag/agentic_rag/agentic_config.py +45 -0
  127. fennec_rag-0.1.1/fennec/rag/agentic_rag/agentic_rag.py +784 -0
  128. fennec_rag-0.1.1/fennec/rag/agentic_rag/agentic_result.py +37 -0
  129. fennec_rag-0.1.1/fennec/rag/agentic_rag/cache.py +33 -0
  130. fennec_rag-0.1.1/fennec/rag/agentic_rag/document.py +23 -0
  131. fennec_rag-0.1.1/fennec/rag/conversational_rag/__init__.py +11 -0
  132. fennec_rag-0.1.1/fennec/rag/conversational_rag/conversation_config.py +29 -0
  133. fennec_rag-0.1.1/fennec/rag/conversational_rag/conversation_history.py +193 -0
  134. fennec_rag-0.1.1/fennec/rag/conversational_rag/conversation_turn.py +42 -0
  135. fennec_rag-0.1.1/fennec/rag/conversational_rag/conversational_rag.py +355 -0
  136. fennec_rag-0.1.1/fennec/rag/core/__init__.py +20 -0
  137. fennec_rag-0.1.1/fennec/rag/core/base_rag_system.py +259 -0
  138. fennec_rag-0.1.1/fennec/rag/core/multi_doc_rag.py +657 -0
  139. fennec_rag-0.1.1/fennec/rag/core/prompt_router.py +307 -0
  140. fennec_rag-0.1.1/fennec/rag/core/rag_config.py +140 -0
  141. fennec_rag-0.1.1/fennec/rag/core/rag_system.py +819 -0
  142. fennec_rag-0.1.1/fennec/rag/core/reranker.py +434 -0
  143. fennec_rag-0.1.1/fennec/rag/domain_rag/__init__.py +12 -0
  144. fennec_rag-0.1.1/fennec/rag/domain_rag/domain_defination.py +211 -0
  145. fennec_rag-0.1.1/fennec/rag/domain_rag/domain_metrics.py +30 -0
  146. fennec_rag-0.1.1/fennec/rag/domain_rag/domain_specific_rag.py +637 -0
  147. fennec_rag-0.1.1/fennec/rag/federated_rag/__init__.py +4 -0
  148. fennec_rag-0.1.1/fennec/rag/federated_rag/circuitbreaker.py +61 -0
  149. fennec_rag-0.1.1/fennec/rag/federated_rag/federat.py +922 -0
  150. fennec_rag-0.1.1/fennec/rag/federated_rag/federat_cache.py +39 -0
  151. fennec_rag-0.1.1/fennec/rag/graph_rag/__init__.py +7 -0
  152. fennec_rag-0.1.1/fennec/rag/graph_rag/config.py +142 -0
  153. fennec_rag-0.1.1/fennec/rag/graph_rag/edges.py +136 -0
  154. fennec_rag-0.1.1/fennec/rag/graph_rag/graph_rag.py +600 -0
  155. fennec_rag-0.1.1/fennec/rag/graph_rag/knowledge_graph.py +344 -0
  156. fennec_rag-0.1.1/fennec/rag/graph_rag/node.py +139 -0
  157. fennec_rag-0.1.1/fennec/rag/hybrid_search/__init__.py +10 -0
  158. fennec_rag-0.1.1/fennec/rag/hybrid_search/bm25.py +134 -0
  159. fennec_rag-0.1.1/fennec/rag/hybrid_search/hybrid_search.py +719 -0
  160. fennec_rag-0.1.1/fennec/rag/hybrid_search/hybrid_search_config.py +16 -0
  161. fennec_rag-0.1.1/fennec/rag/hybrid_search/stanze_.py +150 -0
  162. fennec_rag-0.1.1/fennec/rag/hybrid_search/tfidf.py +103 -0
  163. fennec_rag-0.1.1/fennec/rag/multi_hop/__init__.py +7 -0
  164. fennec_rag-0.1.1/fennec/rag/multi_hop/multi_hop.py +733 -0
  165. fennec_rag-0.1.1/fennec/rag/multi_hop/multihop_dataclass.py +32 -0
  166. fennec_rag-0.1.1/fennec/rag/multi_hop/multihop_strategy.py +11 -0
  167. fennec_rag-0.1.1/fennec/rag/multi_hop/query_decomposer.py +315 -0
  168. fennec_rag-0.1.1/fennec/rag/rag_ui/__init__.py +17 -0
  169. fennec_rag-0.1.1/fennec/rag/rag_ui/adapter.py +549 -0
  170. fennec_rag-0.1.1/fennec/rag/rag_ui/dataclass.py +204 -0
  171. fennec_rag-0.1.1/fennec/rag/rag_ui/enum.py +22 -0
  172. fennec_rag-0.1.1/fennec/rag/rag_ui/file_process.py +122 -0
  173. fennec_rag-0.1.1/fennec/rag/rag_ui/rag_chat_ui.py +529 -0
  174. fennec_rag-0.1.1/fennec/rag/rag_ui/session_store.py +162 -0
  175. fennec_rag-0.1.1/fennec/rag/rag_ui/templet.py +889 -0
  176. fennec_rag-0.1.1/fennec/rag/self_improving_rag/__init__.py +19 -0
  177. fennec_rag-0.1.1/fennec/rag/self_improving_rag/hyde.py +157 -0
  178. fennec_rag-0.1.1/fennec/rag/self_improving_rag/recursive.py +185 -0
  179. fennec_rag-0.1.1/fennec/rag/self_improving_rag/self_config.py +118 -0
  180. fennec_rag-0.1.1/fennec/rag/self_improving_rag/self_improving_rag.py +392 -0
  181. fennec_rag-0.1.1/fennec/rag/self_improving_rag/self_rag_dataclass.py +159 -0
  182. fennec_rag-0.1.1/fennec/rag/streaming_rag/__init__.py +11 -0
  183. fennec_rag-0.1.1/fennec/rag/streaming_rag/protocols.py +24 -0
  184. fennec_rag-0.1.1/fennec/rag/streaming_rag/streaming_config.py +29 -0
  185. fennec_rag-0.1.1/fennec/rag/streaming_rag/streaming_enum.py +9 -0
  186. fennec_rag-0.1.1/fennec/rag/streaming_rag/streaming_rag.py +453 -0
  187. fennec_rag-0.1.1/fennec/router/__init__.py +10 -0
  188. fennec_rag-0.1.1/fennec/router/route.py +275 -0
  189. fennec_rag-0.1.1/fennec/router/route_cache.py +64 -0
  190. fennec_rag-0.1.1/fennec/router/route_collections.py +110 -0
  191. fennec_rag-0.1.1/fennec/router/route_config.py +19 -0
  192. fennec_rag-0.1.1/fennec/router/route_metrics.py +81 -0
  193. fennec_rag-0.1.1/fennec/router/route_result.py +47 -0
  194. fennec_rag-0.1.1/fennec/router/semantic_router.py +461 -0
  195. fennec_rag-0.1.1/fennec/vector_database/__init__.py +14 -0
  196. fennec_rag-0.1.1/fennec/vector_database/base.py +383 -0
  197. fennec_rag-0.1.1/fennec/vector_database/chroma.py +714 -0
  198. fennec_rag-0.1.1/fennec/vector_database/faiss.py +1009 -0
  199. fennec_rag-0.1.1/fennec/vector_database/pinecone.py +1227 -0
  200. fennec_rag-0.1.1/fennec_rag.egg-info/PKG-INFO +222 -0
  201. fennec_rag-0.1.1/fennec_rag.egg-info/SOURCES.txt +206 -0
  202. fennec_rag-0.1.1/fennec_rag.egg-info/dependency_links.txt +1 -0
  203. fennec_rag-0.1.1/fennec_rag.egg-info/requires.txt +106 -0
  204. fennec_rag-0.1.1/fennec_rag.egg-info/top_level.txt +1 -0
  205. fennec_rag-0.1.1/pyproject.toml +3 -0
  206. fennec_rag-0.1.1/setup.cfg +24 -0
  207. fennec_rag-0.1.1/setup.py +116 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 fennec-rag contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,10 @@
1
+ include README.md
2
+ include LICENSE
3
+ include pyproject.toml
4
+ recursive-include fennec *.py
5
+ recursive-include fennec *.typed
6
+ exclude fennec/test.ipynb
7
+ global-exclude __pycache__
8
+ global-exclude *.pyc
9
+ global-exclude *.pyo
10
+ global-exclude .DS_Store
@@ -0,0 +1,222 @@
1
+ Metadata-Version: 2.4
2
+ Name: fennec-rag
3
+ Version: 0.1.1
4
+ Summary: A comprehensive RAG framework with Arabic language support, multi-provider embeddings, and advanced RAG strategies
5
+ Home-page: https://fennec-community.vercel.app/#overview
6
+ Author: Yousef Khalil
7
+ Author-email: yousefkhalil435@gmail.com
8
+ License: MIT
9
+ Project-URL: Documentation, https://github.com/YousefKhalil10/fennec-rag-projects
10
+ Keywords: rag,retrieval-augmented-generation,arabic,nlp,llm,embeddings,vector-database,ai,machine-learning
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Natural Language :: Arabic
23
+ Classifier: Natural Language :: English
24
+ Requires-Python: >=3.9
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: numpy>=1.24.0
28
+ Requires-Dist: requests>=2.28.0
29
+ Requires-Dist: pydantic>=2.0.0
30
+ Requires-Dist: tiktoken>=0.5.0
31
+ Requires-Dist: tqdm>=4.65.0
32
+ Provides-Extra: faiss
33
+ Requires-Dist: faiss-cpu>=1.7.4; extra == "faiss"
34
+ Provides-Extra: faiss-gpu
35
+ Requires-Dist: faiss-gpu>=1.7.4; extra == "faiss-gpu"
36
+ Provides-Extra: chroma
37
+ Requires-Dist: chromadb>=0.4.0; extra == "chroma"
38
+ Provides-Extra: pinecone
39
+ Requires-Dist: pinecone-client>=3.0.0; extra == "pinecone"
40
+ Provides-Extra: openai
41
+ Requires-Dist: openai>=1.0.0; extra == "openai"
42
+ Provides-Extra: anthropic
43
+ Requires-Dist: anthropic>=0.20.0; extra == "anthropic"
44
+ Provides-Extra: gemini
45
+ Requires-Dist: google-genai>=1.0.0; extra == "gemini"
46
+ Provides-Extra: mistral
47
+ Requires-Dist: mistralai>=1.0.0; extra == "mistral"
48
+ Provides-Extra: huggingface
49
+ Requires-Dist: transformers>=4.30.0; extra == "huggingface"
50
+ Requires-Dist: torch>=2.0.0; extra == "huggingface"
51
+ Provides-Extra: ollama
52
+ Requires-Dist: aiohttp>=3.9.0; extra == "ollama"
53
+ Provides-Extra: sentence-transformers
54
+ Requires-Dist: sentence-transformers>=2.2.0; extra == "sentence-transformers"
55
+ Provides-Extra: pdf
56
+ Requires-Dist: pypdf>=3.0.0; extra == "pdf"
57
+ Requires-Dist: PyPDF2>=3.0.0; extra == "pdf"
58
+ Provides-Extra: docx
59
+ Requires-Dist: python-docx>=1.0.0; extra == "docx"
60
+ Provides-Extra: excel
61
+ Requires-Dist: openpyxl>=3.1.0; extra == "excel"
62
+ Provides-Extra: html
63
+ Requires-Dist: beautifulsoup4>=4.12.0; extra == "html"
64
+ Requires-Dist: lxml>=4.9.0; extra == "html"
65
+ Provides-Extra: web
66
+ Requires-Dist: aiohttp>=3.9.0; extra == "web"
67
+ Requires-Dist: beautifulsoup4>=4.12.0; extra == "web"
68
+ Provides-Extra: chardet
69
+ Requires-Dist: chardet>=5.0.0; extra == "chardet"
70
+ Provides-Extra: jq
71
+ Requires-Dist: jq>=1.6.0; extra == "jq"
72
+ Provides-Extra: arabic
73
+ Requires-Dist: stanza>=1.5.0; extra == "arabic"
74
+ Requires-Dist: camel-tools>=1.5.0; extra == "arabic"
75
+ Provides-Extra: jinja2
76
+ Requires-Dist: jinja2>=3.1.0; extra == "jinja2"
77
+ Provides-Extra: observability
78
+ Requires-Dist: fastapi>=0.100.0; extra == "observability"
79
+ Requires-Dist: uvicorn>=0.23.0; extra == "observability"
80
+ Provides-Extra: eval
81
+ Requires-Dist: scikit-learn>=1.3.0; extra == "eval"
82
+ Provides-Extra: crypto
83
+ Requires-Dist: cryptography>=41.0.0; extra == "crypto"
84
+ Provides-Extra: all
85
+ Requires-Dist: faiss-cpu>=1.7.4; extra == "all"
86
+ Requires-Dist: chromadb>=0.4.0; extra == "all"
87
+ Requires-Dist: pinecone-client>=3.0.0; extra == "all"
88
+ Requires-Dist: openai>=1.0.0; extra == "all"
89
+ Requires-Dist: anthropic>=0.20.0; extra == "all"
90
+ Requires-Dist: google-genai>=1.0.0; extra == "all"
91
+ Requires-Dist: mistralai>=1.0.0; extra == "all"
92
+ Requires-Dist: transformers>=4.30.0; extra == "all"
93
+ Requires-Dist: torch>=2.0.0; extra == "all"
94
+ Requires-Dist: sentence-transformers>=2.2.0; extra == "all"
95
+ Requires-Dist: aiohttp>=3.9.0; extra == "all"
96
+ Requires-Dist: pypdf>=3.0.0; extra == "all"
97
+ Requires-Dist: python-docx>=1.0.0; extra == "all"
98
+ Requires-Dist: openpyxl>=3.1.0; extra == "all"
99
+ Requires-Dist: beautifulsoup4>=4.12.0; extra == "all"
100
+ Requires-Dist: lxml>=4.9.0; extra == "all"
101
+ Requires-Dist: chardet>=5.0.0; extra == "all"
102
+ Requires-Dist: jq>=1.6.0; extra == "all"
103
+ Requires-Dist: stanza>=1.5.0; extra == "all"
104
+ Requires-Dist: jinja2>=3.1.0; extra == "all"
105
+ Requires-Dist: fastapi>=0.100.0; extra == "all"
106
+ Requires-Dist: uvicorn>=0.23.0; extra == "all"
107
+ Requires-Dist: scikit-learn>=1.3.0; extra == "all"
108
+ Requires-Dist: cryptography>=41.0.0; extra == "all"
109
+ Dynamic: author
110
+ Dynamic: author-email
111
+ Dynamic: classifier
112
+ Dynamic: description
113
+ Dynamic: description-content-type
114
+ Dynamic: home-page
115
+ Dynamic: keywords
116
+ Dynamic: license
117
+ Dynamic: license-file
118
+ Dynamic: project-url
119
+ Dynamic: provides-extra
120
+ Dynamic: requires-dist
121
+ Dynamic: requires-python
122
+ Dynamic: summary
123
+
124
+
125
+ <p align="center">
126
+ <img src="logo.png" alt="Fennec-RAG " width="300"/>
127
+ </p>
128
+ <div align="center">
129
+
130
+ <br/>
131
+
132
+ # 🦊 fennec-rag
133
+
134
+ A comprehensive, production-ready **Retrieval-Augmented Generation (RAG)** framework with first-class **Arabic language support**, multi-provider embeddings, and a rich set of advanced RAG strategies.
135
+
136
+ [![PyPI version](https://badge.fury.io/py/fennec-rag.svg)](https://badge.fury.io/py/fennec-rag)
137
+ [![Python](https://img.shields.io/pypi/pyversions/fennec-rag)](https://pypi.org/project/fennec-rag/)
138
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
139
+
140
+ ---
141
+
142
+ ## ✨ Features
143
+
144
+ - 🌍 **Arabic-first NLP** — dedicated Arabic chunker, embedder, and prompt templates
145
+ - 🔌 **Multi-provider LLMs** — OpenAI, Anthropic, Gemini, Mistral, HuggingFace, Ollama
146
+ - 🗄️ **Multiple vector databases** — FAISS, ChromaDB, Pinecone
147
+ - 🧩 **Advanced RAG strategies** — Conversational, Agentic, Graph, Multi-hop, Federated, Self-improving, Streaming, Domain-specific
148
+ - 🛡️ **Hallucination Guard** — built-in hallucination detection and grounding
149
+ - 📊 **Observability & Evaluation** — tracing, metrics, dashboards, RAG evaluation suite
150
+ - 📄 **Rich document loaders** — PDF, DOCX, HTML, CSV, JSON, Excel, Web, Directory
151
+ - 💾 **Caching & Persistence** — multi-level cache, backup, encryption support
152
+ - 🔍 **Hybrid Search** — BM25 + semantic search with TF-IDF and Stanza
153
+ - 🧠 **Memory systems** — Buffer, Window, Summary, and Entity memory
154
+ - 🔌 **Plugin system** — extensible architecture for custom components
155
+ - 🖥️ **Chat UI** — built-in RAG chat interface
156
+
157
+ ---
158
+
159
+ ## 📦 Installation
160
+
161
+ ### Basic install (core only)
162
+ ```bash
163
+ pip install fennec-rag
164
+ ```
165
+
166
+ ### With specific providers
167
+ ```bash
168
+ # OpenAI + FAISS
169
+ pip install "fennec-rag[openai,faiss]"
170
+
171
+ # Anthropic + ChromaDB
172
+ pip install "fennec-rag[anthropic,chroma]"
173
+
174
+ # Google Gemini + Pinecone
175
+ pip install "fennec-rag[gemini,pinecone]"
176
+
177
+ # Arabic NLP support
178
+ pip install "fennec-rag[arabic]"
179
+
180
+ # Document loaders
181
+ pip install "fennec-rag[pdf,docx,html,excel]"
182
+
183
+ # Full install (all optional dependencies)
184
+ pip install "fennec-rag[all]"
185
+ ```
186
+
187
+
188
+
189
+
190
+ ---
191
+
192
+ ## 🔧 Optional Dependencies
193
+
194
+ | Extra | Packages | Use case |
195
+ |-------|----------|----------|
196
+ | `faiss` | faiss-cpu | FAISS vector database |
197
+ | `chroma` | chromadb | ChromaDB vector database |
198
+ | `pinecone` | pinecone-client | Pinecone vector database |
199
+ | `openai` | openai | OpenAI LLM & embeddings |
200
+ | `anthropic` | anthropic | Claude LLM |
201
+ | `gemini` | google-genai | Google Gemini LLM & embeddings |
202
+ | `mistral` | mistralai | Mistral LLM & embeddings |
203
+ | `huggingface` | transformers, torch | Local HuggingFace models |
204
+ | `sentence-transformers` | sentence-transformers | Sentence embeddings |
205
+ | `ollama` | aiohttp | Ollama local LLM |
206
+ | `pdf` | pypdf, PyPDF2 | PDF loading |
207
+ | `docx` | python-docx | Word document loading |
208
+ | `excel` | openpyxl | Excel file loading |
209
+ | `html` | beautifulsoup4, lxml | HTML loading |
210
+ | `web` | aiohttp, beautifulsoup4 | Web page loading |
211
+ | `arabic` | stanza, camel-tools | Advanced Arabic NLP |
212
+ | `jinja2` | jinja2 | Jinja2 prompt templates |
213
+ | `observability` | fastapi, uvicorn | Observability API server |
214
+ | `eval` | scikit-learn | RAG evaluation metrics |
215
+ | `crypto` | cryptography | Encrypted persistence |
216
+ | `all` | everything above | Full installation |
217
+
218
+ ---
219
+
220
+ ## 📝 License
221
+
222
+ MIT License — see [LICENSE](LICENSE) for details.
@@ -0,0 +1,99 @@
1
+
2
+ <p align="center">
3
+ <img src="logo.png" alt="Fennec-RAG " width="300"/>
4
+ </p>
5
+ <div align="center">
6
+
7
+ <br/>
8
+
9
+ # 🦊 fennec-rag
10
+
11
+ A comprehensive, production-ready **Retrieval-Augmented Generation (RAG)** framework with first-class **Arabic language support**, multi-provider embeddings, and a rich set of advanced RAG strategies.
12
+
13
+ [![PyPI version](https://badge.fury.io/py/fennec-rag.svg)](https://badge.fury.io/py/fennec-rag)
14
+ [![Python](https://img.shields.io/pypi/pyversions/fennec-rag)](https://pypi.org/project/fennec-rag/)
15
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
16
+
17
+ ---
18
+
19
+ ## ✨ Features
20
+
21
+ - 🌍 **Arabic-first NLP** — dedicated Arabic chunker, embedder, and prompt templates
22
+ - 🔌 **Multi-provider LLMs** — OpenAI, Anthropic, Gemini, Mistral, HuggingFace, Ollama
23
+ - 🗄️ **Multiple vector databases** — FAISS, ChromaDB, Pinecone
24
+ - 🧩 **Advanced RAG strategies** — Conversational, Agentic, Graph, Multi-hop, Federated, Self-improving, Streaming, Domain-specific
25
+ - 🛡️ **Hallucination Guard** — built-in hallucination detection and grounding
26
+ - 📊 **Observability & Evaluation** — tracing, metrics, dashboards, RAG evaluation suite
27
+ - 📄 **Rich document loaders** — PDF, DOCX, HTML, CSV, JSON, Excel, Web, Directory
28
+ - 💾 **Caching & Persistence** — multi-level cache, backup, encryption support
29
+ - 🔍 **Hybrid Search** — BM25 + semantic search with TF-IDF and Stanza
30
+ - 🧠 **Memory systems** — Buffer, Window, Summary, and Entity memory
31
+ - 🔌 **Plugin system** — extensible architecture for custom components
32
+ - 🖥️ **Chat UI** — built-in RAG chat interface
33
+
34
+ ---
35
+
36
+ ## 📦 Installation
37
+
38
+ ### Basic install (core only)
39
+ ```bash
40
+ pip install fennec-rag
41
+ ```
42
+
43
+ ### With specific providers
44
+ ```bash
45
+ # OpenAI + FAISS
46
+ pip install "fennec-rag[openai,faiss]"
47
+
48
+ # Anthropic + ChromaDB
49
+ pip install "fennec-rag[anthropic,chroma]"
50
+
51
+ # Google Gemini + Pinecone
52
+ pip install "fennec-rag[gemini,pinecone]"
53
+
54
+ # Arabic NLP support
55
+ pip install "fennec-rag[arabic]"
56
+
57
+ # Document loaders
58
+ pip install "fennec-rag[pdf,docx,html,excel]"
59
+
60
+ # Full install (all optional dependencies)
61
+ pip install "fennec-rag[all]"
62
+ ```
63
+
64
+
65
+
66
+
67
+ ---
68
+
69
+ ## 🔧 Optional Dependencies
70
+
71
+ | Extra | Packages | Use case |
72
+ |-------|----------|----------|
73
+ | `faiss` | faiss-cpu | FAISS vector database |
74
+ | `chroma` | chromadb | ChromaDB vector database |
75
+ | `pinecone` | pinecone-client | Pinecone vector database |
76
+ | `openai` | openai | OpenAI LLM & embeddings |
77
+ | `anthropic` | anthropic | Claude LLM |
78
+ | `gemini` | google-genai | Google Gemini LLM & embeddings |
79
+ | `mistral` | mistralai | Mistral LLM & embeddings |
80
+ | `huggingface` | transformers, torch | Local HuggingFace models |
81
+ | `sentence-transformers` | sentence-transformers | Sentence embeddings |
82
+ | `ollama` | aiohttp | Ollama local LLM |
83
+ | `pdf` | pypdf, PyPDF2 | PDF loading |
84
+ | `docx` | python-docx | Word document loading |
85
+ | `excel` | openpyxl | Excel file loading |
86
+ | `html` | beautifulsoup4, lxml | HTML loading |
87
+ | `web` | aiohttp, beautifulsoup4 | Web page loading |
88
+ | `arabic` | stanza, camel-tools | Advanced Arabic NLP |
89
+ | `jinja2` | jinja2 | Jinja2 prompt templates |
90
+ | `observability` | fastapi, uvicorn | Observability API server |
91
+ | `eval` | scikit-learn | RAG evaluation metrics |
92
+ | `crypto` | cryptography | Encrypted persistence |
93
+ | `all` | everything above | Full installation |
94
+
95
+ ---
96
+
97
+ ## 📝 License
98
+
99
+ MIT License — see [LICENSE](LICENSE) for details.
File without changes
@@ -0,0 +1,6 @@
1
+ from .multi_level_cache import MultiLevelCache
2
+ from .cache_strategies import CacheStrategy
3
+ from .config_cache import CacheConfig
4
+ from .cache_entry import CacheEntry
5
+ from .cache_metrics import CacheMetrics
6
+ __all__=["CacheEntry","CacheStrategy","MultiLevelCache","CacheMetrics","CacheConfig"]
@@ -0,0 +1,117 @@
1
+ from dataclasses import dataclass, field
2
+ import time
3
+ from typing import Any, Optional
4
+ import pickle
5
+ from .config_cache import CacheConfig
6
+ config=CacheConfig()
7
+
8
+
9
+ @dataclass
10
+ class CacheEntry:
11
+ """
12
+ يمثل عنصر مخزن مؤقتاً مع بيانات وصفية\n
13
+ Represents a cached item with metadata
14
+ """
15
+ key: str # المفتاح | Key
16
+ value: Any # القيمة المخزنة | Cached value
17
+ created_at: float = field(default_factory=time.time) # وقت الإنشاء | Creation time
18
+ last_access: float = field(default_factory=time.time) # آخر وصول | Last access time
19
+ hits: int = 0 # عدد مرات الوصول | Access count
20
+ ttl: Optional[float] = None # مدة الصلاحية بالثواني | Time to live in seconds
21
+ size_bytes: int = 0 # الحجم بالبايتات | Size in bytes
22
+
23
+ def __post_init__(self):
24
+ """
25
+ حساب الحجم بعد التهيئة\n
26
+ Calculate size after initialization
27
+ """
28
+ if self.size_bytes == 0:
29
+ self.size_bytes = self._calculate_size()
30
+
31
+ def _calculate_size(self) -> int:
32
+ """
33
+ تقدير حجم الذاكرة للقيمة المخزنة\n
34
+ Estimate memory size of cached value
35
+
36
+ Returns:
37
+ الحجم بالبايتات | Size in bytes
38
+ """
39
+ try:
40
+ # محاولة حساب الحجم الفعلي
41
+ # Try to calculate actual size
42
+ return len(pickle.dumps(self.value))
43
+ except Exception:
44
+ # حجم افتراضي إذا فشل الحساب
45
+ # Default size if calculation fails
46
+ return config.size_bytes # Default 1KB
47
+
48
+ def increment_hits(self) -> None:
49
+ """
50
+ زيادة عداد الوصول وتحديث وقت الوصول\n
51
+ Increment hit counter and update access time
52
+ """
53
+ self.hits += 1
54
+ self.last_access = time.time()
55
+
56
+ def is_expired(self) -> bool:
57
+ """
58
+ التحقق من انتهاء صلاحية العنصر بناءً على TTL\n
59
+ Check if entry has expired based on TTL
60
+
61
+ Returns:
62
+ True إذا انتهت الصلاحية | True if expired
63
+ """
64
+ if self.ttl is None:
65
+ return False
66
+
67
+ # حساب وقت انتهاء الصلاحية
68
+ # Calculate expiration time
69
+ expiration_time = self.created_at + self.ttl
70
+ return time.time() > expiration_time
71
+
72
+ def age(self) -> float:
73
+ """
74
+ الحصول على عمر العنصر بالثواني\n
75
+ Get age of entry in seconds
76
+
77
+ Returns:
78
+ العمر بالثواني | Age in seconds
79
+ """
80
+ return time.time() - self.created_at
81
+
82
+ def idle_time(self) -> float:
83
+ """
84
+ الحصول على الوقت منذ آخر وصول بالثواني\n
85
+ Get time since last access in seconds
86
+
87
+ Returns:
88
+ الوقت الخامل بالثواني | Idle time in seconds
89
+ """
90
+ return time.time() - self.last_access
91
+
92
+ def get_stats(self) -> dict:
93
+ """
94
+ الحصول على إحصائيات العنصر\n
95
+ Get entry statistics
96
+
97
+ Returns:
98
+ قاموس الإحصائيات | Statistics dictionary
99
+ """
100
+ return {
101
+ 'key': self.key, # المفتاح | Key
102
+ 'hits': self.hits, # عدد الوصولات | Hit count
103
+ 'age_seconds': self.age(), # العمر | Age
104
+ 'idle_seconds': self.idle_time(), # الوقت الخامل | Idle time
105
+ 'size_bytes': self.size_bytes, # الحجم | Size
106
+ 'is_expired': self.is_expired(), # منتهي الصلاحية؟ | Is expired?
107
+ 'ttl': self.ttl # مدة الصلاحية | TTL
108
+ }
109
+
110
+ def __repr__(self) -> str:
111
+ """
112
+ تمثيل نصي للعنصر\n
113
+ Text representation of entry
114
+ """
115
+ status = "expired" if self.is_expired() else "valid"
116
+ return (f"CacheEntry(key='{self.key}', hits={self.hits}, "
117
+ f"age={self.age():.1f}s, status={status})")
@@ -0,0 +1,146 @@
1
+ from dataclasses import dataclass
2
+ from typing import Optional
3
+
4
+
5
+ @dataclass
6
+ class CacheMetrics:
7
+ """
8
+ Track cache performance metrics\n
9
+ تتبع مقاييس أداء ذاكرة التخزين المؤقت
10
+ """
11
+ # L1 cache hits | إصابات المستوى الأول
12
+ l1_hits: int = 0
13
+ # L2 cache hits | إصابات المستوى الثاني
14
+ l2_hits: int = 0
15
+ # L3 cache hits | إصابات المستوى الثالث
16
+ l3_hits: int = 0
17
+ # L1 cache misses | إخفاقات المستوى الأول
18
+ l1_misses: int = 0
19
+ # L2 cache misses | إخفاقات المستوى الثاني
20
+ l2_misses: int = 0
21
+ # L3 cache misses | إخفاقات المستوى الثالث
22
+ l3_misses: int = 0
23
+ # Total set operations | إجمالي عمليات التعيين
24
+ sets: int = 0
25
+ # Total evictions | إجمالي عمليات الإخلاء
26
+ evictions: int = 0
27
+ # Total promotions | إجمالي عمليات الترقية
28
+ promotions: int = 0
29
+ # Total expirations | إجمالي عمليات انتهاء الصلاحية
30
+ expirations: int = 0
31
+
32
+ def record_get(self, level: int, hit: bool) -> None:
33
+ """
34
+ Record a get operation\n
35
+ تسجيل عملية قراءة
36
+
37
+ Args:
38
+ level: Cache level (1, 2, or 3) | مستوى التخزين المؤقت (1 أو 2 أو 3)
39
+ hit: Whether the get was a hit or miss | ما إذا كانت العملية إصابة أم إخفاق
40
+ """
41
+ if level == 1:
42
+ if hit:
43
+ self.l1_hits += 1
44
+ else:
45
+ self.l1_misses += 1
46
+ elif level == 2:
47
+ if hit:
48
+ self.l2_hits += 1
49
+ else:
50
+ self.l2_misses += 1
51
+ elif level == 3:
52
+ if hit:
53
+ self.l3_hits += 1
54
+ else:
55
+ self.l3_misses += 1
56
+
57
+ def record_set(self) -> None:
58
+ """
59
+ Record a set operation\n
60
+ تسجيل عملية تعيين
61
+ """
62
+ self.sets += 1
63
+
64
+ def record_eviction(self) -> None:
65
+ """
66
+ Record a cache eviction\n
67
+ تسجيل عملية إخلاء من ذاكرة التخزين عندما تمتلئ الذاكره
68
+ """
69
+ self.evictions += 1
70
+
71
+ def record_promotion(self) -> None:
72
+ """
73
+ Record a promotion between cache levels\n
74
+ تسجيل عملية ترقية بين مستويات التخزين المؤقت
75
+ """
76
+ self.promotions += 1
77
+
78
+ def record_expiration(self) -> None:
79
+ """
80
+ Record a cache entry expiration\n
81
+ تسجيل عملية انتهاء صلاحية عنصر في ذاكرة التخزين المؤقت
82
+ """
83
+ self.expirations += 1
84
+
85
+ def get_hit_rate(self, level: Optional[int] = None) -> float:
86
+ """
87
+ Calculate hit rate for specified level or overall\n
88
+ حساب معدل الإصابة للمستوى المحدد أو الإجمالي
89
+
90
+ Args:
91
+ level: Cache level (1, 2, 3) or None for overall | مستوى التخزين (1، 2، 3) أو None للإجمالي
92
+
93
+ Returns:
94
+ Hit rate as a float between 0 and 1 | معدل الإصابة كرقم عشري بين 0 و 1
95
+ """
96
+ if level == 1:
97
+ total = self.l1_hits + self.l1_misses
98
+ return self.l1_hits / total if total > 0 else 0.0
99
+ elif level == 2:
100
+ total = self.l2_hits + self.l2_misses
101
+ return self.l2_hits / total if total > 0 else 0.0
102
+ elif level == 3:
103
+ total = self.l3_hits + self.l3_misses
104
+ return self.l3_hits / total if total > 0 else 0.0
105
+ else:
106
+ # Overall hit rate | معدل الإصابة الإجمالي
107
+ total_hits = self.l1_hits + self.l2_hits + self.l3_hits
108
+ total_gets = total_hits + self.l1_misses + self.l2_misses + self.l3_misses
109
+ return total_hits / total_gets if total_gets > 0 else 0.0
110
+
111
+ def get_stats(self) -> dict:
112
+ """
113
+ Get all statistics as dictionary\n
114
+ الحصول على جميع الإحصائيات كقاموس
115
+
116
+ Returns:
117
+ Dictionary containing all cache metrics | قاموس يحتوي على جميع مقاييس التخزين المؤقت
118
+ """
119
+ return {
120
+ 'l1_hits': self.l1_hits,
121
+ 'l2_hits': self.l2_hits,
122
+ 'l3_hits': self.l3_hits,
123
+ 'total_hits': self.l1_hits + self.l2_hits + self.l3_hits,
124
+ 'l1_misses': self.l1_misses,
125
+ 'l2_misses': self.l2_misses,
126
+ 'l3_misses': self.l3_misses,
127
+ 'total_misses': self.l1_misses + self.l2_misses + self.l3_misses,
128
+ 'l1_hit_rate': self.get_hit_rate(1),
129
+ 'l2_hit_rate': self.get_hit_rate(2),
130
+ 'l3_hit_rate': self.get_hit_rate(3),
131
+ 'overall_hit_rate': self.get_hit_rate(),
132
+ 'sets': self.sets,
133
+ 'evictions': self.evictions,
134
+ 'promotions': self.promotions,
135
+ 'expirations': self.expirations,
136
+
137
+ }
138
+
139
+ def reset(self) -> None:
140
+ """
141
+ Reset all metrics to zero\n
142
+ إعادة تعيين جميع المقاييس إلى الصفر
143
+ """
144
+ self.l1_hits = self.l2_hits = self.l3_hits = 0
145
+ self.l1_misses = self.l2_misses = self.l3_misses = 0
146
+ self.sets = self.evictions = self.promotions = self.expirations = 0
@@ -0,0 +1,10 @@
1
+
2
+ from enum import Enum
3
+
4
+ class CacheStrategy(Enum):
5
+ """Cache eviction strategies"""
6
+ LRU = "lru" # Least Recently Used
7
+ LFU = "lfu" # Least Frequently Used
8
+ FIFO = "fifo" # First In First Out
9
+ TTL = "ttl" # Time To Live based
10
+ ADAPTIVE = "adaptive" # Adaptive strategy