Upload app.py with huggingface_hub
Browse files
app.py
CHANGED
|
@@ -37,52 +37,39 @@ gui_stats = {
|
|
| 37 |
'tensor_issues': 0
|
| 38 |
}
|
| 39 |
|
| 40 |
-
#
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
hours, remainder = divmod(uptime.seconds, 3600)
|
| 44 |
-
minutes, seconds = divmod(remainder, 60)
|
| 45 |
-
uptime_str = f"{hours}h {minutes}m {seconds}s"
|
| 46 |
-
|
| 47 |
-
return {
|
| 48 |
-
'errors': gui_stats['errors'],
|
| 49 |
-
'warnings': gui_stats['warnings'],
|
| 50 |
-
'last_error': gui_stats['last_error'],
|
| 51 |
-
'last_error_time': gui_stats['last_error_time'],
|
| 52 |
-
'last_warning': gui_stats['last_warning'],
|
| 53 |
-
'last_warning_time': gui_stats['last_warning_time'],
|
| 54 |
-
'operations': gui_stats['operations_completed'],
|
| 55 |
-
'uptime': uptime_str,
|
| 56 |
-
'tensor_issues': gui_stats['tensor_issues']
|
| 57 |
-
}
|
| 58 |
|
| 59 |
-
#
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
|
|
|
|
|
|
| 86 |
|
| 87 |
# Custom logging handler that captures logs for GUI display
|
| 88 |
class GUILogHandler(logging.Handler):
|
|
@@ -137,52 +124,52 @@ class GUILogHandler(logging.Handler):
|
|
| 137 |
with self.lock:
|
| 138 |
self.log_entries = []
|
| 139 |
|
| 140 |
-
#
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
gui_log_handler.setLevel(logging.DEBUG)
|
| 159 |
-
|
| 160 |
-
# Configure logging
|
| 161 |
-
logging.basicConfig(
|
| 162 |
-
level=logging.DEBUG,
|
| 163 |
-
format='%(asctime)s [%(levelname)s] %(message)s',
|
| 164 |
-
handlers=[
|
| 165 |
-
logging.FileHandler(log_file),
|
| 166 |
-
logging.StreamHandler(sys.stdout),
|
| 167 |
-
gui_log_handler
|
| 168 |
-
]
|
| 169 |
-
)
|
| 170 |
-
|
| 171 |
-
# Create a logger
|
| 172 |
-
logger = logging.getLogger("internvl_analyzer")
|
| 173 |
-
logger.setLevel(logging.DEBUG)
|
| 174 |
|
| 175 |
-
#
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
|
| 187 |
# Function to log tensor info for debugging
|
| 188 |
def log_tensor_info(tensor, name="tensor"):
|
|
@@ -585,83 +572,109 @@ def analyze_dual_images(model, tokenizer, image1, image2, prompt):
|
|
| 585 |
return error_msg
|
| 586 |
|
| 587 |
# Function to process PDF files
|
| 588 |
-
def process_pdf(pdf_path=None,
|
| 589 |
-
"""
|
| 590 |
try:
|
| 591 |
-
logger.info(f"Processing PDF: {pdf_path}")
|
| 592 |
-
logger.debug(f"Current working directory: {os.getcwd()}")
|
| 593 |
|
| 594 |
-
if pdf_path:
|
| 595 |
-
#
|
| 596 |
-
|
| 597 |
-
logger.
|
| 598 |
-
|
| 599 |
-
|
|
|
|
|
|
|
| 600 |
|
|
|
|
| 601 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 602 |
images = convert_from_path(pdf_path)
|
| 603 |
-
logger.info(f"PDF successfully
|
| 604 |
-
|
| 605 |
-
|
|
|
|
| 606 |
logger.error(traceback.format_exc())
|
| 607 |
-
|
| 608 |
-
|
|
|
|
| 609 |
try:
|
| 610 |
-
|
| 611 |
-
|
| 612 |
-
|
| 613 |
-
|
| 614 |
-
|
| 615 |
-
)
|
| 616 |
-
logger.info(f"
|
| 617 |
-
|
| 618 |
-
|
|
|
|
| 619 |
logger.error(traceback.format_exc())
|
|
|
|
| 620 |
raise
|
| 621 |
-
|
| 622 |
-
|
| 623 |
-
logger.info("
|
| 624 |
-
|
|
|
|
|
|
|
|
|
|
| 625 |
|
| 626 |
try:
|
| 627 |
-
|
| 628 |
-
|
| 629 |
-
|
| 630 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 631 |
logger.error(traceback.format_exc())
|
| 632 |
-
|
| 633 |
-
|
| 634 |
-
try:
|
| 635 |
-
images = convert_from_bytes(
|
| 636 |
-
pdf_bytes,
|
| 637 |
-
dpi=150, # Lower DPI
|
| 638 |
-
use_pdftocairo=False,
|
| 639 |
-
strict=False
|
| 640 |
-
)
|
| 641 |
-
logger.info(f"Alternative bytes conversion successful: {len(images)} images")
|
| 642 |
-
except Exception as alt_bytes_err:
|
| 643 |
-
logger.error(f"Alternative bytes conversion also failed: {str(alt_bytes_err)}")
|
| 644 |
-
logger.error(traceback.format_exc())
|
| 645 |
-
raise
|
| 646 |
else:
|
| 647 |
-
|
| 648 |
-
|
| 649 |
-
|
| 650 |
-
# Validate and log the output
|
| 651 |
-
if not images:
|
| 652 |
-
logger.error("PDF conversion returned empty list")
|
| 653 |
return None
|
| 654 |
|
| 655 |
-
# Log details about the first few converted images
|
| 656 |
-
for i, img in enumerate(images[:2]): # Log first 2 pages
|
| 657 |
-
logger.debug(f"PDF Page {i+1}: size={img.size}, mode={img.mode}")
|
| 658 |
-
|
| 659 |
-
logger.info(f"PDF successfully processed, returning {len(images)} images")
|
| 660 |
-
return images
|
| 661 |
except Exception as e:
|
| 662 |
-
logger.error(f"
|
| 663 |
logger.error(traceback.format_exc())
|
| 664 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 665 |
|
| 666 |
# Function to analyze images with a prompt
|
| 667 |
def analyze_with_prompt(image_input, prompt):
|
|
@@ -1551,6 +1564,24 @@ def get_latest_log_content():
|
|
| 1551 |
|
| 1552 |
# Main function
|
| 1553 |
def main():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1554 |
# Load the model
|
| 1555 |
model, tokenizer = load_model()
|
| 1556 |
|
|
@@ -1580,6 +1611,14 @@ def main():
|
|
| 1580 |
def get_debug_logs(num_lines=50):
|
| 1581 |
return gui_log_handler.get_logs(last_n=num_lines)
|
| 1582 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1583 |
# Function to update logs in real-time
|
| 1584 |
def update_logs(history):
|
| 1585 |
latest = gui_log_handler.get_latest()
|
|
@@ -1601,6 +1640,90 @@ def main():
|
|
| 1601 |
gr.Markdown("# InternVL2.5 Image Analyzer")
|
| 1602 |
gr.Markdown("Analyze images using the InternVL2.5 model. You can upload individual images or analyze all images in a folder.")
|
| 1603 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1604 |
# Debug mode toggle and panel
|
| 1605 |
with gr.Accordion("Debug Console", open=False) as debug_accordion:
|
| 1606 |
with gr.Row():
|
|
|
|
| 37 |
'tensor_issues': 0
|
| 38 |
}
|
| 39 |
|
| 40 |
+
# Constants
|
| 41 |
+
IMAGENET_MEAN = (0.485, 0.456, 0.406)
|
| 42 |
+
IMAGENET_STD = (0.229, 0.224, 0.225)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
+
# Configuration
|
| 45 |
+
MODEL_NAME = "OpenGVLab/InternVL2_5-8B" # Smaller model for faster loading
|
| 46 |
+
IMAGE_SIZE = 448
|
| 47 |
+
OUTPUT_DIR = "saved_outputs" # Changed to a visible repo directory
|
| 48 |
+
LOGS_DIR = os.path.join(OUTPUT_DIR, "logs")
|
| 49 |
+
|
| 50 |
+
# Create output and logs directories if they don't exist
|
| 51 |
+
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
| 52 |
+
os.makedirs(LOGS_DIR, exist_ok=True)
|
| 53 |
+
|
| 54 |
+
# Set up logging to write to saved_outputs/logs directory
|
| 55 |
+
timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
|
| 56 |
+
log_file = os.path.join(LOGS_DIR, f"debug_log_{timestamp}.log")
|
| 57 |
+
latest_log = os.path.join(LOGS_DIR, "latest_debug.log")
|
| 58 |
+
|
| 59 |
+
# Configure basic logging first
|
| 60 |
+
logging.basicConfig(
|
| 61 |
+
level=logging.DEBUG,
|
| 62 |
+
format='%(asctime)s [%(levelname)s] %(message)s',
|
| 63 |
+
handlers=[
|
| 64 |
+
logging.FileHandler(log_file),
|
| 65 |
+
logging.FileHandler(latest_log, mode='w'), # Overwrite the latest log file
|
| 66 |
+
logging.StreamHandler(sys.stdout)
|
| 67 |
+
]
|
| 68 |
+
)
|
| 69 |
+
|
| 70 |
+
# Get the root logger
|
| 71 |
+
logger = logging.getLogger()
|
| 72 |
+
logger.setLevel(logging.DEBUG)
|
| 73 |
|
| 74 |
# Custom logging handler that captures logs for GUI display
|
| 75 |
class GUILogHandler(logging.Handler):
|
|
|
|
| 124 |
with self.lock:
|
| 125 |
self.log_entries = []
|
| 126 |
|
| 127 |
+
# Function to get stats for UI display
|
| 128 |
+
def get_debug_stats():
|
| 129 |
+
uptime = datetime.datetime.now() - gui_stats['start_time']
|
| 130 |
+
hours, remainder = divmod(uptime.seconds, 3600)
|
| 131 |
+
minutes, seconds = divmod(remainder, 60)
|
| 132 |
+
uptime_str = f"{hours}h {minutes}m {seconds}s"
|
| 133 |
+
|
| 134 |
+
return {
|
| 135 |
+
'errors': gui_stats['errors'],
|
| 136 |
+
'warnings': gui_stats['warnings'],
|
| 137 |
+
'last_error': gui_stats['last_error'],
|
| 138 |
+
'last_error_time': gui_stats['last_error_time'],
|
| 139 |
+
'last_warning': gui_stats['last_warning'],
|
| 140 |
+
'last_warning_time': gui_stats['last_warning_time'],
|
| 141 |
+
'operations': gui_stats['operations_completed'],
|
| 142 |
+
'uptime': uptime_str,
|
| 143 |
+
'tensor_issues': gui_stats['tensor_issues']
|
| 144 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 145 |
|
| 146 |
+
# Function to format debug stats as HTML
|
| 147 |
+
def format_debug_stats_html():
|
| 148 |
+
stats = get_debug_stats()
|
| 149 |
+
|
| 150 |
+
error_color = "#ff5555" if stats['errors'] > 0 else "#555555"
|
| 151 |
+
warning_color = "#ffaa00" if stats['warnings'] > 0 else "#555555"
|
| 152 |
+
|
| 153 |
+
html = f"""
|
| 154 |
+
<div style="margin: 10px 0; padding: 10px; border: 1px solid #ddd; border-radius: 4px; background-color: #f9f9f9;">
|
| 155 |
+
<div style="display: flex; justify-content: space-between;">
|
| 156 |
+
<div style="flex: 1;">
|
| 157 |
+
<p><strong>Errors:</strong> <span style="color: {error_color};">{stats['errors']}</span></p>
|
| 158 |
+
<p><strong>Warnings:</strong> <span style="color: {warning_color};">{stats['warnings']}</span></p>
|
| 159 |
+
<p><strong>Operations:</strong> {stats['operations']}</p>
|
| 160 |
+
</div>
|
| 161 |
+
<div style="flex: 1;">
|
| 162 |
+
<p><strong>Uptime:</strong> {stats['uptime']}</p>
|
| 163 |
+
<p><strong>Tensor Issues:</strong> {stats['tensor_issues']}</p>
|
| 164 |
+
</div>
|
| 165 |
+
</div>
|
| 166 |
+
<div style="margin-top: 10px; border-top: 1px solid #ddd; padding-top: 10px;">
|
| 167 |
+
<p><strong>Last Error:</strong> {stats['last_error_time']} - {stats['last_error']}</p>
|
| 168 |
+
<p><strong>Last Warning:</strong> {stats['last_warning_time']} - {stats['last_warning']}</p>
|
| 169 |
+
</div>
|
| 170 |
+
</div>
|
| 171 |
+
"""
|
| 172 |
+
return html
|
| 173 |
|
| 174 |
# Function to log tensor info for debugging
|
| 175 |
def log_tensor_info(tensor, name="tensor"):
|
|
|
|
| 572 |
return error_msg
|
| 573 |
|
| 574 |
# Function to process PDF files
|
| 575 |
+
def process_pdf(pdf_path=None, pdf_file=None):
|
| 576 |
+
"""Process a PDF file and return a list of PIL images."""
|
| 577 |
try:
|
| 578 |
+
logger.info(f"Processing PDF: path={pdf_path}, file_upload={pdf_file is not None}")
|
|
|
|
| 579 |
|
| 580 |
+
if pdf_path is not None and os.path.exists(pdf_path):
|
| 581 |
+
# Log file details
|
| 582 |
+
file_size = os.path.getsize(pdf_path) / 1024 # KB
|
| 583 |
+
logger.info(f"PDF file details: path={pdf_path}, size={file_size:.2f} KB")
|
| 584 |
+
|
| 585 |
+
# Direct debug output to console to ensure visibility
|
| 586 |
+
print(f"[DEBUG] Processing PDF from path: {pdf_path}")
|
| 587 |
+
print(f"[DEBUG] File exists: {os.path.exists(pdf_path)}, Size: {file_size:.2f} KB")
|
| 588 |
|
| 589 |
+
# First try to use convert_from_path with detailed logging
|
| 590 |
try:
|
| 591 |
+
logger.debug(f"Converting PDF to images using convert_from_path: {pdf_path}")
|
| 592 |
+
with open(pdf_path, 'rb') as f:
|
| 593 |
+
file_content = f.read()
|
| 594 |
+
logger.debug(f"PDF file read: {len(file_content)} bytes")
|
| 595 |
+
|
| 596 |
+
# Log file header for validation
|
| 597 |
+
if len(file_content) >= 8:
|
| 598 |
+
header_hex = ' '.join([f'{b:02x}' for b in file_content[:8]])
|
| 599 |
+
logger.info(f"PDF header hex: {header_hex}")
|
| 600 |
+
print(f"[DEBUG] PDF header hex: {header_hex}")
|
| 601 |
+
|
| 602 |
+
# Check for valid PDF header
|
| 603 |
+
if not file_content.startswith(b'%PDF'):
|
| 604 |
+
logger.warning(f"File does not have PDF header: {pdf_path}")
|
| 605 |
+
print(f"[WARNING] File does not have PDF header: {pdf_path}")
|
| 606 |
+
|
| 607 |
images = convert_from_path(pdf_path)
|
| 608 |
+
logger.info(f"PDF converted successfully using convert_from_path: {len(images)} pages")
|
| 609 |
+
return images
|
| 610 |
+
except Exception as path_err:
|
| 611 |
+
logger.error(f"Error converting PDF using path method: {str(path_err)}")
|
| 612 |
logger.error(traceback.format_exc())
|
| 613 |
+
print(f"[ERROR] Convert from path failed: {str(path_err)}")
|
| 614 |
+
|
| 615 |
+
# Try fallback method - convert from bytes
|
| 616 |
try:
|
| 617 |
+
logger.debug("Falling back to convert_from_bytes method")
|
| 618 |
+
with open(pdf_path, 'rb') as pdf_file:
|
| 619 |
+
pdf_data = pdf_file.read()
|
| 620 |
+
logger.debug(f"Read {len(pdf_data)} bytes from PDF file")
|
| 621 |
+
|
| 622 |
+
images = convert_from_bytes(pdf_data)
|
| 623 |
+
logger.info(f"PDF converted successfully using convert_from_bytes: {len(images)} pages")
|
| 624 |
+
return images
|
| 625 |
+
except Exception as bytes_err:
|
| 626 |
+
logger.error(f"Error converting PDF using bytes method: {str(bytes_err)}")
|
| 627 |
logger.error(traceback.format_exc())
|
| 628 |
+
print(f"[ERROR] Convert from bytes also failed: {str(bytes_err)}")
|
| 629 |
raise
|
| 630 |
+
|
| 631 |
+
elif pdf_file is not None:
|
| 632 |
+
logger.info("Processing uploaded PDF file")
|
| 633 |
+
print(f"[DEBUG] Processing uploaded PDF file")
|
| 634 |
+
|
| 635 |
+
if hasattr(pdf_file, 'name'):
|
| 636 |
+
logger.debug(f"Uploaded PDF filename: {pdf_file.name}")
|
| 637 |
|
| 638 |
try:
|
| 639 |
+
# Creating a temporary file from the uploaded file
|
| 640 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as temp_file:
|
| 641 |
+
temp_file.write(pdf_file.read())
|
| 642 |
+
temp_path = temp_file.name
|
| 643 |
+
|
| 644 |
+
logger.debug(f"Created temporary file: {temp_path}")
|
| 645 |
+
print(f"[DEBUG] Created temp file: {temp_path}")
|
| 646 |
+
|
| 647 |
+
# Now convert from the temp file
|
| 648 |
+
images = convert_from_path(temp_path)
|
| 649 |
+
logger.info(f"PDF converted successfully: {len(images)} pages")
|
| 650 |
+
|
| 651 |
+
# Clean up
|
| 652 |
+
os.unlink(temp_path)
|
| 653 |
+
return images
|
| 654 |
+
except Exception as upload_err:
|
| 655 |
+
logger.error(f"Error processing uploaded PDF: {str(upload_err)}")
|
| 656 |
logger.error(traceback.format_exc())
|
| 657 |
+
print(f"[ERROR] Processing uploaded PDF failed: {str(upload_err)}")
|
| 658 |
+
raise
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 659 |
else:
|
| 660 |
+
error_msg = "No PDF file provided (both pdf_path and pdf_file are None or invalid)"
|
| 661 |
+
logger.error(error_msg)
|
| 662 |
+
print(f"[ERROR] {error_msg}")
|
|
|
|
|
|
|
|
|
|
| 663 |
return None
|
| 664 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 665 |
except Exception as e:
|
| 666 |
+
logger.error(f"Critical error in PDF processing: {str(e)}")
|
| 667 |
logger.error(traceback.format_exc())
|
| 668 |
+
print(f"[CRITICAL] PDF processing failed: {str(e)}")
|
| 669 |
+
print(traceback.format_exc())
|
| 670 |
+
|
| 671 |
+
# Update error statistics
|
| 672 |
+
gui_stats['errors'] += 1
|
| 673 |
+
gui_stats['last_error'] = f"PDF processing error: {str(e)}"
|
| 674 |
+
gui_stats['last_error_time'] = datetime.datetime.now().strftime("%H:%M:%S")
|
| 675 |
+
|
| 676 |
+
# Reraise for proper handling
|
| 677 |
+
raise
|
| 678 |
|
| 679 |
# Function to analyze images with a prompt
|
| 680 |
def analyze_with_prompt(image_input, prompt):
|
|
|
|
| 1564 |
|
| 1565 |
# Main function
|
| 1566 |
def main():
|
| 1567 |
+
# Create log handler for UI
|
| 1568 |
+
gui_log_handler = GUILogHandler(max_entries=500)
|
| 1569 |
+
gui_log_handler.setFormatter(logging.Formatter('%(asctime)s [%(levelname)s] %(message)s'))
|
| 1570 |
+
gui_log_handler.setLevel(logging.DEBUG)
|
| 1571 |
+
logger.addHandler(gui_log_handler)
|
| 1572 |
+
|
| 1573 |
+
# Log startup information
|
| 1574 |
+
logger.info("="*50)
|
| 1575 |
+
logger.info("InternVL2.5 Image Analyzer starting up")
|
| 1576 |
+
logger.info(f"Log file: {log_file}")
|
| 1577 |
+
logger.info(f"Python version: {sys.version}")
|
| 1578 |
+
logger.info(f"Torch version: {torch.__version__}")
|
| 1579 |
+
logger.info(f"CUDA available: {torch.cuda.is_available()}")
|
| 1580 |
+
if torch.cuda.is_available():
|
| 1581 |
+
logger.info(f"CUDA version: {torch.version.cuda}")
|
| 1582 |
+
logger.info(f"GPU: {torch.cuda.get_device_name(0)}")
|
| 1583 |
+
logger.info("="*50)
|
| 1584 |
+
|
| 1585 |
# Load the model
|
| 1586 |
model, tokenizer = load_model()
|
| 1587 |
|
|
|
|
| 1611 |
def get_debug_logs(num_lines=50):
|
| 1612 |
return gui_log_handler.get_logs(last_n=num_lines)
|
| 1613 |
|
| 1614 |
+
# Function to read the full log file
|
| 1615 |
+
def read_log_file():
|
| 1616 |
+
try:
|
| 1617 |
+
with open(latest_log, 'r') as f:
|
| 1618 |
+
return f.read()
|
| 1619 |
+
except Exception as e:
|
| 1620 |
+
return f"Error reading log file: {str(e)}"
|
| 1621 |
+
|
| 1622 |
# Function to update logs in real-time
|
| 1623 |
def update_logs(history):
|
| 1624 |
latest = gui_log_handler.get_latest()
|
|
|
|
| 1640 |
gr.Markdown("# InternVL2.5 Image Analyzer")
|
| 1641 |
gr.Markdown("Analyze images using the InternVL2.5 model. You can upload individual images or analyze all images in a folder.")
|
| 1642 |
|
| 1643 |
+
# Direct logs view tab
|
| 1644 |
+
with gr.Tab("Logs View"):
|
| 1645 |
+
gr.Markdown("## View Application Logs")
|
| 1646 |
+
gr.Markdown("This tab displays the complete application logs for debugging purposes.")
|
| 1647 |
+
|
| 1648 |
+
with gr.Row():
|
| 1649 |
+
with gr.Column(scale=4):
|
| 1650 |
+
full_logs = gr.Textbox(
|
| 1651 |
+
label="Full Log File",
|
| 1652 |
+
value=read_log_file(),
|
| 1653 |
+
lines=25,
|
| 1654 |
+
max_lines=30,
|
| 1655 |
+
autoscroll=False
|
| 1656 |
+
)
|
| 1657 |
+
with gr.Column(scale=1):
|
| 1658 |
+
refresh_logs_btn = gr.Button("Refresh Logs")
|
| 1659 |
+
log_info = gr.Markdown(f"Log file location: {latest_log}")
|
| 1660 |
+
|
| 1661 |
+
# Stats display
|
| 1662 |
+
stats_html = gr.HTML(format_debug_stats_html())
|
| 1663 |
+
|
| 1664 |
+
# Function to handle automatic log refresh
|
| 1665 |
+
def refresh_logs():
|
| 1666 |
+
return read_log_file(), format_debug_stats_html()
|
| 1667 |
+
|
| 1668 |
+
refresh_logs_btn.click(
|
| 1669 |
+
fn=refresh_logs,
|
| 1670 |
+
inputs=[],
|
| 1671 |
+
outputs=[full_logs, stats_html]
|
| 1672 |
+
)
|
| 1673 |
+
|
| 1674 |
+
# Auto-refresh logs every 10 seconds
|
| 1675 |
+
gr.on(
|
| 1676 |
+
triggers=[],
|
| 1677 |
+
fn=refresh_logs,
|
| 1678 |
+
inputs=[],
|
| 1679 |
+
outputs=[full_logs, stats_html],
|
| 1680 |
+
every=10
|
| 1681 |
+
)
|
| 1682 |
+
|
| 1683 |
+
# Options for log files
|
| 1684 |
+
log_files = [f for f in os.listdir(LOGS_DIR) if f.endswith('.log')]
|
| 1685 |
+
log_dropdown = gr.Dropdown(
|
| 1686 |
+
label="Available Log Files",
|
| 1687 |
+
choices=log_files,
|
| 1688 |
+
value="latest_debug.log" if "latest_debug.log" in log_files else None
|
| 1689 |
+
)
|
| 1690 |
+
|
| 1691 |
+
# Function to load a specific log file
|
| 1692 |
+
def load_log_file(filename):
|
| 1693 |
+
if not filename:
|
| 1694 |
+
return "No log file selected"
|
| 1695 |
+
|
| 1696 |
+
try:
|
| 1697 |
+
with open(os.path.join(LOGS_DIR, filename), 'r') as f:
|
| 1698 |
+
return f.read()
|
| 1699 |
+
except Exception as e:
|
| 1700 |
+
return f"Error reading {filename}: {str(e)}"
|
| 1701 |
+
|
| 1702 |
+
log_dropdown.change(
|
| 1703 |
+
fn=load_log_file,
|
| 1704 |
+
inputs=[log_dropdown],
|
| 1705 |
+
outputs=[full_logs]
|
| 1706 |
+
)
|
| 1707 |
+
|
| 1708 |
+
# Download log file button
|
| 1709 |
+
def get_current_log_file(filename):
|
| 1710 |
+
if not filename:
|
| 1711 |
+
return None
|
| 1712 |
+
|
| 1713 |
+
log_path = os.path.join(LOGS_DIR, filename)
|
| 1714 |
+
if os.path.exists(log_path):
|
| 1715 |
+
return log_path
|
| 1716 |
+
return None
|
| 1717 |
+
|
| 1718 |
+
download_log_btn = gr.Button("Download Selected Log")
|
| 1719 |
+
log_file_download = gr.File(label="Log File for Download")
|
| 1720 |
+
|
| 1721 |
+
download_log_btn.click(
|
| 1722 |
+
fn=get_current_log_file,
|
| 1723 |
+
inputs=[log_dropdown],
|
| 1724 |
+
outputs=[log_file_download]
|
| 1725 |
+
)
|
| 1726 |
+
|
| 1727 |
# Debug mode toggle and panel
|
| 1728 |
with gr.Accordion("Debug Console", open=False) as debug_accordion:
|
| 1729 |
with gr.Row():
|