cali / app.py
Sandroeth's picture
Upload folder using huggingface_hub
a58aec0 verified
Raw History Blame Contribute Delete
7.06 kB
import spaces
import re
import time
import gradio as gr
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
REPOS = {
"translate": ("Sandroeth/cali-id-en-translate", "472c3e80063867ef775fb41d058b9ffec13f44bd"),
"base": ("Sandroeth/cali-0.1B", "c9de368e7e62184e2a70e76f4b3cedcfa170b73a"),
}
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
MODELS = {}
for key, (repo, revision) in REPOS.items():
tokenizer = AutoTokenizer.from_pretrained(repo, revision=revision, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
repo, revision=revision, trust_remote_code=True, dtype=torch.float32,
).to(DEVICE).eval()
MODELS[key] = (tokenizer, model)
print(f"Loaded {repo}@{revision} on {DEVICE}, dtype={model.dtype}", flush=True)
def run_model(key: str, prompt: str, max_new_tokens: int, **options) -> tuple[str, str]:
tokenizer, model = MODELS[key]
inputs = tokenizer(prompt, return_tensors="pt", return_token_type_ids=False).to(DEVICE)
input_length = inputs["input_ids"].shape[1]
if input_length + max_new_tokens > model.config.seq_len:
raise gr.Error("Text is too long. Shorten the input or reduce the output limit (1024 tokens total).")
start = time.perf_counter()
with torch.inference_mode():
output = model.generate(
**inputs, max_new_tokens=max_new_tokens, use_cache=False,
pad_token_id=tokenizer.eos_token_id, **options,
)
generated = output[0][input_length:]
text = tokenizer.decode(generated, skip_special_tokens=True).strip()
elapsed = time.perf_counter() - start
print(f"{key}: input={input_length}, output={len(generated)}, seconds={elapsed:.2f}", flush=True)
return text, f"{input_length} input tokens · {len(generated)} output tokens · {elapsed:.2f} seconds"
@spaces.GPU(duration=60)
def translate(text: str, direction: str = "Indonesian → English", max_new_tokens: int = 64,
first_sentence: bool = True) -> tuple[str, str]:
"""Translate a short sentence between Indonesian and English using CALI's trained prompt format."""
if not text or not text.strip():
raise gr.Error("Enter the text you want to translate.")
if direction not in ("Indonesian → English", "English → Indonesian"):
raise gr.Error("Invalid translation direction.")
max_new_tokens = int(max_new_tokens)
if not 16 <= max_new_tokens <= 256:
raise gr.Error("Choose between 16 and 256 output tokens.")
if len(text.split()) > 200:
raise gr.Error("Use up to 200 words; this model is designed for short texts.")
tag = "[id→en]" if direction == "Indonesian → English" else "[en→id]"
result, stats = run_model("translate", f"{tag}\n{text.strip()}\n→", max_new_tokens,
do_sample=False, repetition_penalty=1.5, no_repeat_ngram_size=3)
if first_sentence:
result = re.split(r"(?<=[.!?])\s+", result)[0]
return result, stats
@spaces.GPU(duration=60)
def complete(prompt: str, max_new_tokens: int = 96, temperature: float = 0.7,
top_p: float = 0.9) -> tuple[str, str]:
"""Continue an Indonesian or English text prompt with the experimental CALI base language model."""
if not prompt or not prompt.strip():
raise gr.Error("Enter a text prompt to continue.")
max_new_tokens = int(max_new_tokens)
if not 16 <= max_new_tokens <= 256 or not 0 <= temperature <= 1.5 or not 0.1 <= top_p <= 1:
raise gr.Error("Generation settings are outside the supported range.")
options = {"do_sample": temperature > 0, "repetition_penalty": 1.1}
if temperature > 0:
options.update(temperature=float(temperature), top_p=float(top_p))
return run_model("base", prompt, max_new_tokens, **options)
with gr.Blocks(title="cali") as demo:
gr.Markdown("# cali\nTwo lightweight models by **Sandroeth** for exploring Indonesian and English.")
with gr.Tab("Translation"):
gr.Markdown("### From one language to another\nBest for everyday sentences. Very short inputs (1–2 words), technical terms, and long passages may produce less accurate translations.")
direction = gr.Radio(["Indonesian → English", "English → Indonesian"], value="Indonesian → English", label="Translation direction")
with gr.Row():
source = gr.Textbox(label="Source text", lines=5, placeholder="Dia pergi ke pasar setiap pagi.", max_length=6000)
translated = gr.Textbox(label="Translation", lines=5, interactive=False)
with gr.Accordion("Settings", open=False):
tokens = gr.Slider(16, 256, value=64, step=1, label="Maximum output tokens")
first = gr.Checkbox(value=True, label="Return the first sentence only (matches the official example)")
translate_button = gr.Button("Translate", variant="primary")
translation_stats = gr.Textbox(label="Stats", interactive=False)
translate_button.click(translate, [source, direction, tokens, first], [translated, translation_stats], api_name="translate")
gr.Examples([
["Dia pergi ke pasar setiap pagi.", "Indonesian → English"],
["Saya makan nasi.", "Indonesian → English"],
["The weather is very cold today.", "English → Indonesian"],
["She is happy.", "English → Indonesian"],
], inputs=[source, direction], outputs=[translated, translation_stats], fn=translate,
cache_examples=True, cache_mode="lazy")
with gr.Tab("Explore CALI"):
gr.Markdown("### Continue a piece of text\nCALI-0.1B is an experimental base model. Start a sentence or paragraph and let it continue. Outputs may repeat or become inconsistent.")
prompt = gr.Textbox(label="Prompt", lines=4, placeholder="Indonesia adalah negara yang")
continuation = gr.Textbox(label="Generated continuation", lines=6, interactive=False)
with gr.Accordion("Settings", open=False):
base_tokens = gr.Slider(16, 256, value=96, step=1, label="Maximum output tokens")
temperature = gr.Slider(0, 1.5, value=0.7, step=0.05, label="Temperature (0 = deterministic)")
top_p = gr.Slider(0.1, 1, value=0.9, step=0.05, label="Top-p")
generate_button = gr.Button("Generate continuation", variant="primary")
base_stats = gr.Textbox(label="Stats", interactive=False)
generate_button.click(complete, [prompt, base_tokens, temperature, top_p], [continuation, base_stats], api_name="complete")
gr.Examples([["Indonesia adalah negara yang"], ["The sun rises in the"]],
inputs=[prompt], outputs=[continuation, base_stats], fn=complete,
cache_examples=True, cache_mode="lazy")
gr.Markdown("Model: [CALI Translate](https://huggingface.co/Sandroeth/cali-id-en-translate) · [CALI-0.1B](https://huggingface.co/Sandroeth/cali-0.1B) · Apache 2.0 license")
if __name__ == "__main__":
demo.queue(max_size=20, default_concurrency_limit=1).launch(mcp_server=True)