sui-api / app.py
cstr's picture
Update app.py
17f7aab verified
import gradio as gr
from gradio_client import Client, handle_file
# Target Space API
API_URL = "ellamind/sui-demo"
# ============================================================================
# Theme & Styling
# ============================================================================
THEME = gr.themes.Soft(
primary_hue="slate",
secondary_hue="slate",
neutral_hue="slate",
font=gr.themes.GoogleFont("Inter"),
).set(
block_radius="0.75rem",
block_shadow="0 1px 3px 0 rgb(0 0 0 / 0.1)",
button_primary_background_fill="*primary_800",
button_primary_background_fill_hover="*primary_700",
)
CSS = """
.gradio-container {
max-width: 1100px !important;
margin: 0 auto !important;
padding-top: 2rem !important;
}
.main-header {
text-align: center;
margin-bottom: 2rem;
}
.main-header h1 {
font-size: 2.25rem;
font-weight: 800;
margin-bottom: 0.5rem;
color: var(--body-text-color);
}
.section-title {
margin-bottom: 1rem !important;
border-bottom: 1px solid var(--border-color-primary);
padding-bottom: 0.5rem;
}
.output-panel {
background: var(--block-background-fill) !important;
border-radius: 0.75rem !important;
border: 1px solid var(--border-color-primary) !important;
padding: 1.5rem !important;
min-height: 400px;
}
.summary-text {
font-size: 1.05rem !important;
line-height: 1.8 !important;
color: var(--body-text-color) !important;
background: transparent !important;
}
/* 1. Base style (Light Mode) */
.thinking-section {
background: rgba(0, 0, 0, 0.05) !important; /* Subtle tint instead of var */
border-left: 4px solid var(--primary-500) !important;
padding: 1.25rem !important;
margin-bottom: 1.5rem !important;
border-radius: 0 0.75rem 0.75rem 0 !important;
font-style: italic !important;
}
/* 2. Dark Mode Override */
.dark .thinking-section {
background: rgba(255, 255, 255, 0.1) !important; /* Light tint on dark background */
border-left-color: var(--primary-400) !important;
}
/* 3. Force the text inside the thinking section to adapt */
.thinking-section,
.thinking-section p,
.thinking-section span {
color: var(--body-text-color) !important;
opacity: 0.9;
}
/* 4. Extra insurance for the summary area text in dark mode */
.dark .summary-text,
.dark .prose {
color: #f1f5f9 !important; /* Explicit light gray/white */
}
.sources-panel {
font-size: 0.9rem !important;
max-height: 400px;
overflow-y: auto;
}
.generate-btn {
margin-top: 1rem;
font-weight: 600 !important;
}
.footer {
text-align: center;
margin-top: 3rem;
padding-bottom: 2rem;
font-size: 0.85rem;
opacity: 0.6;
}
"""
# ============================================================================
# API Proxy Function
# ============================================================================
def summarize_proxy(pdf_file, language, words, custom_instruction):
"""Calls the backend Space API and yields exactly 3 results."""
if not pdf_file:
# Yielding 3 values to match the interface components
yield "Please upload a PDF document.", "", gr.update(visible=False)
return
try:
client = Client(API_URL)
# We start the stream. The backend yields 3 objects: (summary, sources, accordion_update)
job = client.submit(
pdf_file=handle_file(pdf_file),
language=language,
words=words,
custom_instruction=custom_instruction,
api_name="/summarize"
)
for result in job:
# Result from the client should be a list/tuple of 3 items
# But let's be safe and ensure it matches the 3 outputs
if len(result) == 3:
yield result[0], result[1], result[2]
else:
# Fallback in case backend returns unexpected shape
yield result[0], result[1], gr.update(visible=True)
except Exception as e:
yield f"### API Error\n{str(e)}", "Ensure the backend Space is active.", gr.update(visible=False)
# ============================================================================
# Interface
# ============================================================================
def create_app():
# Removed theme and css from constructor for Gradio 6.0 compatibility
with gr.Blocks(title="sui-1-24b") as app:
gr.HTML("""
<div class="main-header">
<h1>sui-1-24b</h1>
<p>Grounded summaries with verifiable source citations</p>
</div>
""")
with gr.Row(equal_height=False):
with gr.Column(scale=2):
gr.Markdown("### Document", elem_classes=["section-title"])
pdf_input = gr.File(label="Upload PDF", file_types=[".pdf"], type="filepath")
gr.Markdown("### Options", elem_classes=["section-title"])
language = gr.Dropdown(
choices=["English", "German", "Spanish", "French", "Italian"],
value="German",
label="Language"
)
words = gr.Slider(minimum=100, maximum=600, value=150, step=50, label="Summary Length")
custom_instruction = gr.Textbox(
label="Instructions (Optional)",
placeholder="Focus on key findings...",
lines=2
)
generate_btn = gr.Button("Generate Summary", variant="primary", elem_classes=["generate-btn"])
with gr.Column(scale=3):
gr.Markdown("### Summary", elem_classes=["section-title"])
summary_output = gr.Markdown(value="*Upload a PDF to begin.*")
# Note: This is output #3
with gr.Accordion("View Source Citations", open=False, visible=False) as sources_accordion:
sources_output = gr.Markdown(elem_classes=["sources-panel"])
generate_btn.click(
fn=summarize_proxy,
inputs=[pdf_input, language, words, custom_instruction],
outputs=[summary_output, sources_output, sources_accordion],
)
gr.HTML("""
<div class="footer">
Powered by <a href="https://huggingface.co/ellamind/sui-1-24b" target="_blank">ellamind/sui-1-24b</a> via API
</div>
""")
return app
if __name__ == "__main__":
# Theme and CSS passed here to comply with Gradio 6.0 warning
create_app().launch(theme=THEME, css=CSS)