Luigi commited on
Commit
6d54864
Β·
1 Parent(s): e78283f

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

Files changed (1) hide show
  1. app.py +93 -17
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">πŸ“€</span> Upload File</div>')
 
 
 
 
 
 
 
 
 
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="Qwen3 only: uses /think for deeper analysis (slower) or /no_think for direct output (faster). Enabled by default.",
759
  interactive=True,
 
760
  )
761
- temperature_display = gr.Textbox(
762
- label="Temperature (Locked)",
763
- value="0.6",
764
- interactive=False,
765
- info="Set by model's recommended settings. Cannot be changed."
 
 
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=get_model_info,
838
  inputs=[model_dropdown],
839
- outputs=[info_output, temperature_display, top_p, top_k],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
  """)