QuantumLearner commited on
Commit
a0c903a
·
verified ·
1 Parent(s): 2dca67f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +81 -64
app.py CHANGED
@@ -5,9 +5,10 @@ from llama_index.embeddings.huggingface import HuggingFaceEmbedding
5
  from llama_index.llms.groq import Groq
6
  from llama_index.core import ServiceContext
7
  from llama_index.core.node_parser import SentenceSplitter
8
- from PyPDF2 import PdfReader
9
- import tempfile
10
  from dotenv import load_dotenv
 
 
 
11
  load_dotenv()
12
 
13
  # Fetch the API key from environment variables
@@ -24,90 +25,106 @@ service_context = ServiceContext.from_defaults(
24
  node_parser=SentenceSplitter(chunk_size=1000, chunk_overlap=200)
25
  )
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  summary_prompt = (
28
- "You are a world-class financial analyst with extensive experience analyzing quarterly reports. "
29
- "Give me a comprehensive summary of the earnings report. Focus on the Strategic Insights and Key Financial Figures. "
30
  "Answer in extensive bullet points please."
31
  )
32
 
33
  question_prompt = (
34
- "You are a financial analyst with extensive experience analyzing quarterly reports. "
35
- "Read the earnings call transcript and earnings presentation report and generate 10 questions focusing on the strategic insights and financial figures. "
36
  "Ask questions that require precise answers and provide strategic insight into the company's financial and strategic performance, such as revenue growth, market trends, profit margins, and more. "
37
  "Only ask questions that can be answered using the provided document, without making any assumptions or inferences beyond the text. "
38
  "Please format the questions as a list with a simple '1. Question 1', '2. Question 2', etc. structure. "
39
  "Unless retrievable from the documents, don't ask questions which cannot be compared to previous periods."
40
  )
41
 
42
- def read_file_content(file):
43
- if file.name.lower().endswith('.pdf'):
44
- with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as temp_file:
45
- temp_file.write(file.content)
46
- temp_file_path = temp_file.name
47
-
48
- try:
49
- pdf_reader = PdfReader(temp_file_path)
50
- text = ""
51
- for page in pdf_reader.pages:
52
- text += page.extract_text()
53
- finally:
54
- os.unlink(temp_file_path)
55
- elif file.name.lower().endswith('.txt'):
56
- text = file.content.decode('utf-8')
57
- else:
58
- raise ValueError("Unsupported file type")
59
-
60
- return text
61
-
62
  @cl.on_chat_start
63
  async def on_chat_start():
64
- # Ask if the user wants to upload files or paste text
65
- choice_response = await cl.AskUserMessage(
66
- content="Would you like to upload files or paste text? (Type 'upload' or 'paste')"
67
  ).send()
68
 
69
- choice_msg = choice_response['content'].lower()
70
- documents = []
71
 
72
- if choice_msg == "upload":
73
- files = await cl.AskFileMessage(
74
- content="Please upload PDF or TXT files to begin!",
75
- accept=["application/pdf", "text/plain"],
76
- max_files=5,
77
- max_size_mb=20,
78
- ).send()
79
-
80
- if not files:
81
- await cl.Message(content="No files were uploaded. Please try again.").send()
82
- return
83
 
84
- for file in files:
85
- text = read_file_content(file)
86
- documents.append(Document(text=text, metadata={"filename": file.name}))
87
 
88
- elif choice_msg == "paste":
89
- pasted_response = await cl.AskUserMessage(
90
- content="Please paste your document text here:"
91
- ).send()
92
 
93
- pasted_text = pasted_response['content']
94
- if not pasted_text:
95
- await cl.Message(content="No text was pasted. Please try again.").send()
96
- return
97
 
98
- documents.append(Document(text=pasted_text, metadata={"source": "pasted_text"}))
 
 
 
99
 
100
- else:
101
- await cl.Message(content="Invalid choice. Please start over and type either 'upload' or 'paste'.").send()
102
- return
 
 
103
 
104
- msg = cl.Message(content="Processing input... Will take a few minutes")
105
- await msg.send()
106
 
107
- try:
108
  # Create index
109
  index = VectorStoreIndex.from_documents(
110
- documents, service_context=service_context
111
  )
112
 
113
  # Store the index in the user session
@@ -129,7 +146,7 @@ async def on_chat_start():
129
  response = await cl.make_async(query_engine.query)(question)
130
  await cl.Message(content=f"**{question}**\n{response}").send()
131
 
132
- msg.content = "Processing done. You can now ask more questions!"
133
  await msg.update()
134
 
135
  except Exception as e:
@@ -140,7 +157,7 @@ async def main(message: cl.Message):
140
  index = cl.user_session.get("index")
141
 
142
  if index is None:
143
- await cl.Message(content="Please upload files first before asking questions.").send()
144
  return
145
 
146
  query_engine = index.as_query_engine()
@@ -151,4 +168,4 @@ async def main(message: cl.Message):
151
  for token in str(response):
152
  await response_message.stream_token(token=token)
153
 
154
- await response_message.send()
 
5
  from llama_index.llms.groq import Groq
6
  from llama_index.core import ServiceContext
7
  from llama_index.core.node_parser import SentenceSplitter
 
 
8
  from dotenv import load_dotenv
9
+ import yfinance as yf
10
+ import pandas as pd
11
+
12
  load_dotenv()
13
 
14
  # Fetch the API key from environment variables
 
25
  node_parser=SentenceSplitter(chunk_size=1000, chunk_overlap=200)
26
  )
27
 
28
+ def format_financial_data(company_info, analysts_target, income_statement, balance_sheet, cash_flow):
29
+ summary = f"# {company_info.get('longName', '')} Financial Summary\n"
30
+
31
+ # Company Overview
32
+ summary += f"\n## Company Overview\n"
33
+ business_summary = company_info.get('longBusinessSummary', '')
34
+ summary += f"{business_summary}\n"
35
+
36
+ # Analyst Price Targets
37
+ if analysts_target is not None and not analysts_target.empty:
38
+ current_price = company_info.get('currentPrice', 'N/A')
39
+ target_mean_price = analysts_target['targetMeanPrice'].iloc[-1]
40
+ target_high_price = analysts_target['targetHighPrice'].iloc[-1]
41
+ target_low_price = analysts_target['targetLowPrice'].iloc[-1]
42
+ number_of_analysts = analysts_target['numberOfAnalysts'].iloc[-1]
43
+
44
+ summary += f"\n## Analyst Price Targets\n"
45
+ summary += f"- **Current Price**: ${current_price}\n"
46
+ summary += f"- **Mean Target Price**: ${target_mean_price}\n"
47
+ summary += f"- **High Target Price**: ${target_high_price}\n"
48
+ summary += f"- **Low Target Price**: ${target_low_price}\n"
49
+ summary += f"- **Number of Analysts**: {number_of_analysts}\n"
50
+
51
+ # Function to format financial tables
52
+ def format_financial_table(df, title):
53
+ summary = f"\n## {title}\n\n"
54
+ df = df.copy()
55
+ df.columns = [col.strftime('%Y-%m-%d') if hasattr(col, 'strftime') else col for col in df.columns]
56
+ df.index = df.index.str.replace(r'([a-z])([A-Z])', r'\1 \2', regex=True) # Add spaces between words
57
+ df = df.apply(lambda x: x.apply(lambda y: f"${y:,.0f}" if pd.notnull(y) and isinstance(y, (int, float)) else y))
58
+ summary += df.to_markdown()
59
+ return summary
60
+
61
+ # Format the quarterly income statement
62
+ if income_statement is not None and not income_statement.empty:
63
+ summary += format_financial_table(income_statement, "Quarterly Income Statement")
64
+
65
+ # Format the quarterly balance sheet
66
+ if balance_sheet is not None and not balance_sheet.empty:
67
+ summary += format_financial_table(balance_sheet, "Quarterly Balance Sheet")
68
+
69
+ # Format the quarterly cash flow statement
70
+ if cash_flow is not None and not cash_flow.empty:
71
+ summary += format_financial_table(cash_flow, "Quarterly Cash Flow Statement")
72
+
73
+ return summary
74
+
75
  summary_prompt = (
76
+ "You are a world-class financial analyst with extensive experience analyzing financial data. "
77
+ "Give me a comprehensive summary of the financial data. Focus on the Strategic Insights and Key Financial Figures. "
78
  "Answer in extensive bullet points please."
79
  )
80
 
81
  question_prompt = (
82
+ "You are a financial analyst with extensive experience analyzing financial data. "
83
+ "Read the financial summary and generate 10 questions focusing on the strategic insights and financial figures. "
84
  "Ask questions that require precise answers and provide strategic insight into the company's financial and strategic performance, such as revenue growth, market trends, profit margins, and more. "
85
  "Only ask questions that can be answered using the provided document, without making any assumptions or inferences beyond the text. "
86
  "Please format the questions as a list with a simple '1. Question 1', '2. Question 2', etc. structure. "
87
  "Unless retrievable from the documents, don't ask questions which cannot be compared to previous periods."
88
  )
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  @cl.on_chat_start
91
  async def on_chat_start():
92
+ ticker_response = await cl.AskUserMessage(
93
+ content="Please enter the ticker symbol for the company you want to analyze:"
 
94
  ).send()
95
 
96
+ ticker_symbol = ticker_response['content'].upper()
 
97
 
98
+ msg = cl.Message(content=f"Retrieving financial data for {ticker_symbol}...")
99
+ await msg.send()
 
 
 
 
 
 
 
 
 
100
 
101
+ try:
102
+ # Get the data for the company
103
+ company = yf.Ticker(ticker_symbol)
104
 
105
+ # Extract company information
106
+ company_info = company.info
 
 
107
 
108
+ # Extract analyst price targets
109
+ analysts_target = company.analyst_price_target
 
 
110
 
111
+ # Retrieve the Quarterly Financial Statements
112
+ quarterly_income_statement = company.quarterly_financials
113
+ quarterly_balance_sheet = company.quarterly_balance_sheet
114
+ quarterly_cash_flow = company.quarterly_cashflow
115
 
116
+ # Generate the formatted financial summary
117
+ financial_summary = format_financial_data(
118
+ company_info, analysts_target, quarterly_income_statement,
119
+ quarterly_balance_sheet, quarterly_cash_flow
120
+ )
121
 
122
+ # Create a Document object with the financial summary
123
+ document = Document(text=financial_summary, metadata={"company": ticker_symbol})
124
 
 
125
  # Create index
126
  index = VectorStoreIndex.from_documents(
127
+ [document], service_context=service_context
128
  )
129
 
130
  # Store the index in the user session
 
146
  response = await cl.make_async(query_engine.query)(question)
147
  await cl.Message(content=f"**{question}**\n{response}").send()
148
 
149
+ msg.content = "Processing done. You can now ask more questions about the financial data!"
150
  await msg.update()
151
 
152
  except Exception as e:
 
157
  index = cl.user_session.get("index")
158
 
159
  if index is None:
160
+ await cl.Message(content="Please provide a ticker symbol first before asking questions.").send()
161
  return
162
 
163
  query_engine = index.as_query_engine()
 
168
  for token in str(response):
169
  await response_message.stream_token(token=token)
170
 
171
+ await response_message.send()