ashu-1069 commited on
Commit
4b509e5
·
verified ·
1 Parent(s): a1c6bd1

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +276 -0
app.py ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import sqlite3
3
+ from hashlib import sha256
4
+ import streamlit as st
5
+ from datetime import datetime
6
+ from langchain_community.embeddings import LlamaCppEmbeddings
7
+ from langchain.text_splitter import CharacterTextSplitter
8
+ from langchain_community.document_loaders import TextLoader
9
+ from langchain_community.vectorstores import FAISS
10
+ from langchain.embeddings import HuggingFaceEmbeddings
11
+ from langchain.chains.llm import LLMChain
12
+ from langchain_community.llms import LlamaCpp
13
+ from langchain.chains import LLMChain
14
+ from langchain_community.llms import OpenAI
15
+ from langchain_core.prompts import PromptTemplate, ChatPromptTemplate
16
+ from langchain_core.runnables import RunnablePassthrough
17
+ from langchain_core.documents import Document
18
+ from langchain.chains import create_retrieval_chain
19
+ from langchain.chains.combine_documents import create_stuff_documents_chain
20
+
21
+
22
+ # Create a SQLite database named 'user_credentials.db'. If it already exists, connect to it.
23
+ # This database is used for storing user credentials.
24
+ conn = sqlite3.connect("user_credentials.db")
25
+
26
+ # Create a cursor object using the connection.
27
+ # The cursor is used to execute SQL commands.
28
+ cursor = conn.cursor()
29
+
30
+ # Execute an SQL command using the cursor.
31
+ # This command attempts to create a new table named 'users' if it doesn't already exist.
32
+ # The table is designed to store usernames and passwords.
33
+ # It has two columns: 'username' and 'password'.
34
+ # 'username' is of type TEXT and is set as the PRIMARY KEY, ensuring that each username is unique.
35
+ # 'password' is also of type TEXT to store the password associated with each username.
36
+ cursor.execute('''
37
+ CREATE TABLE IF NOT EXISTS users (
38
+ username TEXT PRIMARY KEY,
39
+ password TEXT
40
+ )
41
+ ''')
42
+
43
+ # Commit the changes made by the cursor.execute command to the database.
44
+ # This ensures that the creation of the table is saved in the database.
45
+ conn.commit()
46
+
47
+
48
+ # Check if the embeddings model is not already stored in Streamlit's session state
49
+ if 'embeddings' not in st.session_state:
50
+ # Initialize and store the embeddings model in session state for efficient reuse
51
+ st.session_state.embeddings = HuggingFaceEmbeddings(
52
+ model_name="sentence-transformers/all-MiniLM-L6-v2", # Specify the model name to use
53
+ model_kwargs={"device": "cpu"}, # Force the model to run on CPU
54
+ )
55
+
56
+
57
+ def get_similar_docs(query):
58
+ # Load the FAISS index from local storage using the embeddings model stored in session state
59
+ db = FAISS.load_local('faiss_index', st.session_state.embeddings)
60
+ # Perform a similarity search in the FAISS database for the given query, returning top 100 similar documents with scores
61
+ docs = db.similarity_search_with_score(query, 100)
62
+ # Return the list of similar documents and their similarity scores
63
+ return docs
64
+
65
+ def format_docs(docs):
66
+ # Join the page content of each document in docs with a space, and return the concatenated string
67
+ return " ".join(doc.page_content for doc in docs)
68
+
69
+ def get_advice_from_llm(query):
70
+ # Load the FAISS index and initialize it with embeddings from session state for document retrieval
71
+ db = FAISS.load_local('faiss_index', st.session_state.embeddings)
72
+ # Convert the FAISS index into a retriever for fetching documents based on queries
73
+ retriever = db.as_retriever()
74
+ # Initialize the LlamaCpp model with specified model path and context size
75
+ llm = LlamaCpp(model_path="./tinyllama-1.1b-chat-v1.0.Q8_0.gguf", n_ctx=2048)
76
+ # Create a chat history string from session state for inclusion in the prompt template
77
+ chat_history_str = "\n".join(["" + entry[0] + entry[1] + "\n" for entry in st.session_state['chat_history']])
78
+ # Define the prompt template with placeholders for dynamic context and user input
79
+ template = """"
80
+ system
81
+ {context}""" + \
82
+ chat_history_str +\
83
+ """
84
+ user{input}
85
+
86
+ assistant
87
+ """
88
+ # Initialize a PromptTemplate with variables for dynamic insertion into the template
89
+ prompt = PromptTemplate(input_variables=["input", "context"], template=template)
90
+ # Chain the LlamaCpp model with the prompt for generating responses
91
+ llm_chain = LLMChain(llm=llm, prompt=prompt)
92
+ # Define the RAG chain combining retriever and LLM chain for generating advice based on the query
93
+ rag_chain = ({"context": retriever | format_docs, "input": RunnablePassthrough()} | llm_chain)
94
+ # Invoke the RAG chain with the user query to get advice
95
+ answer = rag_chain.invoke(query)
96
+ # Return the generated advice
97
+ return answer
98
+
99
+
100
+ def vectordb_entry():
101
+ # Load text documents from a specified file
102
+ loader = TextLoader("./output.txt")
103
+ documents = loader.load()
104
+ # Split loaded documents into smaller chunks for vectorization
105
+ text_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=10)
106
+ docs = text_splitter.split_documents(documents)
107
+ # Load or create a FAISS vector database using embeddings from session state
108
+ db = FAISS.load_local('faiss_index', st.session_state.embeddings)
109
+ # Add the document chunks to the FAISS database
110
+ db.add_documents(docs)
111
+ # Save the updated database locally
112
+ db.save_local('faiss_index')
113
+
114
+
115
+ def save_into_text_file(file_path, text):
116
+ # Open the specified file path for writing and save the provided text string into it
117
+ with open(file_path, 'w') as file:
118
+ file.write(text)
119
+ # Print a confirmation message indicating where the text was saved
120
+ print(f"String saved to {file_path}")
121
+
122
+
123
+ def journal():
124
+ # Create a container to display chat messages with a specified height
125
+ messages = st.container(height=600)
126
+ # Create a chat input box for users to enter their queries
127
+ query = st.chat_input("Need some advice?")
128
+
129
+ # Initialize an input_key in session state if it doesn't exist, to track input changes
130
+ if 'input_key' not in st.session_state:
131
+ st.session_state.input_key = 0
132
+
133
+ # Initialize chat_history in session state if it doesn't exist, to store chat interactions
134
+ if 'chat_history' not in st.session_state:
135
+ st.session_state.chat_history = []
136
+
137
+ # If the user has entered a query
138
+ if query:
139
+ # Get advice from the language model for the given query
140
+ answer = get_advice_from_llm(query)
141
+ # Append the user's query and the model's response to the chat history
142
+ st.session_state.chat_history.append(("user", query))
143
+ st.session_state.chat_history.append(("assistant", answer['text']))
144
+ # Increment the input_key to trigger updates
145
+ st.session_state.input_key += 1
146
+
147
+ # If there is chat history, display it in the messages container
148
+ if 'chat_history' in st.session_state and st.session_state.chat_history:
149
+ for speaker, message in st.session_state.chat_history:
150
+ # Assign a display name based on the speaker
151
+ who = "You" if speaker == "user" else "JournaLLM"
152
+ # Display each message in the chat container
153
+ messages.chat_message(speaker).write(who + ': '+ str(message))
154
+
155
+ # Provide a button to reset the chat
156
+ if st.button('Reset Chat'):
157
+ # Clear the chat history
158
+ st.session_state.chat_history = []
159
+ # Increment the input_key to trigger updates
160
+ st.session_state.input_key += 1
161
+ # Rerun the Streamlit app to reflect changes
162
+ st.experimental_rerun()
163
+
164
+
165
+
166
+ # Function to hash passwords
167
+ def hash_password(password):
168
+ return sha256(password.encode()).hexdigest()
169
+
170
+ # Function to check login credentials
171
+ def authenticate(username, password):
172
+ hashed_password = hash_password(password)
173
+ cursor.execute("SELECT * FROM users WHERE username=? AND password=?", (username, hashed_password))
174
+ return cursor.fetchone() is not None
175
+
176
+ # Function to add a new user to the database
177
+ def add_user(username, password):
178
+ hashed_password = hash_password(password)
179
+ try:
180
+ cursor.execute("INSERT INTO users (username, password) VALUES (?, ?)", (username, hashed_password))
181
+ conn.commit()
182
+ return True # User added successfully
183
+ except sqlite3.IntegrityError:
184
+ return False # Username already exists
185
+
186
+ # Streamlit Login Page
187
+ def login_page():
188
+ st.title("Login Page")
189
+
190
+ st.session_state['username'] = st.text_input("Username:")
191
+ st.session_state['password'] = st.text_input("Password:", type="password")
192
+
193
+ if st.button("Login"):
194
+ if not st.session_state['username'] or not st.session_state['password']:
195
+ st.error("Both username and password are required.")
196
+ elif authenticate(st.session_state['username'], st.session_state['password']):
197
+ st.success("Login successful!")
198
+ else:
199
+ st.error("Invalid credentials. Please try again.")
200
+
201
+ # Streamlit Signup Page
202
+ def signup_page():
203
+ st.title("Signup Page")
204
+ new_username = st.text_input("New Username:")
205
+ new_password = st.text_input("New Password:", type="password")
206
+
207
+ if st.button("Signup"):
208
+ if not new_username or not new_password:
209
+ st.error("Both username and password are required.")
210
+ else:
211
+ result = add_user(new_username, new_password)
212
+ if result:
213
+ st.success("Signup successful! You can now login.")
214
+ #create db
215
+ else:
216
+ st.error("Username already exists. Please choose a different username.")
217
+
218
+
219
+ def entry():
220
+ st.title('JournaLLM') # Set the title of the Streamlit app
221
+ # Display a welcome message to the user
222
+ 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.')
223
+
224
+ # Initialize an input key in session state if it's not present, to track submissions
225
+ if 'input_key' not in st.session_state:
226
+ st.session_state.input_key = 0
227
+
228
+ file_path = "output.txt" # Define the path for the output file where entries will be saved
229
+
230
+ # Create a text area in the app for users to write their journal entry
231
+ text = st.text_area("Today's Entry")
232
+
233
+ # Prepare a template with questions for the journal entry, including the current date
234
+ template = f'''Question: What happened on {datetime.today().strftime("%B %d, %Y")}?
235
+ How did I feel on {datetime.today().strftime("%B %d, %Y")}?
236
+ What were the events that happened on {datetime.today().strftime("%B %d, %Y")}?
237
+ Describe your day, {datetime.today().strftime("%B %d, %Y")}. \n Answer: '''
238
+
239
+ text = template + text # Append the user's text to the template
240
+
241
+ # Save the journal entry to a file and update the vector database when the 'Pen down' button is pressed
242
+ if st.button('Pen down') and text:
243
+ save_into_text_file(file_path, text) # Call function to save the text into the specified file
244
+ vectordb_entry() # Call function to add the entry to the vector database
245
+ st.write('Entry saved') # Confirm the entry has been saved
246
+ st.write(text) # Display the saved text to the user
247
+ st.session_state.input_key += 1 # Increment the session state's input key to track changes
248
+
249
+
250
+
251
+ # Main Streamlit App
252
+ def main():
253
+ st.set_page_config(layout="wide")
254
+ st.sidebar.title("Navigation")
255
+ page = st.sidebar.radio("Go to", ["Login", "Signup","Entry","Advice"])
256
+
257
+ if page == "Login":
258
+ login_page()
259
+ elif page == "Signup":
260
+ signup_page()
261
+ elif page == "Journal":
262
+ if st.session_state.username == "":
263
+ st.write('Please login to continue.')
264
+ else:
265
+ st.write(f"Logged in as {st.session_state.username}")
266
+ entry()
267
+ elif page == "Advice":
268
+ if st.session_state.username == "":
269
+ st.write('Please login to continue.')
270
+ else:
271
+ st.write(f"Logged in as {st.session_state.username}")
272
+ journal()
273
+
274
+ if __name__ == "__main__":
275
+ main()
276
+