import os import gradio as gr import torch from peft import AutoPeftModelForCausalLM from transformers import AutoTokenizer MODEL_ID = os.getenv("MODEL_ID", "trtd56/LFM2.5-1.2B-JP-bash-explainer-lora") SYSTEM_PROMPT = "あなたは Bash コマンドの内容を説明する日本語アシスタントです。" def load_model(): model = AutoPeftModelForCausalLM.from_pretrained( MODEL_ID, torch_dtype="auto", device_map="auto", ) tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, use_fast=True) if tokenizer.pad_token is None: tokenizer.pad_token = tokenizer.eos_token return model, tokenizer MODEL, TOKENIZER = load_model() def build_prompt(command: str) -> str: return ( f"{SYSTEM_PROMPT}\n\n" "### 入力\n" f"{command.strip()}\n\n" "### 出力\n" ) def explain_command(command: str, max_new_tokens: int) -> str: command = command.strip() if not command: return "bash コマンドを入力してください。" prompt = build_prompt(command) inputs = TOKENIZER(prompt, return_tensors="pt") model_device = next(MODEL.parameters()).device inputs = {k: v.to(model_device) for k, v in inputs.items()} with torch.no_grad(): output = MODEL.generate( **inputs, max_new_tokens=max_new_tokens, do_sample=False, pad_token_id=TOKENIZER.pad_token_id, eos_token_id=TOKENIZER.eos_token_id, ) text = TOKENIZER.decode(output[0], skip_special_tokens=True) if "### 出力" in text: return text.split("### 出力", 1)[-1].strip() return text.strip() EXAMPLES = [ ["sudo apt install curl"], ["ls -la ~/Downloads"], ['grep -R "TODO" .'], ['find . -name "*.log" -delete'], ] CSS = """ :root { --bg: #f4efe4; --card: #fffaf0; --ink: #1d1a16; --muted: #6b6254; --line: #d8ccb8; --accent: #9a3412; --accent-2: #164e63; } .gradio-container { background: radial-gradient(circle at top left, rgba(154, 52, 18, 0.10), transparent 28%), radial-gradient(circle at bottom right, rgba(22, 78, 99, 0.10), transparent 24%), var(--bg); color: var(--ink); font-family: "IBM Plex Sans JP", "Hiragino Sans", sans-serif; } .shell-card { border: 1px solid var(--line); border-radius: 20px; background: linear-gradient(180deg, rgba(255,250,240,0.98), rgba(255,247,235,0.98)); box-shadow: 0 18px 60px rgba(29, 26, 22, 0.08); } .eyebrow { letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent-2); font-size: 12px; font-weight: 700; } .hero { font-family: "Avenir Next", "IBM Plex Sans JP", sans-serif; font-size: 38px; line-height: 1.05; font-weight: 700; margin: 8px 0 12px; } .sub { color: var(--muted); font-size: 15px; line-height: 1.7; } """ with gr.Blocks(css=CSS, theme=gr.themes.Soft()) as demo: gr.HTML( """
trtd56/LFM2.5-1.2B-JP-bash-explainer-lora を読み込み、
bash コマンドの動作を短い日本語で返します。