from InquirerPy import inquirer import sys import os from pathlib import Path from msdl.config import ( CLOUD_LLM_DOCKERFILE, LOCAL_LLM_DOCKERFILE, ) from msdl.i18n import ( t, get_available_languages, set_language, get_env_variable, ) from msdl.utils import ( clean_api_key, get_model_formats, get_existing_api_key, save_api_key_to_env, validate_api_key, ) SEARCH_ENGINES = { "DuckDuckGoSearch": { "name": "DuckDuckGo", "key": "DUCKDUCKGO", "requires_key": False, "env_var": None }, "BingSearch": { "name": "Bing", "key": "BING", "requires_key": True, "env_var": "BING_SEARCH_API_KEY" }, "BraveSearch": { "name": "Brave", "key": "BRAVE", "requires_key": True, "env_var": "BRAVE_SEARCH_API_KEY" }, "GoogleSearch": { "name": "Google Serper", "key": "GOOGLE", "requires_key": True, "env_var": "GOOGLE_SERPER_API_KEY" }, "TencentSearch": { "name": "Tencent", "key": "TENCENT", "requires_key": True, "env_vars": ["TENCENT_SEARCH_SECRET_ID", "TENCENT_SEARCH_SECRET_KEY"] } } def get_language_choice(): """Get user's language preference""" def _get_language_options(): available_langs = get_available_languages() lang_choices = { "en": "English", "zh_CN": "中文" } return [{"name": f"{lang_choices.get(lang, lang)}", "value": lang} for lang in available_langs] current_lang = get_env_variable("LAUNCHER_INTERACTION_LANGUAGE") if not current_lang: lang_options = _get_language_options() language = inquirer.select( message=t("SELECT_INTERFACE_LANGUAGE"), choices=lang_options, default="en" ).execute() if language: set_language(language) sys.stdout.flush() restart_program() def get_backend_language(): """Get user's backend language preference""" return inquirer.select( message=t("SELECT_BACKEND_LANGUAGE"), choices=[ {"name": t("CHINESE"), "value": "cn"}, {"name": t("ENGLISH"), "value": "en"}, ], default="cn", ).execute() def get_model_choice(): """Get user's model deployment type preference""" model_deployment_type = [ { "name": t("CLOUD_MODEL"), "value": CLOUD_LLM_DOCKERFILE }, { "name": t("LOCAL_MODEL"), "value": LOCAL_LLM_DOCKERFILE }, ] return inquirer.select( message=t("MODEL_DEPLOYMENT_TYPE"), choices=model_deployment_type, ).execute() def get_model_format(model): """Get user's model format preference""" model_formats = get_model_formats(model) return inquirer.select( message=t("MODEL_FORMAT_CHOICE"), choices=[{ "name": format, "value": format } for format in model_formats], ).execute() def _handle_api_key_input(env_var_name, message=None): """Handle API key input and validation for a given environment variable""" if message is None: message = t("PLEASE_INPUT_NEW_API_KEY", ENV_VAR_NAME=env_var_name) print(message) while True: api_key = inquirer.secret( message=t("PLEASE_INPUT_NEW_API_KEY_FROM_ZERO", ENV_VAR_NAME=env_var_name) ).execute() cleaned_api_key = clean_api_key(api_key) try: save_api_key_to_env(env_var_name, cleaned_api_key, t) break except ValueError as e: print(str(e)) retry = inquirer.confirm( message=t("RETRY_API_KEY_INPUT"), default=True ).execute() if not retry: print(t("API_KEY_INPUT_CANCELLED")) sys.exit(1) def handle_api_key_input(model, model_format): """Handle API key input and validation""" if model != CLOUD_LLM_DOCKERFILE: return env_var_name = { "internlm_silicon": "SILICON_API_KEY", "gpt4": "OPENAI_API_KEY", "qwen": "QWEN_API_KEY", }.get(model_format) existing_api_key = get_existing_api_key(env_var_name) if existing_api_key: use_existing = inquirer.confirm( message=t("CONFIRM_USE_EXISTING_API_KEY", ENV_VAR_NAME=env_var_name), default=True, ).execute() if use_existing: return print(t("CONFIRM_OVERWRITE_EXISTING_API_KEY", ENV_VAR_NAME=env_var_name)) try: save_api_key_to_env(model_format, clean_api_key(inquirer.secret( message=t("PLEASE_INPUT_NEW_API_KEY_FROM_ZERO", ENV_VAR_NAME=env_var_name) ).execute()), t) except ValueError as e: print(str(e)) retry = inquirer.confirm( message=t("RETRY_API_KEY_INPUT"), default=True ).execute() if not retry: print(t("API_KEY_INPUT_CANCELLED")) sys.exit(1) def get_search_engine(): """Get user's preferred search engine and handle API key if needed""" search_engine = inquirer.select( message=t("SELECT_SEARCH_ENGINE"), choices=[{ "name": f"{t(f'SEARCH_ENGINE_{info["key"]}')} ({t('NO_API_KEY_NEEDED') if not info['requires_key'] else t('API_KEY_REQUIRED')})", "value": engine } for engine, info in SEARCH_ENGINES.items()], ).execute() engine_info = SEARCH_ENGINES[search_engine] if engine_info['requires_key']: if search_engine == "TencentSearch": # Handle Tencent's special case with two keys for env_var in engine_info['env_vars']: is_id = "ID" in env_var message = t("TENCENT_ID_REQUIRED") if is_id else t("TENCENT_KEY_REQUIRED") existing_key = get_existing_api_key(env_var) if existing_key: use_existing = inquirer.confirm( message=t("CONFIRM_USE_EXISTING_API_KEY", ENV_VAR_NAME=env_var), default=True, ).execute() if not use_existing: _handle_api_key_input(env_var, message) else: _handle_api_key_input(env_var, message) else: # Handle standard case with single WEB_SEARCH_API_KEY env_var = engine_info['env_var'] existing_key = get_existing_api_key(env_var) if existing_key: use_existing = inquirer.confirm( message=t("CONFIRM_USE_EXISTING_API_KEY", ENV_VAR_NAME=env_var), default=True, ).execute() if not use_existing: _handle_api_key_input(env_var, t("WEB_SEARCH_KEY_REQUIRED")) else: _handle_api_key_input(env_var, t("WEB_SEARCH_KEY_REQUIRED")) print(t("SEARCH_ENGINE_CONFIGURED", engine=engine_info['name'])) return search_engine def restart_program(): """Restart the current program with the same arguments""" print(t("LANGUAGE_CHANGED_RESTARTING")) python = sys.executable os.execl(python, python, *sys.argv) def get_user_choices(): """Get all user choices in a single function""" # Get language preference get_language_choice() # Get backend language backend_language = get_backend_language() # Get model choice model = get_model_choice() # Get model format model_format = get_model_format(model) # Get search engine choice search_engine = get_search_engine() # Handle API key if needed handle_api_key_input(model, model_format) return backend_language, model, model_format, search_engine