Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -4,11 +4,23 @@ import os
|
|
4 |
import sys
|
5 |
import subprocess
|
6 |
import logging
|
7 |
-
import copy
|
8 |
|
9 |
-
# --- Step 0: Setup Logging
|
10 |
-
|
11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
logger = setup_logging() # Get the configured logger
|
13 |
|
14 |
logger.info("--- RadVision AI Application Start ---")
|
@@ -17,11 +29,12 @@ logger.info(f"Logging Level: {LOG_LEVEL}")
|
|
17 |
|
18 |
# --- Step 1: Handle Core Dependencies and Availability ---
|
19 |
# Try importing essential libraries and set availability flags
|
|
|
|
|
20 |
|
21 |
# Deep Translator (Attempt install if missing)
|
22 |
try:
|
23 |
from deep_translator import GoogleTranslator
|
24 |
-
# Also try importing our translation wrapper
|
25 |
from translation_models import translate, detect_language, LANGUAGE_CODES, AUTO_DETECT_INDICATOR
|
26 |
TRANSLATION_AVAILABLE = True
|
27 |
logger.info("Deep Translator and translation_models imported successfully.")
|
@@ -30,15 +43,14 @@ except ImportError:
|
|
30 |
try:
|
31 |
subprocess.check_call([sys.executable, "-m", "pip", "install", "deep-translator"])
|
32 |
from deep_translator import GoogleTranslator
|
33 |
-
# Re-try importing our wrapper after install
|
34 |
from translation_models import translate, detect_language, LANGUAGE_CODES, AUTO_DETECT_INDICATOR
|
35 |
TRANSLATION_AVAILABLE = True
|
36 |
logger.info("Successfully installed and imported deep-translator and translation_models.")
|
37 |
except Exception as e:
|
38 |
logger.error(f"CRITICAL: Failed to install/import deep-translator or translation_models: {e}", exc_info=True)
|
39 |
-
|
|
|
40 |
TRANSLATION_AVAILABLE = False
|
41 |
-
# Define fallbacks if translation module failed
|
42 |
translate = None
|
43 |
detect_language = None
|
44 |
LANGUAGE_CODES = {"English": "en"}
|
@@ -51,7 +63,7 @@ try:
|
|
51 |
DRAWABLE_CANVAS_AVAILABLE = True
|
52 |
logger.info(f"Streamlit Drawable Canvas Version: {CANVAS_VERSION} available.")
|
53 |
except ImportError:
|
54 |
-
st.error("CRITICAL ERROR: streamlit-drawable-canvas is not installed. ROI drawing disabled. Run `pip install streamlit-drawable-canvas`.")
|
55 |
logger.critical("streamlit-drawable-canvas not found. ROI functionality disabled.")
|
56 |
DRAWABLE_CANVAS_AVAILABLE = False
|
57 |
|
@@ -62,13 +74,12 @@ try:
|
|
62 |
PIL_VERSION = getattr(PIL, '__version__', 'Unknown')
|
63 |
PIL_AVAILABLE = True
|
64 |
logger.info(f"Pillow (PIL) Version: {PIL_VERSION} available.")
|
65 |
-
# Make PIL Image available to utils module if needed
|
66 |
import utils
|
67 |
utils.Image = Image
|
68 |
except ImportError:
|
69 |
-
|
70 |
logger.critical("Pillow (PIL) not found. Application cannot function correctly.")
|
71 |
-
|
72 |
st.stop() # Stop execution if PIL is missing
|
73 |
|
74 |
# Pydicom and related libraries
|
@@ -78,19 +89,16 @@ try:
|
|
78 |
PYDICOM_VERSION = getattr(pydicom, '__version__', 'Unknown')
|
79 |
PYDICOM_AVAILABLE = True
|
80 |
logger.info(f"Pydicom Version: {PYDICOM_VERSION} available.")
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
except ImportError: logger.info("
|
85 |
-
try:
|
86 |
-
import gdcm; logger.info("python-gdcm found (for improved DICOM compatibility).")
|
87 |
-
except ImportError: logger.info("python-gdcm not found. Some DICOM features might be limited.")
|
88 |
except ImportError:
|
89 |
PYDICOM_AVAILABLE = False
|
90 |
PYDICOM_VERSION = 'Not Installed'
|
91 |
logger.warning("pydicom not found. DICOM file support will be disabled.")
|
92 |
-
pydicom =
|
93 |
-
|
94 |
|
95 |
# Custom Utilities & Backend Modules
|
96 |
try:
|
@@ -100,38 +108,43 @@ try:
|
|
100 |
except ImportError as e:
|
101 |
logger.error(f"Failed to import dicom_utils: {e}. DICOM specific features disabled.", exc_info=True)
|
102 |
DICOM_UTILS_AVAILABLE = False
|
103 |
-
if PYDICOM_AVAILABLE:
|
104 |
-
st.warning("DICOM processing utilities (dicom_utils.py) not found. DICOM handling may be limited.")
|
105 |
-
|
106 |
-
try:
|
107 |
-
from llm_interactions import run_initial_analysis, run_multimodal_qa, run_disease_analysis, estimate_ai_confidence
|
108 |
-
LLM_INTERACTIONS_AVAILABLE = True
|
109 |
-
logger.info("llm_interactions imported successfully.")
|
110 |
-
except ImportError as e:
|
111 |
-
st.error(f"Core AI module (llm_interactions.py) failed to import: {e}. Analysis functions disabled.")
|
112 |
-
logger.critical(f"Failed to import llm_interactions: {e}", exc_info=True)
|
113 |
-
LLM_INTERACTIONS_AVAILABLE = False
|
114 |
-
# Consider st.stop() if core AI is essential and fails to load
|
115 |
-
# st.stop()
|
116 |
|
117 |
try:
|
|
|
118 |
from report_utils import generate_pdf_report_bytes
|
119 |
REPORT_UTILS_AVAILABLE = True
|
120 |
logger.info("report_utils imported successfully.")
|
121 |
except ImportError as e:
|
122 |
logger.error(f"Failed to import report_utils: {e}. PDF reporting disabled.", exc_info=True)
|
123 |
REPORT_UTILS_AVAILABLE = False
|
124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
|
126 |
try:
|
127 |
from ui_components import display_dicom_metadata, dicom_wl_sliders
|
128 |
UI_COMPONENTS_AVAILABLE = True
|
129 |
logger.info("ui_components imported successfully.")
|
130 |
except ImportError as e:
|
131 |
-
logger.warning(f"Failed to import ui_components: {e}. Custom UI elements
|
132 |
UI_COMPONENTS_AVAILABLE = False
|
133 |
|
134 |
-
|
135 |
# HF Fallback Models (Optional)
|
136 |
try:
|
137 |
from hf_models import query_hf_vqa_inference_api, HF_VQA_MODEL_ID
|
@@ -142,34 +155,24 @@ except ImportError:
|
|
142 |
HF_MODELS_AVAILABLE = False
|
143 |
logger.warning("hf_models not found or failed to import. Fallback VQA disabled.")
|
144 |
|
145 |
-
|
|
|
146 |
import config
|
|
|
147 |
config.DRAWABLE_CANVAS_AVAILABLE = DRAWABLE_CANVAS_AVAILABLE
|
148 |
-
|
149 |
-
config.
|
150 |
-
config.DICOM_UTILS_AVAILABLE = DICOM_UTILS_AVAILABLE
|
151 |
-
config.LLM_INTERACTIONS_AVAILABLE = LLM_INTERACTIONS_AVAILABLE
|
152 |
-
config.REPORT_UTILS_AVAILABLE = REPORT_UTILS_AVAILABLE
|
153 |
-
config.UI_COMPONENTS_AVAILABLE = UI_COMPONENTS_AVAILABLE
|
154 |
-
config.HF_MODELS_AVAILABLE = HF_MODELS_AVAILABLE
|
155 |
-
config.TRANSLATION_AVAILABLE = TRANSLATION_AVAILABLE
|
156 |
-
|
157 |
|
158 |
# --- Step 2: Configure Streamlit Page ---
|
159 |
-
|
160 |
-
page_title=APP_TITLE,
|
161 |
-
layout=LAYOUT,
|
162 |
-
page_icon=FAVICON,
|
163 |
-
initial_sidebar_state=INITIAL_SIDEBAR_STATE
|
164 |
-
)
|
165 |
|
166 |
# Apply Custom CSS
|
167 |
st.markdown(CUSTOM_CSS, unsafe_allow_html=True)
|
168 |
|
169 |
# --- Step 3: Apply Monkey Patches (Conditional) ---
|
170 |
import streamlit.elements.image as st_image
|
171 |
-
import utils
|
172 |
-
utils.apply_image_to_url_monkey_patch(st_image)
|
173 |
|
174 |
# --- Step 4: Initialize Session State ---
|
175 |
from state import initialize_session_state
|
@@ -178,15 +181,12 @@ logger.debug(f"Session state verified/initialized for session ID: {st.session_st
|
|
178 |
|
179 |
# --- Step 5: Display Logo ---
|
180 |
if os.path.exists(LOGO_PATH):
|
181 |
-
|
182 |
-
logo_col, _ = st.columns([1, 3]) # Adjust ratio as needed
|
183 |
with logo_col:
|
184 |
-
st.image(LOGO_PATH, width=300)
|
185 |
else:
|
186 |
logger.warning(f"Hero logo not found at: {LOGO_PATH}")
|
187 |
-
#
|
188 |
-
# st.warning("RadVision AI Logo missing.")
|
189 |
-
|
190 |
|
191 |
# --- Step 6: Render Sidebar and Get Uploaded File ---
|
192 |
from ui import render_sidebar
|
@@ -194,20 +194,17 @@ uploaded_file = render_sidebar(
|
|
194 |
IS_DICOM=st.session_state.get("is_dicom", False),
|
195 |
UI_COMPONENTS_AVAILABLE=UI_COMPONENTS_AVAILABLE,
|
196 |
DICOM_UTILS_AVAILABLE=DICOM_UTILS_AVAILABLE,
|
197 |
-
REPORT_UTILS_AVAILABLE=REPORT_UTILS_AVAILABLE
|
198 |
)
|
199 |
|
200 |
-
|
201 |
# --- Step 7: Handle File Upload Processing ---
|
202 |
from file_handler import process_uploaded_file
|
203 |
-
# Pass availability flags needed by the handler
|
204 |
process_uploaded_file(uploaded_file, PYDICOM_AVAILABLE, DICOM_UTILS_AVAILABLE, PIL_AVAILABLE)
|
205 |
|
206 |
# --- Step 8: Render Main Page Content ---
|
207 |
st.markdown("---")
|
208 |
st.title(f"⚕️ {APP_TITLE}: AI-Assisted Image Analysis")
|
209 |
|
210 |
-
# User Guide/Disclaimer Expander
|
211 |
with st.expander("User Guide & Disclaimer", expanded=False):
|
212 |
st.warning("⚠️ **Disclaimer**: This tool is for research/educational purposes only and is **NOT** a substitute for professional medical advice or diagnosis.")
|
213 |
st.markdown("""
|
@@ -223,13 +220,12 @@ with st.expander("User Guide & Disclaimer", expanded=False):
|
|
223 |
6. **Review Results**: Check the tabs ('Initial Analysis', 'Q&A History', 'Condition Focus') for AI output.
|
224 |
7. **(Optional) Translation**: Use the 'Translation' tab to translate AI-generated text.
|
225 |
8. **(Optional) Confidence**: Use the 'Estimate AI Confidence' button (sidebar) after analysis.
|
226 |
-
9. **(Optional) Report**: Click 'Generate PDF Report Data' (sidebar) and then 'Download PDF Report' to save a summary.
|
227 |
-
""")
|
228 |
|
229 |
st.markdown("---")
|
230 |
|
231 |
-
|
232 |
-
col1, col2 = st.columns([2, 3]) # Image column wider slightly
|
233 |
|
234 |
with col1:
|
235 |
from ui import render_image_viewer
|
@@ -243,7 +239,6 @@ with col1:
|
|
243 |
|
244 |
with col2:
|
245 |
from ui import render_results_tabs
|
246 |
-
# Pass the actual translation function if available
|
247 |
translate_func = translate if TRANSLATION_AVAILABLE else None
|
248 |
render_results_tabs(
|
249 |
TRANSLATION_SERVICE_AVAILABLE=TRANSLATION_AVAILABLE,
|
@@ -251,11 +246,11 @@ with col2:
|
|
251 |
)
|
252 |
|
253 |
# --- Step 9: Handle Button Actions ---
|
254 |
-
# This logic is now encapsulated in actions.py
|
255 |
from actions import handle_actions
|
|
|
|
|
256 |
handle_actions(LLM_INTERACTIONS_AVAILABLE, REPORT_UTILS_AVAILABLE)
|
257 |
|
258 |
-
|
259 |
# --- Step 10: Render Footer ---
|
260 |
from ui import render_footer
|
261 |
render_footer(st.session_state.get("session_id"))
|
|
|
4 |
import sys
|
5 |
import subprocess
|
6 |
import logging
|
7 |
+
import copy
|
8 |
|
9 |
+
# --- Step 0: Setup Logging and Page Config EARLY ---
|
10 |
+
from config import (
|
11 |
+
setup_logging, LOG_LEVEL, APP_TITLE, FAVICON, LAYOUT,
|
12 |
+
INITIAL_SIDEBAR_STATE, CUSTOM_CSS, LOGO_PATH, FOOTER_HTML
|
13 |
+
)
|
14 |
+
|
15 |
+
# !!! IMPORTANT: Set page config as the VERY FIRST Streamlit command !!!
|
16 |
+
st.set_page_config(
|
17 |
+
page_title=APP_TITLE,
|
18 |
+
layout=LAYOUT,
|
19 |
+
page_icon=FAVICON,
|
20 |
+
initial_sidebar_state=INITIAL_SIDEBAR_STATE
|
21 |
+
)
|
22 |
+
|
23 |
+
# Now, setup logging
|
24 |
logger = setup_logging() # Get the configured logger
|
25 |
|
26 |
logger.info("--- RadVision AI Application Start ---")
|
|
|
29 |
|
30 |
# --- Step 1: Handle Core Dependencies and Availability ---
|
31 |
# Try importing essential libraries and set availability flags
|
32 |
+
# (Error/Warning messages using st.* inside these blocks are now OK,
|
33 |
+
# because set_page_config has already run)
|
34 |
|
35 |
# Deep Translator (Attempt install if missing)
|
36 |
try:
|
37 |
from deep_translator import GoogleTranslator
|
|
|
38 |
from translation_models import translate, detect_language, LANGUAGE_CODES, AUTO_DETECT_INDICATOR
|
39 |
TRANSLATION_AVAILABLE = True
|
40 |
logger.info("Deep Translator and translation_models imported successfully.")
|
|
|
43 |
try:
|
44 |
subprocess.check_call([sys.executable, "-m", "pip", "install", "deep-translator"])
|
45 |
from deep_translator import GoogleTranslator
|
|
|
46 |
from translation_models import translate, detect_language, LANGUAGE_CODES, AUTO_DETECT_INDICATOR
|
47 |
TRANSLATION_AVAILABLE = True
|
48 |
logger.info("Successfully installed and imported deep-translator and translation_models.")
|
49 |
except Exception as e:
|
50 |
logger.error(f"CRITICAL: Failed to install/import deep-translator or translation_models: {e}", exc_info=True)
|
51 |
+
# Display warning in the UI now that set_page_config has run
|
52 |
+
st.warning("Translation features are disabled: Could not load or install 'deep-translator'. See logs for details.")
|
53 |
TRANSLATION_AVAILABLE = False
|
|
|
54 |
translate = None
|
55 |
detect_language = None
|
56 |
LANGUAGE_CODES = {"English": "en"}
|
|
|
63 |
DRAWABLE_CANVAS_AVAILABLE = True
|
64 |
logger.info(f"Streamlit Drawable Canvas Version: {CANVAS_VERSION} available.")
|
65 |
except ImportError:
|
66 |
+
st.error("CRITICAL ERROR: `streamlit-drawable-canvas` is not installed. ROI drawing is disabled. Run `pip install streamlit-drawable-canvas`.")
|
67 |
logger.critical("streamlit-drawable-canvas not found. ROI functionality disabled.")
|
68 |
DRAWABLE_CANVAS_AVAILABLE = False
|
69 |
|
|
|
74 |
PIL_VERSION = getattr(PIL, '__version__', 'Unknown')
|
75 |
PIL_AVAILABLE = True
|
76 |
logger.info(f"Pillow (PIL) Version: {PIL_VERSION} available.")
|
|
|
77 |
import utils
|
78 |
utils.Image = Image
|
79 |
except ImportError:
|
80 |
+
# This error is critical, stop the app
|
81 |
logger.critical("Pillow (PIL) not found. Application cannot function correctly.")
|
82 |
+
st.error("CRITICAL ERROR: Pillow (PIL) is not installed. Image handling is disabled. Run `pip install Pillow`.")
|
83 |
st.stop() # Stop execution if PIL is missing
|
84 |
|
85 |
# Pydicom and related libraries
|
|
|
89 |
PYDICOM_VERSION = getattr(pydicom, '__version__', 'Unknown')
|
90 |
PYDICOM_AVAILABLE = True
|
91 |
logger.info(f"Pydicom Version: {PYDICOM_VERSION} available.")
|
92 |
+
try: import pylibjpeg; logger.info("pylibjpeg found.")
|
93 |
+
except ImportError: logger.info("pylibjpeg not found.")
|
94 |
+
try: import gdcm; logger.info("python-gdcm found.")
|
95 |
+
except ImportError: logger.info("python-gdcm not found.")
|
|
|
|
|
|
|
96 |
except ImportError:
|
97 |
PYDICOM_AVAILABLE = False
|
98 |
PYDICOM_VERSION = 'Not Installed'
|
99 |
logger.warning("pydicom not found. DICOM file support will be disabled.")
|
100 |
+
st.sidebar.warning("`pydicom` library not found. DICOM file support is disabled.", icon="⚠️") # Inform user in UI
|
101 |
+
pydicom = None
|
102 |
|
103 |
# Custom Utilities & Backend Modules
|
104 |
try:
|
|
|
108 |
except ImportError as e:
|
109 |
logger.error(f"Failed to import dicom_utils: {e}. DICOM specific features disabled.", exc_info=True)
|
110 |
DICOM_UTILS_AVAILABLE = False
|
111 |
+
if PYDICOM_AVAILABLE:
|
112 |
+
st.warning("DICOM processing utilities (`dicom_utils.py`) not found. DICOM handling may be limited.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
|
114 |
try:
|
115 |
+
# This file needs to exist now, even if it's basic
|
116 |
from report_utils import generate_pdf_report_bytes
|
117 |
REPORT_UTILS_AVAILABLE = True
|
118 |
logger.info("report_utils imported successfully.")
|
119 |
except ImportError as e:
|
120 |
logger.error(f"Failed to import report_utils: {e}. PDF reporting disabled.", exc_info=True)
|
121 |
REPORT_UTILS_AVAILABLE = False
|
122 |
+
# Display warning in the UI
|
123 |
+
st.warning("Report generation utility (`report_utils.py`) not found or failed to import. PDF reporting disabled.")
|
124 |
+
# Define a placeholder function to avoid errors in actions.py if it's called
|
125 |
+
def generate_pdf_report_bytes(*args, **kwargs):
|
126 |
+
logger.warning("generate_pdf_report_bytes called, but report_utils is unavailable. Returning None.")
|
127 |
+
return None
|
128 |
+
|
129 |
+
|
130 |
+
try:
|
131 |
+
from llm_interactions import run_initial_analysis, run_multimodal_qa, run_disease_analysis, estimate_ai_confidence
|
132 |
+
LLM_INTERACTIONS_AVAILABLE = True
|
133 |
+
logger.info("llm_interactions imported successfully.")
|
134 |
+
except ImportError as e:
|
135 |
+
st.error(f"Core AI module (`llm_interactions.py`) failed to import: {e}. AI analysis functions are disabled.")
|
136 |
+
logger.critical(f"Failed to import llm_interactions: {e}", exc_info=True)
|
137 |
+
LLM_INTERACTIONS_AVAILABLE = False
|
138 |
+
# Define placeholders if needed, or let actions.py handle the disabled state
|
139 |
|
140 |
try:
|
141 |
from ui_components import display_dicom_metadata, dicom_wl_sliders
|
142 |
UI_COMPONENTS_AVAILABLE = True
|
143 |
logger.info("ui_components imported successfully.")
|
144 |
except ImportError as e:
|
145 |
+
logger.warning(f"Failed to import ui_components: {e}. Custom UI elements might use fallbacks.", exc_info=True)
|
146 |
UI_COMPONENTS_AVAILABLE = False
|
147 |
|
|
|
148 |
# HF Fallback Models (Optional)
|
149 |
try:
|
150 |
from hf_models import query_hf_vqa_inference_api, HF_VQA_MODEL_ID
|
|
|
155 |
HF_MODELS_AVAILABLE = False
|
156 |
logger.warning("hf_models not found or failed to import. Fallback VQA disabled.")
|
157 |
|
158 |
+
|
159 |
+
# --- Update config with availability flags (optional) ---
|
160 |
import config
|
161 |
+
# (Keep this section as is)
|
162 |
config.DRAWABLE_CANVAS_AVAILABLE = DRAWABLE_CANVAS_AVAILABLE
|
163 |
+
# ... etc ...
|
164 |
+
config.REPORT_UTILS_AVAILABLE = REPORT_UTILS_AVAILABLE # Update based on import success
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
|
166 |
# --- Step 2: Configure Streamlit Page ---
|
167 |
+
# Already done at the top!
|
|
|
|
|
|
|
|
|
|
|
168 |
|
169 |
# Apply Custom CSS
|
170 |
st.markdown(CUSTOM_CSS, unsafe_allow_html=True)
|
171 |
|
172 |
# --- Step 3: Apply Monkey Patches (Conditional) ---
|
173 |
import streamlit.elements.image as st_image
|
174 |
+
import utils
|
175 |
+
utils.apply_image_to_url_monkey_patch(st_image)
|
176 |
|
177 |
# --- Step 4: Initialize Session State ---
|
178 |
from state import initialize_session_state
|
|
|
181 |
|
182 |
# --- Step 5: Display Logo ---
|
183 |
if os.path.exists(LOGO_PATH):
|
184 |
+
logo_col, _ = st.columns([1, 3])
|
|
|
185 |
with logo_col:
|
186 |
+
st.image(LOGO_PATH, width=300)
|
187 |
else:
|
188 |
logger.warning(f"Hero logo not found at: {LOGO_PATH}")
|
189 |
+
# st.warning("RadVision AI Logo missing.") # Optional UI warning
|
|
|
|
|
190 |
|
191 |
# --- Step 6: Render Sidebar and Get Uploaded File ---
|
192 |
from ui import render_sidebar
|
|
|
194 |
IS_DICOM=st.session_state.get("is_dicom", False),
|
195 |
UI_COMPONENTS_AVAILABLE=UI_COMPONENTS_AVAILABLE,
|
196 |
DICOM_UTILS_AVAILABLE=DICOM_UTILS_AVAILABLE,
|
197 |
+
REPORT_UTILS_AVAILABLE=REPORT_UTILS_AVAILABLE # Pass the actual availability status
|
198 |
)
|
199 |
|
|
|
200 |
# --- Step 7: Handle File Upload Processing ---
|
201 |
from file_handler import process_uploaded_file
|
|
|
202 |
process_uploaded_file(uploaded_file, PYDICOM_AVAILABLE, DICOM_UTILS_AVAILABLE, PIL_AVAILABLE)
|
203 |
|
204 |
# --- Step 8: Render Main Page Content ---
|
205 |
st.markdown("---")
|
206 |
st.title(f"⚕️ {APP_TITLE}: AI-Assisted Image Analysis")
|
207 |
|
|
|
208 |
with st.expander("User Guide & Disclaimer", expanded=False):
|
209 |
st.warning("⚠️ **Disclaimer**: This tool is for research/educational purposes only and is **NOT** a substitute for professional medical advice or diagnosis.")
|
210 |
st.markdown("""
|
|
|
220 |
6. **Review Results**: Check the tabs ('Initial Analysis', 'Q&A History', 'Condition Focus') for AI output.
|
221 |
7. **(Optional) Translation**: Use the 'Translation' tab to translate AI-generated text.
|
222 |
8. **(Optional) Confidence**: Use the 'Estimate AI Confidence' button (sidebar) after analysis.
|
223 |
+
9. **(Optional) Report**: Click 'Generate PDF Report Data' (sidebar) and then 'Download PDF Report' to save a summary. **(Note: PDF generation may be disabled if `report_utils.py` is missing or faulty)**
|
224 |
+
""") # Added note about disabled reporting
|
225 |
|
226 |
st.markdown("---")
|
227 |
|
228 |
+
col1, col2 = st.columns([2, 3])
|
|
|
229 |
|
230 |
with col1:
|
231 |
from ui import render_image_viewer
|
|
|
239 |
|
240 |
with col2:
|
241 |
from ui import render_results_tabs
|
|
|
242 |
translate_func = translate if TRANSLATION_AVAILABLE else None
|
243 |
render_results_tabs(
|
244 |
TRANSLATION_SERVICE_AVAILABLE=TRANSLATION_AVAILABLE,
|
|
|
246 |
)
|
247 |
|
248 |
# --- Step 9: Handle Button Actions ---
|
|
|
249 |
from actions import handle_actions
|
250 |
+
# Check REPORT_UTILS_AVAILABLE before passing to handle_actions,
|
251 |
+
# or handle_actions should already check the flag from session state/config
|
252 |
handle_actions(LLM_INTERACTIONS_AVAILABLE, REPORT_UTILS_AVAILABLE)
|
253 |
|
|
|
254 |
# --- Step 10: Render Footer ---
|
255 |
from ui import render_footer
|
256 |
render_footer(st.session_state.get("session_id"))
|