muzammil-eds commited on
Commit
bdb7320
1 Parent(s): f611a80

Upload 3 files

Browse files
Files changed (3) hide show
  1. htmlTemplates.py +44 -0
  2. main.py +214 -0
  3. requirements.txt +90 -0
htmlTemplates.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ css = '''
2
+ <style>
3
+ .chat-message {
4
+ padding: 1.5rem; border-radius: 0.5rem; margin-bottom: 1rem; display: flex
5
+ }
6
+ .chat-message.user {
7
+ background-color: #2b313e
8
+ }
9
+ .chat-message.bot {
10
+ background-color: #475063
11
+ }
12
+ .chat-message .avatar {
13
+ width: 12%;
14
+ }
15
+ .chat-message .avatar img {
16
+ max-width: 60px;
17
+ max-height: 60px;
18
+ border-radius: 50%;
19
+ object-fit: cover;
20
+ }
21
+ .chat-message .message {
22
+ width: 90%;
23
+ padding: 0 .35rem;
24
+ color: #fff;
25
+ }
26
+ '''
27
+
28
+ bot_template = '''
29
+ <div class="chat-message bot">
30
+ <div class="avatar">
31
+ <img src="https://www.sideshow.com/storage/product-images/2171/c-3po_star-wars_square.jpg">
32
+ </div>
33
+ <div class="message">{{MSG}}</div>
34
+ </div>
35
+ '''
36
+
37
+ user_template = '''
38
+ <div class="chat-message user">
39
+ <div class="avatar">
40
+ <img src="https://resizing.flixster.com/ocuc8yjm8Fu5UK5Ze8lbdp58m9Y=/300x300/v2/https://flxt.tmsimg.com/assets/p11759522_i_h9_aa.jpg">
41
+ </div>
42
+ <div class="message">{{MSG}}</div>
43
+ </div>
44
+ '''
main.py ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import yfinance as yf
3
+ import pandas as pd
4
+ from langchain.agents import create_pandas_dataframe_agent
5
+ import re
6
+ import sqlite3
7
+ from htmlTemplates import css, user_template, bot_template
8
+ from typing import Optional, List, Mapping, Any
9
+ from langchain.llms.base import LLM
10
+ import g4f
11
+
12
+
13
+ class FinLLM(LLM):
14
+
15
+ @property
16
+ def _llm_type(self) -> str:
17
+ return "custom"
18
+
19
+ def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str:
20
+ out = g4f.ChatCompletion.create(
21
+ model="gpt-3.5-turbo",
22
+ messages=[{"role": "user", "content": prompt}],
23
+ temperature=0.5, # You can adjust parameters as needed
24
+ max_tokens=350 # Adjust the token limit as needed
25
+ ) #
26
+ if stop:
27
+ stop_indexes = (out.find(s) for s in stop if s in out)
28
+ min_stop = min(stop_indexes, default=-1)
29
+ if min_stop > -1:
30
+ out = out[:min_stop]
31
+ return out
32
+
33
+
34
+ llm = FinLLM()
35
+
36
+ def create_users_db():
37
+ with sqlite3.connect('MASTER.db') as conn:
38
+ cursor = conn.cursor()
39
+ cursor.execute("""
40
+ CREATE TABLE IF NOT EXISTS Users (
41
+ user_id INTEGER PRIMARY KEY AUTOINCREMENT,
42
+ email TEXT UNIQUE,
43
+ password TEXT
44
+ )
45
+ """)
46
+
47
+ def add_user_to_db(email, password):
48
+ with sqlite3.connect('MASTER.db') as conn:
49
+ cursor = conn.cursor()
50
+ try:
51
+ insert_query = "INSERT INTO Users (email, password) VALUES (?, ?)"
52
+ cursor.execute(insert_query, (email, password))
53
+ except sqlite3.IntegrityError as e:
54
+ # Handle specific error if the email already exists
55
+ print(f"Error: {e}")
56
+ return False
57
+ return True
58
+
59
+ def authenticate_user(email, password):
60
+ with sqlite3.connect('MASTER.db') as conn:
61
+ cursor = conn.cursor()
62
+ select_query = "SELECT * FROM Users WHERE email = ? AND password = ?"
63
+ cursor.execute(select_query, (email, password))
64
+ user = cursor.fetchone()
65
+ return user is not None
66
+
67
+
68
+ def init_ses_states():
69
+ st.session_state.setdefault('chat_history', [])
70
+ st.session_state.setdefault('user_authenticated', False)
71
+
72
+
73
+ def relative_returns(df):
74
+ rel = df.pct_change()
75
+ cumret = ((1 + rel).cumprod() - 1).fillna(0)
76
+ return cumret
77
+
78
+
79
+ def display_convo():
80
+ with st.container():
81
+ for i, message in enumerate(reversed(st.session_state.chat_history)):
82
+ if i % 2 == 0:
83
+ st.markdown(bot_template.replace("{{MSG}}", message), unsafe_allow_html=True)
84
+ else:
85
+ st.markdown(user_template.replace("{{MSG}}", message), unsafe_allow_html=True)
86
+
87
+
88
+ def approve_password(password):
89
+ if len(password) >= 8 and re.search(r"(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[_@$#!?&*%])", password):
90
+ return True
91
+ return False
92
+
93
+
94
+ def approve_email(email):
95
+ email_regex = '^[a-zA-Z0-9]+[\._]?[a-zA-Z0-9]+[@]\w+[.]\w{2,3}$'
96
+ if re.search(email_regex, email):
97
+ return True
98
+ else:
99
+ return False
100
+
101
+
102
+ def user_authentication_tab():
103
+ with st.expander("User Authentication", expanded=True):
104
+ login_tab, create_account_tab = st.tabs(["Login", "Create Account"])
105
+
106
+ with login_tab:
107
+ email = st.text_input("Email:")
108
+ password = st.text_input("Password:", type='password')
109
+ if st.button("Login"):
110
+ if authenticate_user(email=email,password=password):
111
+ st.session_state.user_authenticated = True
112
+ else:
113
+ st.caption('Incorrect Username or Password.')
114
+
115
+ if st.session_state.user_authenticated:
116
+ st.caption("User Authenticated")
117
+
118
+ with create_account_tab:
119
+ new_email = st.text_input("New Email:")
120
+ new_password = st.text_input("New Password:", type='password')
121
+ confirm_password = st.text_input("Confirm Password:", type='password')
122
+ if st.button("Create Account"):
123
+ if not approve_email(new_email):
124
+ st.caption("Invalid Email")
125
+ return
126
+ if not approve_password(new_password):
127
+ st.caption("Invalid Password")
128
+ return
129
+ if new_password != confirm_password:
130
+ st.caption("Passwords do not match")
131
+ return
132
+ add_user_to_db(email=new_email, password=new_password)
133
+ st.caption(f"{new_email} Successfully Added")
134
+
135
+
136
+ def main():
137
+ st.set_page_config(page_title="Stock Price AI Bot", page_icon=":chart:")
138
+ st.write(css, unsafe_allow_html=True)
139
+ create_users_db()
140
+ init_ses_states()
141
+ st.title("Stock Price AI Bot")
142
+ st.caption("Visualizations and OpenAI Chatbot for Multiple Stocks Over A Specified Period")
143
+
144
+
145
+ with st.sidebar:
146
+ user_authentication_tab()
147
+
148
+
149
+ if st.session_state.user_authenticated:
150
+ with st.sidebar:
151
+ with st.expander("Settings",expanded=True):
152
+ asset_tickers = sorted(['DOW','NVDA','TSL','GOOGL','AMZN','AI','NIO','LCID','F','LYFY','AAPL', 'MSFT', 'BTC-USD', 'ETH-USD'])
153
+ asset_dropdown = st.multiselect('Pick Assets:', asset_tickers)
154
+
155
+ metric_tickers = ['Adj. Close', 'Relative Returns']
156
+ metric_dropdown = st.selectbox("Metric", metric_tickers)
157
+
158
+ viz_tickers = ['Line Chart', 'Area Chart']
159
+ viz_dropdown = st.multiselect("Pick Charts:", viz_tickers)
160
+
161
+ start = st.date_input('Start', value=pd.to_datetime('2023-01-01'))
162
+ end = st.date_input('End', value=pd.to_datetime('today'))
163
+
164
+ chatbot_temp = st.slider("Chat Bot Temperature",0.0,1.0,0.5)
165
+
166
+ # Only when a stock is selected
167
+ if len(asset_dropdown) > 0:
168
+ df = yf.download(asset_dropdown,start,end)['Adj Close']
169
+ if metric_dropdown == 'Relative Returns':
170
+ df = relative_returns(df)
171
+ if len(viz_dropdown) > 0:
172
+ with st.expander("Data Visualizations for {} of {}".format(metric_dropdown,asset_dropdown), expanded=True):
173
+ if "Line Chart" in viz_dropdown:
174
+ st.subheader("Line Chart")
175
+ st.line_chart(df)
176
+ if "Area Chart" in viz_dropdown:
177
+ st.subheader("Area Chart")
178
+ st.area_chart(df)
179
+ st.header("Chat with your Data")
180
+
181
+ query = st.text_input("Enter a query:")
182
+
183
+ chat_prompt = f'''
184
+ You are an AI ChatBot intended to help with user stock data.
185
+ \nYou have access to a pandas dataframe with the following specifications
186
+ \nDATA MODE: {metric_dropdown}
187
+ \nSTOCKS: {asset_dropdown}
188
+ \nTIME PERIOD: {start} to {end}
189
+ \nCHAT HISTORY: {st.session_state.chat_history}
190
+ \nUSER MESSAGE: {query}
191
+ \nAI RESPONSE HERE:
192
+ '''
193
+
194
+ if st.button("Execute") and query:
195
+ with st.spinner('Generating response...'):
196
+ try:
197
+ agent = create_pandas_dataframe_agent(
198
+ llm,
199
+ pd.DataFrame(df),
200
+ verbose=True
201
+ )
202
+
203
+ answer = agent.run(chat_prompt)
204
+ st.session_state.chat_history.append(f"USER: {query}\n")
205
+ st.session_state.chat_history.append(f"AI: {answer}\n")
206
+ display_convo()
207
+
208
+ except Exception as e:
209
+ st.error(f"An error occurred: {str(e)}")
210
+
211
+
212
+ if __name__ == '__main__':
213
+ main()
214
+
requirements.txt ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiohttp==3.8.4
2
+ aiosignal==1.3.1
3
+ altair==5.0.1
4
+ appdirs==1.4.4
5
+ async-timeout==4.0.2
6
+ attrs==23.1.0
7
+ beautifulsoup4==4.12.2
8
+ blinker==1.6.2
9
+ cachetools==5.3.1
10
+ certifi==2023.5.7
11
+ cffi==1.15.1
12
+ charset-normalizer==3.1.0
13
+ click==8.1.3
14
+ colorama==0.4.6
15
+ contourpy==1.0.7
16
+ cryptography==41.0.1
17
+ cycler==0.11.0
18
+ dataclasses-json==0.5.7
19
+ decorator==5.1.1
20
+ fonttools==4.39.4
21
+ frozendict==2.3.8
22
+ frozenlist==1.3.3
23
+ gitdb==4.0.10
24
+ GitPython==3.1.31
25
+ gpt-index==0.4.24
26
+ greenlet==2.0.2
27
+ html5lib==1.1
28
+ idna==3.4
29
+ importlib-metadata==6.6.0
30
+ Jinja2==3.1.2
31
+ jsonschema==4.17.3
32
+ kiwisolver==1.4.4
33
+ langchain==0.0.188
34
+ lxml==4.9.2
35
+ markdown-it-py==2.2.0
36
+ MarkupSafe==2.1.2
37
+ marshmallow==3.19.0
38
+ marshmallow-enum==1.5.1
39
+ matplotlib==3.7.1
40
+ mdurl==0.1.2
41
+ multidict==6.0.4
42
+ multitasking==0.0.11
43
+ mypy-extensions==1.0.0
44
+ numexpr==2.8.4
45
+ numpy==1.24.3
46
+ openai==0.27.7
47
+ openapi-schema-pydantic==1.2.4
48
+ packaging==23.1
49
+ pandas==2.0.2
50
+ Pillow==9.5.0
51
+ protobuf==4.23.2
52
+ pyarrow==12.0.0
53
+ pycparser==2.21
54
+ pydantic==1.10.8
55
+ pydeck==0.8.1b0
56
+ Pygments==2.15.1
57
+ Pympler==1.0.1
58
+ pyparsing==3.0.9
59
+ pyrsistent==0.19.3
60
+ python-dateutil==2.8.2
61
+ python-dotenv==1.0.0
62
+ pytz==2023.3
63
+ pytz-deprecation-shim==0.1.0.post0
64
+ PyYAML==6.0
65
+ regex==2023.6.3
66
+ requests==2.31.0
67
+ rich==13.4.1
68
+ six==1.16.0
69
+ smmap==5.0.0
70
+ soupsieve==2.4.1
71
+ SQLAlchemy==1.4.48
72
+ streamlit==1.23.0
73
+ tabulate==0.9.0
74
+ tenacity==8.2.2
75
+ tiktoken==0.4.0
76
+ toml==0.10.2
77
+ toolz==0.12.0
78
+ tornado==6.3.2
79
+ tqdm==4.65.0
80
+ typing-inspect==0.9.0
81
+ typing_extensions==4.6.2
82
+ tzdata==2023.3
83
+ tzlocal==4.3
84
+ urllib3==2.0.2
85
+ validators==0.20.0
86
+ watchdog==3.0.0
87
+ webencodings==0.5.1
88
+ yarl==1.9.2
89
+ yfinance==0.2.18
90
+ zipp==3.15.0