Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -6,6 +6,7 @@ import base64
|
|
| 6 |
import io
|
| 7 |
import json
|
| 8 |
import re
|
|
|
|
| 9 |
from datetime import datetime, timedelta
|
| 10 |
|
| 11 |
# Third-party imports
|
|
@@ -26,6 +27,9 @@ from langchain_community.embeddings import HuggingFaceEmbeddings
|
|
| 26 |
from langchain_community.vectorstores import FAISS
|
| 27 |
from langchain.text_splitter import RecursiveCharacterTextSplitter
|
| 28 |
|
|
|
|
|
|
|
|
|
|
| 29 |
# Load environment variables
|
| 30 |
load_dotenv()
|
| 31 |
client = groq.Client(api_key=os.getenv("GROQ_LEGAL_API_KEY"))
|
|
@@ -78,7 +82,7 @@ class ModelName(str):
|
|
| 78 |
raise ValueError(f"Invalid model name: {v}")
|
| 79 |
return v
|
| 80 |
|
| 81 |
-
# Custom CSS
|
| 82 |
custom_css = """
|
| 83 |
:root {
|
| 84 |
--bg-color: #FFFFFF;
|
|
@@ -125,7 +129,7 @@ body { background-color: var(--bg-color); color: var(--text-color); font-family:
|
|
| 125 |
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
|
| 126 |
"""
|
| 127 |
|
| 128 |
-
# Custom JavaScript
|
| 129 |
custom_js = """
|
| 130 |
function toggleTheme() {
|
| 131 |
const currentTheme = document.body.getAttribute('data-theme');
|
|
@@ -147,22 +151,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 147 |
if (savedTheme) {
|
| 148 |
document.body.setAttribute('data-theme', savedTheme);
|
| 149 |
}
|
| 150 |
-
tippy('#pdf_file', { content: 'Upload a PDF document for analysis', placement: 'top' });
|
| 151 |
-
tippy('#ticker_input', { content: 'Enter a stock ticker symbol (e.g., AAPL)', placement: 'top' });
|
| 152 |
});
|
| 153 |
"""
|
| 154 |
|
| 155 |
-
# Spinner HTML
|
| 156 |
custom_html = """
|
| 157 |
<div id="spinner" style="display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);">
|
| 158 |
<div class="spinner"></div>
|
| 159 |
</div>
|
| 160 |
-
<script src="https://unpkg.com/@popperjs/core@2"></script>
|
| 161 |
-
<script src="https://unpkg.com/tippy.js@6"></script>
|
| 162 |
"""
|
| 163 |
|
| 164 |
# Helper Functions
|
| 165 |
def process_pdf(pdf_file):
|
|
|
|
| 166 |
if pdf_file is None:
|
| 167 |
return None, "No file uploaded", PDFState(page_images=[], total_pages=0, total_words=0)
|
| 168 |
|
|
@@ -188,8 +189,10 @@ def process_pdf(pdf_file):
|
|
| 188 |
|
| 189 |
os.unlink(pdf_path)
|
| 190 |
pdf_state = PDFState(page_images=page_images, total_pages=total_pages, total_words=total_words)
|
|
|
|
| 191 |
return session_id, f"✅ Successfully processed {len(chunks)} text chunks from your PDF", pdf_state
|
| 192 |
except Exception as e:
|
|
|
|
| 193 |
if "pdf_path" in locals() and os.path.exists(pdf_path):
|
| 194 |
os.unlink(pdf_path)
|
| 195 |
return None, f"Error processing PDF: {str(e)}", PDFState(page_images=[], total_pages=0, total_words=0)
|
|
@@ -308,9 +311,11 @@ def create_stock_chart(ticker, period, enable_stock_data):
|
|
| 308 |
return fig
|
| 309 |
|
| 310 |
def analyze_ticker(ticker_input, period, use_brave_search, enable_stock_data, enable_search):
|
|
|
|
| 311 |
try:
|
| 312 |
input_data = StockAnalysisInput(ticker=ticker_input, period=period)
|
| 313 |
except ValueError as e:
|
|
|
|
| 314 |
return None, str(e), None
|
| 315 |
|
| 316 |
ticker = input_data.ticker
|
|
@@ -333,17 +338,21 @@ def analyze_ticker(ticker_input, period, use_brave_search, enable_stock_data, en
|
|
| 333 |
**P/E Ratio:** {stock_data['pe_ratio']}
|
| 334 |
**Market Sentiment:** {sentiment}
|
| 335 |
"""
|
|
|
|
| 336 |
return chart, summary, ticker
|
| 337 |
except Exception as e:
|
|
|
|
| 338 |
return None, f"Error analyzing ticker {ticker}: {str(e)}", None
|
| 339 |
|
| 340 |
def generate_response(message, session_id, model_name, history, current_ticker, use_brave_search, enable_search, enable_stock_data):
|
|
|
|
| 341 |
if not message:
|
| 342 |
return history
|
| 343 |
|
| 344 |
try:
|
| 345 |
model_name = ModelName.validate(model_name)
|
| 346 |
except ValueError as e:
|
|
|
|
| 347 |
return history + [(message, str(e))]
|
| 348 |
|
| 349 |
try:
|
|
@@ -368,6 +377,7 @@ def generate_response(message, session_id, model_name, history, current_ticker,
|
|
| 368 |
for i, item in enumerate(news[:3]):
|
| 369 |
response += f"{i+1}. [{item['title']}]({item['link']})\n {item['snippet'][:100]}...\n"
|
| 370 |
history.append((message, response))
|
|
|
|
| 371 |
return history
|
| 372 |
|
| 373 |
if message.lower().startswith("/news "):
|
|
@@ -377,6 +387,7 @@ def generate_response(message, session_id, model_name, history, current_ticker,
|
|
| 377 |
for i, item in enumerate(news[:5]):
|
| 378 |
response += f"{i+1}. **{item['title']}**\n {item['snippet']}\n [Read more]({item['link']})\n\n"
|
| 379 |
history.append((message, response))
|
|
|
|
| 380 |
return history
|
| 381 |
|
| 382 |
system_prompt = "You are a financial assistant specializing in analyzing financial reports, statements, and market trends."
|
|
@@ -390,10 +401,11 @@ def generate_response(message, session_id, model_name, history, current_ticker,
|
|
| 390 |
)
|
| 391 |
response = completion.choices[0].message.content
|
| 392 |
history.append((message, response))
|
|
|
|
| 393 |
return history
|
| 394 |
except Exception as e:
|
| 395 |
-
|
| 396 |
-
return history
|
| 397 |
|
| 398 |
def update_pdf_viewer(pdf_state: PDFState):
|
| 399 |
if not pdf_state.total_pages:
|
|
@@ -466,48 +478,73 @@ def create_interface():
|
|
| 466 |
|
| 467 |
# Event Handlers
|
| 468 |
upload_button.click(
|
| 469 |
-
js="showSpinner",
|
| 470 |
fn=process_pdf,
|
| 471 |
inputs=[pdf_file],
|
| 472 |
-
outputs=[current_session_id, pdf_status, pdf_state]
|
|
|
|
| 473 |
).then(
|
| 474 |
-
update_pdf_viewer,
|
| 475 |
inputs=[pdf_state],
|
| 476 |
outputs=[page_slider, pdf_image, stats_display]
|
| 477 |
).then(
|
| 478 |
-
|
|
|
|
| 479 |
inputs=[],
|
| 480 |
outputs=[]
|
| 481 |
)
|
| 482 |
|
| 483 |
analyze_button.click(
|
| 484 |
-
js="showSpinner",
|
| 485 |
fn=analyze_ticker,
|
| 486 |
inputs=[ticker_input, period_dropdown, use_brave_search, enable_stock_data, enable_search],
|
| 487 |
-
outputs=[stock_chart, stock_summary, current_ticker]
|
|
|
|
| 488 |
).then(
|
| 489 |
-
|
|
|
|
| 490 |
inputs=[],
|
| 491 |
outputs=[]
|
| 492 |
)
|
| 493 |
|
| 494 |
msg.submit(
|
| 495 |
-
generate_response,
|
| 496 |
inputs=[msg, current_session_id, model_dropdown, chatbot, current_ticker, use_brave_search, enable_search, enable_stock_data],
|
| 497 |
outputs=[chatbot]
|
| 498 |
-
).then(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 499 |
|
| 500 |
send_btn.click(
|
| 501 |
-
generate_response,
|
| 502 |
inputs=[msg, current_session_id, model_dropdown, chatbot, current_ticker, use_brave_search, enable_search, enable_stock_data],
|
| 503 |
-
outputs=[chatbot]
|
| 504 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 505 |
|
| 506 |
-
page_slider.change(
|
| 507 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 508 |
|
| 509 |
return demo
|
| 510 |
|
| 511 |
if __name__ == "__main__":
|
| 512 |
demo = create_interface()
|
| 513 |
-
demo.launch()
|
|
|
|
| 6 |
import io
|
| 7 |
import json
|
| 8 |
import re
|
| 9 |
+
import logging
|
| 10 |
from datetime import datetime, timedelta
|
| 11 |
|
| 12 |
# Third-party imports
|
|
|
|
| 27 |
from langchain_community.vectorstores import FAISS
|
| 28 |
from langchain.text_splitter import RecursiveCharacterTextSplitter
|
| 29 |
|
| 30 |
+
# Setup logging
|
| 31 |
+
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
|
| 32 |
+
|
| 33 |
# Load environment variables
|
| 34 |
load_dotenv()
|
| 35 |
client = groq.Client(api_key=os.getenv("GROQ_LEGAL_API_KEY"))
|
|
|
|
| 82 |
raise ValueError(f"Invalid model name: {v}")
|
| 83 |
return v
|
| 84 |
|
| 85 |
+
# Custom CSS
|
| 86 |
custom_css = """
|
| 87 |
:root {
|
| 88 |
--bg-color: #FFFFFF;
|
|
|
|
| 129 |
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
|
| 130 |
"""
|
| 131 |
|
| 132 |
+
# Custom JavaScript (simplified to avoid interference)
|
| 133 |
custom_js = """
|
| 134 |
function toggleTheme() {
|
| 135 |
const currentTheme = document.body.getAttribute('data-theme');
|
|
|
|
| 151 |
if (savedTheme) {
|
| 152 |
document.body.setAttribute('data-theme', savedTheme);
|
| 153 |
}
|
|
|
|
|
|
|
| 154 |
});
|
| 155 |
"""
|
| 156 |
|
| 157 |
+
# Spinner HTML
|
| 158 |
custom_html = """
|
| 159 |
<div id="spinner" style="display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);">
|
| 160 |
<div class="spinner"></div>
|
| 161 |
</div>
|
|
|
|
|
|
|
| 162 |
"""
|
| 163 |
|
| 164 |
# Helper Functions
|
| 165 |
def process_pdf(pdf_file):
|
| 166 |
+
logging.debug("Processing PDF file")
|
| 167 |
if pdf_file is None:
|
| 168 |
return None, "No file uploaded", PDFState(page_images=[], total_pages=0, total_words=0)
|
| 169 |
|
|
|
|
| 189 |
|
| 190 |
os.unlink(pdf_path)
|
| 191 |
pdf_state = PDFState(page_images=page_images, total_pages=total_pages, total_words=total_words)
|
| 192 |
+
logging.debug(f"PDF processed successfully: {session_id}")
|
| 193 |
return session_id, f"✅ Successfully processed {len(chunks)} text chunks from your PDF", pdf_state
|
| 194 |
except Exception as e:
|
| 195 |
+
logging.error(f"Error processing PDF: {str(e)}")
|
| 196 |
if "pdf_path" in locals() and os.path.exists(pdf_path):
|
| 197 |
os.unlink(pdf_path)
|
| 198 |
return None, f"Error processing PDF: {str(e)}", PDFState(page_images=[], total_pages=0, total_words=0)
|
|
|
|
| 311 |
return fig
|
| 312 |
|
| 313 |
def analyze_ticker(ticker_input, period, use_brave_search, enable_stock_data, enable_search):
|
| 314 |
+
logging.debug(f"Analyzing ticker: {ticker_input}, period: {period}")
|
| 315 |
try:
|
| 316 |
input_data = StockAnalysisInput(ticker=ticker_input, period=period)
|
| 317 |
except ValueError as e:
|
| 318 |
+
logging.error(f"Validation error: {str(e)}")
|
| 319 |
return None, str(e), None
|
| 320 |
|
| 321 |
ticker = input_data.ticker
|
|
|
|
| 338 |
**P/E Ratio:** {stock_data['pe_ratio']}
|
| 339 |
**Market Sentiment:** {sentiment}
|
| 340 |
"""
|
| 341 |
+
logging.debug(f"Ticker {ticker} analyzed successfully")
|
| 342 |
return chart, summary, ticker
|
| 343 |
except Exception as e:
|
| 344 |
+
logging.error(f"Error analyzing ticker {ticker}: {str(e)}")
|
| 345 |
return None, f"Error analyzing ticker {ticker}: {str(e)}", None
|
| 346 |
|
| 347 |
def generate_response(message, session_id, model_name, history, current_ticker, use_brave_search, enable_search, enable_stock_data):
|
| 348 |
+
logging.debug(f"Generating response for message: {message}")
|
| 349 |
if not message:
|
| 350 |
return history
|
| 351 |
|
| 352 |
try:
|
| 353 |
model_name = ModelName.validate(model_name)
|
| 354 |
except ValueError as e:
|
| 355 |
+
logging.error(f"Model validation error: {str(e)}")
|
| 356 |
return history + [(message, str(e))]
|
| 357 |
|
| 358 |
try:
|
|
|
|
| 377 |
for i, item in enumerate(news[:3]):
|
| 378 |
response += f"{i+1}. [{item['title']}]({item['link']})\n {item['snippet'][:100]}...\n"
|
| 379 |
history.append((message, response))
|
| 380 |
+
logging.debug(f"Stock response generated for {ticker}")
|
| 381 |
return history
|
| 382 |
|
| 383 |
if message.lower().startswith("/news "):
|
|
|
|
| 387 |
for i, item in enumerate(news[:5]):
|
| 388 |
response += f"{i+1}. **{item['title']}**\n {item['snippet']}\n [Read more]({item['link']})\n\n"
|
| 389 |
history.append((message, response))
|
| 390 |
+
logging.debug(f"News response generated for {topic}")
|
| 391 |
return history
|
| 392 |
|
| 393 |
system_prompt = "You are a financial assistant specializing in analyzing financial reports, statements, and market trends."
|
|
|
|
| 401 |
)
|
| 402 |
response = completion.choices[0].message.content
|
| 403 |
history.append((message, response))
|
| 404 |
+
logging.debug("Chat response generated")
|
| 405 |
return history
|
| 406 |
except Exception as e:
|
| 407 |
+
logging.error(f"Error generating response: {str(e)}")
|
| 408 |
+
return history + [(message, f"Error generating response: {str(e)}")]
|
| 409 |
|
| 410 |
def update_pdf_viewer(pdf_state: PDFState):
|
| 411 |
if not pdf_state.total_pages:
|
|
|
|
| 478 |
|
| 479 |
# Event Handlers
|
| 480 |
upload_button.click(
|
|
|
|
| 481 |
fn=process_pdf,
|
| 482 |
inputs=[pdf_file],
|
| 483 |
+
outputs=[current_session_id, pdf_status, pdf_state],
|
| 484 |
+
_js="showSpinner"
|
| 485 |
).then(
|
| 486 |
+
fn=update_pdf_viewer,
|
| 487 |
inputs=[pdf_state],
|
| 488 |
outputs=[page_slider, pdf_image, stats_display]
|
| 489 |
).then(
|
| 490 |
+
fn=None,
|
| 491 |
+
_js="hideSpinner",
|
| 492 |
inputs=[],
|
| 493 |
outputs=[]
|
| 494 |
)
|
| 495 |
|
| 496 |
analyze_button.click(
|
|
|
|
| 497 |
fn=analyze_ticker,
|
| 498 |
inputs=[ticker_input, period_dropdown, use_brave_search, enable_stock_data, enable_search],
|
| 499 |
+
outputs=[stock_chart, stock_summary, current_ticker],
|
| 500 |
+
_js="showSpinner"
|
| 501 |
).then(
|
| 502 |
+
fn=None,
|
| 503 |
+
_js="hideSpinner",
|
| 504 |
inputs=[],
|
| 505 |
outputs=[]
|
| 506 |
)
|
| 507 |
|
| 508 |
msg.submit(
|
| 509 |
+
fn=generate_response,
|
| 510 |
inputs=[msg, current_session_id, model_dropdown, chatbot, current_ticker, use_brave_search, enable_search, enable_stock_data],
|
| 511 |
outputs=[chatbot]
|
| 512 |
+
).then(
|
| 513 |
+
fn=lambda: "",
|
| 514 |
+
inputs=None,
|
| 515 |
+
outputs=[msg]
|
| 516 |
+
)
|
| 517 |
|
| 518 |
send_btn.click(
|
| 519 |
+
fn=generate_response,
|
| 520 |
inputs=[msg, current_session_id, model_dropdown, chatbot, current_ticker, use_brave_search, enable_search, enable_stock_data],
|
| 521 |
+
outputs=[chatbot],
|
| 522 |
+
_js="showSpinner"
|
| 523 |
+
).then(
|
| 524 |
+
fn=lambda: "",
|
| 525 |
+
inputs=None,
|
| 526 |
+
outputs=[msg]
|
| 527 |
+
).then(
|
| 528 |
+
fn=None,
|
| 529 |
+
_js="hideSpinner",
|
| 530 |
+
inputs=[],
|
| 531 |
+
outputs=[]
|
| 532 |
+
)
|
| 533 |
|
| 534 |
+
page_slider.change(
|
| 535 |
+
fn=update_image,
|
| 536 |
+
inputs=[page_slider, pdf_state],
|
| 537 |
+
outputs=[pdf_image]
|
| 538 |
+
)
|
| 539 |
+
theme_button.click(
|
| 540 |
+
fn=None,
|
| 541 |
+
_js="toggleTheme",
|
| 542 |
+
inputs=[],
|
| 543 |
+
outputs=[]
|
| 544 |
+
)
|
| 545 |
|
| 546 |
return demo
|
| 547 |
|
| 548 |
if __name__ == "__main__":
|
| 549 |
demo = create_interface()
|
| 550 |
+
demo.launch(debug=True) # Enable debug mode to see logs in console
|