Spaces:
Build error
Build error
Merge pull request #79 from DL4DS/regen_tokens
Browse files- code/app.py +37 -3
- code/main.py +56 -14
- code/modules/chat_processor/helpers.py +48 -7
- code/modules/config/constants.py +3 -1
- code/templates/cooldown.html +44 -18
- code/templates/dashboard.html +25 -9
code/app.py
CHANGED
|
@@ -14,6 +14,8 @@ from modules.config.constants import (
|
|
| 14 |
CHAINLIT_URL,
|
| 15 |
GITHUB_REPO,
|
| 16 |
DOCS_WEBSITE,
|
|
|
|
|
|
|
| 17 |
)
|
| 18 |
from fastapi.middleware.cors import CORSMiddleware
|
| 19 |
from fastapi.staticfiles import StaticFiles
|
|
@@ -207,7 +209,9 @@ async def cooldown(request: Request):
|
|
| 207 |
user_info = await get_user_info_from_cookie(request)
|
| 208 |
user_details = await get_user_details(user_info["email"])
|
| 209 |
current_datetime = get_time()
|
| 210 |
-
cooldown, cooldown_end_time = check_user_cooldown(
|
|
|
|
|
|
|
| 211 |
print(f"User in cooldown: {cooldown}")
|
| 212 |
print(f"Cooldown end time: {cooldown_end_time}")
|
| 213 |
if cooldown and "admin" not in get_user_role(user_info["email"]):
|
|
@@ -218,9 +222,11 @@ async def cooldown(request: Request):
|
|
| 218 |
"username": user_info["email"],
|
| 219 |
"role": get_user_role(user_info["email"]),
|
| 220 |
"cooldown_end_time": cooldown_end_time,
|
|
|
|
| 221 |
},
|
| 222 |
)
|
| 223 |
else:
|
|
|
|
| 224 |
await update_user_info(user_details)
|
| 225 |
await reset_tokens_for_user(user_details)
|
| 226 |
return RedirectResponse("/post-signin")
|
|
@@ -236,15 +242,26 @@ async def post_signin(request: Request):
|
|
| 236 |
user_details.metadata["last_login"] = current_datetime
|
| 237 |
# if new user, set the number of tries
|
| 238 |
if "tokens_left" not in user_details.metadata:
|
| 239 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 240 |
|
| 241 |
if "last_message_time" in user_details.metadata and "admin" not in get_user_role(
|
| 242 |
user_info["email"]
|
| 243 |
):
|
| 244 |
-
cooldown, _ = check_user_cooldown(user_details, current_datetime)
|
| 245 |
if cooldown:
|
|
|
|
| 246 |
return RedirectResponse("/cooldown")
|
| 247 |
else:
|
|
|
|
| 248 |
await reset_tokens_for_user(user_details)
|
| 249 |
|
| 250 |
if user_info:
|
|
@@ -259,6 +276,10 @@ async def post_signin(request: Request):
|
|
| 259 |
"role": role,
|
| 260 |
"jwt_token": jwt_token,
|
| 261 |
"tokens_left": user_details.metadata["tokens_left"],
|
|
|
|
|
|
|
|
|
|
|
|
|
| 262 |
},
|
| 263 |
)
|
| 264 |
return RedirectResponse("/")
|
|
@@ -309,6 +330,19 @@ async def logout(request: Request, response: Response):
|
|
| 309 |
return response
|
| 310 |
|
| 311 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 312 |
mount_chainlit(app=app, target="main.py", path=CHAINLIT_PATH)
|
| 313 |
|
| 314 |
if __name__ == "__main__":
|
|
|
|
| 14 |
CHAINLIT_URL,
|
| 15 |
GITHUB_REPO,
|
| 16 |
DOCS_WEBSITE,
|
| 17 |
+
ALL_TIME_TOKENS_ALLOCATED,
|
| 18 |
+
TOKENS_LEFT,
|
| 19 |
)
|
| 20 |
from fastapi.middleware.cors import CORSMiddleware
|
| 21 |
from fastapi.staticfiles import StaticFiles
|
|
|
|
| 209 |
user_info = await get_user_info_from_cookie(request)
|
| 210 |
user_details = await get_user_details(user_info["email"])
|
| 211 |
current_datetime = get_time()
|
| 212 |
+
cooldown, cooldown_end_time = await check_user_cooldown(
|
| 213 |
+
user_details, current_datetime
|
| 214 |
+
)
|
| 215 |
print(f"User in cooldown: {cooldown}")
|
| 216 |
print(f"Cooldown end time: {cooldown_end_time}")
|
| 217 |
if cooldown and "admin" not in get_user_role(user_info["email"]):
|
|
|
|
| 222 |
"username": user_info["email"],
|
| 223 |
"role": get_user_role(user_info["email"]),
|
| 224 |
"cooldown_end_time": cooldown_end_time,
|
| 225 |
+
"tokens_left": user_details.metadata["tokens_left"],
|
| 226 |
},
|
| 227 |
)
|
| 228 |
else:
|
| 229 |
+
user_details.metadata["in_cooldown"] = False
|
| 230 |
await update_user_info(user_details)
|
| 231 |
await reset_tokens_for_user(user_details)
|
| 232 |
return RedirectResponse("/post-signin")
|
|
|
|
| 242 |
user_details.metadata["last_login"] = current_datetime
|
| 243 |
# if new user, set the number of tries
|
| 244 |
if "tokens_left" not in user_details.metadata:
|
| 245 |
+
user_details.metadata["tokens_left"] = (
|
| 246 |
+
TOKENS_LEFT # set the number of tokens left for the new user
|
| 247 |
+
)
|
| 248 |
+
if "all_time_tokens_allocated" not in user_details.metadata:
|
| 249 |
+
user_details.metadata["all_time_tokens_allocated"] = (
|
| 250 |
+
ALL_TIME_TOKENS_ALLOCATED
|
| 251 |
+
)
|
| 252 |
+
if "in_cooldown" not in user_details.metadata:
|
| 253 |
+
user_details.metadata["in_cooldown"] = False
|
| 254 |
+
await update_user_info(user_details)
|
| 255 |
|
| 256 |
if "last_message_time" in user_details.metadata and "admin" not in get_user_role(
|
| 257 |
user_info["email"]
|
| 258 |
):
|
| 259 |
+
cooldown, _ = await check_user_cooldown(user_details, current_datetime)
|
| 260 |
if cooldown:
|
| 261 |
+
user_details.metadata["in_cooldown"] = True
|
| 262 |
return RedirectResponse("/cooldown")
|
| 263 |
else:
|
| 264 |
+
user_details.metadata["in_cooldown"] = False
|
| 265 |
await reset_tokens_for_user(user_details)
|
| 266 |
|
| 267 |
if user_info:
|
|
|
|
| 276 |
"role": role,
|
| 277 |
"jwt_token": jwt_token,
|
| 278 |
"tokens_left": user_details.metadata["tokens_left"],
|
| 279 |
+
"all_time_tokens_allocated": user_details.metadata[
|
| 280 |
+
"all_time_tokens_allocated"
|
| 281 |
+
],
|
| 282 |
+
"total_tokens_allocated": ALL_TIME_TOKENS_ALLOCATED,
|
| 283 |
},
|
| 284 |
)
|
| 285 |
return RedirectResponse("/")
|
|
|
|
| 330 |
return response
|
| 331 |
|
| 332 |
|
| 333 |
+
@app.get("/get-tokens-left")
|
| 334 |
+
async def get_tokens_left(request: Request):
|
| 335 |
+
try:
|
| 336 |
+
user_info = await get_user_info_from_cookie(request)
|
| 337 |
+
user_details = await get_user_details(user_info["email"])
|
| 338 |
+
await reset_tokens_for_user(user_details)
|
| 339 |
+
tokens_left = user_details.metadata["tokens_left"]
|
| 340 |
+
return {"tokens_left": tokens_left}
|
| 341 |
+
except Exception as e:
|
| 342 |
+
print(f"Error getting tokens left: {e}")
|
| 343 |
+
return {"tokens_left": 0}
|
| 344 |
+
|
| 345 |
+
|
| 346 |
mount_chainlit(app=app, target="main.py", path=CHAINLIT_PATH)
|
| 347 |
|
| 348 |
if __name__ == "__main__":
|
code/main.py
CHANGED
|
@@ -20,6 +20,8 @@ from modules.chat_processor.helpers import (
|
|
| 20 |
update_user_info,
|
| 21 |
get_time,
|
| 22 |
check_user_cooldown,
|
|
|
|
|
|
|
| 23 |
)
|
| 24 |
import copy
|
| 25 |
from typing import Optional
|
|
@@ -54,6 +56,24 @@ async def setup_data_layer():
|
|
| 54 |
return data_layer
|
| 55 |
|
| 56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
class Chatbot:
|
| 58 |
def __init__(self, config):
|
| 59 |
"""
|
|
@@ -221,17 +241,18 @@ class Chatbot:
|
|
| 221 |
"view_sources": llm_settings.get("view_sources"),
|
| 222 |
"follow_up_questions": llm_settings.get("follow_up_questions"),
|
| 223 |
}
|
|
|
|
| 224 |
await cl.Message(
|
| 225 |
author=SYSTEM,
|
| 226 |
content="LLM settings have been updated. You can continue with your Query!",
|
| 227 |
-
elements=[
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
],
|
| 235 |
).send()
|
| 236 |
|
| 237 |
async def set_starters(self):
|
|
@@ -365,6 +386,10 @@ class Chatbot:
|
|
| 365 |
|
| 366 |
# update user info with last message time
|
| 367 |
user = cl.user_session.get("user")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 368 |
|
| 369 |
print("\n\n User Tokens Left: ", user.metadata["tokens_left"])
|
| 370 |
|
|
@@ -372,7 +397,9 @@ class Chatbot:
|
|
| 372 |
# if not, return message saying they have run out of tokens
|
| 373 |
if user.metadata["tokens_left"] <= 0 and "admin" not in user.metadata["role"]:
|
| 374 |
current_datetime = get_time()
|
| 375 |
-
cooldown, cooldown_end_time = check_user_cooldown(
|
|
|
|
|
|
|
| 376 |
if cooldown:
|
| 377 |
# get time left in cooldown
|
| 378 |
# convert both to datetime objects
|
|
@@ -390,7 +417,6 @@ class Chatbot:
|
|
| 390 |
minutes, seconds = divmod(remainder, 60)
|
| 391 |
# Format the time as 00 hrs 00 mins 00 secs
|
| 392 |
formatted_time = f"{hours:02} hrs {minutes:02} mins {seconds:02} secs"
|
| 393 |
-
await update_user_info(user)
|
| 394 |
await cl.Message(
|
| 395 |
content=(
|
| 396 |
"Ah, seems like you have run out of tokens...Click "
|
|
@@ -400,7 +426,20 @@ class Chatbot:
|
|
| 400 |
),
|
| 401 |
author=SYSTEM,
|
| 402 |
).send()
|
|
|
|
|
|
|
| 403 |
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 404 |
|
| 405 |
llm_settings = cl.user_session.get("llm_settings", {})
|
| 406 |
view_sources = llm_settings.get("view_sources", False)
|
|
@@ -479,10 +518,13 @@ class Chatbot:
|
|
| 479 |
print("Time taken to generate questions: ", time.time() - start_time)
|
| 480 |
|
| 481 |
# # update user info with token count
|
| 482 |
-
|
| 483 |
-
|
| 484 |
-
|
| 485 |
-
|
|
|
|
|
|
|
|
|
|
| 486 |
|
| 487 |
await cl.Message(
|
| 488 |
content=answer_with_sources,
|
|
|
|
| 20 |
update_user_info,
|
| 21 |
get_time,
|
| 22 |
check_user_cooldown,
|
| 23 |
+
reset_tokens_for_user,
|
| 24 |
+
get_user_details,
|
| 25 |
)
|
| 26 |
import copy
|
| 27 |
from typing import Optional
|
|
|
|
| 56 |
return data_layer
|
| 57 |
|
| 58 |
|
| 59 |
+
async def update_user_from_chainlit(user, token_count=0):
|
| 60 |
+
if "admin" not in user.metadata["role"]:
|
| 61 |
+
user.metadata["tokens_left"] = user.metadata["tokens_left"] - token_count
|
| 62 |
+
user.metadata["all_time_tokens_allocated"] = (
|
| 63 |
+
user.metadata["all_time_tokens_allocated"] - token_count
|
| 64 |
+
)
|
| 65 |
+
user.metadata["tokens_left_at_last_message"] = user.metadata[
|
| 66 |
+
"tokens_left"
|
| 67 |
+
] # tokens_left will keep regenerating outside of chainlit
|
| 68 |
+
user.metadata["last_message_time"] = get_time()
|
| 69 |
+
await update_user_info(user)
|
| 70 |
+
|
| 71 |
+
tokens_left = user.metadata["tokens_left"]
|
| 72 |
+
if tokens_left < 0:
|
| 73 |
+
tokens_left = 0
|
| 74 |
+
return tokens_left
|
| 75 |
+
|
| 76 |
+
|
| 77 |
class Chatbot:
|
| 78 |
def __init__(self, config):
|
| 79 |
"""
|
|
|
|
| 241 |
"view_sources": llm_settings.get("view_sources"),
|
| 242 |
"follow_up_questions": llm_settings.get("follow_up_questions"),
|
| 243 |
}
|
| 244 |
+
print("Settings Dict: ", settings_dict)
|
| 245 |
await cl.Message(
|
| 246 |
author=SYSTEM,
|
| 247 |
content="LLM settings have been updated. You can continue with your Query!",
|
| 248 |
+
# elements=[
|
| 249 |
+
# cl.Text(
|
| 250 |
+
# name="settings",
|
| 251 |
+
# display="side",
|
| 252 |
+
# content=json.dumps(settings_dict, indent=4),
|
| 253 |
+
# language="json",
|
| 254 |
+
# ),
|
| 255 |
+
# ],
|
| 256 |
).send()
|
| 257 |
|
| 258 |
async def set_starters(self):
|
|
|
|
| 386 |
|
| 387 |
# update user info with last message time
|
| 388 |
user = cl.user_session.get("user")
|
| 389 |
+
await reset_tokens_for_user(user)
|
| 390 |
+
updated_user = await get_user_details(user.identifier)
|
| 391 |
+
user.metadata = updated_user.metadata
|
| 392 |
+
cl.user_session.set("user", user)
|
| 393 |
|
| 394 |
print("\n\n User Tokens Left: ", user.metadata["tokens_left"])
|
| 395 |
|
|
|
|
| 397 |
# if not, return message saying they have run out of tokens
|
| 398 |
if user.metadata["tokens_left"] <= 0 and "admin" not in user.metadata["role"]:
|
| 399 |
current_datetime = get_time()
|
| 400 |
+
cooldown, cooldown_end_time = await check_user_cooldown(
|
| 401 |
+
user, current_datetime
|
| 402 |
+
)
|
| 403 |
if cooldown:
|
| 404 |
# get time left in cooldown
|
| 405 |
# convert both to datetime objects
|
|
|
|
| 417 |
minutes, seconds = divmod(remainder, 60)
|
| 418 |
# Format the time as 00 hrs 00 mins 00 secs
|
| 419 |
formatted_time = f"{hours:02} hrs {minutes:02} mins {seconds:02} secs"
|
|
|
|
| 420 |
await cl.Message(
|
| 421 |
content=(
|
| 422 |
"Ah, seems like you have run out of tokens...Click "
|
|
|
|
| 426 |
),
|
| 427 |
author=SYSTEM,
|
| 428 |
).send()
|
| 429 |
+
user.metadata["in_cooldown"] = True
|
| 430 |
+
await update_user_info(user)
|
| 431 |
return
|
| 432 |
+
else:
|
| 433 |
+
await cl.Message(
|
| 434 |
+
content=(
|
| 435 |
+
"Ah, seems like you don't have any tokens left...Please wait while we regenerate your tokens. Click "
|
| 436 |
+
'<a href="/cooldown" style="color: #0000CD; text-decoration: none;" target="_self">here</a> to view your token credits.'
|
| 437 |
+
),
|
| 438 |
+
author=SYSTEM,
|
| 439 |
+
).send()
|
| 440 |
+
return
|
| 441 |
+
|
| 442 |
+
user.metadata["in_cooldown"] = False
|
| 443 |
|
| 444 |
llm_settings = cl.user_session.get("llm_settings", {})
|
| 445 |
view_sources = llm_settings.get("view_sources", False)
|
|
|
|
| 518 |
print("Time taken to generate questions: ", time.time() - start_time)
|
| 519 |
|
| 520 |
# # update user info with token count
|
| 521 |
+
tokens_left = await update_user_from_chainlit(user, token_count)
|
| 522 |
+
|
| 523 |
+
answer_with_sources += (
|
| 524 |
+
'\n\n<footer><span style="font-size: 0.8em; text-align: right; display: block;">Tokens Left: '
|
| 525 |
+
+ str(tokens_left)
|
| 526 |
+
+ "</span></footer>\n"
|
| 527 |
+
)
|
| 528 |
|
| 529 |
await cl.Message(
|
| 530 |
content=answer_with_sources,
|
code/modules/chat_processor/helpers.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
import os
|
| 2 |
from literalai import AsyncLiteralClient
|
| 3 |
from datetime import datetime, timedelta, timezone
|
| 4 |
-
from modules.config.constants import COOLDOWN_TIME, TOKENS_LEFT
|
| 5 |
from typing_extensions import TypedDict
|
| 6 |
import tiktoken
|
| 7 |
from typing import Any, Generic, List, Literal, Optional, TypeVar, Union
|
|
@@ -141,7 +141,7 @@ def get_time():
|
|
| 141 |
|
| 142 |
|
| 143 |
async def get_user_details(user_email_id):
|
| 144 |
-
user_info = await literal_client.api.
|
| 145 |
return user_info
|
| 146 |
|
| 147 |
|
|
@@ -155,11 +155,11 @@ async def update_user_info(user_info):
|
|
| 155 |
)
|
| 156 |
|
| 157 |
|
| 158 |
-
def check_user_cooldown(user_info, current_time):
|
| 159 |
|
| 160 |
-
# Check if no tokens left
|
| 161 |
tokens_left = user_info.metadata.get("tokens_left", 0)
|
| 162 |
-
if tokens_left > 0:
|
| 163 |
return False, None
|
| 164 |
|
| 165 |
user_info = convert_to_dict(user_info)
|
|
@@ -186,13 +186,54 @@ def check_user_cooldown(user_info, current_time):
|
|
| 186 |
if elapsed_time_in_seconds < COOLDOWN_TIME:
|
| 187 |
return True, cooldown_end_time_iso # Return in ISO 8601 format
|
| 188 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 189 |
return False, None
|
| 190 |
|
| 191 |
|
| 192 |
async def reset_tokens_for_user(user_info):
|
| 193 |
user_info = convert_to_dict(user_info)
|
| 194 |
-
user_info["metadata"]
|
| 195 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
|
| 197 |
|
| 198 |
async def get_thread_step_info(thread_id):
|
|
|
|
| 1 |
import os
|
| 2 |
from literalai import AsyncLiteralClient
|
| 3 |
from datetime import datetime, timedelta, timezone
|
| 4 |
+
from modules.config.constants import COOLDOWN_TIME, TOKENS_LEFT, REGEN_TIME
|
| 5 |
from typing_extensions import TypedDict
|
| 6 |
import tiktoken
|
| 7 |
from typing import Any, Generic, List, Literal, Optional, TypeVar, Union
|
|
|
|
| 141 |
|
| 142 |
|
| 143 |
async def get_user_details(user_email_id):
|
| 144 |
+
user_info = await literal_client.api.get_or_create_user(identifier=user_email_id)
|
| 145 |
return user_info
|
| 146 |
|
| 147 |
|
|
|
|
| 155 |
)
|
| 156 |
|
| 157 |
|
| 158 |
+
async def check_user_cooldown(user_info, current_time):
|
| 159 |
|
| 160 |
+
# # Check if no tokens left
|
| 161 |
tokens_left = user_info.metadata.get("tokens_left", 0)
|
| 162 |
+
if tokens_left > 0 and not user_info.metadata.get("in_cooldown", False):
|
| 163 |
return False, None
|
| 164 |
|
| 165 |
user_info = convert_to_dict(user_info)
|
|
|
|
| 186 |
if elapsed_time_in_seconds < COOLDOWN_TIME:
|
| 187 |
return True, cooldown_end_time_iso # Return in ISO 8601 format
|
| 188 |
|
| 189 |
+
user_info["metadata"]["in_cooldown"] = False
|
| 190 |
+
# If not in cooldown, regenerate tokens
|
| 191 |
+
await reset_tokens_for_user(user_info)
|
| 192 |
+
|
| 193 |
return False, None
|
| 194 |
|
| 195 |
|
| 196 |
async def reset_tokens_for_user(user_info):
|
| 197 |
user_info = convert_to_dict(user_info)
|
| 198 |
+
last_message_time_str = user_info["metadata"].get("last_message_time")
|
| 199 |
+
|
| 200 |
+
last_message_time = datetime.fromisoformat(last_message_time_str).replace(
|
| 201 |
+
tzinfo=timezone.utc
|
| 202 |
+
)
|
| 203 |
+
current_time = datetime.fromisoformat(get_time()).replace(tzinfo=timezone.utc)
|
| 204 |
+
|
| 205 |
+
# Calculate the elapsed time since the last message
|
| 206 |
+
elapsed_time_in_seconds = (current_time - last_message_time).total_seconds()
|
| 207 |
+
|
| 208 |
+
# Current token count (can be negative)
|
| 209 |
+
current_tokens = user_info["metadata"].get("tokens_left_at_last_message", 0)
|
| 210 |
+
current_tokens = min(current_tokens, TOKENS_LEFT)
|
| 211 |
+
|
| 212 |
+
# Maximum tokens that can be regenerated
|
| 213 |
+
max_tokens = user_info["metadata"].get("max_tokens", TOKENS_LEFT)
|
| 214 |
+
|
| 215 |
+
# Calculate how many tokens should have been regenerated proportionally
|
| 216 |
+
if current_tokens < max_tokens:
|
| 217 |
+
|
| 218 |
+
# Calculate the regeneration rate per second based on REGEN_TIME for full regeneration
|
| 219 |
+
regeneration_rate_per_second = max_tokens / REGEN_TIME
|
| 220 |
+
|
| 221 |
+
# Calculate how many tokens should have been regenerated based on the elapsed time
|
| 222 |
+
tokens_to_regenerate = int(
|
| 223 |
+
elapsed_time_in_seconds * regeneration_rate_per_second
|
| 224 |
+
)
|
| 225 |
+
|
| 226 |
+
# Ensure the new token count does not exceed max_tokens
|
| 227 |
+
new_token_count = min(current_tokens + tokens_to_regenerate, max_tokens)
|
| 228 |
+
|
| 229 |
+
print(
|
| 230 |
+
f"\n\n Adding {tokens_to_regenerate} tokens to the user, Time elapsed: {elapsed_time_in_seconds} seconds, Tokens after regeneration: {new_token_count}, Tokens before: {current_tokens} \n\n"
|
| 231 |
+
)
|
| 232 |
+
|
| 233 |
+
# Update the user's token count
|
| 234 |
+
user_info["metadata"]["tokens_left"] = new_token_count
|
| 235 |
+
|
| 236 |
+
await update_user_info(user_info)
|
| 237 |
|
| 238 |
|
| 239 |
async def get_thread_step_info(thread_id):
|
code/modules/config/constants.py
CHANGED
|
@@ -5,7 +5,9 @@ load_dotenv()
|
|
| 5 |
|
| 6 |
TIMEOUT = 60
|
| 7 |
COOLDOWN_TIME = 60
|
| 8 |
-
|
|
|
|
|
|
|
| 9 |
|
| 10 |
GITHUB_REPO = "https://github.com/DL4DS/dl4ds_tutor"
|
| 11 |
DOCS_WEBSITE = "https://dl4ds.github.io/dl4ds_tutor/"
|
|
|
|
| 5 |
|
| 6 |
TIMEOUT = 60
|
| 7 |
COOLDOWN_TIME = 60
|
| 8 |
+
REGEN_TIME = 180
|
| 9 |
+
TOKENS_LEFT = 2000
|
| 10 |
+
ALL_TIME_TOKENS_ALLOCATED = 1000000
|
| 11 |
|
| 12 |
GITHUB_REPO = "https://github.com/DL4DS/dl4ds_tutor"
|
| 13 |
DOCS_WEBSITE = "https://dl4ds.github.io/dl4ds_tutor/"
|
code/templates/cooldown.html
CHANGED
|
@@ -63,6 +63,13 @@
|
|
| 63 |
margin-bottom: 30px;
|
| 64 |
}
|
| 65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
.button {
|
| 67 |
padding: 12px 0;
|
| 68 |
margin: 12px 0;
|
|
@@ -70,33 +77,33 @@
|
|
| 70 |
border-radius: 6px;
|
| 71 |
cursor: pointer;
|
| 72 |
width: 100%;
|
| 73 |
-
border: 1px solid #4285F4;
|
| 74 |
-
background-color: #fff;
|
| 75 |
-
color: #4285F4;
|
| 76 |
transition: background-color 0.3s ease, border-color 0.3s ease;
|
| 77 |
-
display: none;
|
| 78 |
}
|
| 79 |
|
| 80 |
.button.start-tutor {
|
| 81 |
-
display: none;
|
| 82 |
}
|
| 83 |
|
| 84 |
.button:hover {
|
| 85 |
background-color: #e0e0e0;
|
| 86 |
-
border-color: #357ae8;
|
| 87 |
}
|
| 88 |
|
| 89 |
.sign-out-button {
|
| 90 |
border: 1px solid #FF4C4C;
|
| 91 |
background-color: #fff;
|
| 92 |
color: #FF4C4C;
|
| 93 |
-
display: block;
|
| 94 |
}
|
| 95 |
|
| 96 |
.sign-out-button:hover {
|
| 97 |
-
background-color: #ffe6e6;
|
| 98 |
-
border-color: #e04343;
|
| 99 |
-
color: #e04343;
|
| 100 |
}
|
| 101 |
|
| 102 |
#countdown {
|
|
@@ -104,6 +111,12 @@
|
|
| 104 |
color: #555;
|
| 105 |
margin-bottom: 20px;
|
| 106 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
</style>
|
| 108 |
</head>
|
| 109 |
<body>
|
|
@@ -113,24 +126,26 @@
|
|
| 113 |
<p>It seems like you need to wait a bit before starting a new session.</p>
|
| 114 |
<p class="cooldown-message">Time remaining until the cooldown period ends:</p>
|
| 115 |
<p id="countdown"></p>
|
|
|
|
| 116 |
<button id="startTutorBtn" class="button start-tutor" onclick="startTutor()">Start AI Tutor</button>
|
| 117 |
<form action="/logout" method="get">
|
| 118 |
<button type="submit" class="button sign-out-button">Sign Out</button>
|
| 119 |
</form>
|
|
|
|
| 120 |
</div>
|
| 121 |
<script>
|
| 122 |
function startCountdown(endTime) {
|
| 123 |
const countdownElement = document.getElementById('countdown');
|
| 124 |
const startTutorBtn = document.getElementById('startTutorBtn');
|
| 125 |
-
const endTimeDate = new Date(endTime);
|
| 126 |
|
| 127 |
function updateCountdown() {
|
| 128 |
-
const now = new Date();
|
| 129 |
-
const timeLeft = endTimeDate.getTime() - now.getTime();
|
| 130 |
|
| 131 |
if (timeLeft <= 0) {
|
| 132 |
countdownElement.textContent = "Cooldown period has ended.";
|
| 133 |
-
startTutorBtn.style.display = "block";
|
| 134 |
} else {
|
| 135 |
const hours = Math.floor(timeLeft / 1000 / 60 / 60);
|
| 136 |
const minutes = Math.floor((timeLeft / 1000 / 60) % 60);
|
|
@@ -139,17 +154,28 @@
|
|
| 139 |
}
|
| 140 |
}
|
| 141 |
|
| 142 |
-
updateCountdown();
|
| 143 |
-
setInterval(updateCountdown, 1000);
|
| 144 |
}
|
| 145 |
|
| 146 |
function startTutor() {
|
| 147 |
-
// Redirect to AI Tutor session start or any other logic to start the tutor
|
| 148 |
window.location.href = "/start-tutor";
|
| 149 |
}
|
| 150 |
|
| 151 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
startCountdown("{{ cooldown_end_time }}");
|
|
|
|
|
|
|
|
|
|
| 153 |
</script>
|
| 154 |
</body>
|
| 155 |
</html>
|
|
|
|
| 63 |
margin-bottom: 30px;
|
| 64 |
}
|
| 65 |
|
| 66 |
+
.tokens-left {
|
| 67 |
+
font-size: 14px;
|
| 68 |
+
color: #333;
|
| 69 |
+
margin-bottom: 30px;
|
| 70 |
+
font-weight: 600;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
.button {
|
| 74 |
padding: 12px 0;
|
| 75 |
margin: 12px 0;
|
|
|
|
| 77 |
border-radius: 6px;
|
| 78 |
cursor: pointer;
|
| 79 |
width: 100%;
|
| 80 |
+
border: 1px solid #4285F4;
|
| 81 |
+
background-color: #fff;
|
| 82 |
+
color: #4285F4;
|
| 83 |
transition: background-color 0.3s ease, border-color 0.3s ease;
|
| 84 |
+
display: none;
|
| 85 |
}
|
| 86 |
|
| 87 |
.button.start-tutor {
|
| 88 |
+
display: none;
|
| 89 |
}
|
| 90 |
|
| 91 |
.button:hover {
|
| 92 |
background-color: #e0e0e0;
|
| 93 |
+
border-color: #357ae8;
|
| 94 |
}
|
| 95 |
|
| 96 |
.sign-out-button {
|
| 97 |
border: 1px solid #FF4C4C;
|
| 98 |
background-color: #fff;
|
| 99 |
color: #FF4C4C;
|
| 100 |
+
display: block;
|
| 101 |
}
|
| 102 |
|
| 103 |
.sign-out-button:hover {
|
| 104 |
+
background-color: #ffe6e6;
|
| 105 |
+
border-color: #e04343;
|
| 106 |
+
color: #e04343;
|
| 107 |
}
|
| 108 |
|
| 109 |
#countdown {
|
|
|
|
| 111 |
color: #555;
|
| 112 |
margin-bottom: 20px;
|
| 113 |
}
|
| 114 |
+
|
| 115 |
+
.footer {
|
| 116 |
+
font-size: 12px;
|
| 117 |
+
color: #777;
|
| 118 |
+
margin-top: 20px;
|
| 119 |
+
}
|
| 120 |
</style>
|
| 121 |
</head>
|
| 122 |
<body>
|
|
|
|
| 126 |
<p>It seems like you need to wait a bit before starting a new session.</p>
|
| 127 |
<p class="cooldown-message">Time remaining until the cooldown period ends:</p>
|
| 128 |
<p id="countdown"></p>
|
| 129 |
+
<p class="tokens-left">Tokens Left: <span id="tokensLeft">{{ tokens_left }}</span></p>
|
| 130 |
<button id="startTutorBtn" class="button start-tutor" onclick="startTutor()">Start AI Tutor</button>
|
| 131 |
<form action="/logout" method="get">
|
| 132 |
<button type="submit" class="button sign-out-button">Sign Out</button>
|
| 133 |
</form>
|
| 134 |
+
<div class="footer">Reload the page to update token stats</div>
|
| 135 |
</div>
|
| 136 |
<script>
|
| 137 |
function startCountdown(endTime) {
|
| 138 |
const countdownElement = document.getElementById('countdown');
|
| 139 |
const startTutorBtn = document.getElementById('startTutorBtn');
|
| 140 |
+
const endTimeDate = new Date(endTime);
|
| 141 |
|
| 142 |
function updateCountdown() {
|
| 143 |
+
const now = new Date();
|
| 144 |
+
const timeLeft = endTimeDate.getTime() - now.getTime();
|
| 145 |
|
| 146 |
if (timeLeft <= 0) {
|
| 147 |
countdownElement.textContent = "Cooldown period has ended.";
|
| 148 |
+
startTutorBtn.style.display = "block";
|
| 149 |
} else {
|
| 150 |
const hours = Math.floor(timeLeft / 1000 / 60 / 60);
|
| 151 |
const minutes = Math.floor((timeLeft / 1000 / 60) % 60);
|
|
|
|
| 154 |
}
|
| 155 |
}
|
| 156 |
|
| 157 |
+
updateCountdown();
|
| 158 |
+
setInterval(updateCountdown, 1000);
|
| 159 |
}
|
| 160 |
|
| 161 |
function startTutor() {
|
|
|
|
| 162 |
window.location.href = "/start-tutor";
|
| 163 |
}
|
| 164 |
|
| 165 |
+
function updateTokensLeft() {
|
| 166 |
+
fetch('/get-tokens-left')
|
| 167 |
+
.then(response => response.json())
|
| 168 |
+
.then(data => {
|
| 169 |
+
document.getElementById('tokensLeft').textContent = data.tokens_left;
|
| 170 |
+
})
|
| 171 |
+
.catch(error => console.error('Error fetching tokens:', error));
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
// Start the countdown
|
| 175 |
startCountdown("{{ cooldown_end_time }}");
|
| 176 |
+
|
| 177 |
+
// Update tokens left when the page loads
|
| 178 |
+
updateTokensLeft();
|
| 179 |
</script>
|
| 180 |
</body>
|
| 181 |
</html>
|
code/templates/dashboard.html
CHANGED
|
@@ -27,7 +27,7 @@
|
|
| 27 |
border-radius: 8px;
|
| 28 |
width: 100%;
|
| 29 |
max-width: 400px;
|
| 30 |
-
padding:
|
| 31 |
box-sizing: border-box;
|
| 32 |
text-align: center;
|
| 33 |
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
|
@@ -39,35 +39,43 @@
|
|
| 39 |
width: 90px;
|
| 40 |
height: 90px;
|
| 41 |
border-radius: 50%;
|
| 42 |
-
margin-bottom:
|
| 43 |
border: 2px solid #ddd;
|
| 44 |
}
|
| 45 |
|
| 46 |
.container h1 {
|
| 47 |
-
margin-bottom:
|
| 48 |
-
font-size:
|
| 49 |
font-weight: 600;
|
| 50 |
color: #1a1a1a;
|
| 51 |
}
|
| 52 |
|
| 53 |
.container p {
|
| 54 |
-
font-size:
|
| 55 |
color: #4a4a4a;
|
| 56 |
-
margin-bottom:
|
| 57 |
line-height: 1.5;
|
| 58 |
}
|
| 59 |
|
| 60 |
.tokens-left {
|
| 61 |
-
font-size:
|
| 62 |
color: #333;
|
| 63 |
-
margin-bottom:
|
| 64 |
font-weight: 600;
|
| 65 |
}
|
| 66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
.button {
|
| 68 |
padding: 12px 0;
|
| 69 |
margin: 12px 0;
|
| 70 |
-
font-size:
|
| 71 |
border-radius: 6px;
|
| 72 |
cursor: pointer;
|
| 73 |
width: 100%;
|
|
@@ -105,6 +113,12 @@
|
|
| 105 |
border-color: #e04343; /* Darker red for hover */
|
| 106 |
color: #e04343; /* Red text on hover */
|
| 107 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
</style>
|
| 109 |
</head>
|
| 110 |
<body>
|
|
@@ -113,12 +127,14 @@
|
|
| 113 |
<h1>Welcome, {{ username }}</h1>
|
| 114 |
<p>Ready to start your AI tutoring session?</p>
|
| 115 |
<p class="tokens-left">Tokens Left: {{ tokens_left }}</p>
|
|
|
|
| 116 |
<form action="/start-tutor" method="post">
|
| 117 |
<button type="submit" class="button start-button">Start AI Tutor</button>
|
| 118 |
</form>
|
| 119 |
<form action="/logout" method="get">
|
| 120 |
<button type="submit" class="button sign-out-button">Sign Out</button>
|
| 121 |
</form>
|
|
|
|
| 122 |
</div>
|
| 123 |
<script>
|
| 124 |
let token = "{{ jwt_token }}";
|
|
|
|
| 27 |
border-radius: 8px;
|
| 28 |
width: 100%;
|
| 29 |
max-width: 400px;
|
| 30 |
+
padding: 40px;
|
| 31 |
box-sizing: border-box;
|
| 32 |
text-align: center;
|
| 33 |
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
|
|
|
| 39 |
width: 90px;
|
| 40 |
height: 90px;
|
| 41 |
border-radius: 50%;
|
| 42 |
+
margin-bottom: 20px;
|
| 43 |
border: 2px solid #ddd;
|
| 44 |
}
|
| 45 |
|
| 46 |
.container h1 {
|
| 47 |
+
margin-bottom: 20px;
|
| 48 |
+
font-size: 26px;
|
| 49 |
font-weight: 600;
|
| 50 |
color: #1a1a1a;
|
| 51 |
}
|
| 52 |
|
| 53 |
.container p {
|
| 54 |
+
font-size: 15px;
|
| 55 |
color: #4a4a4a;
|
| 56 |
+
margin-bottom: 25px;
|
| 57 |
line-height: 1.5;
|
| 58 |
}
|
| 59 |
|
| 60 |
.tokens-left {
|
| 61 |
+
font-size: 17px;
|
| 62 |
color: #333;
|
| 63 |
+
margin-bottom: 10px;
|
| 64 |
font-weight: 600;
|
| 65 |
}
|
| 66 |
|
| 67 |
+
.all-time-tokens {
|
| 68 |
+
font-size: 14px; /* Reduced font size */
|
| 69 |
+
color: #555;
|
| 70 |
+
margin-bottom: 30px;
|
| 71 |
+
font-weight: 500;
|
| 72 |
+
white-space: nowrap; /* Prevents breaking to a new line */
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
.button {
|
| 76 |
padding: 12px 0;
|
| 77 |
margin: 12px 0;
|
| 78 |
+
font-size: 15px;
|
| 79 |
border-radius: 6px;
|
| 80 |
cursor: pointer;
|
| 81 |
width: 100%;
|
|
|
|
| 113 |
border-color: #e04343; /* Darker red for hover */
|
| 114 |
color: #e04343; /* Red text on hover */
|
| 115 |
}
|
| 116 |
+
|
| 117 |
+
.footer {
|
| 118 |
+
font-size: 12px;
|
| 119 |
+
color: #777;
|
| 120 |
+
margin-top: 25px;
|
| 121 |
+
}
|
| 122 |
</style>
|
| 123 |
</head>
|
| 124 |
<body>
|
|
|
|
| 127 |
<h1>Welcome, {{ username }}</h1>
|
| 128 |
<p>Ready to start your AI tutoring session?</p>
|
| 129 |
<p class="tokens-left">Tokens Left: {{ tokens_left }}</p>
|
| 130 |
+
<p class="all-time-tokens">All-Time Tokens Allocated: {{ all_time_tokens_allocated }} / {{ total_tokens_allocated }}</p>
|
| 131 |
<form action="/start-tutor" method="post">
|
| 132 |
<button type="submit" class="button start-button">Start AI Tutor</button>
|
| 133 |
</form>
|
| 134 |
<form action="/logout" method="get">
|
| 135 |
<button type="submit" class="button sign-out-button">Sign Out</button>
|
| 136 |
</form>
|
| 137 |
+
<div class="footer">Reload the page to update token stats</div>
|
| 138 |
</div>
|
| 139 |
<script>
|
| 140 |
let token = "{{ jwt_token }}";
|