Skip to content

Commit a2c40b7

Browse files
committed
v1.9.6: 新增API配置管理功能 - 预设管理、API测试、获取模型列表
1 parent a0effa9 commit a2c40b7

13 files changed

Lines changed: 532 additions & 29 deletions

File tree

desktop_qt_ui/app_logic.py

Lines changed: 198 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -378,22 +378,52 @@ def get_hq_prompt_options(self) -> List[str]:
378378
@pyqtSlot(str, str)
379379
def save_env_var(self, key: str, value: str):
380380
self.config_service.save_env_var(key, value)
381-
self.logger.info(f"Saved {key} to .env file.")
381+
# 不再输出日志,避免刷屏
382382

383383
# region 预设管理
384384
def get_presets_list(self) -> List[str]:
385385
"""获取所有预设名称列表"""
386386
return self.preset_service.get_presets_list()
387387

388388
@pyqtSlot(str)
389-
def save_preset(self, preset_name: str) -> bool:
390-
"""保存当前.env配置为预设"""
389+
def save_preset(self, preset_name: str, copy_current: bool = False) -> bool:
390+
"""保存预设
391+
392+
Args:
393+
preset_name: 预设名称
394+
copy_current: 是否复制当前配置。False=创建空白预设,True=复制当前配置
395+
"""
391396
try:
392-
env_vars = self.config_service.load_env_vars()
393-
success = self.preset_service.save_preset(preset_name, env_vars)
394-
if success:
395-
self._ui_log(f"预设已保存: {preset_name}")
397+
if copy_current:
398+
# 复制当前配置模式:保存当前翻译器相关的环境变量
399+
current_translator = self.config_service.get_config().translator.translator
400+
translator_env_vars = self.config_service.get_all_env_vars(current_translator)
401+
all_env_vars = self.config_service.load_env_vars()
402+
403+
# 只保存当前翻译器相关的环境变量,并且只保存非空的值
404+
filtered_env_vars = {}
405+
for key in translator_env_vars:
406+
value = all_env_vars.get(key, "")
407+
if value and value.strip():
408+
filtered_env_vars[key] = value
409+
410+
success = self.preset_service.save_preset(preset_name, filtered_env_vars)
411+
if success:
412+
# 不输出日志,避免刷屏
413+
pass
396414
else:
415+
# 创建空白预设模式:只保存空的环境变量结构
416+
current_translator = self.config_service.get_config().translator.translator
417+
translator_env_vars = self.config_service.get_all_env_vars(current_translator)
418+
419+
# 创建空白的环境变量字典
420+
empty_env_vars = {key: "" for key in translator_env_vars}
421+
422+
success = self.preset_service.save_preset(preset_name, empty_env_vars)
423+
if success:
424+
self._ui_log(f"预设已创建: {preset_name} (空白预设)")
425+
426+
if not success:
397427
self._ui_log(f"保存预设失败: {preset_name}", "ERROR")
398428
return success
399429
except Exception as e:
@@ -413,7 +443,8 @@ def load_preset(self, preset_name: str) -> bool:
413443
# 批量保存环境变量
414444
success = self.config_service.save_env_vars(env_vars)
415445
if success:
416-
self._ui_log(f"预设已加载: {preset_name}")
446+
# 不输出日志,避免刷屏
447+
pass
417448
else:
418449
self._ui_log(f"应用预设失败: {preset_name}", "ERROR")
419450
return success
@@ -437,6 +468,165 @@ def delete_preset(self, preset_name: str) -> bool:
437468
self._ui_log(f"删除预设失败: {e}", "ERROR")
438469
return False
439470
# endregion
471+
472+
# region API测试
473+
async def test_api_connection_async(self, translator_key: str, api_key: str, api_base: str = None, model: str = None) -> tuple[bool, str]:
474+
"""异步测试API连接(如果指定了模型,会测试该模型是否可用)"""
475+
try:
476+
if "openai" in translator_key.lower():
477+
from openai import AsyncOpenAI
478+
client = AsyncOpenAI(
479+
api_key=api_key,
480+
base_url=api_base or "https://api.openai.com/v1"
481+
)
482+
483+
# 如果指定了模型,测试该模型是否可用
484+
if model and model.strip():
485+
try:
486+
# 尝试用该模型发送一个简单的测试请求
487+
response = await client.chat.completions.create(
488+
model=model,
489+
messages=[{"role": "user", "content": "test"}],
490+
max_tokens=5
491+
)
492+
return True, f"连接成功,模型 {model} 可用"
493+
except Exception as e:
494+
# 如果模型测试失败,返回详细错误
495+
return False, f"连接成功但模型 {model} 不可用: {str(e)}"
496+
else:
497+
# 没有指定模型,只测试连接
498+
models = await client.models.list()
499+
return True, "连接成功"
500+
501+
elif "gemini" in translator_key.lower():
502+
import google.generativeai as genai
503+
504+
# 如果指定了自定义API Base,使用OpenAI兼容模式
505+
if api_base and api_base != "https://generativelanguage.googleapis.com":
506+
from openai import AsyncOpenAI
507+
client = AsyncOpenAI(
508+
api_key=api_key,
509+
base_url=api_base
510+
)
511+
512+
# 如果指定了模型,测试该模型
513+
if model and model.strip():
514+
try:
515+
response = await client.chat.completions.create(
516+
model=model,
517+
messages=[{"role": "user", "content": "test"}],
518+
max_tokens=5
519+
)
520+
return True, f"连接成功,模型 {model} 可用"
521+
except Exception as e:
522+
return False, f"连接成功但模型 {model} 不可用: {str(e)}"
523+
else:
524+
models = await client.models.list()
525+
return True, "连接成功"
526+
else:
527+
# 使用官方Gemini API
528+
genai.configure(api_key=api_key)
529+
530+
# 如果指定了模型,测试该模型
531+
if model and model.strip():
532+
try:
533+
test_model = genai.GenerativeModel(model)
534+
response = test_model.generate_content("test")
535+
return True, f"连接成功,模型 {model} 可用"
536+
except Exception as e:
537+
return False, f"连接成功但模型 {model} 不可用: {str(e)}"
538+
else:
539+
models = genai.list_models()
540+
return True, "连接成功"
541+
542+
elif "sakura" in translator_key.lower():
543+
# Sakura使用OpenAI兼容API
544+
from openai import AsyncOpenAI
545+
if not api_base:
546+
return False, "请先配置SAKURA_API_BASE"
547+
client = AsyncOpenAI(
548+
api_key="sk-114514", # Sakura使用固定密钥
549+
base_url=api_base
550+
)
551+
552+
# 如果指定了模型,测试该模型
553+
if model and model.strip():
554+
try:
555+
response = await client.chat.completions.create(
556+
model=model,
557+
messages=[{"role": "user", "content": "test"}],
558+
max_tokens=5
559+
)
560+
return True, f"连接成功,模型 {model} 可用"
561+
except Exception as e:
562+
return False, f"连接成功但模型 {model} 不可用: {str(e)}"
563+
else:
564+
models = await client.models.list()
565+
return True, "连接成功"
566+
567+
else:
568+
return False, "该翻译器不支持API测试"
569+
570+
except Exception as e:
571+
return False, f"连接失败: {str(e)}"
572+
573+
async def get_available_models_async(self, translator_key: str, api_key: str, api_base: str = None) -> tuple[bool, List[str], str]:
574+
"""异步获取可用模型列表"""
575+
try:
576+
if "openai" in translator_key.lower():
577+
from openai import AsyncOpenAI
578+
client = AsyncOpenAI(
579+
api_key=api_key,
580+
base_url=api_base or "https://api.openai.com/v1"
581+
)
582+
models_response = await client.models.list()
583+
584+
# 获取所有模型ID,不过滤
585+
model_ids = [m.id for m in models_response.data]
586+
model_ids.sort(reverse=True) # 新模型在前
587+
588+
return True, model_ids, "获取成功"
589+
590+
elif "gemini" in translator_key.lower():
591+
import google.generativeai as genai
592+
593+
# 如果指定了自定义API Base,使用OpenAI兼容模式
594+
if api_base and api_base != "https://generativelanguage.googleapis.com":
595+
from openai import AsyncOpenAI
596+
client = AsyncOpenAI(
597+
api_key=api_key,
598+
base_url=api_base
599+
)
600+
models_response = await client.models.list()
601+
model_ids = [m.id for m in models_response.data]
602+
return True, model_ids, "获取成功"
603+
else:
604+
# 使用官方Gemini API - 返回所有模型,不过滤
605+
genai.configure(api_key=api_key)
606+
models = genai.list_models()
607+
# 获取所有模型名称
608+
model_names = [m.name.replace("models/", "") for m in models]
609+
return True, model_names, "获取成功"
610+
611+
elif "sakura" in translator_key.lower():
612+
# Sakura使用OpenAI兼容API
613+
from openai import AsyncOpenAI
614+
if not api_base:
615+
return False, [], "请先配置SAKURA_API_BASE"
616+
client = AsyncOpenAI(
617+
api_key="sk-114514",
618+
base_url=api_base
619+
)
620+
models_response = await client.models.list()
621+
model_ids = [m.id for m in models_response.data]
622+
return True, model_ids, "获取成功"
623+
624+
else:
625+
return False, [], "该翻译器不支持获取模型列表"
626+
627+
except Exception as e:
628+
return False, [], f"获取失败: {str(e)}"
629+
# endregion
440630

441631
# region 配置管理
442632
def load_config_file(self, config_path: str) -> bool:

desktop_qt_ui/locales/en_US.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,5 +667,17 @@
667667
"web_used": "Used",
668668
"web_unlimited_quota_info": "You have unlimited quota",
669669
"web_used_today": "Used today",
670-
"web_active_sessions": "Active Sessions"
670+
"web_active_sessions": "Active Sessions",
671+
"Test": "Test",
672+
"Testing": "Testing",
673+
"Get Models": "Get Models",
674+
"Select Model": "Select Model",
675+
"Available models:": "Available models:",
676+
"Please enter API key first": "Please enter API key first",
677+
"Testing API connection, please wait...": "Testing API connection, please wait...",
678+
"API connection test successful!": "API connection test successful!",
679+
"API connection test failed": "API connection test failed",
680+
"Fetching models, please wait...": "Fetching models, please wait...",
681+
"Failed to get models": "Failed to get models",
682+
"No models available": "No models available"
671683
}

desktop_qt_ui/locales/es_ES.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,5 +553,17 @@
553553
"web_total_files": "Total de Archivos",
554554
"web_total_storage": "Almacenamiento Total",
555555
"web_storage_used": "Almacenamiento Usado",
556-
"web_storage_available": "Almacenamiento Disponible"
556+
"web_storage_available": "Almacenamiento Disponible",
557+
"Test": "Probar",
558+
"Testing": "Probando",
559+
"Get Models": "Obtener Modelos",
560+
"Select Model": "Seleccionar Modelo",
561+
"Available models:": "Modelos disponibles:",
562+
"Please enter API key first": "Por favor, ingrese la clave API primero",
563+
"Testing API connection, please wait...": "Probando conexión API, por favor espere...",
564+
"API connection test successful!": "¡Prueba de conexión API exitosa!",
565+
"API connection test failed": "Prueba de conexión API fallida",
566+
"Fetching models, please wait...": "Obteniendo lista de modelos, por favor espere...",
567+
"Failed to get models": "Error al obtener lista de modelos",
568+
"No models available": "No hay modelos disponibles"
557569
}

desktop_qt_ui/locales/ja_JP.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,5 +549,17 @@
549549
"web_total_files": "総ファイル数",
550550
"web_total_storage": "総ストレージ",
551551
"web_storage_used": "使用済み容量",
552-
"web_storage_available": "利用可能容量"
552+
"web_storage_available": "利用可能容量",
553+
"Test": "テスト",
554+
"Testing": "テスト中",
555+
"Get Models": "モデルを取得",
556+
"Select Model": "モデルを選択",
557+
"Available models:": "利用可能なモデル:",
558+
"Please enter API key first": "先にAPIキーを入力してください",
559+
"Testing API connection, please wait...": "API接続をテスト中、お待ちください...",
560+
"API connection test successful!": "API接続テスト成功!",
561+
"API connection test failed": "API接続テスト失敗",
562+
"Fetching models, please wait...": "モデルリストを取得中、お待ちください...",
563+
"Failed to get models": "モデルリストの取得に失敗しました",
564+
"No models available": "利用可能なモデルがありません"
553565
}

desktop_qt_ui/locales/ko_KR.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,5 +553,17 @@
553553
"web_total_files": "총 파일 수",
554554
"web_total_storage": "총 저장 공간",
555555
"web_storage_used": "사용된 공간",
556-
"web_storage_available": "사용 가능한 공간"
556+
"web_storage_available": "사용 가능한 공간",
557+
"Test": "테스트",
558+
"Testing": "테스트 중",
559+
"Get Models": "모델 가져오기",
560+
"Select Model": "모델 선택",
561+
"Available models:": "사용 가능한 모델:",
562+
"Please enter API key first": "먼저 API 키를 입력하세요",
563+
"Testing API connection, please wait...": "API 연결을 테스트하는 중입니다. 잠시만 기다려주세요...",
564+
"API connection test successful!": "API 연결 테스트 성공!",
565+
"API connection test failed": "API 연결 테스트 실패",
566+
"Fetching models, please wait...": "모델 목록을 가져오는 중입니다. 잠시만 기다려주세요...",
567+
"Failed to get models": "모델 목록 가져오기 실패",
568+
"No models available": "사용 가능한 모델이 없습니다"
557569
}

desktop_qt_ui/locales/zh_CN.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,5 +667,17 @@
667667
"web_image": "图片",
668668
"web_today": "今天",
669669
"web_this_week": "本周",
670-
"web_this_month": "本月"
670+
"web_this_month": "本月",
671+
"Test": "测试",
672+
"Testing": "测试中",
673+
"Get Models": "获取模型",
674+
"Select Model": "选择模型",
675+
"Available models:": "可用模型:",
676+
"Please enter API key first": "请先输入API密钥",
677+
"Testing API connection, please wait...": "正在测试API连接,请稍候...",
678+
"API connection test successful!": "API连接测试成功!",
679+
"API connection test failed": "API连接测试失败",
680+
"Fetching models, please wait...": "正在获取模型列表,请稍候...",
681+
"Failed to get models": "获取模型列表失败",
682+
"No models available": "没有可用的模型"
671683
}

desktop_qt_ui/locales/zh_TW.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,5 +563,17 @@
563563
"web_image": "圖片",
564564
"web_today": "今天",
565565
"web_this_week": "本週",
566-
"web_this_month": "本月"
566+
"web_this_month": "本月",
567+
"Test": "測試",
568+
"Testing": "測試中",
569+
"Get Models": "獲取模型",
570+
"Select Model": "選擇模型",
571+
"Available models:": "可用模型:",
572+
"Please enter API key first": "請先輸入API密鑰",
573+
"Testing API connection, please wait...": "正在測試API連接,請稍候...",
574+
"API connection test successful!": "API連接測試成功!",
575+
"API connection test failed": "API連接測試失敗",
576+
"Fetching models, please wait...": "正在獲取模型列表,請稍候...",
577+
"Failed to get models": "獲取模型列表失敗",
578+
"No models available": "沒有可用的模型"
567579
}

0 commit comments

Comments
 (0)