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.
- fennec_rag-0.1.1/LICENSE +21 -0
- fennec_rag-0.1.1/MANIFEST.in +10 -0
- fennec_rag-0.1.1/PKG-INFO +222 -0
- fennec_rag-0.1.1/README.md +99 -0
- fennec_rag-0.1.1/fennec/__init__.py +0 -0
- fennec_rag-0.1.1/fennec/cache/__init__.py +6 -0
- fennec_rag-0.1.1/fennec/cache/cache_entry.py +117 -0
- fennec_rag-0.1.1/fennec/cache/cache_metrics.py +146 -0
- fennec_rag-0.1.1/fennec/cache/cache_strategies.py +10 -0
- fennec_rag-0.1.1/fennec/cache/config_cache.py +116 -0
- fennec_rag-0.1.1/fennec/cache/multi_level_cache.py +961 -0
- fennec_rag-0.1.1/fennec/chunks/__init__.py +35 -0
- fennec_rag-0.1.1/fennec/chunks/arabic_chunker.py +831 -0
- fennec_rag-0.1.1/fennec/chunks/base.py +118 -0
- fennec_rag-0.1.1/fennec/chunks/chunk_config.py +54 -0
- fennec_rag-0.1.1/fennec/chunks/doc_model.py +32 -0
- fennec_rag-0.1.1/fennec/chunks/multi_chunker.py +860 -0
- fennec_rag-0.1.1/fennec/chunks/text_splitter.py +250 -0
- fennec_rag-0.1.1/fennec/context/__init__.py +12 -0
- fennec_rag-0.1.1/fennec/context/allocations.py +39 -0
- fennec_rag-0.1.1/fennec/context/context_config.py +24 -0
- fennec_rag-0.1.1/fennec/context/context_manager.py +525 -0
- fennec_rag-0.1.1/fennec/context/stratgey.py +40 -0
- fennec_rag-0.1.1/fennec/document_loaders/__init__.py +74 -0
- fennec_rag-0.1.1/fennec/document_loaders/auto_loader.py +202 -0
- fennec_rag-0.1.1/fennec/document_loaders/base_loader.py +211 -0
- fennec_rag-0.1.1/fennec/document_loaders/config_loader.py +156 -0
- fennec_rag-0.1.1/fennec/document_loaders/csv_loader.py +302 -0
- fennec_rag-0.1.1/fennec/document_loaders/directory_loader.py +302 -0
- fennec_rag-0.1.1/fennec/document_loaders/docx_loader.py +188 -0
- fennec_rag-0.1.1/fennec/document_loaders/html_loader.py +241 -0
- fennec_rag-0.1.1/fennec/document_loaders/json_loader.py +271 -0
- fennec_rag-0.1.1/fennec/document_loaders/pdf_loader.py +255 -0
- fennec_rag-0.1.1/fennec/document_loaders/text_loader.py +233 -0
- fennec_rag-0.1.1/fennec/document_loaders/web_loader.py +235 -0
- fennec_rag-0.1.1/fennec/embeddings/__init__.py +99 -0
- fennec_rag-0.1.1/fennec/embeddings/arabic_embedder.py +903 -0
- fennec_rag-0.1.1/fennec/embeddings/base_embedder.py +512 -0
- fennec_rag-0.1.1/fennec/embeddings/config_embedder.py +54 -0
- fennec_rag-0.1.1/fennec/embeddings/gemini_embedder.py +788 -0
- fennec_rag-0.1.1/fennec/embeddings/hugginface_embedder.py +484 -0
- fennec_rag-0.1.1/fennec/embeddings/mistral_embedder.py +604 -0
- fennec_rag-0.1.1/fennec/embeddings/ollama_embedder.py +681 -0
- fennec_rag-0.1.1/fennec/embeddings/openai_embedder.py +743 -0
- fennec_rag-0.1.1/fennec/evaluator/__init__.py +17 -0
- fennec_rag-0.1.1/fennec/evaluator/dashboard.py +426 -0
- fennec_rag-0.1.1/fennec/evaluator/eval_report.py +83 -0
- fennec_rag-0.1.1/fennec/evaluator/eval_result.py +47 -0
- fennec_rag-0.1.1/fennec/evaluator/evaluator.py +349 -0
- fennec_rag-0.1.1/fennec/evaluator/generation_metrics.py +38 -0
- fennec_rag-0.1.1/fennec/evaluator/retrieval_metrics.py +22 -0
- fennec_rag-0.1.1/fennec/llm/__init__.py +60 -0
- fennec_rag-0.1.1/fennec/llm/anthropic_interface.py +134 -0
- fennec_rag-0.1.1/fennec/llm/base_llm_interface.py +163 -0
- fennec_rag-0.1.1/fennec/llm/config_llm.py +22 -0
- fennec_rag-0.1.1/fennec/llm/gemini_interface.py +227 -0
- fennec_rag-0.1.1/fennec/llm/hallucination/__init__.py +40 -0
- fennec_rag-0.1.1/fennec/llm/hallucination/config.py +419 -0
- fennec_rag-0.1.1/fennec/llm/hallucination/hallucination_guard.py +567 -0
- fennec_rag-0.1.1/fennec/llm/hallucination/hallucination_pattern.py +57 -0
- fennec_rag-0.1.1/fennec/llm/hallucination/protected_llm_interface.py +473 -0
- fennec_rag-0.1.1/fennec/llm/hugginface_interface.py +275 -0
- fennec_rag-0.1.1/fennec/llm/mistral_interface.py +135 -0
- fennec_rag-0.1.1/fennec/llm/ollama_interface.py +282 -0
- fennec_rag-0.1.1/fennec/llm/openai_interface.py +134 -0
- fennec_rag-0.1.1/fennec/memory/__init__.py +42 -0
- fennec_rag-0.1.1/fennec/memory/core/__init__.py +22 -0
- fennec_rag-0.1.1/fennec/memory/core/base.py +103 -0
- fennec_rag-0.1.1/fennec/memory/core/config.py +147 -0
- fennec_rag-0.1.1/fennec/memory/core/memory_entry.py +231 -0
- fennec_rag-0.1.1/fennec/memory/core/memory_type.py +122 -0
- fennec_rag-0.1.1/fennec/memory/core/models.py +62 -0
- fennec_rag-0.1.1/fennec/memory/memories/__init__.py +14 -0
- fennec_rag-0.1.1/fennec/memory/memories/buffer_memory.py +116 -0
- fennec_rag-0.1.1/fennec/memory/memories/entity_memory.py +228 -0
- fennec_rag-0.1.1/fennec/memory/memories/summary_memory.py +206 -0
- fennec_rag-0.1.1/fennec/memory/memories/window_memory.py +66 -0
- fennec_rag-0.1.1/fennec/monitor/__init__.py +30 -0
- fennec_rag-0.1.1/fennec/monitor/metrics_point.py +38 -0
- fennec_rag-0.1.1/fennec/monitor/monitor.py +415 -0
- fennec_rag-0.1.1/fennec/monitor/timer_context.py +60 -0
- fennec_rag-0.1.1/fennec/observability/__init__.py +104 -0
- fennec_rag-0.1.1/fennec/observability/anomaly.py +288 -0
- fennec_rag-0.1.1/fennec/observability/api.py +327 -0
- fennec_rag-0.1.1/fennec/observability/config.py +73 -0
- fennec_rag-0.1.1/fennec/observability/dashboard.py +732 -0
- fennec_rag-0.1.1/fennec/observability/export.py +330 -0
- fennec_rag-0.1.1/fennec/observability/observability.py +611 -0
- fennec_rag-0.1.1/fennec/observability/storage.py +494 -0
- fennec_rag-0.1.1/fennec/observability/tracer.py +511 -0
- fennec_rag-0.1.1/fennec/output_parser/__init__.py +26 -0
- fennec_rag-0.1.1/fennec/output_parser/base_parser.py +255 -0
- fennec_rag-0.1.1/fennec/output_parser/csv_parser.py +175 -0
- fennec_rag-0.1.1/fennec/output_parser/json_parser.py +180 -0
- fennec_rag-0.1.1/fennec/output_parser/list_parser.py +182 -0
- fennec_rag-0.1.1/fennec/output_parser/pydantic_parser.py +172 -0
- fennec_rag-0.1.1/fennec/output_parser/structured_parser.py +250 -0
- fennec_rag-0.1.1/fennec/output_parser/yaml_parser.py +260 -0
- fennec_rag-0.1.1/fennec/persistence/__init__.py +33 -0
- fennec_rag-0.1.1/fennec/persistence/backup.py +166 -0
- fennec_rag-0.1.1/fennec/persistence/cache.py +156 -0
- fennec_rag-0.1.1/fennec/persistence/enums.py +60 -0
- fennec_rag-0.1.1/fennec/persistence/manager.py +578 -0
- fennec_rag-0.1.1/fennec/persistence/metadata.py +129 -0
- fennec_rag-0.1.1/fennec/persistence/serializers.py +243 -0
- fennec_rag-0.1.1/fennec/plugins/__init__.py +17 -0
- fennec_rag-0.1.1/fennec/plugins/base.py +163 -0
- fennec_rag-0.1.1/fennec/plugins/manager.py +905 -0
- fennec_rag-0.1.1/fennec/plugins/plugin.py +280 -0
- fennec_rag-0.1.1/fennec/prompt/__init__.py +43 -0
- fennec_rag-0.1.1/fennec/prompt/core/__init__.py +10 -0
- fennec_rag-0.1.1/fennec/prompt/core/base_template.py +111 -0
- fennec_rag-0.1.1/fennec/prompt/core/chat_template.py +201 -0
- fennec_rag-0.1.1/fennec/prompt/core/few_shot_template.py +194 -0
- fennec_rag-0.1.1/fennec/prompt/core/prompt_template.py +275 -0
- fennec_rag-0.1.1/fennec/prompt/templates/__init__.py +17 -0
- fennec_rag-0.1.1/fennec/prompt/templates/arabic_prompts.py +281 -0
- fennec_rag-0.1.1/fennec/prompt/templates/system_prompts.py +221 -0
- fennec_rag-0.1.1/fennec/prompt/templates/task_prompts.py +327 -0
- fennec_rag-0.1.1/fennec/prompt/utils/__init__.py +17 -0
- fennec_rag-0.1.1/fennec/prompt/utils/formatters.py +354 -0
- fennec_rag-0.1.1/fennec/prompt/utils/validators.py +323 -0
- fennec_rag-0.1.1/fennec/prompt/utils/variable_extractor.py +267 -0
- fennec_rag-0.1.1/fennec/rag/agentic_rag/__init__.py +4 -0
- fennec_rag-0.1.1/fennec/rag/agentic_rag/action_step.py +15 -0
- fennec_rag-0.1.1/fennec/rag/agentic_rag/agentic_config.py +45 -0
- fennec_rag-0.1.1/fennec/rag/agentic_rag/agentic_rag.py +784 -0
- fennec_rag-0.1.1/fennec/rag/agentic_rag/agentic_result.py +37 -0
- fennec_rag-0.1.1/fennec/rag/agentic_rag/cache.py +33 -0
- fennec_rag-0.1.1/fennec/rag/agentic_rag/document.py +23 -0
- fennec_rag-0.1.1/fennec/rag/conversational_rag/__init__.py +11 -0
- fennec_rag-0.1.1/fennec/rag/conversational_rag/conversation_config.py +29 -0
- fennec_rag-0.1.1/fennec/rag/conversational_rag/conversation_history.py +193 -0
- fennec_rag-0.1.1/fennec/rag/conversational_rag/conversation_turn.py +42 -0
- fennec_rag-0.1.1/fennec/rag/conversational_rag/conversational_rag.py +355 -0
- fennec_rag-0.1.1/fennec/rag/core/__init__.py +20 -0
- fennec_rag-0.1.1/fennec/rag/core/base_rag_system.py +259 -0
- fennec_rag-0.1.1/fennec/rag/core/multi_doc_rag.py +657 -0
- fennec_rag-0.1.1/fennec/rag/core/prompt_router.py +307 -0
- fennec_rag-0.1.1/fennec/rag/core/rag_config.py +140 -0
- fennec_rag-0.1.1/fennec/rag/core/rag_system.py +819 -0
- fennec_rag-0.1.1/fennec/rag/core/reranker.py +434 -0
- fennec_rag-0.1.1/fennec/rag/domain_rag/__init__.py +12 -0
- fennec_rag-0.1.1/fennec/rag/domain_rag/domain_defination.py +211 -0
- fennec_rag-0.1.1/fennec/rag/domain_rag/domain_metrics.py +30 -0
- fennec_rag-0.1.1/fennec/rag/domain_rag/domain_specific_rag.py +637 -0
- fennec_rag-0.1.1/fennec/rag/federated_rag/__init__.py +4 -0
- fennec_rag-0.1.1/fennec/rag/federated_rag/circuitbreaker.py +61 -0
- fennec_rag-0.1.1/fennec/rag/federated_rag/federat.py +922 -0
- fennec_rag-0.1.1/fennec/rag/federated_rag/federat_cache.py +39 -0
- fennec_rag-0.1.1/fennec/rag/graph_rag/__init__.py +7 -0
- fennec_rag-0.1.1/fennec/rag/graph_rag/config.py +142 -0
- fennec_rag-0.1.1/fennec/rag/graph_rag/edges.py +136 -0
- fennec_rag-0.1.1/fennec/rag/graph_rag/graph_rag.py +600 -0
- fennec_rag-0.1.1/fennec/rag/graph_rag/knowledge_graph.py +344 -0
- fennec_rag-0.1.1/fennec/rag/graph_rag/node.py +139 -0
- fennec_rag-0.1.1/fennec/rag/hybrid_search/__init__.py +10 -0
- fennec_rag-0.1.1/fennec/rag/hybrid_search/bm25.py +134 -0
- fennec_rag-0.1.1/fennec/rag/hybrid_search/hybrid_search.py +719 -0
- fennec_rag-0.1.1/fennec/rag/hybrid_search/hybrid_search_config.py +16 -0
- fennec_rag-0.1.1/fennec/rag/hybrid_search/stanze_.py +150 -0
- fennec_rag-0.1.1/fennec/rag/hybrid_search/tfidf.py +103 -0
- fennec_rag-0.1.1/fennec/rag/multi_hop/__init__.py +7 -0
- fennec_rag-0.1.1/fennec/rag/multi_hop/multi_hop.py +733 -0
- fennec_rag-0.1.1/fennec/rag/multi_hop/multihop_dataclass.py +32 -0
- fennec_rag-0.1.1/fennec/rag/multi_hop/multihop_strategy.py +11 -0
- fennec_rag-0.1.1/fennec/rag/multi_hop/query_decomposer.py +315 -0
- fennec_rag-0.1.1/fennec/rag/rag_ui/__init__.py +17 -0
- fennec_rag-0.1.1/fennec/rag/rag_ui/adapter.py +549 -0
- fennec_rag-0.1.1/fennec/rag/rag_ui/dataclass.py +204 -0
- fennec_rag-0.1.1/fennec/rag/rag_ui/enum.py +22 -0
- fennec_rag-0.1.1/fennec/rag/rag_ui/file_process.py +122 -0
- fennec_rag-0.1.1/fennec/rag/rag_ui/rag_chat_ui.py +529 -0
- fennec_rag-0.1.1/fennec/rag/rag_ui/session_store.py +162 -0
- fennec_rag-0.1.1/fennec/rag/rag_ui/templet.py +889 -0
- fennec_rag-0.1.1/fennec/rag/self_improving_rag/__init__.py +19 -0
- fennec_rag-0.1.1/fennec/rag/self_improving_rag/hyde.py +157 -0
- fennec_rag-0.1.1/fennec/rag/self_improving_rag/recursive.py +185 -0
- fennec_rag-0.1.1/fennec/rag/self_improving_rag/self_config.py +118 -0
- fennec_rag-0.1.1/fennec/rag/self_improving_rag/self_improving_rag.py +392 -0
- fennec_rag-0.1.1/fennec/rag/self_improving_rag/self_rag_dataclass.py +159 -0
- fennec_rag-0.1.1/fennec/rag/streaming_rag/__init__.py +11 -0
- fennec_rag-0.1.1/fennec/rag/streaming_rag/protocols.py +24 -0
- fennec_rag-0.1.1/fennec/rag/streaming_rag/streaming_config.py +29 -0
- fennec_rag-0.1.1/fennec/rag/streaming_rag/streaming_enum.py +9 -0
- fennec_rag-0.1.1/fennec/rag/streaming_rag/streaming_rag.py +453 -0
- fennec_rag-0.1.1/fennec/router/__init__.py +10 -0
- fennec_rag-0.1.1/fennec/router/route.py +275 -0
- fennec_rag-0.1.1/fennec/router/route_cache.py +64 -0
- fennec_rag-0.1.1/fennec/router/route_collections.py +110 -0
- fennec_rag-0.1.1/fennec/router/route_config.py +19 -0
- fennec_rag-0.1.1/fennec/router/route_metrics.py +81 -0
- fennec_rag-0.1.1/fennec/router/route_result.py +47 -0
- fennec_rag-0.1.1/fennec/router/semantic_router.py +461 -0
- fennec_rag-0.1.1/fennec/vector_database/__init__.py +14 -0
- fennec_rag-0.1.1/fennec/vector_database/base.py +383 -0
- fennec_rag-0.1.1/fennec/vector_database/chroma.py +714 -0
- fennec_rag-0.1.1/fennec/vector_database/faiss.py +1009 -0
- fennec_rag-0.1.1/fennec/vector_database/pinecone.py +1227 -0
- fennec_rag-0.1.1/fennec_rag.egg-info/PKG-INFO +222 -0
- fennec_rag-0.1.1/fennec_rag.egg-info/SOURCES.txt +206 -0
- fennec_rag-0.1.1/fennec_rag.egg-info/dependency_links.txt +1 -0
- fennec_rag-0.1.1/fennec_rag.egg-info/requires.txt +106 -0
- fennec_rag-0.1.1/fennec_rag.egg-info/top_level.txt +1 -0
- fennec_rag-0.1.1/pyproject.toml +3 -0
- fennec_rag-0.1.1/setup.cfg +24 -0
- fennec_rag-0.1.1/setup.py +116 -0
fennec_rag-0.1.1/LICENSE
ADDED
|
@@ -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,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
|
+
[](https://badge.fury.io/py/fennec-rag)
|
|
137
|
+
[](https://pypi.org/project/fennec-rag/)
|
|
138
|
+
[](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
|
+
[](https://badge.fury.io/py/fennec-rag)
|
|
14
|
+
[](https://pypi.org/project/fennec-rag/)
|
|
15
|
+
[](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
|