Karthikeyen92 commited on
Commit
dd16aed
1 Parent(s): 4bfd700

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +168 -54
app.py CHANGED
@@ -106,7 +106,7 @@ class StockAdviserUI:
106
 
107
  def _setup_header(self):
108
  st.markdown("<h1 class='main-header'>Stock Analysis with Generative AI</h1>", unsafe_allow_html=True)
109
- st.markdown("<h3 class='main-header'>using RAG</h3>", unsafe_allow_html=True)
110
  with st.expander("Available Historical Demo Companies"):
111
  st.markdown("""
112
  For Demo purpose, historical data is available only for the below companies:
@@ -219,6 +219,91 @@ class StockAdviser:
219
  self.config.models.embedding_model = embedding_model
220
  return self.config.models
221
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  def get_symbol(self, user_question):
223
  qna_system_message = """
224
  You are an assistant to a financial services firm who finds the 'nse company symbol' (assigned to the company in the provided stock market)) of the company in the question provided.
@@ -258,8 +343,7 @@ class StockAdviser:
258
  return cmp_tkr
259
 
260
 
261
- def process_historical_data(self, user_question, hugg = False):
262
- cmp_tr = self.get_symbol(user_question)
263
 
264
  # Initialize ChromaDB Database
265
  chroma_db = DBStorage(hugg)
@@ -274,8 +358,7 @@ class StockAdviser:
274
 
275
  return cmp_tr
276
 
277
- def display_charts(self,cmp_tr,sentiment_response):
278
- sentiment = self._extract_between(sentiment_response, "Overall Sentiment:", "Overall Justification:").strip()
279
 
280
  days = 365
281
 
@@ -318,18 +401,21 @@ class StockAdviser:
318
  # Display volume chart
319
  st.plotly_chart(self.visualizer.create_volume_chart(df, cmp_tr))
320
 
321
- # Display sentiment gauge (simulate sentiment score)
322
- # Generating random score for Demo purpose
323
- if sentiment == "Negative":
324
- sentiment_score = np.random.uniform(-1, -0.75)
325
- elif sentiment == "Neutral":
326
- sentiment_score = np.random.uniform(-0.75, 0.25)
327
- elif sentiment == "Positive":
328
- sentiment_score = np.random.uniform(0.25, 1)
329
- else:
330
- sentiment_score = 0
331
-
332
- st.plotly_chart(self.visualizer.create_sentiment_gauge(sentiment_score))
 
 
 
333
 
334
  def get_nse_stock_data(self,symbol, days):
335
  """
@@ -623,6 +709,34 @@ class StockAdviser:
623
 
624
  return base_prompt + example_analysis + response_format + common_format + citation_format + instr + instr2, dcument
625
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
626
 
627
  def main(hugg):
628
  adviser = StockAdviser()
@@ -635,62 +749,62 @@ def main(hugg):
635
  )
636
 
637
  with st.sidebar:
638
- # About the Application
639
  st.markdown("""
640
  <div style="background-color: #2d2d2d; padding: 20px; border-radius: 10px; box-shadow: 0 4px 8px rgba(255, 255, 255, 0.1);">
641
- <h2 style="color: #e6e6e6; text-align: Left;">About the Application</h2>
642
- <p style="font-size: 16px; color: #cccccc; line-height: 1.6; text-align: justify;">
643
- This application provides investment managers with daily insights into social media and news sentiment surrounding specific stocks and companies.
644
- By analyzing posts and articles across major platforms such as <strong>Reddit</strong>, <strong>YouTube</strong>, <strong>Tumblr</strong>, <strong>Google News</strong>,
645
- <strong>Financial Times</strong>, <strong>Bloomberg</strong>, <strong>Reuters</strong>, and <strong>Wall Street Journal</strong> (WSJ), it detects shifts
646
- in public and media opinion that may impact stock performance.
 
 
 
 
 
 
 
 
 
 
 
 
647
  </p>
648
- <p style="font-size: 16px; color: #cccccc; line-height: 1.6; text-align: justify;">
649
- Additionally, sources like <strong>Serper</strong> provide data from <strong>StockNews</strong>, <strong>Yahoo Finance</strong>, <strong>Insider Monkey</strong>,
650
- <strong>Investor's Business Daily</strong>, and others. Using advanced AI techniques, the application generates a sentiment report that serves as a leading indicator,
651
- helping managers make informed, timely adjustments to their positions. With daily updates and historical trend analysis, it empowers users to stay ahead in a fast-paced,
652
- sentiment-driven market.
653
  </p>
654
  </div>
655
-
656
  """, unsafe_allow_html=True)
 
657
  # Sidebar Footer (Floating Footer)
658
  st.sidebar.markdown("""
659
- <div style="position: fixed; bottom: 5px; padding: 5px; background-color: #1f1f1f; border-radius: 5px; text-align: left;">
660
- <p style="color: #cccccc; font-size: 14px;">
661
  Developed by: <a href="https://www.linkedin.com/in/karthikeyen92/" target="_blank" style="color: #4DA8DA; text-decoration: none;">Karthikeyen Packirisamy</a>
662
  </p>
663
  </div>
664
  """, unsafe_allow_html=True)
665
-
666
 
667
 
668
  # Main content
669
  cmp_tr = "NOTICKER"
670
  st.header("Ask a question")
671
- user_question = st.text_input("Ask a stock advice related question", key="user_question")
672
-
673
- col1, col2 = st.columns(2)
674
-
675
- with col1:
676
- if user_question:
677
- st.markdown("<h3 class='little-header'>Historical Analysis</h3>", unsafe_allow_html=True)
678
- with st.container():
679
- cmp_tr = adviser.process_historical_data(user_question, hugg)
680
-
681
- with col2:
682
- if user_question:
683
- st.markdown("<h3 class='little-header'>Real-Time Analysis</h3>", unsafe_allow_html=True)
684
- with st.container():
685
- sentiment_response = adviser.process_realtime_data(cmp_tr, hugg)
686
-
687
- if (str(cmp_tr) != "NOTICKER"):
688
- with st.container():
689
- if user_question:
690
- adviser.display_charts(cmp_tr,sentiment_response)
691
 
 
 
 
 
 
 
 
 
692
  st.markdown("---")
693
- st.markdown("<p style='text-align: center; color: #666;'>© 2024 EY</p>", unsafe_allow_html=True)
694
 
695
  if __name__ == "__main__":
696
  hugg = os.getenv("IS_HUGG") == "True"
 
106
 
107
  def _setup_header(self):
108
  st.markdown("<h1 class='main-header'>Stock Analysis with Generative AI</h1>", unsafe_allow_html=True)
109
+ st.markdown("<h3 class='main-header'>using Agents and RAG</h3>", unsafe_allow_html=True)
110
  with st.expander("Available Historical Demo Companies"):
111
  st.markdown("""
112
  For Demo purpose, historical data is available only for the below companies:
 
219
  self.config.models.embedding_model = embedding_model
220
  return self.config.models
221
 
222
+ def stock_agent(self, user_question):
223
+ functions=[
224
+ {
225
+ "name":"get_advise",
226
+ "description":"Get only advise on a NSE stock",
227
+ "parameters":{
228
+ "type":"object",
229
+ "properties":{
230
+ "company":{
231
+ "type":"string",
232
+ "description":"Please find the 'nse company symbol' of the company in the question provided. In case of an invalid company, return 'NOTICKER'.",
233
+ },
234
+
235
+ },
236
+ "required":["company"]
237
+ },
238
+ },
239
+ {
240
+ "name":"get_stats",
241
+ "description":"Get only statistics/status on a NSE stock",
242
+ "parameters":{
243
+ "type":"object",
244
+ "properties":{
245
+ "company":{
246
+ "type":"string",
247
+ "description":"Please find the 'nse company symbol' of the company in the question provided. In case of an invalid company, return 'NOTICKER'.",
248
+ },
249
+
250
+ },
251
+ "required":["company"]
252
+ },
253
+ },
254
+ {
255
+ "name":"get_adv_stats",
256
+ "description":"Get both advise and statistics/status on a NSE stock",
257
+ "parameters":{
258
+ "type":"object",
259
+ "properties":{
260
+ "company":{
261
+ "type":"string",
262
+ "description":"Please find the 'nse company symbol' of the company in the question provided. In case of an invalid company, return 'NOTICKER'.",
263
+ },
264
+
265
+ },
266
+ "required":["company"]
267
+ },
268
+ },
269
+ {
270
+ "name":"get_none",
271
+ "description":"Get details other than advise or statistics/status on a NSE stock",
272
+ "parameters":{
273
+ "type":"object",
274
+ "properties":{
275
+ "company":{
276
+ "type":"string",
277
+ "description":"""
278
+ For any queries other than advise or statistics/status on a NSE stock, only return "NOTICKER".
279
+ """,
280
+ },
281
+
282
+ },
283
+ "required":["company"]
284
+ },
285
+ }
286
+ ]
287
+
288
+
289
+ initial_response = self.client.chat.completions.create(
290
+ model=self.config.azure_config["model_deployment"],
291
+ messages=[
292
+ {"role": "system", "content": "You are a helpful assistant to understand the context of input query on NSE stock advise and statistics."},
293
+ {"role": "user", "content": user_question}
294
+ ],
295
+ functions=functions
296
+ )
297
+
298
+ print (initial_response)
299
+ function_name = initial_response.choices[0].message.function_call.name
300
+ function_argument = json.loads(initial_response.choices[0].message.function_call.arguments)
301
+ company= function_argument['company']
302
+ print(function_name)
303
+ print(company)
304
+ return function_name
305
+
306
+
307
  def get_symbol(self, user_question):
308
  qna_system_message = """
309
  You are an assistant to a financial services firm who finds the 'nse company symbol' (assigned to the company in the provided stock market)) of the company in the question provided.
 
343
  return cmp_tkr
344
 
345
 
346
+ def process_historical_data(self, cmp_tr, hugg = False):
 
347
 
348
  # Initialize ChromaDB Database
349
  chroma_db = DBStorage(hugg)
 
358
 
359
  return cmp_tr
360
 
361
+ def display_charts(self,cmp_tr,sentiment_response="none"):
 
362
 
363
  days = 365
364
 
 
401
  # Display volume chart
402
  st.plotly_chart(self.visualizer.create_volume_chart(df, cmp_tr))
403
 
404
+ if sentiment_response != "none":
405
+ sentiment = self._extract_between(sentiment_response, "Overall Sentiment:", "Overall Justification:").strip()
406
+
407
+ # Display sentiment gauge (simulate sentiment score)
408
+ # Generating random score for Demo purpose
409
+ if sentiment == "Negative":
410
+ sentiment_score = np.random.uniform(-1, -0.75)
411
+ elif sentiment == "Neutral":
412
+ sentiment_score = np.random.uniform(-0.75, 0.25)
413
+ elif sentiment == "Positive":
414
+ sentiment_score = np.random.uniform(0.25, 1)
415
+ else:
416
+ sentiment_score = 0
417
+
418
+ st.plotly_chart(self.visualizer.create_sentiment_gauge(sentiment_score))
419
 
420
  def get_nse_stock_data(self,symbol, days):
421
  """
 
709
 
710
  return base_prompt + example_analysis + response_format + common_format + citation_format + instr + instr2, dcument
711
 
712
+ def get_advise(user_question,adviser,cmp_tr,sentiment_response,hugg):
713
+ col1, col2 = st.columns(2)
714
+ with col1:
715
+ if user_question:
716
+ st.markdown("<h3 class='little-header'>Historical Analysis</h3>", unsafe_allow_html=True)
717
+ with st.container():
718
+ adviser.process_historical_data(cmp_tr, hugg)
719
+
720
+ with col2:
721
+ if user_question:
722
+ st.markdown("<h3 class='little-header'>Real-Time Analysis</h3>", unsafe_allow_html=True)
723
+ with st.container():
724
+ sentiment_response = adviser.process_realtime_data(cmp_tr, hugg)
725
+
726
+ return sentiment_response
727
+
728
+ def get_stats(user_question,adviser,cmp_tr,sentiment_response,hugg):
729
+ if (str(cmp_tr) != "NOTICKER"):
730
+ with st.container():
731
+ if user_question:
732
+ adviser.display_charts(cmp_tr,sentiment_response)
733
+
734
+ def get_adv_stats(user_question,adviser,cmp_tr,sentiment_response,hugg):
735
+ sentiment_response = get_advise(user_question,adviser,cmp_tr,sentiment_response,hugg)
736
+ get_stats(user_question,adviser,cmp_tr,sentiment_response,hugg)
737
+
738
+ def get_none(user_question,adviser,cmp_tr,sentiment_response,hugg):
739
+ st.write("Please enter a valid NSE stock enquiry.")
740
 
741
  def main(hugg):
742
  adviser = StockAdviser()
 
749
  )
750
 
751
  with st.sidebar:
752
+ # About the Application (Main Area)
753
  st.markdown("""
754
  <div style="background-color: #2d2d2d; padding: 20px; border-radius: 10px; box-shadow: 0 4px 8px rgba(255, 255, 255, 0.1);">
755
+ <h2 style="color: #e6e6e6; text-align: center;">About the Application</h2>
756
+ <p style="font-size: 16px; color: #d9d9d9; line-height: 1.6; text-align: justify;">
757
+ This application provides <span style="color: #80b1c1;"><strong>investment managers</strong></span> with daily insights into
758
+ <span style="color: #d3b673;"><strong>social media</strong></span> and <span style="color: #d3b673;"><strong>news sentiment</strong></span> surrounding
759
+ specific <span style="color: #80b1c1;"><strong>stocks and companies</strong></span>. By analyzing posts and articles across major platforms
760
+ such as <strong style="color: #b0b0b0;">Reddit</strong>, <strong style="color: #b0b0b0;">YouTube</strong>, <strong style="color: #b0b0b0;">Tumblr</strong>,
761
+ <strong style="color: #b0b0b0;">Google News</strong>, <strong style="color: #b0b0b0;">Financial Times</strong>, <strong style="color: #b0b0b0;">Bloomberg</strong>,
762
+ <strong style="color: #b0b0b0;">Reuters</strong>, and <strong style="color: #b0b0b0;">Wall Street Journal</strong> (WSJ), it detects shifts in public
763
+ and media opinion that may impact stock performance.
764
+ </p>
765
+ <p style="font-size: 16px; color: #d9d9d9; line-height: 1.6; text-align: justify;">
766
+ Additionally, sources like <span style="color: #80b1c1;"><strong>Serper</strong></span> provide data from
767
+ <span style="color: #d3b673;"><strong>StockNews</strong></span>, <span style="color: #d3b673;"><strong>Yahoo Finance</strong></span>,
768
+ <span style="color: #d3b673;"><strong>Insider Monkey</strong></span>, <span style="color: #d3b673;"><strong>Investor's Business Daily</strong></span>,
769
+ and others. Using advanced <span style="color: #80b1c1;"><strong>AI techniques</strong></span>, the application generates a
770
+ <span style="color: #d3b673;"><strong>sentiment report</strong></span> that serves as a leading indicator, helping managers make informed,
771
+ timely adjustments to their positions. With daily updates and <span style="color: #d3b673;"><strong>historical trend analysis</strong></span>,
772
+ it empowers users to stay ahead in a fast-paced, sentiment-driven market.
773
  </p>
774
+ <p style="font-size: 16px; color: #d9d9d9; line-height: 1.6; text-align: justify;">
775
+ The application also utilizes <span style="color: #80b1c1;"><strong>intelligent agent functions</strong></span> to determine the type of query input
776
+ by the user. It assesses whether the query seeks <span style="color: #d3b673;"><strong>stock statistics</strong></span>,
777
+ <span style="color: #d3b673;"><strong>sentiment-analyzed advice</strong></span>, both, or is unrelated, providing the most relevant response accordingly.
 
778
  </p>
779
  </div>
 
780
  """, unsafe_allow_html=True)
781
+
782
  # Sidebar Footer (Floating Footer)
783
  st.sidebar.markdown("""
784
+ <div style="position: fixed; bottom: 25px; background-color: #1f1f1f; padding: 1px; border-radius: 15px; text-align: center;">
785
+ <p style="color: #cccccc; font-size: 14px; text-align: center; margin: 0;">
786
  Developed by: <a href="https://www.linkedin.com/in/karthikeyen92/" target="_blank" style="color: #4DA8DA; text-decoration: none;">Karthikeyen Packirisamy</a>
787
  </p>
788
  </div>
789
  """, unsafe_allow_html=True)
790
+
791
 
792
 
793
  # Main content
794
  cmp_tr = "NOTICKER"
795
  st.header("Ask a question")
796
+ user_question = st.text_input("Please ask statistical or advice or both related questions on a NSE stock.", key="user_question")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
797
 
798
+ if user_question.strip():
799
+ cmp_tr = adviser.get_symbol(user_question)
800
+ sentiment_response = "none"
801
+
802
+ agent_function = adviser.stock_agent(user_question)
803
+ getattr(sys.modules[__name__], agent_function)(user_question,adviser,cmp_tr,sentiment_response,hugg)
804
+
805
+ # get_adv_stats(user_question,adviser,cmp_tr,sentiment_response,hugg)
806
  st.markdown("---")
807
+ st.markdown("<p style='text-align: center; color: #666;'>© 2024 Karthikeyen</p>", unsafe_allow_html=True)
808
 
809
  if __name__ == "__main__":
810
  hugg = os.getenv("IS_HUGG") == "True"