import streamlit as st
import os
import openai
import json
import bcrypt
import os
from groq import Groq
import re
import warnings
warnings.filterwarnings('ignore')
client = Groq(
api_key=os.environ.get("GROQ_API_KEY"),
)
# hiding streamlit header and menus
hide_menu = """
"""
st.markdown(hide_menu, unsafe_allow_html = True)
# function to remove the streamlit tag from webpage title
def set_page_title(title):
st.markdown(unsafe_allow_html=True, body=f"""
""")
# Define a Streamlit key for storing whether the user is authenticated.
if 'authenticated' not in st.session_state:
st.session_state.authenticated = False
# loading user logins from config
config_file_path = "config.json" # Path to your configuration file
with open(config_file_path) as config_file:
credentials = json.load(config_file)
# Function to verify credentials
def check_credentials(password):
# Check if the entered credentials match the hashed passwords in the config file
# if username in credentials and bcrypt.checkpw(password.encode("utf-8"), credentials[username].encode("utf-8")):
if password=='123':
return True
return False
# Main login page
def login_page():
set_page_title("TGPT")
st.markdown("
Welcome to Team-GPT
", unsafe_allow_html=True)
st.markdown('\n')
# Login form
with st.form(key='login_form'):
username = st.text_input("Username")
password = st.text_input("Password", type="password")
# Add some CSS styling to center-align the button
login_button = st.form_submit_button(label='Login', type = 'primary', use_container_width = True)
st.session_state.username = username
if login_button:
if check_credentials(password):
pattern = r"^[a-zA-Z]+$"
if re.fullmatch(pattern, username):
st.session_state['authenticated'] = True # Set the session state
st.rerun() # Rerun the app to update the state
else:
st.error("Username can't contain numbers or special characters!")
else:
st.error("The password is incorrect!")
st.write('Password: 123')
st.markdown('\n')
st.markdown("Instructions :", unsafe_allow_html=True)
st.markdown("""
- Username can't have numbers or special characters.
- By default, every new conversation is Private.
- To make the conversation Public, select 'Shared' before submitting first prompt.
- Once the first prompt is submitted, you can't change the chat visibility.
""", unsafe_allow_html=True)
# function to create new chat
def create_new_chat(st):
st.session_state.messages = []
# function to update chat
def update_chat(st):
# getting file messages
file_var = open(st.session_state.file_name, encoding='utf-8')
file_content = file_var.read()
file_messages = file_content.split('-end-\n')
file_messages = [file_messages[i].replace('-end-','') for i in range(len(file_messages))]
# getting session_messages
session_messages = st.session_state.messages
# computing the message difference
diff = len(file_messages) - len(session_messages)
# appending the messages to update session state
new_messages = []
if diff>0:
for i in range(len(session_messages), len(file_messages)):
session_messages.append(file_messages[i])
new_messages.append(file_messages[i])
# displaying new messages
for message in new_messages:
print(message)
with st.chat_message(message["added_by"]):
st.markdown(message["content"])
def run_chatbot(st):
set_page_title("TGPT")
# Initialize chat history
if "messages" not in st.session_state:
st.session_state.messages = []
# default chat is New
if "chat_type" not in st.session_state:
st.session_state.chat_type = 'New'
# replace current chat variable
if "replace_current_chat" not in st.session_state:
st.session_state.replace_current_chat = False
# creating file name variable in session_state
if "file_name" not in st.session_state:
st.session_state.file_name = ''
# initializing visibility as shared
if "visibility" not in st.session_state:
st.session_state.visibility = 'Shared👥'
# sidebar
with st.sidebar:
if st.button("Logout", type = "secondary", key = 'logout'):
st.session_state.clear() # Clear all session state variables
st.rerun()
if st.button("New Chat ➕", type = "primary", key = 'new_chat'):
st.session_state.messages = []
st.session_state.file_name = ''
st.session_state.chat_type = 'New'
st.session_state.replace_current_chat = False
st.session_state.visibility = 'Private🔒'
# displaying chat history from history files
st.header('Chat History')
history_files = os.listdir('chat_history/')
# Sort the files based on their creation time in descending order
complete_files = sorted(history_files, key=lambda x: os.path.getctime(os.path.join('chat_history/', x)),
reverse=True)
# removing the username and visibility from chat heading
usersnames = [f.split('_')[0] for f in complete_files]
visibility_status = [f.split('_')[1] for f in complete_files]
files = [f.split('_')[2] for f in complete_files]
# iterating over each history file to add as a button
for i in range(len(complete_files)):
add_chat = False
# based on user who created file and visibility, deciding if chat should be visible to a user or not
if (visibility_status[i]=='Private🔒') & (usersnames[i]==st.session_state.username):
add_chat = True
elif visibility_status[i]=='Shared👥':
add_chat = True
if add_chat:
unique_key = f"{i}_{files[i][:-4]}"
if st.button(files[i][:-4], key=unique_key):
# print('Loading : ', chat)
st.session_state.replace_current_chat = True
st.session_state.chat_type = 'Old'
st.session_state.file_name = 'chat_history/' + complete_files[i]
else:
continue
# replacing current chat with old
if st.session_state.replace_current_chat:
st.session_state.messages = []
st.session_state.visibility = st.session_state.file_name.split('_')[2]
prev_file = open(st.session_state.file_name, encoding='utf-8')
file_content = prev_file.read()
msgs = file_content.split('-end-\n')
for i in range(len(msgs)):
msgs[i] = msgs[i].replace('-end-','')
# text format -> user:username:msg (for AI, the user and username are same : assistant)
# first word is reserved for the user type : user, assistant
# second word is for username
# third is text
msg_content = msgs[i].split(':',2) # splitting the text into 3 parts [user, username, msg]
user_type = msg_content[0]
from_user = msg_content[1]
msg_text = msg_content[2]
st.session_state.messages.append({"role": user_type, "added_by" : from_user, "content": msg_text})
# creating columns to seperate title and visibility buttons
header1, header2 = st.columns(2)
with header1:
# Setting title for chat window
st.markdown("Team-GPT v0.2
", unsafe_allow_html=True)
# Shared-private option through radio button
with header2:
# css for button positioning
st.markdown(
"""
""",
unsafe_allow_html=True
)
# for the past chats, we just display the visibility status earlier selected
if st.session_state.chat_type=='Old':
option = st.radio(label = '', options = (st.session_state.visibility,))
else:
option = st.radio(label = '', options = ('Private🔒', 'Shared👥'))
st.session_state.visibility = option
# displaying all the messages
for message in st.session_state.messages:
with st.chat_message(message["added_by"]):
st.markdown(message["content"])
# user input
prompt = st.chat_input("Type here...")
if prompt:
if st.session_state.chat_type=='New':
# making sure all the characters are alpha-numeric
file_name = "".join(c if c.isalnum() or c in {'_', ' ', '.'} else ' ' for c in prompt)
file_name = " ".join(file_name.split()[:5])
file_name = file_name.strip() # removing any trailing spaces
# naming file after user and its visibility
file_name = "chat_history/" + st.session_state.username + '_' + st.session_state.visibility + '_' + file_name + ".txt"
st.session_state.file_name = file_name
with st.chat_message(st.session_state.username):
st.markdown(prompt)
# add user msg to chat history
st.session_state.messages.append({"role":"user", "added_by":st.session_state.username, "content":prompt})
# writing prompt to file
# print("file : ", st.session_state.file_name)
file = open(st.session_state.file_name, "a", encoding='utf-8')
if st.session_state.chat_type=='New':
file.write('user:' + st.session_state.username + ':' + prompt + "-end-")
st.session_state.chat_type = 'Old'
elif st.session_state.chat_type=='Old':
file.write("\n" + 'user:' + st.session_state.username + ':' + prompt + "-end-")
with st.chat_message("assistant"):
message_placeholder = st.empty()
full_response = ""
response = client.chat.completions.create(
messages = [{"role":m["role"], "content":m["content"]} for m in st.session_state.messages[-10:]],
model= 'llama-3.1-8b-instant',
temperature = 1,
max_tokens = 3000
)
full_response = response.choices[0].message.content
# sending just last 10 messages with the prompt to create some context to prompt
# for response in openai.ChatCompletion.create(model = "gpt-3.5-turbo",
# messages = [
# {"role":m["role"], "content":m["content"]} for m in st.session_state.messages[-10:]
# ], stream = True):
# print(response,'\n\n')
# full_response += response.choices[0].delta.get("content", "")
# message_placeholder.markdown(full_response + "| ")
message_placeholder.markdown(full_response)
file.write("\n" + 'assistant:assistant:' + full_response + "-end-")
st.session_state.messages.append({"role":"assistant", "added_by":"assistant", "content":full_response})
print(st.session_state.messages,'\n')
update_chat(st)
if not st.session_state['authenticated']:
login_page()
else:
run_chatbot(st)