ragforge-framework 0.1.0__py3-none-any.whl
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.
- ragforge_framework/__init__.py +13 -0
- ragforge_framework/admin/__init__.py +1 -0
- ragforge_framework/admin/routes.py +224 -0
- ragforge_framework/app.py +88 -0
- ragforge_framework/cache/__init__.py +1 -0
- ragforge_framework/cache/repository.py +155 -0
- ragforge_framework/cache/response_cache.py +105 -0
- ragforge_framework/cache/user_manager.py +264 -0
- ragforge_framework/cli.py +91 -0
- ragforge_framework/config.py +50 -0
- ragforge_framework/core.py +42 -0
- ragforge_framework/llm/__init__.py +1 -0
- ragforge_framework/llm/gateway.py +95 -0
- ragforge_framework/llm/service.py +50 -0
- ragforge_framework/models/__init__.py +1 -0
- ragforge_framework/models/schemas.py +90 -0
- ragforge_framework/rag/__init__.py +1 -0
- ragforge_framework/rag/chain.py +28 -0
- ragforge_framework/rag/embeddings.py +10 -0
- ragforge_framework/rag/engine.py +31 -0
- ragforge_framework/rag/injest.py +81 -0
- ragforge_framework/rag/prompt.py +61 -0
- ragforge_framework/rag/retriever.py +19 -0
- ragforge_framework/rag/vectorstore.py +31 -0
- ragforge_framework-0.1.0.dist-info/METADATA +148 -0
- ragforge_framework-0.1.0.dist-info/RECORD +28 -0
- ragforge_framework-0.1.0.dist-info/WHEEL +4 -0
- ragforge_framework-0.1.0.dist-info/entry_points.txt +2 -0
|
@@ -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
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
from typing import Any, Dict, List, Optional
|
|
2
|
+
from diskcache import Cache
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Repository:
|
|
6
|
+
"""
|
|
7
|
+
DiskCache Repository layer.
|
|
8
|
+
Manages low-level cache read, write, update, delete operations.
|
|
9
|
+
"""
|
|
10
|
+
def __init__(self, cache_dir: str):
|
|
11
|
+
self.cache = Cache(cache_dir)
|
|
12
|
+
|
|
13
|
+
# ==========================================================
|
|
14
|
+
# BASIC CRUD
|
|
15
|
+
# ==========================================================
|
|
16
|
+
|
|
17
|
+
def get(self, key: str) -> Optional[Dict]:
|
|
18
|
+
return self.cache.get(key)
|
|
19
|
+
|
|
20
|
+
def set(self, key: str, value: Dict):
|
|
21
|
+
self.cache[key] = value
|
|
22
|
+
|
|
23
|
+
def exists(self, key: str) -> bool:
|
|
24
|
+
return key in self.cache
|
|
25
|
+
|
|
26
|
+
def delete(self, key: str):
|
|
27
|
+
self.cache.pop(key, None)
|
|
28
|
+
|
|
29
|
+
def clear(self):
|
|
30
|
+
self.cache.clear()
|
|
31
|
+
|
|
32
|
+
# ==========================================================
|
|
33
|
+
# ITERATORS
|
|
34
|
+
# ==========================================================
|
|
35
|
+
|
|
36
|
+
def keys(self) -> List[str]:
|
|
37
|
+
return list(self.cache.iterkeys())
|
|
38
|
+
|
|
39
|
+
def values(self) -> List[Dict]:
|
|
40
|
+
return [self.cache[key] for key in self.cache.iterkeys()]
|
|
41
|
+
|
|
42
|
+
def items(self):
|
|
43
|
+
return [
|
|
44
|
+
(key, self.cache[key])
|
|
45
|
+
for key in self.cache.iterkeys()
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
# ==========================================================
|
|
49
|
+
# UPDATE
|
|
50
|
+
# ==========================================================
|
|
51
|
+
|
|
52
|
+
def update(self, key: str, **kwargs):
|
|
53
|
+
data = self.get(key)
|
|
54
|
+
if data is None:
|
|
55
|
+
return None
|
|
56
|
+
data.update(kwargs)
|
|
57
|
+
self.set(key, data)
|
|
58
|
+
return data
|
|
59
|
+
|
|
60
|
+
# ==========================================================
|
|
61
|
+
# NESTED UPDATE
|
|
62
|
+
# ==========================================================
|
|
63
|
+
|
|
64
|
+
def update_nested(
|
|
65
|
+
self,
|
|
66
|
+
key: str,
|
|
67
|
+
field: str,
|
|
68
|
+
nested_key: str,
|
|
69
|
+
value: Any,
|
|
70
|
+
):
|
|
71
|
+
data = self.get(key)
|
|
72
|
+
if data is None:
|
|
73
|
+
return None
|
|
74
|
+
if field not in data:
|
|
75
|
+
data[field] = {}
|
|
76
|
+
data[field][nested_key] = value
|
|
77
|
+
self.set(key, data)
|
|
78
|
+
return data
|
|
79
|
+
|
|
80
|
+
# ==========================================================
|
|
81
|
+
# INCREMENT
|
|
82
|
+
# ==========================================================
|
|
83
|
+
|
|
84
|
+
def increment(
|
|
85
|
+
self,
|
|
86
|
+
key: str,
|
|
87
|
+
field: str,
|
|
88
|
+
amount: int = 1,
|
|
89
|
+
):
|
|
90
|
+
data = self.get(key)
|
|
91
|
+
if data is None:
|
|
92
|
+
return None
|
|
93
|
+
data[field] += amount
|
|
94
|
+
self.set(key, data)
|
|
95
|
+
return data
|
|
96
|
+
|
|
97
|
+
# ==========================================================
|
|
98
|
+
# INCREMENT NESTED
|
|
99
|
+
# ==========================================================
|
|
100
|
+
|
|
101
|
+
def increment_nested(
|
|
102
|
+
self,
|
|
103
|
+
key: str,
|
|
104
|
+
field: str,
|
|
105
|
+
nested_key: str,
|
|
106
|
+
amount: int = 1,
|
|
107
|
+
):
|
|
108
|
+
data = self.get(key)
|
|
109
|
+
if data is None:
|
|
110
|
+
return None
|
|
111
|
+
if field not in data:
|
|
112
|
+
data[field] = {}
|
|
113
|
+
if nested_key not in data[field]:
|
|
114
|
+
data[field][nested_key] = 0
|
|
115
|
+
data[field][nested_key] += amount
|
|
116
|
+
self.set(key, data)
|
|
117
|
+
return data
|
|
118
|
+
|
|
119
|
+
# ==========================================================
|
|
120
|
+
# SEARCH
|
|
121
|
+
# ==========================================================
|
|
122
|
+
|
|
123
|
+
def find(
|
|
124
|
+
self,
|
|
125
|
+
field: str,
|
|
126
|
+
value: Any,
|
|
127
|
+
) -> Optional[Dict]:
|
|
128
|
+
for _, data in self.items():
|
|
129
|
+
if data.get(field) == value:
|
|
130
|
+
return data
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
def find_key(
|
|
134
|
+
self,
|
|
135
|
+
field: str,
|
|
136
|
+
value: Any,
|
|
137
|
+
) -> Optional[str]:
|
|
138
|
+
for key, data in self.items():
|
|
139
|
+
if data.get(field) == value:
|
|
140
|
+
return key
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
# ==========================================================
|
|
144
|
+
# COUNT
|
|
145
|
+
# ==========================================================
|
|
146
|
+
|
|
147
|
+
def count(self):
|
|
148
|
+
return len(self.cache)
|
|
149
|
+
|
|
150
|
+
# ==========================================================
|
|
151
|
+
# EXPORT
|
|
152
|
+
# ==========================================================
|
|
153
|
+
|
|
154
|
+
def export(self):
|
|
155
|
+
return self.values()
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
from hashlib import sha256
|
|
2
|
+
|
|
3
|
+
from .repository import Repository
|
|
4
|
+
from .user_manager import UserManager
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ResponseCache:
|
|
8
|
+
"""
|
|
9
|
+
Cache layer for persisting generated responses.
|
|
10
|
+
"""
|
|
11
|
+
def __init__(self, config):
|
|
12
|
+
self.repository = Repository(config.RESPONSE_CACHE_DIR)
|
|
13
|
+
self.user_manager = UserManager(config)
|
|
14
|
+
|
|
15
|
+
# =====================================================
|
|
16
|
+
# PRIVATE
|
|
17
|
+
# =====================================================
|
|
18
|
+
|
|
19
|
+
def _key(self, prompt: str):
|
|
20
|
+
return sha256(
|
|
21
|
+
prompt.strip().lower().encode()
|
|
22
|
+
).hexdigest()
|
|
23
|
+
|
|
24
|
+
# =====================================================
|
|
25
|
+
# GET
|
|
26
|
+
# =====================================================
|
|
27
|
+
|
|
28
|
+
def get(self, ip: str, prompt: str):
|
|
29
|
+
key = self._key(prompt)
|
|
30
|
+
response = self.repository.get(key)
|
|
31
|
+
if response:
|
|
32
|
+
self.user_manager.cache_hit(ip)
|
|
33
|
+
else:
|
|
34
|
+
self.user_manager.cache_miss(ip)
|
|
35
|
+
return response
|
|
36
|
+
|
|
37
|
+
# =====================================================
|
|
38
|
+
# SAVE
|
|
39
|
+
# =====================================================
|
|
40
|
+
|
|
41
|
+
def save(
|
|
42
|
+
self,
|
|
43
|
+
prompt: str,
|
|
44
|
+
answer: str
|
|
45
|
+
):
|
|
46
|
+
key = self._key(prompt)
|
|
47
|
+
self.repository.set(
|
|
48
|
+
key,
|
|
49
|
+
{
|
|
50
|
+
"answer": answer
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# =====================================================
|
|
55
|
+
# DELETE
|
|
56
|
+
# =====================================================
|
|
57
|
+
|
|
58
|
+
def delete(
|
|
59
|
+
self,
|
|
60
|
+
prompt: str
|
|
61
|
+
):
|
|
62
|
+
key = self._key(prompt)
|
|
63
|
+
self.repository.delete(key)
|
|
64
|
+
|
|
65
|
+
# =====================================================
|
|
66
|
+
# CLEAR
|
|
67
|
+
# =====================================================
|
|
68
|
+
|
|
69
|
+
def clear(self):
|
|
70
|
+
self.repository.clear()
|
|
71
|
+
|
|
72
|
+
# =====================================================
|
|
73
|
+
# EXISTS
|
|
74
|
+
# =====================================================
|
|
75
|
+
|
|
76
|
+
def exists(
|
|
77
|
+
self,
|
|
78
|
+
prompt: str
|
|
79
|
+
):
|
|
80
|
+
key = self._key(prompt)
|
|
81
|
+
return self.repository.exists(key)
|
|
82
|
+
|
|
83
|
+
# =====================================================
|
|
84
|
+
# TOTAL CACHE
|
|
85
|
+
# =====================================================
|
|
86
|
+
|
|
87
|
+
def total_cached_responses(self):
|
|
88
|
+
return self.repository.count()
|
|
89
|
+
|
|
90
|
+
# =====================================================
|
|
91
|
+
# ALL CACHE
|
|
92
|
+
# =====================================================
|
|
93
|
+
|
|
94
|
+
def get_all(self):
|
|
95
|
+
return self.repository.values()
|
|
96
|
+
|
|
97
|
+
# =====================================================
|
|
98
|
+
# DEBUG
|
|
99
|
+
# =====================================================
|
|
100
|
+
|
|
101
|
+
def __len__(self):
|
|
102
|
+
return self.repository.count()
|
|
103
|
+
|
|
104
|
+
def __repr__(self):
|
|
105
|
+
return f"<ResponseCache size={len(self)}>"
|