ragforge-framework 0.1.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 (33) hide show
  1. ragforge_framework-0.1.0/.gitignore +15 -0
  2. ragforge_framework-0.1.0/.python-version +1 -0
  3. ragforge_framework-0.1.0/PKG-INFO +148 -0
  4. ragforge_framework-0.1.0/README.md +120 -0
  5. ragforge_framework-0.1.0/app.py +15 -0
  6. ragforge_framework-0.1.0/data/data.txt +1 -0
  7. ragforge_framework-0.1.0/pyproject.toml +36 -0
  8. ragforge_framework-0.1.0/ragforge_framework/__init__.py +13 -0
  9. ragforge_framework-0.1.0/ragforge_framework/admin/__init__.py +1 -0
  10. ragforge_framework-0.1.0/ragforge_framework/admin/routes.py +224 -0
  11. ragforge_framework-0.1.0/ragforge_framework/app.py +88 -0
  12. ragforge_framework-0.1.0/ragforge_framework/cache/__init__.py +1 -0
  13. ragforge_framework-0.1.0/ragforge_framework/cache/repository.py +155 -0
  14. ragforge_framework-0.1.0/ragforge_framework/cache/response_cache.py +105 -0
  15. ragforge_framework-0.1.0/ragforge_framework/cache/user_manager.py +264 -0
  16. ragforge_framework-0.1.0/ragforge_framework/cli.py +91 -0
  17. ragforge_framework-0.1.0/ragforge_framework/config.py +50 -0
  18. ragforge_framework-0.1.0/ragforge_framework/core.py +42 -0
  19. ragforge_framework-0.1.0/ragforge_framework/llm/__init__.py +1 -0
  20. ragforge_framework-0.1.0/ragforge_framework/llm/gateway.py +95 -0
  21. ragforge_framework-0.1.0/ragforge_framework/llm/service.py +50 -0
  22. ragforge_framework-0.1.0/ragforge_framework/models/__init__.py +1 -0
  23. ragforge_framework-0.1.0/ragforge_framework/models/schemas.py +90 -0
  24. ragforge_framework-0.1.0/ragforge_framework/rag/__init__.py +1 -0
  25. ragforge_framework-0.1.0/ragforge_framework/rag/chain.py +28 -0
  26. ragforge_framework-0.1.0/ragforge_framework/rag/embeddings.py +10 -0
  27. ragforge_framework-0.1.0/ragforge_framework/rag/engine.py +31 -0
  28. ragforge_framework-0.1.0/ragforge_framework/rag/injest.py +81 -0
  29. ragforge_framework-0.1.0/ragforge_framework/rag/prompt.py +61 -0
  30. ragforge_framework-0.1.0/ragforge_framework/rag/retriever.py +19 -0
  31. ragforge_framework-0.1.0/ragforge_framework/rag/vectorstore.py +31 -0
  32. ragforge_framework-0.1.0/requirements.txt +19 -0
  33. ragforge_framework-0.1.0/uv.lock +3502 -0
@@ -0,0 +1,15 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+ .env
12
+
13
+ response_cache/
14
+ user_cache/
15
+
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,148 @@
1
+ Metadata-Version: 2.4
2
+ Name: ragforge-framework
3
+ Version: 0.1.0
4
+ Summary: Modular AI Backend Framework built with FastAPI, LiteLLM and LangChain
5
+ Requires-Python: >=3.12
6
+ Requires-Dist: diskcache>=5.6.3
7
+ Requires-Dist: faiss-cpu>=1.14.3
8
+ Requires-Dist: fastapi>=0.139.0
9
+ Requires-Dist: langchain-community>=0.4.2
10
+ Requires-Dist: langchain-google-genai>=4.2.7
11
+ Requires-Dist: langchain-groq>=1.1.3
12
+ Requires-Dist: langchain-huggingface>=1.2.2
13
+ Requires-Dist: langchain-litellm>=0.7.0
14
+ Requires-Dist: langchain-mistralai>=1.1.6
15
+ Requires-Dist: langchain-ollama>=1.1.0
16
+ Requires-Dist: langchain-openai>=1.3.5
17
+ Requires-Dist: langchain-redis>=0.2.5
18
+ Requires-Dist: langchain-text-splitters>=1.1.2
19
+ Requires-Dist: langchain>=1.3.12
20
+ Requires-Dist: langgraph>=1.2.9
21
+ Requires-Dist: litellm>=1.91.1
22
+ Requires-Dist: pandas>=3.0.3
23
+ Requires-Dist: pypdf>=6.14.2
24
+ Requires-Dist: python-dotenv>=1.2.2
25
+ Requires-Dist: sentence-transformers>=5.6.0
26
+ Requires-Dist: uvicorn>=0.51.0
27
+ Description-Content-Type: text/markdown
28
+
29
+ # 🚀 RAGForge Framework
30
+
31
+ ### Production-Ready AI Backend Framework built with FastAPI, LiteLLM and LangChain
32
+
33
+ RAGForge is a modular Python RAG (Retrieval-Augmented Generation) framework that helps developers build and deploy production-ready AI backends with built-in semantic caching, IP-based rate limiting, automatic LLM fallbacks, and comprehensive administrative APIs.
34
+
35
+ ---
36
+
37
+ ## 📖 Features
38
+
39
+ - **Retrieval-Augmented Generation (RAG):** Powered by LangChain, FAISS Vector Store, and HuggingFace Embeddings.
40
+ - **LiteLLM Gateway:** Connect to Ollama, Groq, Mistral, OpenAI, Gemini, etc. with automatic LLM fallback switching.
41
+ - **Semantic caching:** Persistent cache layers using `diskcache` to reduce latency and API costs.
42
+ - **IP-Based Rate Limiting:** Daily limit controls to prevent abuse.
43
+ - **Admin APIs:** Built-in endpoints for viewing user statistics, resetting cache, tracking LLM provider metrics, and clearing cache.
44
+ - **Unified CLI:** Simple CLI tool to initialize, build, and run applications.
45
+
46
+ ---
47
+
48
+ ## ⚙️ Installation
49
+
50
+ To install RAGForge locally from source:
51
+
52
+ ```bash
53
+ git clone https://github.com/yourusername/RAGForge.git
54
+ cd RAGForge
55
+ pip install -e .
56
+ ```
57
+
58
+ ---
59
+
60
+ ## 🚀 Quick Start (CLI Mode)
61
+
62
+ RAGForge includes a CLI executable to quickly manage projects.
63
+
64
+ ### 1. Initialize a new project
65
+
66
+ ```bash
67
+ ragforge init
68
+ ```
69
+
70
+ This generates a starter project structure:
71
+
72
+ - `data/data.txt`: Your source document repository.
73
+ - `app.py`: The entry point script configuring your framework.
74
+
75
+ ### 2. Ingest documents
76
+
77
+ Add your knowledge text database to `data/data.txt` and generate the vector index:
78
+
79
+ ```bash
80
+ ragforge ingest
81
+ ```
82
+
83
+ ### 3. Start the API server
84
+
85
+ ```bash
86
+ ragforge run --port 8000
87
+ ```
88
+
89
+ This launches a FastAPI server. Open [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) in your browser to inspect the interactive Swagger API documentation.
90
+
91
+ ---
92
+
93
+ ## 🐍 Programmatic Usage
94
+
95
+ You can import and configure `RAGForge` inside any Python application:
96
+
97
+ ```python
98
+ from ragforge_framework import RAGForge
99
+
100
+ # 1. Initialize with custom configurations
101
+ forge = RAGForge(
102
+ data_path="data/data.txt",
103
+ faiss_path="faiss_index",
104
+ primary_model="ollama/llama3.2:latest",
105
+ fallback_models=["groq/llama-3.1-8b-instant"],
106
+ daily_limit=15,
107
+ admin_key="mysecretkey"
108
+ )
109
+
110
+ # Expose FastAPI application instance for uvicorn/gunicorn
111
+ app = forge.app
112
+
113
+ if __name__ == "__main__":
114
+ # 2. Run the application
115
+ forge.run(host="127.0.0.1", port=8000)
116
+ ```
117
+
118
+ ---
119
+
120
+ ## 🔧 Configuration Options
121
+
122
+ The `RAGForge` orchestrator accepts the following keyword arguments during instantiation:
123
+
124
+ | Parameter | Type | Default | Description |
125
+ | :------------------- | :----- | :----------------------------------- | :--------------------------------------------- |
126
+ | `primary_model` | `str` | `"ollama/llama3.2:latest"` | The primary LLM to query. |
127
+ | `fallback_models` | `list` | `["groq/llama-3.1-8b-instant", ...]` | Backup LLMs to trigger if primary fails. |
128
+ | `daily_limit` | `int` | `10` | Daily LLM request quota per IP. |
129
+ | `admin_key` | `str` | `"yashodeep"` | The secret key to secure `/admin` endpoints. |
130
+ | `data_path` | `str` | `"data/data.txt"` | Path to the source text file to index. |
131
+ | `faiss_path` | `str` | `"faiss_index"` | Path to save the FAISS vector database. |
132
+ | `embedding_model` | `str` | `"sentence-transformers/..."` | HuggingFace embedding model name. |
133
+ | `response_cache_dir` | `str` | `"./response_cache"` | Directory to store query cache. |
134
+ | `user_cache_dir` | `str` | `"./user_cache"` | Directory to store user rate limit statistics. |
135
+ | `chunk_size` | `int` | `800` | Size of split text chunks. |
136
+ | `chunk_overlap` | `int` | `100` | Text chunk overlap tokens. |
137
+
138
+ ---
139
+
140
+ ## 📊 Administration Endpoints
141
+
142
+ Secure administrative APIs are exposed under `/admin/` (requires `x-admin-key` header matching your `admin_key`):
143
+
144
+ - `GET /admin/users`: Lists stats for all registered users.
145
+ - `GET /admin/stats`: Exposes global metrics (total queries, cache hits, provider splits).
146
+ - `GET /admin/cache`: Inspects all currently cached queries and responses.
147
+ - `DELETE /admin/cache`: Clears the response cache.
148
+ - `DELETE /admin/reset`: Clears all caches and user request quotas.
@@ -0,0 +1,120 @@
1
+ # 🚀 RAGForge Framework
2
+
3
+ ### Production-Ready AI Backend Framework built with FastAPI, LiteLLM and LangChain
4
+
5
+ RAGForge is a modular Python RAG (Retrieval-Augmented Generation) framework that helps developers build and deploy production-ready AI backends with built-in semantic caching, IP-based rate limiting, automatic LLM fallbacks, and comprehensive administrative APIs.
6
+
7
+ ---
8
+
9
+ ## 📖 Features
10
+
11
+ - **Retrieval-Augmented Generation (RAG):** Powered by LangChain, FAISS Vector Store, and HuggingFace Embeddings.
12
+ - **LiteLLM Gateway:** Connect to Ollama, Groq, Mistral, OpenAI, Gemini, etc. with automatic LLM fallback switching.
13
+ - **Semantic caching:** Persistent cache layers using `diskcache` to reduce latency and API costs.
14
+ - **IP-Based Rate Limiting:** Daily limit controls to prevent abuse.
15
+ - **Admin APIs:** Built-in endpoints for viewing user statistics, resetting cache, tracking LLM provider metrics, and clearing cache.
16
+ - **Unified CLI:** Simple CLI tool to initialize, build, and run applications.
17
+
18
+ ---
19
+
20
+ ## ⚙️ Installation
21
+
22
+ To install RAGForge locally from source:
23
+
24
+ ```bash
25
+ git clone https://github.com/yourusername/RAGForge.git
26
+ cd RAGForge
27
+ pip install -e .
28
+ ```
29
+
30
+ ---
31
+
32
+ ## 🚀 Quick Start (CLI Mode)
33
+
34
+ RAGForge includes a CLI executable to quickly manage projects.
35
+
36
+ ### 1. Initialize a new project
37
+
38
+ ```bash
39
+ ragforge init
40
+ ```
41
+
42
+ This generates a starter project structure:
43
+
44
+ - `data/data.txt`: Your source document repository.
45
+ - `app.py`: The entry point script configuring your framework.
46
+
47
+ ### 2. Ingest documents
48
+
49
+ Add your knowledge text database to `data/data.txt` and generate the vector index:
50
+
51
+ ```bash
52
+ ragforge ingest
53
+ ```
54
+
55
+ ### 3. Start the API server
56
+
57
+ ```bash
58
+ ragforge run --port 8000
59
+ ```
60
+
61
+ This launches a FastAPI server. Open [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) in your browser to inspect the interactive Swagger API documentation.
62
+
63
+ ---
64
+
65
+ ## 🐍 Programmatic Usage
66
+
67
+ You can import and configure `RAGForge` inside any Python application:
68
+
69
+ ```python
70
+ from ragforge_framework import RAGForge
71
+
72
+ # 1. Initialize with custom configurations
73
+ forge = RAGForge(
74
+ data_path="data/data.txt",
75
+ faiss_path="faiss_index",
76
+ primary_model="ollama/llama3.2:latest",
77
+ fallback_models=["groq/llama-3.1-8b-instant"],
78
+ daily_limit=15,
79
+ admin_key="mysecretkey"
80
+ )
81
+
82
+ # Expose FastAPI application instance for uvicorn/gunicorn
83
+ app = forge.app
84
+
85
+ if __name__ == "__main__":
86
+ # 2. Run the application
87
+ forge.run(host="127.0.0.1", port=8000)
88
+ ```
89
+
90
+ ---
91
+
92
+ ## 🔧 Configuration Options
93
+
94
+ The `RAGForge` orchestrator accepts the following keyword arguments during instantiation:
95
+
96
+ | Parameter | Type | Default | Description |
97
+ | :------------------- | :----- | :----------------------------------- | :--------------------------------------------- |
98
+ | `primary_model` | `str` | `"ollama/llama3.2:latest"` | The primary LLM to query. |
99
+ | `fallback_models` | `list` | `["groq/llama-3.1-8b-instant", ...]` | Backup LLMs to trigger if primary fails. |
100
+ | `daily_limit` | `int` | `10` | Daily LLM request quota per IP. |
101
+ | `admin_key` | `str` | `"yashodeep"` | The secret key to secure `/admin` endpoints. |
102
+ | `data_path` | `str` | `"data/data.txt"` | Path to the source text file to index. |
103
+ | `faiss_path` | `str` | `"faiss_index"` | Path to save the FAISS vector database. |
104
+ | `embedding_model` | `str` | `"sentence-transformers/..."` | HuggingFace embedding model name. |
105
+ | `response_cache_dir` | `str` | `"./response_cache"` | Directory to store query cache. |
106
+ | `user_cache_dir` | `str` | `"./user_cache"` | Directory to store user rate limit statistics. |
107
+ | `chunk_size` | `int` | `800` | Size of split text chunks. |
108
+ | `chunk_overlap` | `int` | `100` | Text chunk overlap tokens. |
109
+
110
+ ---
111
+
112
+ ## 📊 Administration Endpoints
113
+
114
+ Secure administrative APIs are exposed under `/admin/` (requires `x-admin-key` header matching your `admin_key`):
115
+
116
+ - `GET /admin/users`: Lists stats for all registered users.
117
+ - `GET /admin/stats`: Exposes global metrics (total queries, cache hits, provider splits).
118
+ - `GET /admin/cache`: Inspects all currently cached queries and responses.
119
+ - `DELETE /admin/cache`: Clears the response cache.
120
+ - `DELETE /admin/reset`: Clears all caches and user request quotas.
@@ -0,0 +1,15 @@
1
+ from ragforge_framework import RAGForge
2
+
3
+ # Instantiate the RAGForge framework config and services
4
+ forge = RAGForge(
5
+ data_path="data/data.txt",
6
+ faiss_path="faiss_index",
7
+ primary_model="ollama/llama3.2:latest"
8
+ )
9
+
10
+ # Expose fastapi app for production WSGI/ASGI servers (e.g. gunicorn/uvicorn)
11
+ app = forge.app
12
+
13
+ if __name__ == "__main__":
14
+ # Start the server locally when running app.py directly
15
+ forge.run(host="127.0.0.1", port=8000)
@@ -0,0 +1 @@
1
+ Yashodeep Hundiwale is an experienced AI Engineer and creator of RAGForge.
@@ -0,0 +1,36 @@
1
+ [project]
2
+ name = "ragforge-framework"
3
+ version = "0.1.0"
4
+ description = "Modular AI Backend Framework built with FastAPI, LiteLLM and LangChain"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = [
8
+ "diskcache>=5.6.3",
9
+ "faiss-cpu>=1.14.3",
10
+ "fastapi>=0.139.0",
11
+ "langchain>=1.3.12",
12
+ "langchain-community>=0.4.2",
13
+ "langchain-google-genai>=4.2.7",
14
+ "langchain-groq>=1.1.3",
15
+ "langchain-huggingface>=1.2.2",
16
+ "langchain-litellm>=0.7.0",
17
+ "langchain-mistralai>=1.1.6",
18
+ "langchain-ollama>=1.1.0",
19
+ "langchain-openai>=1.3.5",
20
+ "langchain-redis>=0.2.5",
21
+ "langchain-text-splitters>=1.1.2",
22
+ "langgraph>=1.2.9",
23
+ "litellm>=1.91.1",
24
+ "pandas>=3.0.3",
25
+ "pypdf>=6.14.2",
26
+ "python-dotenv>=1.2.2",
27
+ "sentence-transformers>=5.6.0",
28
+ "uvicorn>=0.51.0",
29
+ ]
30
+
31
+ [project.scripts]
32
+ ragforge = "ragforge_framework.cli:main"
33
+
34
+ [build-system]
35
+ requires = ["hatchling"]
36
+ build-backend = "hatchling.build"
@@ -0,0 +1,13 @@
1
+ from .config import RAGForgeConfig
2
+ from .core import RAGForge
3
+ from .rag.engine import RAGEngine
4
+ from .cache.user_manager import UserManager
5
+ from .cache.response_cache import ResponseCache
6
+
7
+ __all__ = [
8
+ "RAGForge",
9
+ "RAGForgeConfig",
10
+ "RAGEngine",
11
+ "UserManager",
12
+ "ResponseCache",
13
+ ]
@@ -0,0 +1 @@
1
+ # Admin Package Initialization
@@ -0,0 +1,224 @@
1
+ from fastapi import APIRouter, Header, HTTPException, Request
2
+
3
+ from ..models.schemas import (
4
+ UserResponse,
5
+ StatisticsResponse,
6
+ AllUsersResponse,
7
+ TopUsersResponse,
8
+ CacheInformationResponse
9
+ )
10
+
11
+
12
+ def get_admin_router(forge) -> APIRouter:
13
+ """
14
+ Admin Router Factory.
15
+ Builds the APIRouter instance dynamically, linking state dependencies to Request.app.state.
16
+ """
17
+ router = APIRouter(
18
+ prefix="/admin",
19
+ tags=["Admin"]
20
+ )
21
+
22
+ def verify_admin(request: Request, key: str):
23
+ config = request.app.state.config
24
+ if key != config.ADMIN_KEY:
25
+ raise HTTPException(
26
+ status_code=403,
27
+ detail="Invalid Admin Key."
28
+ )
29
+
30
+ # ==========================================================
31
+ # HOME
32
+ # ==========================================================
33
+
34
+ @router.get("/")
35
+ def admin_home(
36
+ request: Request,
37
+ x_admin_key: str = Header(...)
38
+ ):
39
+ verify_admin(request, x_admin_key)
40
+ return {
41
+ "message": "Admin API Running"
42
+ }
43
+
44
+ # ==========================================================
45
+ # ALL USERS
46
+ # ==========================================================
47
+
48
+ @router.get("/users", response_model=AllUsersResponse)
49
+ def get_all_users(
50
+ request: Request,
51
+ x_admin_key: str = Header(...)
52
+ ):
53
+ verify_admin(request, x_admin_key)
54
+ user_manager = request.app.state.user_manager
55
+ users = user_manager.get_all_users()
56
+
57
+ return {
58
+ "total_users": len(users),
59
+ "users": users
60
+ }
61
+
62
+ # ==========================================================
63
+ # SINGLE USER
64
+ # ==========================================================
65
+
66
+ @router.get("/user/{user_id}", response_model=UserResponse)
67
+ def get_user(
68
+ request: Request,
69
+ user_id: str,
70
+ x_admin_key: str = Header(...)
71
+ ):
72
+ verify_admin(request, x_admin_key)
73
+ user_manager = request.app.state.user_manager
74
+ user = user_manager.search_user(user_id)
75
+
76
+ if user is None:
77
+ raise HTTPException(
78
+ status_code=404,
79
+ detail="User not found."
80
+ )
81
+ return user
82
+
83
+ # ==========================================================
84
+ # RESET USER
85
+ # ==========================================================
86
+
87
+ @router.delete("/user/{user_id}")
88
+ def reset_user(
89
+ request: Request,
90
+ user_id: str,
91
+ x_admin_key: str = Header(...)
92
+ ):
93
+ verify_admin(request, x_admin_key)
94
+ user_manager = request.app.state.user_manager
95
+ success = user_manager.reset_user(user_id)
96
+
97
+ if not success:
98
+ raise HTTPException(
99
+ status_code=404,
100
+ detail="User not found."
101
+ )
102
+ return {
103
+ "message": "User reset successfully."
104
+ }
105
+
106
+ # ==========================================================
107
+ # RESET ALL USERS
108
+ # ==========================================================
109
+
110
+ @router.delete("/users")
111
+ def reset_all_users(
112
+ request: Request,
113
+ x_admin_key: str = Header(...)
114
+ ):
115
+ verify_admin(request, x_admin_key)
116
+ user_manager = request.app.state.user_manager
117
+ user_manager.reset_all()
118
+
119
+ return {
120
+ "message": "All users reset successfully."
121
+ }
122
+
123
+ # ==========================================================
124
+ # STATISTICS
125
+ # ==========================================================
126
+
127
+ @router.get("/stats", response_model=StatisticsResponse)
128
+ def statistics(
129
+ request: Request,
130
+ x_admin_key: str = Header(...)
131
+ ):
132
+ verify_admin(request, x_admin_key)
133
+ user_manager = request.app.state.user_manager
134
+
135
+ return user_manager.get_statistics()
136
+
137
+ # ==========================================================
138
+ # TOP USERS
139
+ # ==========================================================
140
+
141
+ @router.get("/top-users", response_model=TopUsersResponse)
142
+ def top_users(
143
+ request: Request,
144
+ limit: int = 10,
145
+ x_admin_key: str = Header(...)
146
+ ):
147
+ verify_admin(request, x_admin_key)
148
+ user_manager = request.app.state.user_manager
149
+
150
+ return {
151
+ "users": user_manager.get_top_users(limit)
152
+ }
153
+
154
+ # ==========================================================
155
+ # ACTIVE USERS
156
+ # ==========================================================
157
+
158
+ @router.get("/active-users", response_model=TopUsersResponse)
159
+ def active_users(
160
+ request: Request,
161
+ x_admin_key: str = Header(...)
162
+ ):
163
+ verify_admin(request, x_admin_key)
164
+ user_manager = request.app.state.user_manager
165
+
166
+ return {
167
+ "users": user_manager.active_users()
168
+ }
169
+
170
+ # ==========================================================
171
+ # CACHE INFO
172
+ # ==========================================================
173
+
174
+ @router.get("/cache", response_model=CacheInformationResponse)
175
+ def cache_information(
176
+ request: Request,
177
+ x_admin_key: str = Header(...)
178
+ ):
179
+ verify_admin(request, x_admin_key)
180
+ response_cache = request.app.state.response_cache
181
+
182
+ return {
183
+ "cached_responses": response_cache.total_cached_responses(),
184
+ "responses": response_cache.get_all()
185
+ }
186
+
187
+ # ==========================================================
188
+ # CLEAR RESPONSE CACHE
189
+ # ==========================================================
190
+
191
+ @router.delete("/cache")
192
+ def clear_cache(
193
+ request: Request,
194
+ x_admin_key: str = Header(...)
195
+ ):
196
+ verify_admin(request, x_admin_key)
197
+ response_cache = request.app.state.response_cache
198
+ response_cache.clear()
199
+
200
+ return {
201
+ "message": "Response cache cleared."
202
+ }
203
+
204
+ # ==========================================================
205
+ # RESET EVERYTHING
206
+ # ==========================================================
207
+
208
+ @router.delete("/reset")
209
+ def reset_everything(
210
+ request: Request,
211
+ x_admin_key: str = Header(...)
212
+ ):
213
+ verify_admin(request, x_admin_key)
214
+ user_manager = request.app.state.user_manager
215
+ response_cache = request.app.state.response_cache
216
+
217
+ user_manager.reset_all()
218
+ response_cache.clear()
219
+
220
+ return {
221
+ "message": "Users and response cache reset successfully."
222
+ }
223
+
224
+ return router
@@ -0,0 +1,88 @@
1
+ from fastapi import FastAPI, Request, HTTPException
2
+ from .models.schemas import ChatRequest, ChatResponse
3
+ from .admin.routes import get_admin_router
4
+
5
+ def create_app(forge) -> FastAPI:
6
+ """
7
+ App Factory.
8
+ Builds the FastAPI application at runtime and loads configuration and services
9
+ into app.state.
10
+ """
11
+ app = FastAPI(
12
+ title="RAGForge Framework Backend",
13
+ version="1.1.0"
14
+ )
15
+
16
+ # Attach orchestrator and configuration to app state
17
+ app.state.forge = forge
18
+ app.state.config = forge.config
19
+ app.state.user_manager = forge.user_manager
20
+ app.state.response_cache = forge.response_cache
21
+ app.state.engine = forge.engine
22
+
23
+ # Mount admin route router
24
+ app.include_router(get_admin_router(forge))
25
+
26
+ @app.get("/")
27
+ def home():
28
+ return {
29
+ "message": "🚀 RAGForge Framework Running Successfully"
30
+ }
31
+
32
+ @app.post("/chat", response_model=ChatResponse)
33
+ def chat(
34
+ data: ChatRequest,
35
+ request: Request
36
+ ):
37
+ prompt = data.prompt.strip()
38
+
39
+ # Resolve request IP (check proxy headers first)
40
+ ip = request.headers.get(
41
+ "X-Forwarded-For",
42
+ request.client.host
43
+ ).split(",")[0].strip()
44
+
45
+ # Load references from app.state
46
+ user_manager = request.app.state.user_manager
47
+ response_cache = request.app.state.response_cache
48
+ engine = request.app.state.engine
49
+ config = request.app.state.config
50
+
51
+ # 1. Register User Request
52
+ user_manager.register_request(ip)
53
+
54
+ # 2. Check Cache
55
+ cached = response_cache.get(ip, prompt)
56
+ if cached:
57
+ user = user_manager.get_user(ip)
58
+ return {
59
+ "success": True,
60
+ "cached": True,
61
+ "provider": "cache",
62
+ "remaining_questions": user["remaining"],
63
+ "answer": cached["answer"]
64
+ }
65
+
66
+ # 3. Check Rate Limit
67
+ allowed, user = user_manager.allow_request(ip)
68
+ if not allowed:
69
+ raise HTTPException(
70
+ status_code=429,
71
+ detail=f"Daily limit reached. ({user['llm_requests']}/{config.DAILY_LIMIT})"
72
+ )
73
+
74
+ # 4. Invoke RAG engine
75
+ answer = engine.chat(prompt, ip=ip)
76
+
77
+ # 5. Save response to cache
78
+ response_cache.save(prompt, answer)
79
+
80
+ return {
81
+ "success": True,
82
+ "cached": False,
83
+ "provider": "rag",
84
+ "remaining_questions": user["remaining"],
85
+ "answer": answer
86
+ }
87
+
88
+ return app
@@ -0,0 +1 @@
1
+ # Cache Package Initialization