JournaLLM / app.py
ashu-1069's picture
Update app.py
f8c8a8b verified
import streamlit as st
import sqlite3
from hashlib import sha256
import streamlit as st
from langchain_community.embeddings import LlamaCppEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain_community.document_loaders import TextLoader
from langchain_community.vectorstores import FAISS
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.chains.llm import LLMChain
from langchain_community.llms import LlamaCpp
from langchain.chains import LLMChain
from langchain_community.llms import OpenAI
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.documents import Document
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from datetime import date
# Create a SQLite database and table
conn = sqlite3.connect("user_credentials.db")
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
username TEXT PRIMARY KEY,
password TEXT
)
''')
conn.commit()
if 'embeddings' not in st.session_state:
st.session_state.embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/all-MiniLM-L6-v2",
model_kwargs={"device": "cpu"},
)
def get_similar_docs(query):
db = FAISS.load_local('faiss_index',st.session_state.embeddings)
docs = db.similarity_search_with_score(query,100)
return docs
def format_docs(docs):
return " ".join(doc.page_content for doc in docs)
def get_advice_from_llm(query):
db = FAISS.load_local(st.session_state.username,st.session_state.embeddings)
retriever = db.as_retriever()
llm = LlamaCpp(model_path="./tinyllama-1.1b-chat-v1.0.Q8_0.gguf",n_ctx = 2048)
chat_history_str = "\n".join(["<|im_start|>" + entry[0]+ entry[1] +"<|im_emd|>\n" for entry in st.session_state['chat_history']])
template = """"
<|im_start|>system
{context}""" + chat_history_str + "<|im_end|>"\
"""
<|im_start|>user{input}<|im_end|>
<|im_start|>assistant
"""
prompt = PromptTemplate(input_variables=["input","context"], template=template)
llm_chain = LLMChain(llm=llm, prompt=prompt)
rag_chain = ( {"context": retriever|format_docs, "input": RunnablePassthrough()}| llm_chain)
answer = rag_chain.invoke(query)
return answer
def vectordb_entry():
loader = TextLoader(f"./{st.session_state.username}.txt")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=10)
docs = text_splitter.split_documents(documents)
db = FAISS.load_local(st.session_state.username,st.session_state.embeddings)
db.add_documents(docs)
db.save_local(st.session_state.username)
def save_into_text_file(file_path,text):
with open(file_path, 'w') as file:
file.write(text)
print(f"String saved to {file_path}")
def journal():
messages = st.container(height=600)
query = st.chat_input("Need some advice?")
if 'input_key' not in st.session_state:
st.session_state.input_key = 0
if 'chat_history' not in st.session_state:
st.session_state.chat_history = []
if query:
answer = get_advice_from_llm(query)
st.session_state.chat_history.append(("user", query))
st.session_state.chat_history.append(("assistant", answer['text']))
st.session_state.input_key += 1
if 'chat_history' in st.session_state and st.session_state.chat_history:
for speaker, message in st.session_state.chat_history:
if speaker == "user":
who = "You"
else:
who = "JournaLLM"
messages.chat_message(speaker).write(who + ': '+ str(message))
if st.button('Reset Chat'):
st.session_state.chat_history = []
st.session_state.input_key += 1
st.experimental_rerun()
# Function to hash passwords
def hash_password(password):
return sha256(password.encode()).hexdigest()
# Function to check login credentials
def authenticate(username, password):
hashed_password = hash_password(password)
cursor.execute("SELECT * FROM users WHERE username=? AND password=?", (username, hashed_password))
return cursor.fetchone() is not None
# Function to add a new user to the database
def add_user(username, password):
hashed_password = hash_password(password)
try:
cursor.execute("INSERT INTO users (username, password) VALUES (?, ?)", (username, hashed_password))
conn.commit()
return True # User added successfully
except sqlite3.IntegrityError:
return False # Username already exists
# Streamlit Login Page
def login_page():
st.title("Login Page")
un = st.text_input("Username:")
pw = st.text_input("Password:", type="password")
if un and pw:
st.session_state['username'] = un
st.session_state['password'] = pw
if st.button("Login"):
if not st.session_state['username'] or not st.session_state['password']:
st.error("Both username and password are required.")
elif authenticate(st.session_state['username'], st.session_state['password']):
create_table()
st.success("Login successful!")
else:
st.error("Invalid credentials. Please try again.")
# Streamlit Signup Page
def signup_page():
st.title("Signup Page")
new_username = st.text_input("New Username:")
new_password = st.text_input("New Password:", type="password")
if st.button("Signup"):
if not new_username or not new_password:
st.error("Both username and password are required.")
else:
result = add_user(new_username, new_password)
if result:
file_path = f"{new_username}.txt"
text = "I've started writing my journal"
# Open the file in write mode and write the string
with open(file_path, 'w') as file:
file.write(text)
print(f"String saved to {file_path}")
loader = TextLoader(f"./{new_username}.txt")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(documents)
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/all-MiniLM-L6-v2",
model_kwargs={"device": "cpu"},
)
db = FAISS.from_documents(docs,embeddings)
db.save_local(new_username)
st.success("Signup successful! You can now login.")
else:
st.error("Username already exists. Please choose a different username.")
def create_table():
conn = sqlite3.connect(f'{st.session_state.username}_entries.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT,
notes TEXT
)
''')
conn.commit()
conn.close()
# Function to insert data into the SQLite database
def insert_data(date, notes):
conn = sqlite3.connect(f'{st.session_state.username}_entries.db')
cursor = conn.cursor()
cursor.execute('''
INSERT INTO entries (date, notes)
VALUES (?, ?)
''', (date, notes))
conn.commit()
conn.close()
# Function to retrieve data for a selected date
def retrieve_data(selected_date):
conn = sqlite3.connect(f'{st.session_state.username}_entries.db')
cursor = conn.cursor()
cursor.execute('''
SELECT date, notes FROM entries WHERE date = ?
''', (selected_date,))
data = cursor.fetchall()
conn.close()
return data
def entry():
st.title('JournaLLM')
st.write('Welcome to JournaLLM, \
your personal space for mindful \
reflection and goal tracking! This app is designed to help you \
seamlessly capture your daily thoughts, \
set meaningful goals, and track your progress.')
c1,c2 = st.columns(2)
if 'input_key' not in st.session_state:
st.session_state.input_key = 0
file_path = f"{st.session_state.username}.txt"
c1.write("Today's Entry")
text0 = c1.text_area("Enter text ")
# template = f'''Question: What happened on {date.today().strftime("%B %d, %Y")}?
# How did I feel on {date.today().strftime("%B %d, %Y")}?
# What were the events that happened on {date.today().strftime("%B %d, %Y")}?
# Describe your day, {date.today().strftime("%B %d, %Y")}. \n Answer: '''
text = f""" <|im_start|>system
What happened on {date.today().strftime("%B %d, %Y")}?
How did I feel on {date.today().strftime("%B %d, %Y")}?
What were the events that happened on {date.today().strftime("%B %d, %Y")}?
Describe your day, {date.today().strftime("%B %d, %Y")}.<|im_end|>
<|im_start|>user
{text0}<|im_end|>"""
if c1.button('Pen down') and text:
save_into_text_file(file_path,text)
vectordb_entry()
c1.write('Entry saved')
st.session_state.input_key += 1
#display previous entries
insert_data(date.today().strftime("%B %d, %Y"), text0)
#displaying
c2.write('View previous entries')
selected_date = c2.date_input('Select a date', date.today())
data = retrieve_data(selected_date.strftime("%B %d, %Y"))
if data:
en = c2.container(height=300)
for i in data:
en.write(i[1])
#[en.write(x[1]) for x in data]
else:
c2.info('No entries for the selected date.')
# Main Streamlit App
def main():
st.set_page_config(layout="wide")
st.sidebar.title("Navigation")
page = st.sidebar.radio("Go to", ["Login", "Signup","Journal","Advice"])
if page == "Login":
login_page()
elif page == "Signup":
signup_page()
elif page == "Journal":
if 'username' not in st.session_state:
st.write('Please login to continue.')
else:
st.write(f"Logged in as {st.session_state.username}")
entry()
elif page == "Advice":
if "username" not in st.session_state:
st.write('Please login to continue')
else:
st.write(f"Logged in as {st.session_state.username}")
journal()
if __name__ == "__main__":
main()