Spaces:
Running
Running
UI/UX improvements: language selector, dynamic reasoning, copy buttons, adjustable temperature
Browse files- Move language selector above file uploader for better visibility
- Make reasoning checkbox dynamically visible (only for Qwen3 models)
- Add copy buttons for summary and thinking panels
- Add JSON download button with metadata
- Convert temperature from locked display to adjustable slider (0.0-2.0)
- Update footer to mention bilingual support
- Add helper functions: update_reasoning_visibility, download_summary_json
- Update summarize_streaming to accept temperature parameter
app.py
CHANGED
|
@@ -35,6 +35,7 @@ AVAILABLE_MODELS = {
|
|
| 35 |
"repo_id": "mradermacher/Falcon-H1-Tiny-Multilingual-100M-Instruct-GGUF",
|
| 36 |
"filename": "*Q8_0.gguf",
|
| 37 |
"max_context": 32768,
|
|
|
|
| 38 |
"inference_settings": {
|
| 39 |
"temperature": 0.1,
|
| 40 |
"top_p": 0.9,
|
|
@@ -47,6 +48,7 @@ AVAILABLE_MODELS = {
|
|
| 47 |
"repo_id": "unsloth/gemma-3-270m-it-qat-GGUF",
|
| 48 |
"filename": "*Q8_0.gguf",
|
| 49 |
"max_context": 32768,
|
|
|
|
| 50 |
"inference_settings": {
|
| 51 |
"temperature": 1.0,
|
| 52 |
"top_p": 0.95,
|
|
@@ -59,6 +61,7 @@ AVAILABLE_MODELS = {
|
|
| 59 |
"repo_id": "unsloth/ERNIE-4.5-0.3B-PT-GGUF",
|
| 60 |
"filename": "*Q8_0.gguf",
|
| 61 |
"max_context": 131072,
|
|
|
|
| 62 |
"inference_settings": {
|
| 63 |
"temperature": 0.3,
|
| 64 |
"top_p": 0.95,
|
|
@@ -71,6 +74,7 @@ AVAILABLE_MODELS = {
|
|
| 71 |
"repo_id": "unsloth/granite-4.0-h-350m-GGUF",
|
| 72 |
"filename": "*Q8_0.gguf",
|
| 73 |
"max_context": 32768,
|
|
|
|
| 74 |
"inference_settings": {
|
| 75 |
"temperature": 0.0,
|
| 76 |
"top_p": 1.0,
|
|
@@ -83,6 +87,7 @@ AVAILABLE_MODELS = {
|
|
| 83 |
"repo_id": "LiquidAI/LFM2-350M-GGUF",
|
| 84 |
"filename": "*Q8_0.gguf",
|
| 85 |
"max_context": 32768,
|
|
|
|
| 86 |
"inference_settings": {
|
| 87 |
"temperature": 0.1,
|
| 88 |
"top_p": 0.1,
|
|
@@ -95,6 +100,7 @@ AVAILABLE_MODELS = {
|
|
| 95 |
"repo_id": "openbmb/BitCPM4-0.5B-GGUF",
|
| 96 |
"filename": "*q4_0.gguf",
|
| 97 |
"max_context": 131072,
|
|
|
|
| 98 |
"inference_settings": {
|
| 99 |
"temperature": 0.3,
|
| 100 |
"top_p": 0.95,
|
|
@@ -107,6 +113,7 @@ AVAILABLE_MODELS = {
|
|
| 107 |
"repo_id": "mradermacher/Hunyuan-0.5B-Instruct-GGUF",
|
| 108 |
"filename": "*Q8_0.gguf",
|
| 109 |
"max_context": 262144,
|
|
|
|
| 110 |
"inference_settings": {
|
| 111 |
"temperature": 0.3,
|
| 112 |
"top_p": 0.95,
|
|
@@ -119,6 +126,7 @@ AVAILABLE_MODELS = {
|
|
| 119 |
"repo_id": "unsloth/Qwen3-0.6B-GGUF",
|
| 120 |
"filename": "*Q4_K_M.gguf",
|
| 121 |
"max_context": 32768,
|
|
|
|
| 122 |
"supports_toggle": True,
|
| 123 |
"inference_settings": {
|
| 124 |
"temperature": 0.6,
|
|
@@ -132,6 +140,7 @@ AVAILABLE_MODELS = {
|
|
| 132 |
"repo_id": "unsloth/Falcon-H1-1.5B-Deep-Instruct-GGUF",
|
| 133 |
"filename": "*Q4_K_M.gguf",
|
| 134 |
"max_context": 32768,
|
|
|
|
| 135 |
"inference_settings": {
|
| 136 |
"temperature": 0.1,
|
| 137 |
"top_p": 0.9,
|
|
@@ -144,6 +153,7 @@ AVAILABLE_MODELS = {
|
|
| 144 |
"repo_id": "unsloth/Qwen3-1.7B-GGUF",
|
| 145 |
"filename": "*Q4_K_M.gguf",
|
| 146 |
"max_context": 32768,
|
|
|
|
| 147 |
"supports_toggle": True,
|
| 148 |
"inference_settings": {
|
| 149 |
"temperature": 0.6,
|
|
@@ -157,6 +167,7 @@ AVAILABLE_MODELS = {
|
|
| 157 |
"repo_id": "mradermacher/LFM2-2.6B-Transcript-GGUF",
|
| 158 |
"filename": "*Q4_K_M.gguf",
|
| 159 |
"max_context": 32768,
|
|
|
|
| 160 |
"supports_toggle": False,
|
| 161 |
"inference_settings": {
|
| 162 |
"temperature": 0.3,
|
|
@@ -170,6 +181,7 @@ AVAILABLE_MODELS = {
|
|
| 170 |
"repo_id": "unsloth/Qwen3-4B-Thinking-2507-GGUF",
|
| 171 |
"filename": "*Q3_K_M.gguf",
|
| 172 |
"max_context": 262144,
|
|
|
|
| 173 |
"supports_toggle": False, # Thinking-only mode
|
| 174 |
"inference_settings": {
|
| 175 |
"temperature": 0.6,
|
|
@@ -183,6 +195,7 @@ AVAILABLE_MODELS = {
|
|
| 183 |
"repo_id": "unsloth/granite-4.0-h-tiny-GGUF",
|
| 184 |
"filename": "*Q3_K_M.gguf",
|
| 185 |
"max_context": 131072,
|
|
|
|
| 186 |
"supports_toggle": False,
|
| 187 |
"inference_settings": {
|
| 188 |
"temperature": 0.0,
|
|
@@ -196,6 +209,7 @@ AVAILABLE_MODELS = {
|
|
| 196 |
"repo_id": "unsloth/ERNIE-4.5-21B-A3B-Thinking-GGUF",
|
| 197 |
"filename": "*TQ1_0.gguf",
|
| 198 |
"max_context": 131072,
|
|
|
|
| 199 |
"supports_toggle": False, # Thinking-only mode
|
| 200 |
"inference_settings": {
|
| 201 |
"temperature": 0.3,
|
|
@@ -270,6 +284,33 @@ def load_model(model_key: str = None) -> Tuple[Llama, str]:
|
|
| 270 |
raise
|
| 271 |
|
| 272 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 273 |
def estimate_tokens(text: str) -> int:
|
| 274 |
"""
|
| 275 |
Estimate token count for mixed CJK/English text.
|
|
@@ -378,6 +419,7 @@ def summarize_streaming(
|
|
| 378 |
model_key: str,
|
| 379 |
enable_reasoning: bool = True,
|
| 380 |
max_tokens: int = 2048,
|
|
|
|
| 381 |
top_p: float = None,
|
| 382 |
top_k: int = None,
|
| 383 |
output_language: str = "en",
|
|
@@ -729,7 +771,16 @@ def create_interface():
|
|
| 729 |
# Left column - Input
|
| 730 |
with gr.Column(scale=1):
|
| 731 |
with gr.Group():
|
| 732 |
-
gr.HTML('<div class="section-header"><span class="section-icon">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 733 |
|
| 734 |
file_input = gr.File(
|
| 735 |
label="Drag & drop or click to upload",
|
|
@@ -746,23 +797,20 @@ def create_interface():
|
|
| 746 |
label="Model",
|
| 747 |
info="Smaller = faster. Large files need models with bigger context."
|
| 748 |
)
|
| 749 |
-
language_selector = gr.Dropdown(
|
| 750 |
-
choices=[("English", "en"), ("Traditional Chinese (zh-TW)", "zh-TW")],
|
| 751 |
-
value="en",
|
| 752 |
-
label="Output Language",
|
| 753 |
-
info="Select target language for the summary"
|
| 754 |
-
)
|
| 755 |
enable_reasoning = gr.Checkbox(
|
| 756 |
value=True,
|
| 757 |
label="Enable Reasoning Mode",
|
| 758 |
-
info="
|
| 759 |
interactive=True,
|
|
|
|
| 760 |
)
|
| 761 |
-
|
| 762 |
-
|
| 763 |
-
|
| 764 |
-
|
| 765 |
-
|
|
|
|
|
|
|
| 766 |
)
|
| 767 |
max_tokens = gr.Slider(
|
| 768 |
minimum=256,
|
|
@@ -824,25 +872,53 @@ def create_interface():
|
|
| 824 |
value="*Your summarized content will appear here...*",
|
| 825 |
elem_classes=["summary-box"]
|
| 826 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 827 |
|
| 828 |
# Event handlers
|
| 829 |
submit_btn.click(
|
| 830 |
fn=summarize_streaming,
|
| 831 |
-
inputs=[file_input, model_dropdown, enable_reasoning, max_tokens, top_p, top_k, language_selector],
|
| 832 |
outputs=[thinking_output, summary_output, info_output],
|
| 833 |
show_progress="full"
|
| 834 |
)
|
| 835 |
|
| 836 |
model_dropdown.change(
|
| 837 |
-
fn=
|
| 838 |
inputs=[model_dropdown],
|
| 839 |
-
outputs=[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 840 |
)
|
| 841 |
|
| 842 |
# Footer
|
| 843 |
gr.HTML("""
|
| 844 |
<div style="text-align: center; margin-top: 2rem; padding: 1rem; color: #64748b; font-size: 0.85rem; border-top: 1px solid #e2e8f0;">
|
| 845 |
-
Powered by <strong>llama-cpp-python</strong> β’ Running on <strong>HuggingFace Spaces Free Tier</strong><br>
|
| 846 |
Traditional Chinese conversion via <strong>OpenCC</strong>
|
| 847 |
</div>
|
| 848 |
""")
|
|
|
|
| 35 |
"repo_id": "mradermacher/Falcon-H1-Tiny-Multilingual-100M-Instruct-GGUF",
|
| 36 |
"filename": "*Q8_0.gguf",
|
| 37 |
"max_context": 32768,
|
| 38 |
+
"default_temperature": 0.6,
|
| 39 |
"inference_settings": {
|
| 40 |
"temperature": 0.1,
|
| 41 |
"top_p": 0.9,
|
|
|
|
| 48 |
"repo_id": "unsloth/gemma-3-270m-it-qat-GGUF",
|
| 49 |
"filename": "*Q8_0.gguf",
|
| 50 |
"max_context": 32768,
|
| 51 |
+
"default_temperature": 0.6,
|
| 52 |
"inference_settings": {
|
| 53 |
"temperature": 1.0,
|
| 54 |
"top_p": 0.95,
|
|
|
|
| 61 |
"repo_id": "unsloth/ERNIE-4.5-0.3B-PT-GGUF",
|
| 62 |
"filename": "*Q8_0.gguf",
|
| 63 |
"max_context": 131072,
|
| 64 |
+
"default_temperature": 0.6,
|
| 65 |
"inference_settings": {
|
| 66 |
"temperature": 0.3,
|
| 67 |
"top_p": 0.95,
|
|
|
|
| 74 |
"repo_id": "unsloth/granite-4.0-h-350m-GGUF",
|
| 75 |
"filename": "*Q8_0.gguf",
|
| 76 |
"max_context": 32768,
|
| 77 |
+
"default_temperature": 0.6,
|
| 78 |
"inference_settings": {
|
| 79 |
"temperature": 0.0,
|
| 80 |
"top_p": 1.0,
|
|
|
|
| 87 |
"repo_id": "LiquidAI/LFM2-350M-GGUF",
|
| 88 |
"filename": "*Q8_0.gguf",
|
| 89 |
"max_context": 32768,
|
| 90 |
+
"default_temperature": 0.6,
|
| 91 |
"inference_settings": {
|
| 92 |
"temperature": 0.1,
|
| 93 |
"top_p": 0.1,
|
|
|
|
| 100 |
"repo_id": "openbmb/BitCPM4-0.5B-GGUF",
|
| 101 |
"filename": "*q4_0.gguf",
|
| 102 |
"max_context": 131072,
|
| 103 |
+
"default_temperature": 0.6,
|
| 104 |
"inference_settings": {
|
| 105 |
"temperature": 0.3,
|
| 106 |
"top_p": 0.95,
|
|
|
|
| 113 |
"repo_id": "mradermacher/Hunyuan-0.5B-Instruct-GGUF",
|
| 114 |
"filename": "*Q8_0.gguf",
|
| 115 |
"max_context": 262144,
|
| 116 |
+
"default_temperature": 0.6,
|
| 117 |
"inference_settings": {
|
| 118 |
"temperature": 0.3,
|
| 119 |
"top_p": 0.95,
|
|
|
|
| 126 |
"repo_id": "unsloth/Qwen3-0.6B-GGUF",
|
| 127 |
"filename": "*Q4_K_M.gguf",
|
| 128 |
"max_context": 32768,
|
| 129 |
+
"default_temperature": 0.6,
|
| 130 |
"supports_toggle": True,
|
| 131 |
"inference_settings": {
|
| 132 |
"temperature": 0.6,
|
|
|
|
| 140 |
"repo_id": "unsloth/Falcon-H1-1.5B-Deep-Instruct-GGUF",
|
| 141 |
"filename": "*Q4_K_M.gguf",
|
| 142 |
"max_context": 32768,
|
| 143 |
+
"default_temperature": 0.6,
|
| 144 |
"inference_settings": {
|
| 145 |
"temperature": 0.1,
|
| 146 |
"top_p": 0.9,
|
|
|
|
| 153 |
"repo_id": "unsloth/Qwen3-1.7B-GGUF",
|
| 154 |
"filename": "*Q4_K_M.gguf",
|
| 155 |
"max_context": 32768,
|
| 156 |
+
"default_temperature": 0.6,
|
| 157 |
"supports_toggle": True,
|
| 158 |
"inference_settings": {
|
| 159 |
"temperature": 0.6,
|
|
|
|
| 167 |
"repo_id": "mradermacher/LFM2-2.6B-Transcript-GGUF",
|
| 168 |
"filename": "*Q4_K_M.gguf",
|
| 169 |
"max_context": 32768,
|
| 170 |
+
"default_temperature": 0.6,
|
| 171 |
"supports_toggle": False,
|
| 172 |
"inference_settings": {
|
| 173 |
"temperature": 0.3,
|
|
|
|
| 181 |
"repo_id": "unsloth/Qwen3-4B-Thinking-2507-GGUF",
|
| 182 |
"filename": "*Q3_K_M.gguf",
|
| 183 |
"max_context": 262144,
|
| 184 |
+
"default_temperature": 0.6,
|
| 185 |
"supports_toggle": False, # Thinking-only mode
|
| 186 |
"inference_settings": {
|
| 187 |
"temperature": 0.6,
|
|
|
|
| 195 |
"repo_id": "unsloth/granite-4.0-h-tiny-GGUF",
|
| 196 |
"filename": "*Q3_K_M.gguf",
|
| 197 |
"max_context": 131072,
|
| 198 |
+
"default_temperature": 0.6,
|
| 199 |
"supports_toggle": False,
|
| 200 |
"inference_settings": {
|
| 201 |
"temperature": 0.0,
|
|
|
|
| 209 |
"repo_id": "unsloth/ERNIE-4.5-21B-A3B-Thinking-GGUF",
|
| 210 |
"filename": "*TQ1_0.gguf",
|
| 211 |
"max_context": 131072,
|
| 212 |
+
"default_temperature": 0.6,
|
| 213 |
"supports_toggle": False, # Thinking-only mode
|
| 214 |
"inference_settings": {
|
| 215 |
"temperature": 0.3,
|
|
|
|
| 284 |
raise
|
| 285 |
|
| 286 |
|
| 287 |
+
|
| 288 |
+
def update_reasoning_visibility(model_key):
|
| 289 |
+
"""Show or hide reasoning checkbox based on model capabilities."""
|
| 290 |
+
model = AVAILABLE_MODELS[model_key]
|
| 291 |
+
supports_toggle = model.get("supports_toggle", False)
|
| 292 |
+
return gr.update(visible=supports_toggle)
|
| 293 |
+
|
| 294 |
+
def download_summary_json(summary, thinking, model_key, language):
|
| 295 |
+
"""Generate JSON file with summary and metadata."""
|
| 296 |
+
import json
|
| 297 |
+
from datetime import datetime
|
| 298 |
+
|
| 299 |
+
data = {
|
| 300 |
+
"metadata": {
|
| 301 |
+
"generated_at": datetime.now().isoformat(),
|
| 302 |
+
"model": AVAILABLE_MODELS[model_key]["name"],
|
| 303 |
+
"model_id": model_key,
|
| 304 |
+
"language": language
|
| 305 |
+
},
|
| 306 |
+
"thinking_process": thinking,
|
| 307 |
+
"summary": summary
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
filename = f"summary_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
|
| 311 |
+
with open(filename, 'w', encoding='utf-8') as f:
|
| 312 |
+
json.dump(data, f, ensure_ascii=False, indent=2)
|
| 313 |
+
return filename
|
| 314 |
def estimate_tokens(text: str) -> int:
|
| 315 |
"""
|
| 316 |
Estimate token count for mixed CJK/English text.
|
|
|
|
| 419 |
model_key: str,
|
| 420 |
enable_reasoning: bool = True,
|
| 421 |
max_tokens: int = 2048,
|
| 422 |
+
temperature: float = 0.6,
|
| 423 |
top_p: float = None,
|
| 424 |
top_k: int = None,
|
| 425 |
output_language: str = "en",
|
|
|
|
| 771 |
# Left column - Input
|
| 772 |
with gr.Column(scale=1):
|
| 773 |
with gr.Group():
|
| 774 |
+
gr.HTML('<div class="section-header"><span class="section-icon">π</span> Output Language</div>')
|
| 775 |
+
|
| 776 |
+
language_selector = gr.Dropdown(
|
| 777 |
+
choices=[("English", "en"), ("Traditional Chinese (zh-TW)", "zh-TW")],
|
| 778 |
+
value="en",
|
| 779 |
+
label="Select Language",
|
| 780 |
+
info="Choose the target language for your summary"
|
| 781 |
+
)
|
| 782 |
+
|
| 783 |
+
gr.HTML('<div class="section-header" style="margin-top: 20px;"><span class="section-icon">π€</span> Upload File</div>')
|
| 784 |
|
| 785 |
file_input = gr.File(
|
| 786 |
label="Drag & drop or click to upload",
|
|
|
|
| 797 |
label="Model",
|
| 798 |
info="Smaller = faster. Large files need models with bigger context."
|
| 799 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 800 |
enable_reasoning = gr.Checkbox(
|
| 801 |
value=True,
|
| 802 |
label="Enable Reasoning Mode",
|
| 803 |
+
info="Uses /think for deeper analysis (slower) or /no_think for direct output (faster). Only available for Qwen3 models.",
|
| 804 |
interactive=True,
|
| 805 |
+
visible=AVAILABLE_MODELS[DEFAULT_MODEL_KEY].get("supports_toggle", False)
|
| 806 |
)
|
| 807 |
+
temperature_slider = gr.Slider(
|
| 808 |
+
minimum=0.0,
|
| 809 |
+
maximum=2.0,
|
| 810 |
+
value=0.6,
|
| 811 |
+
step=0.1,
|
| 812 |
+
label="Temperature",
|
| 813 |
+
info="Lower = more focused, Higher = more creative"
|
| 814 |
)
|
| 815 |
max_tokens = gr.Slider(
|
| 816 |
minimum=256,
|
|
|
|
| 872 |
value="*Your summarized content will appear here...*",
|
| 873 |
elem_classes=["summary-box"]
|
| 874 |
)
|
| 875 |
+
|
| 876 |
+
# Action buttons for outputs
|
| 877 |
+
with gr.Row():
|
| 878 |
+
copy_summary_btn = gr.Button("π Copy Summary", size="sm")
|
| 879 |
+
copy_thinking_btn = gr.Button("π Copy Thinking", size="sm")
|
| 880 |
+
download_btn = gr.Button("β¬οΈ Download (JSON)", size="sm")
|
| 881 |
|
| 882 |
# Event handlers
|
| 883 |
submit_btn.click(
|
| 884 |
fn=summarize_streaming,
|
| 885 |
+
inputs=[file_input, model_dropdown, enable_reasoning, max_tokens, temperature_slider, top_p, top_k, language_selector],
|
| 886 |
outputs=[thinking_output, summary_output, info_output],
|
| 887 |
show_progress="full"
|
| 888 |
)
|
| 889 |
|
| 890 |
model_dropdown.change(
|
| 891 |
+
fn=update_reasoning_visibility,
|
| 892 |
inputs=[model_dropdown],
|
| 893 |
+
outputs=[enable_reasoning]
|
| 894 |
+
)
|
| 895 |
+
|
| 896 |
+
# Copy buttons
|
| 897 |
+
copy_summary_btn.click(
|
| 898 |
+
fn=lambda x: x,
|
| 899 |
+
inputs=[summary_output],
|
| 900 |
+
outputs=[],
|
| 901 |
+
js="(text) => { navigator.clipboard.writeText(text); return text; }"
|
| 902 |
+
)
|
| 903 |
+
|
| 904 |
+
copy_thinking_btn.click(
|
| 905 |
+
fn=lambda x: x,
|
| 906 |
+
inputs=[thinking_output],
|
| 907 |
+
outputs=[],
|
| 908 |
+
js="(text) => { navigator.clipboard.writeText(text); return text; }"
|
| 909 |
+
)
|
| 910 |
+
|
| 911 |
+
# Download button
|
| 912 |
+
download_btn.click(
|
| 913 |
+
fn=download_summary_json,
|
| 914 |
+
inputs=[summary_output, thinking_output, model_dropdown, language_selector],
|
| 915 |
+
outputs=[gr.File(label="Download")]
|
| 916 |
)
|
| 917 |
|
| 918 |
# Footer
|
| 919 |
gr.HTML("""
|
| 920 |
<div style="text-align: center; margin-top: 2rem; padding: 1rem; color: #64748b; font-size: 0.85rem; border-top: 1px solid #e2e8f0;">
|
| 921 |
+
Bilingual summaries (English & zh-TW) β’ Powered by <strong>llama-cpp-python</strong> β’ Running on <strong>HuggingFace Spaces Free Tier</strong><br>
|
| 922 |
Traditional Chinese conversion via <strong>OpenCC</strong>
|
| 923 |
</div>
|
| 924 |
""")
|