Spaces:
Build error
Build error
XThomasBU
commited on
Commit
·
da00fb2
1
Parent(s):
1796f63
updates
Browse files- code/app.py +11 -9
- code/main.py +29 -9
- code/modules/chat_processor/helpers.py +6 -0
- code/templates/cooldown.html +1 -0
code/app.py
CHANGED
|
@@ -43,9 +43,10 @@ templates = Jinja2Templates(directory="templates")
|
|
| 43 |
session_store = {}
|
| 44 |
CHAINLIT_PATH = "/chainlit_tutor"
|
| 45 |
|
|
|
|
| 46 |
USER_ROLES = {
|
| 47 |
"tgardos@bu.edu": ["instructor", "bu"],
|
| 48 |
-
"xthomas@bu.edu": ["instructor", "bu"],
|
| 49 |
"faridkar@bu.edu": ["instructor", "bu"],
|
| 50 |
"xavierohan1@gmail.com": ["guest"],
|
| 51 |
# Add more users and roles as needed
|
|
@@ -168,6 +169,7 @@ async def auth_google(request: Request):
|
|
| 168 |
email = user_info["email"]
|
| 169 |
name = user_info.get("name", "")
|
| 170 |
profile_image = user_info.get("picture", "")
|
|
|
|
| 171 |
|
| 172 |
session_token = secrets.token_hex(16)
|
| 173 |
session_store[session_token] = {
|
|
@@ -180,6 +182,7 @@ async def auth_google(request: Request):
|
|
| 180 |
# add literalai user info to session store to be sent to chainlit
|
| 181 |
literalai_user = await get_user_details(email)
|
| 182 |
session_store[session_token]["literalai_info"] = literalai_user.to_dict()
|
|
|
|
| 183 |
|
| 184 |
user_info_json = json.dumps(session_store[session_token])
|
| 185 |
user_info_encoded = base64.b64encode(user_info_json.encode()).decode()
|
|
@@ -204,18 +207,17 @@ async def cooldown(request: Request):
|
|
| 204 |
cooldown, cooldown_end_time = check_user_cooldown(user_details, current_datetime)
|
| 205 |
print(f"User in cooldown: {cooldown}")
|
| 206 |
print(f"Cooldown end time: {cooldown_end_time}")
|
| 207 |
-
if cooldown:
|
| 208 |
return templates.TemplateResponse(
|
| 209 |
"cooldown.html",
|
| 210 |
{
|
| 211 |
"request": request,
|
| 212 |
"username": user_info["email"],
|
| 213 |
"role": get_user_role(user_info["email"]),
|
| 214 |
-
"cooldown_end_time": cooldown_end_time,
|
| 215 |
},
|
| 216 |
)
|
| 217 |
else:
|
| 218 |
-
user_details.metadata["in_cooldown"] = False
|
| 219 |
await update_user_info(user_details)
|
| 220 |
await reset_tokens_for_user(user_details)
|
| 221 |
return RedirectResponse("/post-signin")
|
|
@@ -232,14 +234,14 @@ async def post_signin(request: Request):
|
|
| 232 |
# if new user, set the number of tries
|
| 233 |
if "tokens_left" not in user_details.metadata:
|
| 234 |
await reset_tokens_for_user(user_details)
|
| 235 |
-
|
| 236 |
-
if "last_message_time" in user_details.metadata
|
|
|
|
|
|
|
| 237 |
cooldown, _ = check_user_cooldown(user_details, current_datetime)
|
| 238 |
if cooldown:
|
| 239 |
return RedirectResponse("/cooldown")
|
| 240 |
-
|
| 241 |
-
user_details.metadata["in_cooldown"] = False
|
| 242 |
-
await reset_tokens_for_user(user_details)
|
| 243 |
if user_info:
|
| 244 |
username = user_info["email"]
|
| 245 |
role = get_user_role(username)
|
|
|
|
| 43 |
session_store = {}
|
| 44 |
CHAINLIT_PATH = "/chainlit_tutor"
|
| 45 |
|
| 46 |
+
# only admin is given any additional permissions for now -- no limits on tokens
|
| 47 |
USER_ROLES = {
|
| 48 |
"tgardos@bu.edu": ["instructor", "bu"],
|
| 49 |
+
"xthomas@bu.edu": ["admin", "instructor", "bu"],
|
| 50 |
"faridkar@bu.edu": ["instructor", "bu"],
|
| 51 |
"xavierohan1@gmail.com": ["guest"],
|
| 52 |
# Add more users and roles as needed
|
|
|
|
| 169 |
email = user_info["email"]
|
| 170 |
name = user_info.get("name", "")
|
| 171 |
profile_image = user_info.get("picture", "")
|
| 172 |
+
role = get_user_role(email)
|
| 173 |
|
| 174 |
session_token = secrets.token_hex(16)
|
| 175 |
session_store[session_token] = {
|
|
|
|
| 182 |
# add literalai user info to session store to be sent to chainlit
|
| 183 |
literalai_user = await get_user_details(email)
|
| 184 |
session_store[session_token]["literalai_info"] = literalai_user.to_dict()
|
| 185 |
+
session_store[session_token]["literalai_info"]["metadata"]["role"] = role
|
| 186 |
|
| 187 |
user_info_json = json.dumps(session_store[session_token])
|
| 188 |
user_info_encoded = base64.b64encode(user_info_json.encode()).decode()
|
|
|
|
| 207 |
cooldown, cooldown_end_time = check_user_cooldown(user_details, current_datetime)
|
| 208 |
print(f"User in cooldown: {cooldown}")
|
| 209 |
print(f"Cooldown end time: {cooldown_end_time}")
|
| 210 |
+
if cooldown and "admin" not in get_user_role(user_info["email"]):
|
| 211 |
return templates.TemplateResponse(
|
| 212 |
"cooldown.html",
|
| 213 |
{
|
| 214 |
"request": request,
|
| 215 |
"username": user_info["email"],
|
| 216 |
"role": get_user_role(user_info["email"]),
|
| 217 |
+
"cooldown_end_time": cooldown_end_time,
|
| 218 |
},
|
| 219 |
)
|
| 220 |
else:
|
|
|
|
| 221 |
await update_user_info(user_details)
|
| 222 |
await reset_tokens_for_user(user_details)
|
| 223 |
return RedirectResponse("/post-signin")
|
|
|
|
| 234 |
# if new user, set the number of tries
|
| 235 |
if "tokens_left" not in user_details.metadata:
|
| 236 |
await reset_tokens_for_user(user_details)
|
| 237 |
+
|
| 238 |
+
if "last_message_time" in user_details.metadata and "admin" not in get_user_role(
|
| 239 |
+
user_info["email"]
|
| 240 |
+
):
|
| 241 |
cooldown, _ = check_user_cooldown(user_details, current_datetime)
|
| 242 |
if cooldown:
|
| 243 |
return RedirectResponse("/cooldown")
|
| 244 |
+
|
|
|
|
|
|
|
| 245 |
if user_info:
|
| 246 |
username = user_info["email"]
|
| 247 |
role = get_user_role(username)
|
code/main.py
CHANGED
|
@@ -27,6 +27,7 @@ from chainlit.types import ThreadDict
|
|
| 27 |
import time
|
| 28 |
import base64
|
| 29 |
from langchain_community.callbacks import get_openai_callback
|
|
|
|
| 30 |
|
| 31 |
USER_TIMEOUT = 60_000
|
| 32 |
SYSTEM = "System"
|
|
@@ -365,21 +366,37 @@ class Chatbot:
|
|
| 365 |
# update user info with last message time
|
| 366 |
user = cl.user_session.get("user")
|
| 367 |
|
| 368 |
-
print("\n\n User Token Usage: ", user.metadata["all_time_tokens"])
|
| 369 |
print("\n\n User Tokens Left: ", user.metadata["tokens_left"])
|
| 370 |
|
| 371 |
# see if user has token credits left
|
| 372 |
# if not, return message saying they have run out of tokens
|
| 373 |
-
if user.metadata["tokens_left"] <= 0:
|
| 374 |
current_datetime = get_time()
|
| 375 |
cooldown, cooldown_end_time = check_user_cooldown(user, current_datetime)
|
| 376 |
if cooldown:
|
| 377 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 378 |
await update_user_info(user)
|
| 379 |
await cl.Message(
|
| 380 |
content=(
|
| 381 |
"Ah, seems like you have run out of tokens...Click "
|
| 382 |
-
'<a href="/cooldown" style="color: #0000CD; text-decoration: none;" target="_self">here</a> for more info.'
|
|
|
|
|
|
|
| 383 |
),
|
| 384 |
author=SYSTEM,
|
| 385 |
).send()
|
|
@@ -462,10 +479,8 @@ class Chatbot:
|
|
| 462 |
print("Time taken to generate questions: ", time.time() - start_time)
|
| 463 |
|
| 464 |
# # update user info with token count
|
| 465 |
-
|
| 466 |
-
|
| 467 |
-
user.metadata.get("all_time_tokens", 0) + token_count
|
| 468 |
-
)
|
| 469 |
user.metadata["last_message_time"] = get_time()
|
| 470 |
await update_user_info(user)
|
| 471 |
|
|
@@ -509,6 +524,10 @@ class Chatbot:
|
|
| 509 |
).decode()
|
| 510 |
decoded_user_info = json.loads(decoded_user_info)
|
| 511 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 512 |
return cl.User(
|
| 513 |
id=decoded_user_info["literalai_info"]["id"],
|
| 514 |
identifier=decoded_user_info["literalai_info"]["identifier"],
|
|
@@ -516,10 +535,11 @@ class Chatbot:
|
|
| 516 |
)
|
| 517 |
|
| 518 |
async def on_follow_up(self, action: cl.Action):
|
|
|
|
| 519 |
message = await cl.Message(
|
| 520 |
content=action.description,
|
| 521 |
type="user_message",
|
| 522 |
-
author=
|
| 523 |
).send()
|
| 524 |
async with cl.Step(
|
| 525 |
name="on_follow_up", type="run", parent_id=message.id
|
|
|
|
| 27 |
import time
|
| 28 |
import base64
|
| 29 |
from langchain_community.callbacks import get_openai_callback
|
| 30 |
+
from datetime import datetime, timezone
|
| 31 |
|
| 32 |
USER_TIMEOUT = 60_000
|
| 33 |
SYSTEM = "System"
|
|
|
|
| 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 |
|
| 371 |
# see if user has token credits left
|
| 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(user, current_datetime)
|
| 376 |
if cooldown:
|
| 377 |
+
# get time left in cooldown
|
| 378 |
+
# convert both to datetime objects
|
| 379 |
+
cooldown_end_time = datetime.fromisoformat(cooldown_end_time).replace(
|
| 380 |
+
tzinfo=timezone.utc
|
| 381 |
+
)
|
| 382 |
+
current_datetime = datetime.fromisoformat(current_datetime).replace(
|
| 383 |
+
tzinfo=timezone.utc
|
| 384 |
+
)
|
| 385 |
+
cooldown_time_left = cooldown_end_time - current_datetime
|
| 386 |
+
# Get the total seconds
|
| 387 |
+
total_seconds = int(cooldown_time_left.total_seconds())
|
| 388 |
+
# Calculate hours, minutes, and seconds
|
| 389 |
+
hours, remainder = divmod(total_seconds, 3600)
|
| 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 "
|
| 397 |
+
'<a href="/cooldown" style="color: #0000CD; text-decoration: none;" target="_self">here</a> for more info. Please come back after {}'.format(
|
| 398 |
+
formatted_time
|
| 399 |
+
)
|
| 400 |
),
|
| 401 |
author=SYSTEM,
|
| 402 |
).send()
|
|
|
|
| 479 |
print("Time taken to generate questions: ", time.time() - start_time)
|
| 480 |
|
| 481 |
# # update user info with token count
|
| 482 |
+
if "admin" not in user.metadata["role"]:
|
| 483 |
+
user.metadata["tokens_left"] = user.metadata["tokens_left"] - token_count
|
|
|
|
|
|
|
| 484 |
user.metadata["last_message_time"] = get_time()
|
| 485 |
await update_user_info(user)
|
| 486 |
|
|
|
|
| 524 |
).decode()
|
| 525 |
decoded_user_info = json.loads(decoded_user_info)
|
| 526 |
|
| 527 |
+
print(
|
| 528 |
+
f"\n\n USER ROLE: {decoded_user_info['literalai_info']['metadata']['role']} \n\n"
|
| 529 |
+
)
|
| 530 |
+
|
| 531 |
return cl.User(
|
| 532 |
id=decoded_user_info["literalai_info"]["id"],
|
| 533 |
identifier=decoded_user_info["literalai_info"]["identifier"],
|
|
|
|
| 535 |
)
|
| 536 |
|
| 537 |
async def on_follow_up(self, action: cl.Action):
|
| 538 |
+
user = cl.user_session.get("user")
|
| 539 |
message = await cl.Message(
|
| 540 |
content=action.description,
|
| 541 |
type="user_message",
|
| 542 |
+
author=user.identifier,
|
| 543 |
).send()
|
| 544 |
async with cl.Step(
|
| 545 |
name="on_follow_up", type="run", parent_id=message.id
|
code/modules/chat_processor/helpers.py
CHANGED
|
@@ -156,6 +156,12 @@ async def update_user_info(user_info):
|
|
| 156 |
|
| 157 |
|
| 158 |
def check_user_cooldown(user_info, current_time):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
user_info = convert_to_dict(user_info)
|
| 160 |
last_message_time_str = user_info["metadata"].get("last_message_time")
|
| 161 |
|
|
|
|
| 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)
|
| 166 |
last_message_time_str = user_info["metadata"].get("last_message_time")
|
| 167 |
|
code/templates/cooldown.html
CHANGED
|
@@ -90,6 +90,7 @@
|
|
| 90 |
border: 1px solid #FF4C4C;
|
| 91 |
background-color: #fff;
|
| 92 |
color: #FF4C4C;
|
|
|
|
| 93 |
}
|
| 94 |
|
| 95 |
.sign-out-button:hover {
|
|
|
|
| 90 |
border: 1px solid #FF4C4C;
|
| 91 |
background-color: #fff;
|
| 92 |
color: #FF4C4C;
|
| 93 |
+
display: block; /* Ensure this button is always visible */
|
| 94 |
}
|
| 95 |
|
| 96 |
.sign-out-button:hover {
|