Spaces:
Running
Running
UI improvements: Remove confidence scores from display, make Document Preview collapsible, simplify HTML output formatting
Browse files- app.py +75 -87
- process_file.py +2 -5
- structured_ocr.py +2 -5
app.py
CHANGED
@@ -364,8 +364,8 @@ with main_tab2:
|
|
364 |
else:
|
365 |
st.subheader("Previously Processed Documents")
|
366 |
|
367 |
-
# Display previous results in a selectable list
|
368 |
-
previous_files = [f"{i+1}. {result.get('file_name', 'Document')}
|
369 |
for i, result in enumerate(st.session_state.previous_results)]
|
370 |
|
371 |
selected_index = st.selectbox("Select a previous document:",
|
@@ -385,9 +385,7 @@ with main_tab2:
|
|
385 |
with prev_tabs[0]:
|
386 |
st.write(f"**File:** {selected_result.get('file_name', 'Document')}")
|
387 |
|
388 |
-
#
|
389 |
-
confidence = selected_result.get('confidence_score', 0.85)
|
390 |
-
st.write(f"**OCR Confidence:** {confidence:.1%}")
|
391 |
|
392 |
# Show languages if available
|
393 |
if 'languages' in selected_result and selected_result['languages']:
|
@@ -551,78 +549,77 @@ with main_tab1:
|
|
551 |
# Preview column
|
552 |
with col2:
|
553 |
if uploaded_file is not None:
|
554 |
-
st.
|
555 |
-
|
556 |
-
file_ext = Path(uploaded_file.name).suffix.lower()
|
557 |
-
|
558 |
-
# Show preview tabs for original and processed (if applicable)
|
559 |
-
if uploaded_file.type and uploaded_file.type.startswith('image/'):
|
560 |
-
# For image files
|
561 |
-
preview_tabs = st.tabs(["Original"])
|
562 |
|
563 |
-
# Show original
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
if image:
|
568 |
-
# Display with controlled size
|
569 |
-
st.image(image, caption=uploaded_file.name, width=400)
|
570 |
-
else:
|
571 |
-
st.info("Image preview not available")
|
572 |
-
except Exception:
|
573 |
-
st.info("Image preview could not be displayed")
|
574 |
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
st.subheader("Preprocessing Preview")
|
579 |
-
|
580 |
-
try:
|
581 |
-
# Process the image with selected options
|
582 |
-
processed_bytes = preprocess_image(uploaded_file.getvalue(), preprocessing_options)
|
583 |
-
processed_image = safe_open_image(processed_bytes)
|
584 |
-
|
585 |
-
# Show before/after in columns
|
586 |
-
col1, col2 = st.columns(2)
|
587 |
-
|
588 |
-
with col1:
|
589 |
-
st.write("**Original**")
|
590 |
image = safe_open_image(uploaded_file.getvalue())
|
591 |
if image:
|
592 |
-
|
593 |
-
|
594 |
-
with col2:
|
595 |
-
st.write("**Processed**")
|
596 |
-
if processed_image:
|
597 |
-
st.image(processed_image, width=300)
|
598 |
else:
|
599 |
-
st.info("
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
elif file_ext == ".pdf":
|
604 |
-
# For PDF files
|
605 |
-
try:
|
606 |
-
# Convert first page of PDF to image
|
607 |
-
pdf_bytes = uploaded_file.getvalue()
|
608 |
-
|
609 |
-
with st.spinner("Generating PDF preview..."):
|
610 |
-
images = convert_from_bytes(pdf_bytes, first_page=1, last_page=1, dpi=150)
|
611 |
|
612 |
-
if
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
first_page.save(img_bytes, format='JPEG')
|
617 |
-
img_bytes.seek(0)
|
618 |
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
626 |
|
627 |
# Results section - spans full width
|
628 |
if 'process_button' in locals() and process_button:
|
@@ -656,9 +653,7 @@ with main_tab1:
|
|
656 |
# Display file info
|
657 |
st.write(f"**File:** {result.get('file_name', uploaded_file.name)}")
|
658 |
|
659 |
-
#
|
660 |
-
confidence = result.get('confidence_score', 0.85)
|
661 |
-
st.write(f"**OCR Confidence:** {confidence:.1%}")
|
662 |
|
663 |
# Show languages if available
|
664 |
if 'languages' in result and result['languages']:
|
@@ -705,10 +700,9 @@ with main_tab1:
|
|
705 |
if isinstance(item, str):
|
706 |
st.markdown(f"* {item}")
|
707 |
elif isinstance(item, dict):
|
708 |
-
# Create formatted display for dictionary items instead of raw JSON
|
709 |
-
|
710 |
-
|
711 |
-
st.markdown(f"**{k}:** {v}")
|
712 |
elif isinstance(content, dict):
|
713 |
# Special handling for poem type
|
714 |
if 'type' in content and content['type'] == 'poem' and 'lines' in content:
|
@@ -812,16 +806,10 @@ with main_tab1:
|
|
812 |
if isinstance(item, str):
|
813 |
html_content += f'<li>{item}</li>\n'
|
814 |
elif isinstance(item, dict):
|
815 |
-
# Format dictionary items in the list
|
816 |
-
|
817 |
-
|
818 |
-
html_content += f'<
|
819 |
-
html_content += '<dl>\n'
|
820 |
-
for k, v in item.items():
|
821 |
-
html_content += f'<dt>{k}</dt>\n<dd>{v}</dd>\n'
|
822 |
-
html_content += '</dl>\n'
|
823 |
-
html_content += '</details>\n'
|
824 |
-
html_content += '</li>\n'
|
825 |
else:
|
826 |
html_content += f'<li>{str(item)}</li>\n'
|
827 |
html_content += '</ul>\n'
|
|
|
364 |
else:
|
365 |
st.subheader("Previously Processed Documents")
|
366 |
|
367 |
+
# Display previous results in a selectable list
|
368 |
+
previous_files = [f"{i+1}. {result.get('file_name', 'Document')}"
|
369 |
for i, result in enumerate(st.session_state.previous_results)]
|
370 |
|
371 |
selected_index = st.selectbox("Select a previous document:",
|
|
|
385 |
with prev_tabs[0]:
|
386 |
st.write(f"**File:** {selected_result.get('file_name', 'Document')}")
|
387 |
|
388 |
+
# Remove confidence score from display
|
|
|
|
|
389 |
|
390 |
# Show languages if available
|
391 |
if 'languages' in selected_result and selected_result['languages']:
|
|
|
549 |
# Preview column
|
550 |
with col2:
|
551 |
if uploaded_file is not None:
|
552 |
+
with st.expander("Document Preview", expanded=False):
|
553 |
+
file_ext = Path(uploaded_file.name).suffix.lower()
|
|
|
|
|
|
|
|
|
|
|
|
|
554 |
|
555 |
+
# Show preview tabs for original and processed (if applicable)
|
556 |
+
if uploaded_file.type and uploaded_file.type.startswith('image/'):
|
557 |
+
# For image files
|
558 |
+
preview_tabs = st.tabs(["Original"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
559 |
|
560 |
+
# Show original image preview
|
561 |
+
with preview_tabs[0]:
|
562 |
+
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
563 |
image = safe_open_image(uploaded_file.getvalue())
|
564 |
if image:
|
565 |
+
# Display with controlled size
|
566 |
+
st.image(image, caption=uploaded_file.name, width=400)
|
|
|
|
|
|
|
|
|
567 |
else:
|
568 |
+
st.info("Image preview not available")
|
569 |
+
except Exception:
|
570 |
+
st.info("Image preview could not be displayed")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
571 |
|
572 |
+
# Add processed preview if preprocessing options are selected
|
573 |
+
if any(preprocessing_options.values()):
|
574 |
+
# Create a before-after comparison
|
575 |
+
st.subheader("Preprocessing Preview")
|
|
|
|
|
576 |
|
577 |
+
try:
|
578 |
+
# Process the image with selected options
|
579 |
+
processed_bytes = preprocess_image(uploaded_file.getvalue(), preprocessing_options)
|
580 |
+
processed_image = safe_open_image(processed_bytes)
|
581 |
+
|
582 |
+
# Show before/after in columns
|
583 |
+
col1, col2 = st.columns(2)
|
584 |
+
|
585 |
+
with col1:
|
586 |
+
st.write("**Original**")
|
587 |
+
image = safe_open_image(uploaded_file.getvalue())
|
588 |
+
if image:
|
589 |
+
st.image(image, width=300)
|
590 |
+
|
591 |
+
with col2:
|
592 |
+
st.write("**Processed**")
|
593 |
+
if processed_image:
|
594 |
+
st.image(processed_image, width=300)
|
595 |
+
else:
|
596 |
+
st.info("Processed preview not available")
|
597 |
+
except Exception:
|
598 |
+
st.info("Preprocessing preview could not be generated")
|
599 |
+
|
600 |
+
elif file_ext == ".pdf":
|
601 |
+
# For PDF files
|
602 |
+
try:
|
603 |
+
# Convert first page of PDF to image
|
604 |
+
pdf_bytes = uploaded_file.getvalue()
|
605 |
+
|
606 |
+
with st.spinner("Generating PDF preview..."):
|
607 |
+
images = convert_from_bytes(pdf_bytes, first_page=1, last_page=1, dpi=150)
|
608 |
+
|
609 |
+
if images:
|
610 |
+
# Convert to JPEG for display
|
611 |
+
first_page = images[0]
|
612 |
+
img_bytes = io.BytesIO()
|
613 |
+
first_page.save(img_bytes, format='JPEG')
|
614 |
+
img_bytes.seek(0)
|
615 |
+
|
616 |
+
# Display preview
|
617 |
+
st.image(img_bytes, caption=f"PDF Preview: {uploaded_file.name}", width=400)
|
618 |
+
st.info(f"PDF document with {len(convert_from_bytes(pdf_bytes, dpi=100))} pages")
|
619 |
+
else:
|
620 |
+
st.info(f"PDF preview not available: {uploaded_file.name}")
|
621 |
+
except Exception:
|
622 |
+
st.info(f"PDF preview could not be displayed: {uploaded_file.name}")
|
623 |
|
624 |
# Results section - spans full width
|
625 |
if 'process_button' in locals() and process_button:
|
|
|
653 |
# Display file info
|
654 |
st.write(f"**File:** {result.get('file_name', uploaded_file.name)}")
|
655 |
|
656 |
+
# Remove confidence score from display
|
|
|
|
|
657 |
|
658 |
# Show languages if available
|
659 |
if 'languages' in result and result['languages']:
|
|
|
700 |
if isinstance(item, str):
|
701 |
st.markdown(f"* {item}")
|
702 |
elif isinstance(item, dict):
|
703 |
+
# Create formatted text display for dictionary items instead of raw JSON
|
704 |
+
st.markdown(f"* **{list(item.keys())[0] if item else 'Item'}**: " +
|
705 |
+
", ".join([f"{k}: {v}" for k, v in item.items()]))
|
|
|
706 |
elif isinstance(content, dict):
|
707 |
# Special handling for poem type
|
708 |
if 'type' in content and content['type'] == 'poem' and 'lines' in content:
|
|
|
806 |
if isinstance(item, str):
|
807 |
html_content += f'<li>{item}</li>\n'
|
808 |
elif isinstance(item, dict):
|
809 |
+
# Format dictionary items in the list as simple text
|
810 |
+
key_item = list(item.keys())[0] if item else "Item"
|
811 |
+
value_text = ", ".join([f"{k}: {v}" for k, v in item.items()])
|
812 |
+
html_content += f'<li><strong>{key_item}</strong>: {value_text}</li>\n'
|
|
|
|
|
|
|
|
|
|
|
|
|
813 |
else:
|
814 |
html_content += f'<li>{str(item)}</li>\n'
|
815 |
html_content += '</ul>\n'
|
process_file.py
CHANGED
@@ -54,16 +54,13 @@ def process_file(uploaded_file, use_vision=True, processor=None, custom_prompt=N
|
|
54 |
"use_vision": use_vision
|
55 |
})
|
56 |
|
57 |
-
#
|
58 |
-
if 'confidence_score' not in result:
|
59 |
-
result['confidence_score'] = 0.85
|
60 |
|
61 |
return result
|
62 |
except Exception as e:
|
63 |
return {
|
64 |
"error": str(e),
|
65 |
-
"file_name": uploaded_file.name
|
66 |
-
"confidence_score": 0.85 # Add default confidence score even to error results
|
67 |
}
|
68 |
finally:
|
69 |
# Clean up the temporary file
|
|
|
54 |
"use_vision": use_vision
|
55 |
})
|
56 |
|
57 |
+
# No longer needed - removing confidence score
|
|
|
|
|
58 |
|
59 |
return result
|
60 |
except Exception as e:
|
61 |
return {
|
62 |
"error": str(e),
|
63 |
+
"file_name": uploaded_file.name
|
|
|
64 |
}
|
65 |
finally:
|
66 |
# Clean up the temporary file
|
structured_ocr.py
CHANGED
@@ -308,8 +308,7 @@ class StructuredOCR:
|
|
308 |
'total': total_pages
|
309 |
}
|
310 |
|
311 |
-
#
|
312 |
-
result['confidence_score'] = confidence_score
|
313 |
|
314 |
# Store key parts of the OCR response for image rendering
|
315 |
# First store the raw response for backwards compatibility
|
@@ -515,8 +514,7 @@ class StructuredOCR:
|
|
515 |
logger.info(f"Using text-only model: {TEXT_MODEL}")
|
516 |
result = self._extract_structured_data_text_only(image_ocr_markdown, file_path.name, custom_prompt)
|
517 |
|
518 |
-
#
|
519 |
-
result['confidence_score'] = confidence_score
|
520 |
|
521 |
# Store key parts of the OCR response for image rendering
|
522 |
# First store the raw response for backwards compatibility
|
@@ -555,7 +553,6 @@ class StructuredOCR:
|
|
555 |
"file_name": file_path.name,
|
556 |
"topics": ["Document"],
|
557 |
"languages": ["English"],
|
558 |
-
"confidence_score": 0.0,
|
559 |
"error": str(e),
|
560 |
"ocr_contents": {
|
561 |
"error": f"Failed to process image: {str(e)}",
|
|
|
308 |
'total': total_pages
|
309 |
}
|
310 |
|
311 |
+
# Remove confidence score from results
|
|
|
312 |
|
313 |
# Store key parts of the OCR response for image rendering
|
314 |
# First store the raw response for backwards compatibility
|
|
|
514 |
logger.info(f"Using text-only model: {TEXT_MODEL}")
|
515 |
result = self._extract_structured_data_text_only(image_ocr_markdown, file_path.name, custom_prompt)
|
516 |
|
517 |
+
# Remove confidence score from results
|
|
|
518 |
|
519 |
# Store key parts of the OCR response for image rendering
|
520 |
# First store the raw response for backwards compatibility
|
|
|
553 |
"file_name": file_path.name,
|
554 |
"topics": ["Document"],
|
555 |
"languages": ["English"],
|
|
|
556 |
"error": str(e),
|
557 |
"ocr_contents": {
|
558 |
"error": f"Failed to process image: {str(e)}",
|