chore(api-server): 外部模型与网关配置改为环境变量

This commit is contained in:
2026-05-07 15:59:00 +08:00
parent 6a830b349b
commit 13547091ca
6 changed files with 243 additions and 53 deletions

View File

@@ -5,7 +5,6 @@ use platform_llm::{
DEFAULT_RETRY_BACKOFF_MS, LlmProvider,
};
const DEFAULT_LLM_MODEL: &str = "doubao-1-5-pro-32k-character-250715";
const DEFAULT_INTERNAL_API_SECRET: &str = "genarrative-dev-internal-bridge";
const DEFAULT_AUTH_STORE_PATH: &str = "server-rs/.data/auth-store.json";
const SPACETIME_LOCAL_CONFIG_FILE: &str = "spacetime.local.json";
@@ -171,9 +170,9 @@ impl Default for AppConfig {
spacetime_pool_size: 4,
spacetime_procedure_timeout: Duration::from_secs(30),
llm_provider: LlmProvider::Ark,
llm_base_url: DEFAULT_ARK_BASE_URL.to_string(),
llm_base_url: String::new(),
llm_api_key: None,
llm_model: DEFAULT_LLM_MODEL.to_string(),
llm_model: String::new(),
llm_request_timeout_ms: DEFAULT_REQUEST_TIMEOUT_MS,
llm_max_retries: DEFAULT_MAX_RETRIES,
llm_retry_backoff_ms: DEFAULT_RETRY_BACKOFF_MS,
@@ -181,18 +180,18 @@ impl Default for AppConfig {
creation_agent_llm_web_search_enabled: true,
dashscope_base_url: "https://dashscope.aliyuncs.com/api/v1".to_string(),
dashscope_api_key: None,
dashscope_scene_image_model: "wan2.2-t2i-flash".to_string(),
dashscope_reference_image_model: "qwen-image-2.0".to_string(),
dashscope_cover_image_model: "wan2.2-t2i-flash".to_string(),
dashscope_scene_image_model: String::new(),
dashscope_reference_image_model: String::new(),
dashscope_cover_image_model: String::new(),
dashscope_image_request_timeout_ms: 150_000,
apimart_base_url: "https://api.apimart.ai/v1".to_string(),
apimart_base_url: String::new(),
apimart_api_key: None,
apimart_image_request_timeout_ms: 180_000,
draft_asset_generation_max_concurrent_requests: 4,
ark_character_video_base_url: DEFAULT_ARK_BASE_URL.to_string(),
ark_character_video_base_url: String::new(),
ark_character_video_api_key: None,
ark_character_video_request_timeout_ms: 420_000,
ark_character_video_model: "doubao-seedance-2-0-fast-260128".to_string(),
ark_character_video_model: String::new(),
character_animation_ffmpeg_path: "ffmpeg".to_string(),
character_animation_ffprobe_path: "ffprobe".to_string(),
character_animation_frame_extract_timeout_ms: 120_000,
@@ -456,6 +455,8 @@ impl AppConfig {
read_first_non_empty_env(&["GENARRATIVE_LLM_BASE_URL", "LLM_BASE_URL"])
{
config.llm_base_url = llm_base_url;
} else if config.llm_provider == LlmProvider::Ark {
config.llm_base_url = DEFAULT_ARK_BASE_URL.to_string();
}
config.llm_api_key =
@@ -557,6 +558,8 @@ impl AppConfig {
"LLM_BASE_URL",
]) {
config.ark_character_video_base_url = ark_character_video_base_url;
} else if config.llm_provider == LlmProvider::Ark {
config.ark_character_video_base_url = DEFAULT_ARK_BASE_URL.to_string();
}
config.ark_character_video_api_key = read_first_non_empty_env(&[
@@ -816,11 +819,95 @@ fn parse_positive_u16(raw: &str) -> Option<u16> {
#[cfg(test)]
mod tests {
use super::AppConfig;
use super::{AppConfig, LlmProvider};
use std::sync::{Mutex, OnceLock};
static ENV_LOCK: OnceLock<Mutex<()>> = OnceLock::new();
#[test]
fn default_keeps_non_public_model_and_base_url_empty() {
let config = AppConfig::default();
assert!(config.llm_model.is_empty());
assert!(config.llm_base_url.is_empty());
assert!(config.apimart_base_url.is_empty());
assert!(config.ark_character_video_base_url.is_empty());
assert!(config.ark_character_video_model.is_empty());
assert!(config.dashscope_scene_image_model.is_empty());
assert!(config.dashscope_reference_image_model.is_empty());
assert!(config.dashscope_cover_image_model.is_empty());
assert_eq!(
config.dashscope_base_url,
"https://dashscope.aliyuncs.com/api/v1"
);
assert_eq!(config.sms_endpoint, "dypnsapi.aliyuncs.com");
assert_eq!(
config.wechat_authorize_endpoint,
"https://open.weixin.qq.com/connect/qrconnect"
);
}
#[test]
fn from_env_reads_non_public_models_and_urls() {
let _guard = ENV_LOCK
.get_or_init(|| Mutex::new(()))
.lock()
.expect("env lock should not poison");
unsafe {
std::env::remove_var("GENARRATIVE_LLM_PROVIDER");
std::env::remove_var("GENARRATIVE_LLM_BASE_URL");
std::env::remove_var("GENARRATIVE_LLM_MODEL");
std::env::remove_var("APIMART_BASE_URL");
std::env::remove_var("DASHSCOPE_SCENE_IMAGE_MODEL");
std::env::remove_var("DASHSCOPE_REFERENCE_IMAGE_MODEL");
std::env::remove_var("DASHSCOPE_COVER_IMAGE_MODEL");
std::env::remove_var("ARK_CHARACTER_VIDEO_BASE_URL");
std::env::remove_var("ARK_CHARACTER_VIDEO_MODEL");
std::env::set_var("GENARRATIVE_LLM_PROVIDER", "openai-compatible");
std::env::set_var(
"GENARRATIVE_LLM_BASE_URL",
"https://llm.internal.example/v1",
);
std::env::set_var("GENARRATIVE_LLM_MODEL", "internal-text-model");
std::env::set_var("APIMART_BASE_URL", "https://image.internal.example/v1");
std::env::set_var("DASHSCOPE_SCENE_IMAGE_MODEL", "scene-model");
std::env::set_var("DASHSCOPE_REFERENCE_IMAGE_MODEL", "reference-model");
std::env::set_var("DASHSCOPE_COVER_IMAGE_MODEL", "cover-model");
std::env::set_var(
"ARK_CHARACTER_VIDEO_BASE_URL",
"https://video.internal.example/v1",
);
std::env::set_var("ARK_CHARACTER_VIDEO_MODEL", "video-model");
}
let config = AppConfig::from_env();
assert_eq!(config.llm_provider, LlmProvider::OpenAiCompatible);
assert_eq!(config.llm_base_url, "https://llm.internal.example/v1");
assert_eq!(config.llm_model, "internal-text-model");
assert_eq!(config.apimart_base_url, "https://image.internal.example/v1");
assert_eq!(config.dashscope_scene_image_model, "scene-model");
assert_eq!(config.dashscope_reference_image_model, "reference-model");
assert_eq!(config.dashscope_cover_image_model, "cover-model");
assert_eq!(
config.ark_character_video_base_url,
"https://video.internal.example/v1"
);
assert_eq!(config.ark_character_video_model, "video-model");
unsafe {
std::env::remove_var("GENARRATIVE_LLM_PROVIDER");
std::env::remove_var("GENARRATIVE_LLM_BASE_URL");
std::env::remove_var("GENARRATIVE_LLM_MODEL");
std::env::remove_var("APIMART_BASE_URL");
std::env::remove_var("DASHSCOPE_SCENE_IMAGE_MODEL");
std::env::remove_var("DASHSCOPE_REFERENCE_IMAGE_MODEL");
std::env::remove_var("DASHSCOPE_COVER_IMAGE_MODEL");
std::env::remove_var("ARK_CHARACTER_VIDEO_BASE_URL");
std::env::remove_var("ARK_CHARACTER_VIDEO_MODEL");
}
}
#[test]
fn from_env_reads_spacetime_pool_size() {
let _guard = ENV_LOCK