SmolVLA部署教程Gradio界面国际化i18n多语言支持实现1. 项目简介与国际化需求SmolVLA是一个专门为经济型机器人设计的紧凑型视觉-语言-动作模型。它体积小巧但功能强大能够理解图像、处理语言指令并生成相应的机器人动作。这个模型特别适合那些预算有限但又需要智能机器人解决方案的场景。现在这个模型有一个基于Gradio的Web界面让用户可以通过浏览器直接与模型交互。你上传几张图片输入一些指令它就能告诉机器人该怎么动。听起来很酷对吧但这里有个问题这个界面目前只有英文版本。想象一下如果你的团队里有说中文、日语、西班牙语的成员或者你的产品要面向全球用户每个人都得用英文操作这体验就不太友好了。这就是为什么我们要给这个界面加上多语言支持也就是国际化i18n。国际化不是简单的翻译而是让界面能够根据用户的语言偏好自动切换显示语言。今天我就带你一步步实现这个功能让SmolVLA的Gradio界面真正走向世界。2. 环境准备与基础部署2.1 检查现有环境首先我们得确保SmolVLA的基础环境已经搭建好了。如果你还没部署别担心跟着我做就行。打开终端进入项目目录cd /root/smolvla_base看看目录里有什么文件ls -la你应该能看到这些文件app.py- 主程序文件config.json- 模型配置文件requirements.txt- 依赖包列表start.sh- 启动脚本USAGE.md- 使用说明2.2 安装必要依赖确保所有依赖都安装好了pip install -r requirements.txt如果requirements.txt里没有国际化相关的包我们还需要额外安装pip install gradio4.0.0 pip install python-i18n这里解释一下几个关键包gradio- 构建Web界面的框架python-i18n- 处理多语言翻译的库num2words- 把数字转成文字有些语言需要2.3 启动基础服务先试试能不能正常启动python /root/smolvla_base/app.py如果一切正常你应该能看到类似这样的输出Running on local URL: http://127.0.0.1:7860用浏览器打开http://localhost:7860就能看到原始的英文界面了。记住这个界面长什么样等会儿我们要把它变成多语言的。3. 国际化方案设计与实现3.1 理解Gradio的界面结构在开始改代码之前我们先看看app.py里界面是怎么构建的。打开文件看看# 这是界面的大致结构简化版 import gradio as gr def create_interface(): with gr.Blocks() as demo: gr.Markdown(# SmolVLA Web Interface) with gr.Row(): # 图像输入部分 with gr.Column(): gr.Markdown(## Image Input) image_input gr.Image(...) # 机器人状态部分 with gr.Column(): gr.Markdown(## Robot State) joint0 gr.Slider(...) joint1 gr.Slider(...) # ... 其他关节 # 语言指令 gr.Markdown(## Language Instruction) instruction gr.Textbox(...) # 生成按钮 generate_btn gr.Button( Generate Robot Action) # 结果显示 gr.Markdown(## Results) output gr.Textbox(...) return demo看到问题了吗所有文字都是硬编码的英文。比如SmolVLA Web Interface、Image Input、Generate Robot Action这些。3.2 设计多语言架构我们要做的就是把所有硬编码的文字提取出来放到翻译文件里。这里我设计一个简单的三层架构语言配置文件- 存储所有语言的翻译翻译函数- 根据当前语言返回对应文字界面构建- 使用翻译函数而不是硬编码文字先创建语言文件目录mkdir -p /root/smolvla_base/locales3.3 创建翻译文件创建英文翻译文件作为基准cat /root/smolvla_base/locales/en.json EOF { app_title: SmolVLA Web Interface, image_input: Image Input, image_input_desc: Upload or capture 3 perspective images, robot_state: Robot State, joint_0: Base Rotation, joint_1: Shoulder, joint_2: Elbow, joint_3: Wrist Bend, joint_4: Wrist Rotation, joint_5: Gripper, language_instruction: Language Instruction, instruction_placeholder: Pick up the red cube and place it in the blue box, generate_button: Generate Robot Action, results: Results, predicted_action: Predicted Action, input_state: Input State, running_mode: Running Mode, quick_test: Quick Test Examples, example_1: Pick and Place: Grab red cube into blue box, example_2: Reach Task: Reach forward to grasp object on table, example_3: Return Home: Return gripper to home and close, example_4: Stack Task: Stack yellow cube on green cube, loading: Loading..., generating: Generating action..., complete: Complete, error: Error, language_selector: Language } EOF再创建中文翻译文件cat /root/smolvla_base/locales/zh.json EOF { app_title: SmolVLA Web 界面, image_input: 图像输入, image_input_desc: 上传或拍摄3个视角的图像, robot_state: 机器人状态, joint_0: 基座旋转, joint_1: 肩部, joint_2: 肘部, joint_3: 腕部弯曲, joint_4: 腕部旋转, joint_5: 夹爪, language_instruction: 语言指令, instruction_placeholder: 抓起红色方块放入蓝色盒子, generate_button: 生成机器人动作, results: 结果, predicted_action: 预测动作, input_state: 输入状态, running_mode: 运行模式, quick_test: 快速测试示例, example_1: 抓取放置: 抓取红色方块放入蓝色盒子, example_2: 伸展任务: 向前抓取桌面物体, example_3: 回原位: 夹爪回原位并关闭, example_4: 堆叠任务: 将黄色方块堆在绿色方块上, loading: 加载中..., generating: 生成动作中..., complete: 完成, error: 错误, language_selector: 语言选择 } EOF你可以用同样的方法添加更多语言比如日语、西班牙语等。4. 修改主程序实现多语言4.1 创建翻译工具在app.py同目录下创建一个新的翻译工具文件# /root/smolvla_base/translation.py import json import os class Translator: def __init__(self, locale_dirlocales, default_langen): self.locale_dir locale_dir self.default_lang default_lang self.translations {} self.current_lang default_lang # 加载所有语言文件 self.load_all_translations() def load_all_translations(self): 加载所有语言翻译文件 if not os.path.exists(self.locale_dir): os.makedirs(self.locale_dir) for filename in os.listdir(self.locale_dir): if filename.endswith(.json): lang_code filename.split(.)[0] filepath os.path.join(self.locale_dir, filename) try: with open(filepath, r, encodingutf-8) as f: self.translations[lang_code] json.load(f) except Exception as e: print(fError loading {filename}: {e}) def set_language(self, lang_code): 设置当前语言 if lang_code in self.translations: self.current_lang lang_code return True return False def get_languages(self): 获取支持的语言列表 return list(self.translations.keys()) def t(self, key, **kwargs): 获取翻译文本 # 先从当前语言获取 if (self.current_lang in self.translations and key in self.translations[self.current_lang]): text self.translations[self.current_lang][key] # 如果当前语言没有用默认语言 elif key in self.translations.get(self.default_lang, {}): text self.translations[self.default_lang][key] # 如果都没有返回键名 else: text key # 替换参数如果有 if kwargs: for k, v in kwargs.items(): text text.replace(f{{{k}}}, str(v)) return text # 创建全局翻译器实例 translator Translator()4.2 修改主程序文件现在我们来修改app.py让它支持多语言。这是修改后的核心部分# /root/smolvla_base/app.py import gradio as gr import torch import numpy as np from PIL import Image import os import json # 导入我们的翻译工具 from translation import translator # 添加语言切换的回调函数 def change_language(lang): 切换界面语言 if translator.set_language(lang): # 这里我们返回一个刷新信号 # 实际刷新会在Gradio的js回调中处理 return gr.update(valuelang) return gr.update() def create_interface(): # 获取支持的语言列表 supported_langs translator.get_languages() with gr.Blocks(titletranslator.t(app_title)) as demo: # 语言选择器放在右上角 with gr.Row(): gr.Markdown(f# {translator.t(app_title)}) lang_dropdown gr.Dropdown( choicessupported_langs, valuetranslator.current_lang, labeltranslator.t(language_selector), scale0, min_width100 ) # 图像输入部分 - 现在使用翻译文本 with gr.Row(): with gr.Column(): gr.Markdown(f## {translator.t(image_input)}) gr.Markdown(translator.t(image_input_desc)) # 三个图像输入 image_inputs [] for i in range(3): image_inputs.append( gr.Image( labelfView {i1}, typepil, height200 ) ) # 机器人状态部分 with gr.Column(): gr.Markdown(f## {translator.t(robot_state)}) # 六个关节的状态输入 joint_sliders [] joint_labels [ translator.t(joint_0), translator.t(joint_1), translator.t(joint_2), translator.t(joint_3), translator.t(joint_4), translator.t(joint_5) ] for i, label in enumerate(joint_labels): joint_sliders.append( gr.Slider( minimum-3.14, maximum3.14, value0.0, step0.01, labellabel ) ) # 语言指令输入 gr.Markdown(f## {translator.t(language_instruction)}) instruction gr.Textbox( label, placeholdertranslator.t(instruction_placeholder), lines3 ) # 生成按钮 generate_btn gr.Button( translator.t(generate_button), variantprimary ) # 结果显示区域 gr.Markdown(f## {translator.t(results)}) with gr.Row(): with gr.Column(): gr.Markdown(f### {translator.t(predicted_action)}) action_output gr.Textbox(label, lines6) with gr.Column(): gr.Markdown(f### {translator.t(input_state)}) state_output gr.Textbox(label, lines6) with gr.Column(): gr.Markdown(f### {translator.t(running_mode)}) mode_output gr.Textbox(label, lines2) # 快速测试示例 gr.Markdown(f## {translator.t(quick_test)}) with gr.Row(): examples [ [None]*3 [0]*6 [translator.t(example_1)], [None]*3 [0.5, 0.2, -0.3, 0, 0, 0] [translator.t(example_2)], [None]*3 [0]*5 [1.0] [translator.t(example_3)], [None]*3 [0.3, 0.4, -0.2, 0.1, 0, 0] [translator.t(example_4)] ] example_component gr.Examples( examplesexamples, inputsimage_inputs joint_sliders [instruction], labelClick to load example ) # 语言切换的回调 lang_dropdown.change( fnchange_language, inputs[lang_dropdown], outputs[lang_dropdown], # 这里添加js回调来刷新页面 js function(lang) { // 简单刷新页面来应用新语言 setTimeout(() { window.location.reload(); }, 100); return lang; } ) return demo # 推理函数保持原有逻辑只更新显示文本 def run_inference(images, joint_states, instruction): # 这里是你原有的推理逻辑 # 为了演示我简化一下 # 模拟处理时间 import time time.sleep(1) # 模拟返回结果 result { predicted_action: [0.1, 0.2, -0.1, 0.05, 0.02, 0.0], input_state: joint_states, mode: Real Model Inference } # 使用翻译文本格式化输出 output_text f{translator.t(predicted_action)}:\n output_text str(result[predicted_action]) \n\n output_text f{translator.t(input_state)}:\n output_text str(result[input_state]) \n\n output_text f{translator.t(running_mode)}:\n output_text result[mode] return output_text # 主函数 def main(): # 创建界面 demo create_interface() # 设置推理函数 # 注意这里需要根据你的实际输入组件调整 generate_btn.click( fnrun_inference, inputs[*image_inputs, *joint_sliders, instruction], outputs[action_output] ) # 启动服务 demo.launch( server_name0.0.0.0, server_port7860, shareFalse ) if __name__ __main__: main()5. 高级功能与优化5.1 实时语言切换无刷新上面的实现需要刷新页面才能切换语言体验不太好。我们可以用Gradio的动态组件实现无刷新切换# 在translation.py中添加这个函数 def get_all_translations(lang): 获取指定语言的所有翻译 translator.set_language(lang) return translator.translations.get(lang, {}) # 在app.py中添加动态更新函数 def update_ui_text(lang): 更新所有UI文本 translator.set_language(lang) translations translator.translations.get(lang, {}) # 返回所有需要更新的组件 return [ gr.Markdown.update(valuef# {translations.get(app_title, )}), gr.Markdown.update(valuef## {translations.get(image_input, )}), gr.Markdown.update(valuetranslations.get(image_input_desc, )), gr.Markdown.update(valuef## {translations.get(robot_state, )}), # ... 更新所有其他文本组件 gr.Button.update(valuetranslations.get(generate_button, )), gr.Markdown.update(valuef## {translations.get(results, )}), gr.Markdown.update(valuef### {translations.get(predicted_action, )}), gr.Markdown.update(valuef### {translations.get(input_state, )}), gr.Markdown.update(valuef### {translations.get(running_mode, )}), gr.Markdown.update(valuef## {translations.get(quick_test, )}), gr.Textbox.update(placeholdertranslations.get(instruction_placeholder, )) ]5.2 保存用户语言偏好我们可以把用户的语言选择保存到cookie或localStorage// 在Gradio的js回调中添加 function saveLanguagePreference(lang) { localStorage.setItem(smolvla_language, lang); return lang; } function loadLanguagePreference() { return localStorage.getItem(smolvla_language) || en; }然后在界面加载时自动应用保存的语言# 在create_interface函数开头添加 initial_lang gr.Textbox(valueen, visibleFalse) # 添加加载时的js demo.load( fnNone, inputs[], outputs[], js function() { const savedLang localStorage.getItem(smolvla_language); if (savedLang) { // 触发语言切换 document.querySelector([data-testiddropdown]).value savedLang; document.querySelector([data-testiddropdown]).dispatchEvent(new Event(change)); } } )5.3 支持更多语言添加日语翻译示例{ app_title: SmolVLA Web インターフェース, image_input: 画像入力, image_input_desc: 3つの視点画像をアップロードまたは撮影, robot_state: ロボット状態, joint_0: ベース回転, joint_1: ショルダー, joint_2: エルボー, joint_3: 手首曲げ, joint_4: 手首回転, joint_5: グリッパー, language_instruction: 言語指示, instruction_placeholder: 赤い立方体をつかんで青い箱に入れてください, generate_button: ロボット動作を生成, results: 結果, predicted_action: 予測動作, input_state: 入力状態, running_mode: 実行モード, quick_test: クイックテスト例, example_1: ピックアンドプレース: 赤い立方体を青い箱に入れる, example_2: リーチタスク: 前方に伸びてテーブルの物体をつかむ, example_3: ホームポジションに戻る: グリッパーをホームポジションに戻して閉じる, example_4: スタックタスク: 黄色い立方体を緑色の立方体の上に積む, loading: 読み込み中..., generating: 動作生成中..., complete: 完了, error: エラー, language_selector: 言語 }6. 部署测试与问题解决6.1 完整部署步骤现在让我们把所有的修改整合起来完成部署备份原始文件重要cp /root/smolvla_base/app.py /root/smolvla_base/app.py.backup创建翻译文件目录和文件mkdir -p /root/smolvla_base/locales # 创建en.json、zh.json、ja.json等翻译文件创建翻译工具# 创建translation.py文件修改主程序# 用上面的代码替换app.py测试运行cd /root/smolvla_base python app.py6.2 常见问题解决问题1翻译文件找不到FileNotFoundError: [Errno 2] No such file or directory: locales/en.json解决确保locales目录存在且包含翻译文件。问题2Gradio组件更新错误ValueError: Cannot update component of type Markdown with value of type str解决确保返回的是gr.update()对象而不是普通字符串。问题3语言切换不生效解决检查浏览器控制台是否有JavaScript错误确保localStorage可用。问题4界面布局错乱解决Gradio在动态更新组件时可能重排布局可以尝试使用gr.Column和gr.Row明确布局设置固定的组件高度使用scale参数控制组件宽度比例6.3 性能优化建议如果你的界面响应变慢可以尝试这些优化懒加载翻译不要一次性加载所有语言按需加载缓存翻译把翻译结果缓存起来避免重复读取文件精简翻译文件只翻译实际用到的文本使用CDN如果翻译文件很大可以考虑放到CDN# 懒加载示例 class LazyTranslator: def __init__(self): self.loaded_langs {} def load_lang(self, lang_code): if lang_code not in self.loaded_langs: filepath flocales/{lang_code}.json with open(filepath, r, encodingutf-8) as f: self.loaded_langs[lang_code] json.load(f) return self.loaded_langs[lang_code]7. 总结通过这个教程我们成功为SmolVLA的Gradio界面添加了多语言支持。现在用户可以根据自己的偏好选择界面语言大大提升了用户体验。回顾一下我们完成的工作分析了原有界面的结构找出所有需要翻译的文本设计了翻译系统架构创建了可扩展的多语言支持实现了翻译文件管理支持轻松添加新语言修改了Gradio界面用翻译函数替换硬编码文本添加了语言切换功能支持实时切换有刷新或无刷新版本优化了用户体验保存用户语言偏好这个方案有几个明显的优点易于维护所有翻译文本集中管理修改方便扩展性强添加新语言只需创建新的JSON文件用户体验好界面语言符合用户习惯代码清晰业务逻辑和界面文本分离如果你还想进一步优化可以考虑添加自动检测浏览器语言功能支持RTL从右到左语言布局添加翻译管理后台方便非技术人员维护集成专业的翻译服务API现在你的SmolVLA界面已经准备好服务全球用户了。无论他们说什么语言都能轻松操作这个强大的机器人控制界面。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。