feat: 优化LLM服务配置与迁移适配,并更新相关UI设置及中文翻译

This commit is contained in:
linyq 2025-11-19 20:00:08 +08:00
parent 6697535c57
commit 238c1c13f1
5 changed files with 167 additions and 74 deletions

View File

@ -217,6 +217,12 @@ class LiteLLMVisionProvider(VisionModelProvider):
if hasattr(self, '_api_base'):
completion_kwargs["api_base"] = self._api_base
# 支持动态传递 api_key 和 api_base
if "api_key" in kwargs:
completion_kwargs["api_key"] = kwargs["api_key"]
if "api_base" in kwargs:
completion_kwargs["api_base"] = kwargs["api_base"]
response = await acompletion(**completion_kwargs)
if response.choices and len(response.choices) > 0:
@ -407,6 +413,12 @@ class LiteLLMTextProvider(TextModelProvider):
if hasattr(self, '_api_base'):
completion_kwargs["api_base"] = self._api_base
# 支持动态传递 api_key 和 api_base (修复认证问题)
if "api_key" in kwargs:
completion_kwargs["api_key"] = kwargs["api_key"]
if "api_base" in kwargs:
completion_kwargs["api_base"] = kwargs["api_base"]
try:
# 调用 LiteLLM自动重试
response = await acompletion(**completion_kwargs)

View File

@ -251,7 +251,9 @@ class SubtitleAnalyzerAdapter:
UnifiedLLMService.analyze_subtitle,
subtitle_content=subtitle_content,
provider=self.provider,
temperature=1.0
temperature=1.0,
api_key=self.api_key,
api_base=self.base_url
)
return {
@ -301,7 +303,9 @@ class SubtitleAnalyzerAdapter:
system_prompt="你是一位专业的短视频解说脚本撰写专家。",
provider=self.provider,
temperature=temperature,
response_format="json"
response_format="json",
api_key=self.api_key,
api_base=self.base_url
)
# 清理JSON输出

View File

@ -5,6 +5,7 @@ import os
from app.config import config
from app.utils import utils
from loguru import logger
from app.services.llm.unified_service import UnifiedLLMService
def validate_api_key(api_key: str, provider: str) -> tuple[bool, str]:
@ -663,6 +664,8 @@ def render_vision_llm_settings(tr):
if config_changed and not validation_errors:
try:
config.save_config()
# 清除缓存,确保下次使用新配置
UnifiedLLMService.clear_cache()
if st_vision_api_key or st_vision_base_url or st_vision_model_name:
st.success(f"视频分析模型配置已保存LiteLLM")
except Exception as e:
@ -932,6 +935,8 @@ def render_text_llm_settings(tr):
if text_config_changed and not text_validation_errors:
try:
config.save_config()
# 清除缓存,确保下次使用新配置
UnifiedLLMService.clear_cache()
if st_text_api_key or st_text_base_url or st_text_model_name:
st.success(f"文案生成模型配置已保存LiteLLM")
except Exception as e:

View File

@ -49,11 +49,74 @@ def render_script_panel(tr):
def render_script_file(tr, params):
"""渲染脚本文件选择"""
# 定义功能模式
MODE_FILE = "file_selection"
MODE_AUTO = "auto"
MODE_SHORT = "short"
MODE_SUMMARY = "summary"
# 模式选项映射
mode_options = {
tr("Select/Upload Script"): MODE_FILE,
tr("Auto Generate"): MODE_AUTO,
tr("Short Generate"): MODE_SHORT,
tr("Short Drama Summary"): MODE_SUMMARY,
}
# 获取当前状态
current_path = st.session_state.get('video_clip_json_path', '')
# 确定当前选中的模式索引
default_index = 0
mode_keys = list(mode_options.keys())
if current_path == "auto":
default_index = mode_keys.index(tr("Auto Generate"))
elif current_path == "short":
default_index = mode_keys.index(tr("Short Generate"))
elif current_path == "summary":
default_index = mode_keys.index(tr("Short Drama Summary"))
else:
default_index = mode_keys.index(tr("Select/Upload Script"))
# 1. 渲染功能选择下拉框
# 使用 segmented_control 替代 selectbox提供更好的视觉体验
default_mode_label = mode_keys[default_index]
# 定义回调函数来处理状态更新
def update_script_mode():
# 获取当前选中的标签
selected_label = st.session_state.script_mode_selection
if selected_label:
# 更新实际的 path 状态
new_mode = mode_options[selected_label]
st.session_state.video_clip_json_path = new_mode
params.video_clip_json_path = new_mode
else:
# 如果用户取消选择segmented_control 允许取消),恢复到默认或上一个状态
# 这里我们强制保持当前状态,或者重置为默认
st.session_state.script_mode_selection = default_mode_label
# 渲染组件
selected_mode_label = st.segmented_control(
tr("Video Type"),
options=mode_keys,
default=default_mode_label,
key="script_mode_selection",
on_change=update_script_mode
)
# 处理未选择的情况虽然有default但在某些交互下可能为空
if not selected_mode_label:
selected_mode_label = default_mode_label
selected_mode = mode_options[selected_mode_label]
# 2. 根据选择的模式处理逻辑
if selected_mode == MODE_FILE:
# --- 文件选择模式 ---
script_list = [
(tr("None"), ""),
(tr("Auto Generate"), "auto"),
(tr("Short Generate"), "short"),
(tr("Short Drama Summary"), "summary"),
(tr("Upload Script"), "upload_script")
]
@ -76,7 +139,9 @@ def render_script_file(tr, params):
script_list.append((display_name, file['file']))
# 找到保存的脚本文件在列表中的索引
saved_script_path = st.session_state.get('video_clip_json_path', '')
# 如果当前path是特殊值(auto/short/summary),则重置为空
saved_script_path = current_path if current_path not in [MODE_AUTO, MODE_SHORT, MODE_SUMMARY] else ""
selected_index = 0
for i, (_, path) in enumerate(script_list):
if path == saved_script_path:
@ -87,7 +152,8 @@ def render_script_file(tr, params):
tr("Script Files"),
index=selected_index,
options=range(len(script_list)),
format_func=lambda x: script_list[x][0]
format_func=lambda x: script_list[x][0],
key="script_file_selection"
)
script_path = script_list[selected_script_index][1]
@ -133,6 +199,10 @@ def render_script_file(tr, params):
st.error(tr("Invalid JSON format"))
except Exception as e:
st.error(f"{tr('Upload failed')}: {str(e)}")
else:
# --- 功能生成模式 ---
st.session_state['video_clip_json_path'] = selected_mode
params.video_clip_json_path = selected_mode
def render_video_file(tr, params):

View File

@ -161,6 +161,8 @@
"Frame Interval (seconds) (More keyframes consume more tokens)": "帧间隔 (秒) (更多关键帧消耗更多令牌)",
"Batch Size": "批处理大小",
"Batch Size (More keyframes consume more tokens)": "批处理大小, 每批处理越少消耗 token 越多",
"Short Drama Summary": "短剧解说"
"Short Drama Summary": "短剧解说",
"Video Type": "视频类型",
"Select/Upload Script": "选择/上传脚本"
}
}