# app.py (为 Hugging Face ZeroGPU 修改) import gradio as gr import torch from transformers import AutoModelForCausalLM, AutoTokenizer, GenerationConfig import spaces # -------------------------------------------------------------------------- # 1. 配置 (在应用启动时执行) # -------------------------------------------------------------------------- # !! 重要的模型 ID (从 HF Hub 加载) model_id = "AIDC-AI/Marco-MT-Algharb" # --- ZeroGPU 修改 1: # 在启动时 *只* 定义全局变量为 None # 大模型将在第一个请求到来时被加载 # --- model = None tokenizer = None generation_config = None print("ZeroGPU 启动脚本开始...") print(f"准备从 {model_id} 加载 Tokenizer...") # Tokenizer 很小, 可以在启动时加载 # ★★★ 提醒: 这仍然需要你已在 Space settings 中设置 HF_TOKEN 密钥 ★★★ try: tokenizer = AutoTokenizer.from_pretrained( model_id, trust_remote_code=True ) print("Tokenizer 加载成功!") # --- ZeroGPU 修改 2: # Tokenizer 加载成功后, *立即* 定义 GenerationConfig # (这解决了你之前关于 Qwen3 停止 token 的问题) # --- im_end_id = tokenizer.convert_tokens_to_ids("<|im_end|>") eot_id = tokenizer.eos_token_id print(f"设置停止 IDs: <|im_end|_id={im_end_id}, <|endoftext|_id={eot_id}") generation_config = GenerationConfig( do_sample=False, max_new_tokens=512, eos_token_id=[im_end_id, eot_id], pad_token_id=eot_id ) print("GenerationConfig 配置成功。") except Exception as e: print(f"Tokenizer 加载失败: {e}") print("!! 严重错误: 如果这是 Gated Repo 问题, 请确保 HF_TOKEN 密钥已设置并重启 Space。") # 语言代码到全名的映射 (保持不变) source_lang_name_map = { "en": "english", "ja": "japanese", "cs": "czech", "de": "german", } target_lang_name_map = { "zh": "chinese", "ko": "korean", "ja": "japanese", "ar": "arabic", "cs": "czech", "ru": "russian", "uk": "ukraine", "et": "estonian", "bho": "bhojpuri", "sr_latin": "serbian", "de": "german", } # -------------------------------------------------------------------------- # 2. 定义核心翻译函数 (修改版) # -------------------------------------------------------------------------- @spaces.GPU def translate(source_text, source_lang_code, target_lang_code): """ 接收用户输入并返回翻译结果 (ZeroGPU: 在首次调用时加载模型) """ global model # ★★★ 关键: 引用全局 'model' 变量 # --- ZeroGPU 修改 3: 首次调用时加载模型 --- if model is None: if tokenizer is None: return "错误:Tokenizer 未能成功加载,无法继续。请检查启动日志。" print("--- 首次请求 ---") print("检测到模型未加载。正在加载模型到 ZeroGPU (Nvidia H200)...") try: # 这一步会触发 ZeroGPU 分配 H200 model = AutoModelForCausalLM.from_pretrained( model_id, torch_dtype="auto", device_map="auto", # 'auto' 将会检测到 H200 trust_remote_code=True ) model.eval() print("模型已成功加载到 GPU!") except Exception as e: print(f"在首次加载时模型失败: {e}") return f"错误:模型在加载到 GPU 时失败: {e}" # ----------------------------------------- # (从这里开始, 代码与之前版本相同) # 简单的输入验证 if not source_text or not source_text.strip(): return "" source_language_name = source_lang_name_map.get(source_lang_code, "the source language") target_language_name = target_lang_name_map.get(target_lang_code, "the target language") prompt = ( f"Human: Please translate the following text into {target_language_name}: \n" f"{source_text}<|im_end|>\n" f"Assistant:" ) try: inputs = tokenizer(prompt, return_tensors="pt").to(model.device) with torch.no_grad(): outputs = model.generate( **inputs, generation_config=generation_config ) input_length = inputs.input_ids.shape[1] generated_ids = outputs[0][input_length:] generated_text = tokenizer.decode(generated_ids, skip_special_tokens=True).strip() return generated_text except Exception as e: print(f"翻译过程中出错: {e}") return f"翻译时发生错误: {e}" # -------------------------------------------------------------------------- # 3. 创建并配置 Gradio 界面 (这部分保持不变) # -------------------------------------------------------------------------- # <--- 定义自定义 CSS 样式 ---> css = """ /* ... 你的所有 CSS 样式 ... */ .gradio-textbox { min-height: 300px !important; } """ # <--- 修复: choices 定义 --- source_lang_choices = [(name.capitalize(), code) for code, name in source_lang_name_map.items()] target_lang_choices = [(name.capitalize(), code) for code, name in target_lang_name_map.items()] # <--- 使用 gr.Blocks 并保持主题 ---> with gr.Blocks( theme=gr.themes.Soft(primary_hue="amber", secondary_hue="amber"), css=css, ) as demo: gr.HTML( """
""" ) # --- 标题 --- gr.HTML(f""" """) # --- 翻译器主界面 (两栏布局) --- with gr.Row(variant="panel", equal_height=True): # --- 左侧输入卡片 --- with gr.Group(): source_lang_dd = gr.Dropdown( choices=source_lang_choices, value="en", label="源语言 (Source Language)" ) source_text_tb = gr.Textbox( lines=10, label="源文本 (Source Text)", placeholder="Enter text to translate here...", elem_classes=["gradio-textbox"] ) # --- 右侧输出卡片 --- with gr.Group(): target_lang_dd = gr.Dropdown( choices=target_lang_choices, value="zh", label="目标语言 (Target Language)" ) output_text_tb = gr.Textbox( lines=10, label="翻译结果 (Translation)", interactive=False, elem_classes=["gradio-textbox"] ) # --- 按钮行 --- with gr.Row(): clear_btn = gr.ClearButton( value="清除 (Clear)", components=[source_text_tb, output_text_tb, source_lang_dd, target_lang_dd] ) submit_btn = gr.Button("翻译 (Submit)", variant="primary", scale=1) # --- 示例 --- example_list = [ ["The quick brown fox jumps over the lazy dog.", "en", "zh"], ["The sunset painted the sky with brilliant shades of orange and purple.", "en", "ko"], ["The ancient ruins stand as a silent testament to the rise and fall of a great civilization.", "en", "ja"], ] gr.Examples( examples=example_list, inputs=[source_text_tb, source_lang_dd, target_lang_dd] ) # --- 支持的语向卡片 --- gr.HTML(f"""