fix: query Dify DB directly for available models instead of API call
- Replace API-based model fetching with direct SQL query on provider_models table (shared PostgreSQL, no auth needed) - Frontend: auto-detect base_url from model name when selecting a Dify model, set provider to 'custom' - Remove unused requests import and API key fallback logic Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
6d571f56a8
commit
53346c9def
@ -497,53 +497,30 @@ class PptAdminService:
|
|||||||
return {"code": 0, "data": {"models": self._BUILTIN_MODELS, "source": "builtin"}}
|
return {"code": 0, "data": {"models": self._BUILTIN_MODELS, "source": "builtin"}}
|
||||||
|
|
||||||
def _fetch_dify_models(self) -> list | None:
|
def _fetch_dify_models(self) -> list | None:
|
||||||
"""调用 Dify API 获取可用 LLM 模型列表,失败返回 None。"""
|
"""从 Dify 数据库直接查询已配置的 LLM 模型列表。"""
|
||||||
import requests
|
|
||||||
try:
|
try:
|
||||||
base_url = os.getenv("DIFY_BASE_URL", "http://localhost:5001")
|
rows = db.session.execute(db.text(
|
||||||
|
"SELECT DISTINCT pm.model_name, pm.provider_name "
|
||||||
# 收集可用的 API Key,按优先级尝试
|
"FROM provider_models pm "
|
||||||
candidate_keys: list[str] = []
|
"WHERE pm.model_type = 'llm' AND pm.is_valid = true "
|
||||||
key_setting = SystemSetting.query.filter_by(key="dify_workspace_api_key").first()
|
"ORDER BY pm.provider_name, pm.model_name"
|
||||||
if key_setting and key_setting.value:
|
)).fetchall()
|
||||||
candidate_keys.append(key_setting.value)
|
if not rows:
|
||||||
for env_key in ("DIFY_CHAT_APP_API_KEY", "DIFY_WORKFLOW_APP_API_KEY",
|
return None
|
||||||
"BAODAN_CHAT_API_KEY", "BAODAN_WORKFLOW_API_KEY"):
|
models = []
|
||||||
val = os.getenv(env_key, "").strip()
|
for row in rows:
|
||||||
if val:
|
model_name = row[0]
|
||||||
candidate_keys.append(val)
|
provider_name = row[1]
|
||||||
# 去重保持顺序
|
# 从插件标识中提取简短供应商名
|
||||||
seen = set()
|
short_provider = provider_name.split("/")[-1] if "/" in provider_name else provider_name
|
||||||
api_keys = []
|
models.append({
|
||||||
for k in candidate_keys:
|
"provider": short_provider,
|
||||||
if k not in seen:
|
"model": model_name,
|
||||||
seen.add(k)
|
"label": f"{model_name}",
|
||||||
api_keys.append(k)
|
})
|
||||||
|
return models
|
||||||
for api_key in api_keys:
|
|
||||||
try:
|
|
||||||
resp = requests.get(
|
|
||||||
f"{base_url}/v1/workspaces/current/models/model-types/llm",
|
|
||||||
headers={"Authorization": f"Bearer {api_key}"},
|
|
||||||
timeout=10,
|
|
||||||
)
|
|
||||||
if resp.status_code != 200:
|
|
||||||
continue
|
|
||||||
data = resp.json()
|
|
||||||
models = []
|
|
||||||
for item in data.get("data", []):
|
|
||||||
provider = item.get("provider", "")
|
|
||||||
for model in item.get("models", []):
|
|
||||||
model_name = model.get("model", "")
|
|
||||||
label = model.get("label", {}).get("zh_Hans", "") or model.get("label", {}).get("en_US", "") or model_name
|
|
||||||
models.append({"provider": provider, "model": model_name, "label": label})
|
|
||||||
if models:
|
|
||||||
return models
|
|
||||||
except Exception:
|
|
||||||
continue
|
|
||||||
return None
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"从 Dify 获取模型列表失败: {e}")
|
logger.warning(f"从 Dify 数据库获取模型列表失败: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_settings(self) -> dict:
|
def get_settings(self) -> dict:
|
||||||
|
|||||||
@ -159,14 +159,34 @@ function onPosterProviderChange(val: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从模型名推断 base_url
|
||||||
|
const MODEL_BASE_URLS: Record<string, string> = {
|
||||||
|
'deepseek': 'https://api.deepseek.com/v1',
|
||||||
|
'minimax': 'https://api.minimax.chat/v1',
|
||||||
|
'gemini': 'https://generativelanguage.googleapis.com/v1/models',
|
||||||
|
'gpt': 'https://api.openai.com/v1',
|
||||||
|
'claude': 'https://api.anthropic.com/v1',
|
||||||
|
}
|
||||||
|
|
||||||
|
function inferBaseUrl(model: string): string {
|
||||||
|
const lower = model.toLowerCase()
|
||||||
|
for (const [keyword, url] of Object.entries(MODEL_BASE_URLS)) {
|
||||||
|
if (lower.startsWith(keyword)) return url
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
function applyDifyModel(target: 'ppt' | 'poster', command: string) {
|
function applyDifyModel(target: 'ppt' | 'poster', command: string) {
|
||||||
const [provider, model] = command.split('|')
|
const [, model] = command.split('|')
|
||||||
|
const baseUrl = inferBaseUrl(model)
|
||||||
if (target === 'ppt') {
|
if (target === 'ppt') {
|
||||||
form.ppt_llm_provider = provider
|
form.ppt_llm_provider = 'custom'
|
||||||
form.ppt_llm_model = model
|
form.ppt_llm_model = model
|
||||||
|
form.ppt_llm_base_url = baseUrl
|
||||||
} else {
|
} else {
|
||||||
form.poster_llm_provider = provider
|
form.poster_llm_provider = 'custom'
|
||||||
form.poster_llm_model = model
|
form.poster_llm_model = model
|
||||||
|
form.poster_llm_base_url = baseUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user