Daryl Lim Claude Opus 4.8 (1M context) commited on
Commit
9fdec8c
Β·
1 Parent(s): 42772e1

fix: remove invalid Textbox clear button and tighten model/tokenizer types

Browse files

ty surfaced that buttons=["clear"] is not a valid gradio Textbox
built-in (only "copy" is), so the input's clear button silently did
nothing β€” remove it and update CLAUDE.md.

Annotate the loaders with PreTrainedTokenizerBase/PreTrainedModel
instead of the Auto* factory classes, resolving the get_vocab/device/
decode/callable warnings. With decode now typed as str, the dead
isinstance guard in translate() is removed. The remaining
model.generate warning is an irreducible transformers stub gap,
already downgraded to warn in ty.toml.

Verified: ty 6->1, 38 fast tests pass, ruff clean, app imports.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files changed (2) hide show
  1. CLAUDE.md +1 -1
  2. app.py +4 -8
CLAUDE.md CHANGED
@@ -35,7 +35,7 @@ uv run scripts/generate_langmap.py <path-to-paper.pdf>
35
 
36
  ## Architecture
37
 
38
- **`app.py`** β€” Single-file application with a Google Translate-style layout: top row has two symmetric, filterable, region-sorted language dropdowns (source defaults to "English (en)", target defaults to "French (fr)") with a swap button ("⇄") between them; below that, input textbox with inline clear button and output textbox with copy button side by side. The Translate button spans full width below both textboxes (shows "Translating..." during processing). Ctrl+Enter submits from the input. The model auto-detects source language; the source dropdown is for user reference and the swap button only. Uses `@lru_cache` for lazy loading of the `google/madlad400-3b-mt` tokenizer and model (no download on import). Uses `float16` on CUDA, `float32` on CPU. MPS is not supported (produces garbage output with T5 models). Translation prepends a target language token with a space to the input text (e.g., `<2fr> Hello`) before tokenization and generation. The `@spaces.GPU` decorator allocates GPU on HF Spaces infrastructure.
39
 
40
  **`langmap/`** β€” Package with `langid_mapping.py`, mapping 418 language tokens to `{"name": ..., "region": ...}` dicts. Auto-generated by `scripts/generate_langmap.py` from Table 9 (Section A.1) of the MADLAD-400 paper. Available languages at runtime are the intersection of this mapping and the model's vocabulary.
41
 
 
35
 
36
  ## Architecture
37
 
38
+ **`app.py`** β€” Single-file application with a Google Translate-style layout: top row has two symmetric, filterable, region-sorted language dropdowns (source defaults to "English (en)", target defaults to "French (fr)") with a swap button ("⇄") between them; below that, input textbox and output textbox with copy button side by side. The Translate button spans full width below both textboxes (shows "Translating..." during processing). Ctrl+Enter submits from the input. The model auto-detects source language; the source dropdown is for user reference and the swap button only. Uses `@lru_cache` for lazy loading of the `google/madlad400-3b-mt` tokenizer and model (no download on import). Uses `float16` on CUDA, `float32` on CPU. MPS is not supported (produces garbage output with T5 models). Translation prepends a target language token with a space to the input text (e.g., `<2fr> Hello`) before tokenization and generation. The `@spaces.GPU` decorator allocates GPU on HF Spaces infrastructure.
39
 
40
  **`langmap/`** β€” Package with `langid_mapping.py`, mapping 418 language tokens to `{"name": ..., "region": ...}` dicts. Auto-generated by `scripts/generate_langmap.py` from Table 9 (Section A.1) of the MADLAD-400 paper. Available languages at runtime are the intersection of this mapping and the model's vocabulary.
41
 
app.py CHANGED
@@ -10,7 +10,7 @@ from functools import lru_cache
10
  import gradio as gr
11
  import spaces
12
  import torch
13
- from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
14
 
15
  from langmap.langid_mapping import langid_to_language
16
 
@@ -25,7 +25,7 @@ def _get_device() -> torch.device:
25
 
26
 
27
  @lru_cache(maxsize=1)
28
- def _load_tokenizer() -> AutoTokenizer:
29
  tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, use_fast=True)
30
  if tokenizer is None:
31
  raise RuntimeError(f"Failed to load tokenizer for {MODEL_NAME}")
@@ -33,7 +33,7 @@ def _load_tokenizer() -> AutoTokenizer:
33
 
34
 
35
  @lru_cache(maxsize=1)
36
- def _load_model() -> AutoModelForSeq2SeqLM:
37
  device = _get_device()
38
  dtype = torch.float16 if device.type == "cuda" else torch.float32
39
  return AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME, dtype=dtype).to(device)
@@ -85,10 +85,7 @@ def translate(
85
  generate_kwargs["temperature"] = temperature
86
 
87
  outputs = model.generate(**generate_kwargs)
88
- result = tokenizer.decode(outputs[0], skip_special_tokens=True)
89
- if not isinstance(result, str):
90
- raise TypeError(f"Expected str from decode, got {type(result)}")
91
- return result
92
 
93
 
94
  def _translate_with_loading(
@@ -131,7 +128,6 @@ def _build_demo() -> gr.Blocks:
131
  lines=6,
132
  max_length=2000,
133
  show_label=False,
134
- buttons=["clear"],
135
  )
136
  output_text = gr.Textbox(
137
  placeholder="Translation",
 
10
  import gradio as gr
11
  import spaces
12
  import torch
13
+ from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, PreTrainedModel, PreTrainedTokenizerBase
14
 
15
  from langmap.langid_mapping import langid_to_language
16
 
 
25
 
26
 
27
  @lru_cache(maxsize=1)
28
+ def _load_tokenizer() -> PreTrainedTokenizerBase:
29
  tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, use_fast=True)
30
  if tokenizer is None:
31
  raise RuntimeError(f"Failed to load tokenizer for {MODEL_NAME}")
 
33
 
34
 
35
  @lru_cache(maxsize=1)
36
+ def _load_model() -> PreTrainedModel:
37
  device = _get_device()
38
  dtype = torch.float16 if device.type == "cuda" else torch.float32
39
  return AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME, dtype=dtype).to(device)
 
85
  generate_kwargs["temperature"] = temperature
86
 
87
  outputs = model.generate(**generate_kwargs)
88
+ return tokenizer.decode(outputs[0], skip_special_tokens=True)
 
 
 
89
 
90
 
91
  def _translate_with_loading(
 
128
  lines=6,
129
  max_length=2000,
130
  show_label=False,
 
131
  )
132
  output_text = gr.Textbox(
133
  placeholder="Translation",