mirror of
https://github.com/linyqh/NarratoAI.git
synced 2025-12-12 19:52:48 +00:00
feat: 优化LLM服务配置与迁移适配,并更新相关UI设置及中文翻译
This commit is contained in:
parent
6697535c57
commit
238c1c13f1
@ -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)
|
||||
|
||||
@ -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输出
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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": "选择/上传脚本"
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user