CosmickVisions commited on
Commit
99f3982
Β·
verified Β·
1 Parent(s): 411b3c1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -66
app.py CHANGED
@@ -17,15 +17,15 @@ import fitz # PyMuPDF
17
  from PIL import Image
18
  from dotenv import load_dotenv
19
  import torch
20
- import yfinance as yf # Added missing import
21
- import plotly.graph_objects as go # Added missing import
22
 
23
  # Assuming groq is a custom module or typo; replace with actual import if needed
24
- from groq import Client as GroqClient # Placeholder; adjust based on your setup
25
 
26
  # LangChain imports (optional, only if embeddings are available)
27
  try:
28
- from langchain_community.embeddings import HuggingFaceInstructEmbeddings
29
  from langchain_community.vectorstores import FAISS
30
  from langchain.text_splitter import RecursiveCharacterTextSplitter
31
  langchain_available = True
@@ -35,25 +35,18 @@ except ImportError:
35
 
36
  # Load environment variables
37
  load_dotenv()
38
- client = GroqClient(api_key=os.getenv("GROQ_LEGAL_API_KEY")) # Adjust if groq is different
39
 
40
  # Embeddings initialization with fallback
41
  if langchain_available:
42
  try:
43
- embeddings = HuggingFaceInstructEmbeddings(
44
- model_name="hkunlp/instructor-base",
45
  model_kwargs={"device": "cuda" if torch.cuda.is_available() else "cpu"}
46
  )
47
  except Exception as e:
48
- print(f"Warning: Failed to load primary embeddings model: {e}")
49
- try:
50
- embeddings = HuggingFaceInstructEmbeddings(
51
- model_name="all-MiniLM-L6-v2",
52
- model_kwargs={"device": "cuda" if torch.cuda.is_available() else "cpu"}
53
- )
54
- except Exception as e:
55
- print(f"Warning: Failed to load fallback embeddings model: {e}")
56
- embeddings = None
57
  else:
58
  embeddings = None
59
  print("Embeddings disabled due to missing LangChain dependencies.")
@@ -106,7 +99,7 @@ body { background-color: var(--light-color); font-family: 'IBM Plex Sans', sans-
106
  .search-toggle { margin-left: 5px; }
107
  """
108
 
109
- # Function to process PDF files
110
  def process_pdf(pdf_file):
111
  if pdf_file is None:
112
  return None, "No file uploaded", {"page_images": [], "total_pages": 0, "total_words": 0}
@@ -144,9 +137,96 @@ def process_pdf(pdf_file):
144
  os.unlink(pdf_path)
145
  return None, f"Error processing PDF: {str(e)}", {"page_images": [], "total_pages": 0, "total_words": 0}
146
 
147
- # [Rest of your functions remain unchanged up to the Gradio interface]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
 
149
- # Update the Gradio interface
150
  with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
151
  current_session_id = gr.State(None)
152
  pdf_state = gr.State({"page_images": [], "total_pages": 0, "total_words": 0})
@@ -159,9 +239,7 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
159
  </div>
160
  """)
161
 
162
- # Main container with all functionality in tabs
163
  with gr.Tabs() as main_tabs:
164
- # Chat Assistant Tab
165
  with gr.TabItem("πŸ’¬ Chat Assistant", id=0):
166
  with gr.Row():
167
  with gr.Column(scale=1):
@@ -181,7 +259,7 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
181
  show_copy_button=True,
182
  elem_classes="chat-container",
183
  container=True,
184
- type="messages" # Updated to use messages format
185
  )
186
  with gr.Row():
187
  msg = gr.Textbox(
@@ -192,7 +270,6 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
192
  send_btn = gr.Button("Send", scale=1)
193
  clear_btn = gr.Button("Clear Conversation")
194
 
195
- # Document Analysis Tab
196
  with gr.TabItem("πŸ“„ Document Analysis", id=1):
197
  with gr.Row():
198
  with gr.Column(scale=1):
@@ -217,10 +294,8 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
217
  pdf_image = gr.Image(label="Document Page", type="pil")
218
  stats_display = gr.Markdown(elem_classes="stats-box")
219
 
220
- # Financial Tools Tab
221
  with gr.TabItem("πŸ” Financial Tools", id=2):
222
  with gr.Tabs() as financial_tabs:
223
- # Stock Analysis
224
  with gr.TabItem("Stock Analysis"):
225
  with gr.Row():
226
  with gr.Column():
@@ -238,43 +313,19 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
238
  stock_chart = gr.Plot(label="Stock Price Chart")
239
  stock_analysis = gr.Markdown()
240
 
241
- # Market News
242
- with gr.TabItem("Market News"):
243
- news_ticker = gr.Textbox(
244
- label="Company/Ticker",
245
- placeholder="Enter company name or ticker symbol"
246
- )
247
- news_btn = gr.Button("Fetch News")
248
- news_results = gr.Markdown()
249
-
250
- # Financial Report Analysis
251
- with gr.TabItem("Report Analysis"):
252
- with gr.Row():
253
- with gr.Column():
254
- report_image = gr.File(
255
- label="Upload Financial Chart/Image",
256
- file_types=["image"],
257
- type="filepath"
258
- )
259
- analyze_report_btn = gr.Button("Analyze Image")
260
- with gr.Column():
261
- report_preview = gr.Image(label="Preview", type="pil")
262
- report_analysis = gr.Markdown()
263
-
264
- # Event Handlers (Example implementation)
265
- def chat_handler(message, history, session_id, model, ticker, web_search):
266
- # Convert tuple history to messages format if needed
267
- if history and isinstance(history[0], tuple):
268
- history = [{"role": "user" if i % 2 == 0 else "assistant", "content": msg} for i, msg in enumerate(sum(history, ()))]
269
- response = generate_response(message, session_id, model, history, ticker, web_search)
270
- return response
271
-
272
  send_btn.click(
273
- fn=chat_handler,
274
- inputs=[msg, chatbot, current_session_id, model_dropdown, current_ticker, web_search_toggle],
275
  outputs=[chatbot]
276
  )
277
- clear_btn.click(lambda: [], outputs=[chatbot])
 
 
 
 
 
 
278
 
279
  upload_button.click(
280
  fn=process_pdf,
@@ -286,19 +337,24 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
286
  outputs=[page_slider, pdf_image, stats_display]
287
  )
288
 
 
 
 
 
 
 
289
  analyze_stock_btn.click(
290
  fn=analyze_ticker,
291
  inputs=[ticker_input, period_dropdown, web_search_toggle],
292
  outputs=[stock_chart, stock_analysis, current_ticker]
293
  )
294
 
295
- # Add footer with attribution
296
- gr.HTML("""
297
- <div style="text-align: center; margin-top: 20px; padding: 10px; color: #666; font-size: 0.8rem; border-top: 1px solid #eee;">
298
- Created by Calvin Allen Crawford
299
- </div>
300
- """)
301
 
302
- # Launch the app
303
  if __name__ == "__main__":
 
304
  demo.launch()
 
17
  from PIL import Image
18
  from dotenv import load_dotenv
19
  import torch
20
+ import yfinance as yf
21
+ import plotly.graph_objects as go
22
 
23
  # Assuming groq is a custom module or typo; replace with actual import if needed
24
+ from groq import Client as GroqClient # Adjust based on your setup
25
 
26
  # LangChain imports (optional, only if embeddings are available)
27
  try:
28
+ from langchain_community.embeddings import HuggingFaceEmbeddings # Changed to basic embeddings
29
  from langchain_community.vectorstores import FAISS
30
  from langchain.text_splitter import RecursiveCharacterTextSplitter
31
  langchain_available = True
 
35
 
36
  # Load environment variables
37
  load_dotenv()
38
+ client = GroqClient(api_key=os.getenv("GROQ_LEGAL_API_KEY"))
39
 
40
  # Embeddings initialization with fallback
41
  if langchain_available:
42
  try:
43
+ embeddings = HuggingFaceEmbeddings(
44
+ model_name="sentence-transformers/all-MiniLM-L6-v2",
45
  model_kwargs={"device": "cuda" if torch.cuda.is_available() else "cpu"}
46
  )
47
  except Exception as e:
48
+ print(f"Warning: Failed to load embeddings model: {e}")
49
+ embeddings = None
 
 
 
 
 
 
 
50
  else:
51
  embeddings = None
52
  print("Embeddings disabled due to missing LangChain dependencies.")
 
99
  .search-toggle { margin-left: 5px; }
100
  """
101
 
102
+ # Function definitions
103
  def process_pdf(pdf_file):
104
  if pdf_file is None:
105
  return None, "No file uploaded", {"page_images": [], "total_pages": 0, "total_words": 0}
 
137
  os.unlink(pdf_path)
138
  return None, f"Error processing PDF: {str(e)}", {"page_images": [], "total_pages": 0, "total_words": 0}
139
 
140
+ def update_pdf_viewer(pdf_state):
141
+ if not pdf_state["total_pages"]:
142
+ return 0, None, "No PDF uploaded yet"
143
+ try:
144
+ img_data = base64.b64decode(pdf_state["page_images"][0])
145
+ img = Image.open(io.BytesIO(img_data))
146
+ return pdf_state["total_pages"], img, f"**Total Pages:** {pdf_state['total_pages']}\n**Total Words:** {pdf_state['total_words']}"
147
+ except Exception as e:
148
+ print(f"Error decoding image: {e}")
149
+ return 0, None, "Error displaying PDF"
150
+
151
+ def update_image(page_num, pdf_state):
152
+ if not pdf_state["total_pages"] or page_num < 1 or page_num > pdf_state["total_pages"]:
153
+ return None
154
+ try:
155
+ img_data = base64.b64decode(pdf_state["page_images"][page_num - 1])
156
+ img = Image.open(io.BytesIO(img_data))
157
+ return img
158
+ except Exception as e:
159
+ print(f"Error decoding image: {e}")
160
+ return None
161
+
162
+ def analyze_ticker(ticker, period, web_search_enabled):
163
+ try:
164
+ stock = yf.Ticker(ticker)
165
+ hist = stock.history(period=period)
166
+ if hist.empty:
167
+ return None, f"No data found for {ticker}", ticker
168
+
169
+ fig = go.Figure()
170
+ fig.add_trace(go.Candlestick(
171
+ x=hist.index,
172
+ open=hist['Open'],
173
+ high=hist['High'],
174
+ low=hist['Low'],
175
+ close=hist['Close'],
176
+ name='OHLC'
177
+ ))
178
+ fig.update_layout(
179
+ title=f'{ticker} Stock Price ({period})',
180
+ yaxis_title='Price',
181
+ template='plotly_white'
182
+ )
183
+
184
+ analysis = f"## {ticker} Analysis\n\n"
185
+ analysis += f"Latest Close: ${hist['Close'][-1]:.2f}\n"
186
+ analysis += f"52 Week High: ${hist['High'].max():.2f}\n"
187
+ analysis += f"52 Week Low: ${hist['Low'].min():.2f}\n"
188
+
189
+ return fig, analysis, ticker
190
+ except Exception as e:
191
+ return None, f"Error analyzing ticker: {str(e)}", ticker
192
+
193
+ def generate_response(message, session_id, model_name, history, ticker, web_search_enabled):
194
+ if not message:
195
+ return history
196
+ try:
197
+ context = ""
198
+ if session_id and session_id in user_vectorstores:
199
+ vectorstore = user_vectorstores[session_id]
200
+ docs = vectorstore.similarity_search(message, k=3)
201
+ if docs:
202
+ context = "\n\nRelevant information from uploaded document:\n" + "\n".join(f"- {doc.page_content}" for doc in docs)
203
+
204
+ system_prompt = "You are a financial assistant specializing in analyzing markets, stocks, and financial documents."
205
+ system_prompt += " You can help with understanding financial data, analyzing stocks, and explaining financial concepts."
206
+ if ticker:
207
+ system_prompt += f" Current ticker in focus: {ticker}"
208
+ if context:
209
+ system_prompt += " Use the following context to answer the question if relevant: " + context
210
+
211
+ completion = client.chat.completions.create(
212
+ model=model_name,
213
+ messages=[
214
+ {"role": "system", "content": system_prompt},
215
+ {"role": "user", "content": message}
216
+ ],
217
+ temperature=0.5,
218
+ max_tokens=1024
219
+ )
220
+ response = completion.choices[0].message.content
221
+ history.append({"role": "user", "content": message})
222
+ history.append({"role": "assistant", "content": response})
223
+ return history
224
+ except Exception as e:
225
+ history.append({"role": "user", "content": message})
226
+ history.append({"role": "assistant", "content": f"Error generating response: {str(e)}"})
227
+ return history
228
 
229
+ # Gradio interface
230
  with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
231
  current_session_id = gr.State(None)
232
  pdf_state = gr.State({"page_images": [], "total_pages": 0, "total_words": 0})
 
239
  </div>
240
  """)
241
 
 
242
  with gr.Tabs() as main_tabs:
 
243
  with gr.TabItem("πŸ’¬ Chat Assistant", id=0):
244
  with gr.Row():
245
  with gr.Column(scale=1):
 
259
  show_copy_button=True,
260
  elem_classes="chat-container",
261
  container=True,
262
+ type="messages"
263
  )
264
  with gr.Row():
265
  msg = gr.Textbox(
 
270
  send_btn = gr.Button("Send", scale=1)
271
  clear_btn = gr.Button("Clear Conversation")
272
 
 
273
  with gr.TabItem("πŸ“„ Document Analysis", id=1):
274
  with gr.Row():
275
  with gr.Column(scale=1):
 
294
  pdf_image = gr.Image(label="Document Page", type="pil")
295
  stats_display = gr.Markdown(elem_classes="stats-box")
296
 
 
297
  with gr.TabItem("πŸ” Financial Tools", id=2):
298
  with gr.Tabs() as financial_tabs:
 
299
  with gr.TabItem("Stock Analysis"):
300
  with gr.Row():
301
  with gr.Column():
 
313
  stock_chart = gr.Plot(label="Stock Price Chart")
314
  stock_analysis = gr.Markdown()
315
 
316
+ # Event Handlers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  send_btn.click(
318
+ fn=generate_response,
319
+ inputs=[msg, current_session_id, model_dropdown, chatbot, current_ticker, web_search_toggle],
320
  outputs=[chatbot]
321
  )
322
+
323
+ clear_btn.click(
324
+ fn=lambda: [],
325
+ inputs=None,
326
+ outputs=[chatbot],
327
+ queue=False
328
+ )
329
 
330
  upload_button.click(
331
  fn=process_pdf,
 
337
  outputs=[page_slider, pdf_image, stats_display]
338
  )
339
 
340
+ page_slider.change(
341
+ fn=update_image,
342
+ inputs=[page_slider, pdf_state],
343
+ outputs=[pdf_image]
344
+ )
345
+
346
  analyze_stock_btn.click(
347
  fn=analyze_ticker,
348
  inputs=[ticker_input, period_dropdown, web_search_toggle],
349
  outputs=[stock_chart, stock_analysis, current_ticker]
350
  )
351
 
352
+ gr.HTML("""
353
+ <div style="text-align: center; margin-top: 20px; padding: 10px; color: #666; font-size: 0.8rem; border-top: 1px solid #eee;">
354
+ Created by Calvin Allen Crawford
355
+ </div>
356
+ """)
 
357
 
 
358
  if __name__ == "__main__":
359
+ demo = create_interface()
360
  demo.launch()