chore: harden dynamic provider logging
This commit is contained in:
parent
303535b22a
commit
a1d59e0db8
@ -12,6 +12,7 @@ import {
|
||||
getAiModelById,
|
||||
} from "@/lib/db/queries";
|
||||
import type { AiProvider } from "@/lib/db/schema";
|
||||
import { createLogger } from "@/lib/observability/logger";
|
||||
import { createLocalQwen } from "./providers/local-qwen";
|
||||
import { createGeminiImage } from "./providers/gemini-image";
|
||||
import { createHuankeGemini } from "./providers/huanke-gemini";
|
||||
@ -39,6 +40,7 @@ import { isBltcyVideoBaseUrl } from "./bltcy-video-models";
|
||||
|
||||
// 缓存已创建的 provider 实例
|
||||
const providerCache = new Map<string, any>();
|
||||
const logger = createLogger("dynamic-provider");
|
||||
|
||||
function isVolcanoMultimodalBaseUrl(baseUrl?: string | null) {
|
||||
if (!baseUrl) return false;
|
||||
@ -49,6 +51,20 @@ function getOpenAICompatibleFetch(baseUrl?: string | null) {
|
||||
return isMoonshotOfficialBaseUrl(baseUrl) ? createMoonshotKimiFetch() : undefined;
|
||||
}
|
||||
|
||||
function logProviderCreated(providerType: string, baseUrl?: string | null) {
|
||||
logger.debug("provider created", { providerType, baseUrl });
|
||||
}
|
||||
|
||||
function logChatModelResult(providerType: string, baseModel: unknown) {
|
||||
logger.debug("chat model resolved", {
|
||||
providerType,
|
||||
success: Boolean(baseModel),
|
||||
modelType: typeof baseModel,
|
||||
modelKeyCount:
|
||||
baseModel && typeof baseModel === "object" ? Object.keys(baseModel).length : 0,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据提供商类型创建对应的 AI Provider 实例
|
||||
* 不同供应商使用OpenAI兼容的API格式,但可能有细微差异
|
||||
@ -80,7 +96,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
fetch: getOpenAICompatibleFetch(resolvedBaseUrl),
|
||||
});
|
||||
console.log(`[Provider] Created Alibaba DashScope provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("alibaba", resolvedBaseUrl);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -92,7 +108,10 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl || "https://api.openai.com/v1",
|
||||
fetch: getOpenAICompatibleFetch(resolvedBaseUrl),
|
||||
});
|
||||
console.log(`[Provider] Created OpenAI provider: ${resolvedBaseUrl || "https://api.openai.com/v1"}`);
|
||||
logProviderCreated(
|
||||
"openai",
|
||||
resolvedBaseUrl || "https://api.openai.com/v1"
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -102,8 +121,9 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl || "https://open.bigmodel.cn/api/paas/v4",
|
||||
fetch: getOpenAICompatibleFetch(resolvedBaseUrl),
|
||||
});
|
||||
console.log(
|
||||
`[Provider] Created Zhipu Open Platform provider: ${resolvedBaseUrl || "https://open.bigmodel.cn/api/paas/v4"}`
|
||||
logProviderCreated(
|
||||
"zhipu",
|
||||
resolvedBaseUrl || "https://open.bigmodel.cn/api/paas/v4"
|
||||
);
|
||||
break;
|
||||
}
|
||||
@ -116,7 +136,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created local model provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("local", resolvedBaseUrl);
|
||||
return localProvider as any;
|
||||
}
|
||||
|
||||
@ -127,7 +147,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created Gemini image generation provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("gemini", resolvedBaseUrl);
|
||||
return geminiProvider as any;
|
||||
}
|
||||
|
||||
@ -136,14 +156,15 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created Grsai GPT Image provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("grsai-gpt-image", resolvedBaseUrl);
|
||||
return grsaiGptImageProvider as any;
|
||||
}
|
||||
|
||||
case "grsai-video": {
|
||||
console.warn(
|
||||
`[Provider] Grsai Video provider is configured but its runtime adapter is not connected yet: ${resolvedBaseUrl}`
|
||||
);
|
||||
logger.warn("provider adapter unavailable", {
|
||||
providerType: "grsai-video",
|
||||
baseUrl: resolvedBaseUrl,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -154,7 +175,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created Huanke Gemini image generation provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("huanke-gemini", resolvedBaseUrl);
|
||||
return huankeGeminiProvider as any;
|
||||
}
|
||||
|
||||
@ -165,7 +186,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created Qianwen video generation provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("qianwen-video", resolvedBaseUrl);
|
||||
return qianwenVideoProvider as any;
|
||||
}
|
||||
|
||||
@ -175,8 +196,9 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl || "https://ark.cn-beijing.volces.com/api/v3",
|
||||
fetch: getOpenAICompatibleFetch(resolvedBaseUrl),
|
||||
});
|
||||
console.log(
|
||||
`[Provider] Created Doubao video provider: ${resolvedBaseUrl || "https://ark.cn-beijing.volces.com/api/v3"}`
|
||||
logProviderCreated(
|
||||
"doubao-video",
|
||||
resolvedBaseUrl || "https://ark.cn-beijing.volces.com/api/v3"
|
||||
);
|
||||
break;
|
||||
}
|
||||
@ -187,7 +209,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created Fal Video generation provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("fal-video", resolvedBaseUrl);
|
||||
return falVideoProvider as any;
|
||||
}
|
||||
|
||||
@ -197,7 +219,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created Ruxa Video generation provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("ruxa-video", resolvedBaseUrl);
|
||||
return ruxaVideoProvider as any;
|
||||
}
|
||||
|
||||
@ -208,7 +230,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created Volcano Vision image generation provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("volcano-vision", resolvedBaseUrl);
|
||||
return volcanoVisionProvider as any;
|
||||
}
|
||||
|
||||
@ -219,7 +241,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created Alibaba Image generation provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("alibaba-image", resolvedBaseUrl);
|
||||
return alibabaImageProvider as any;
|
||||
}
|
||||
|
||||
@ -228,7 +250,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created BFL Image generation provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("bfl-image", resolvedBaseUrl);
|
||||
return bflImageProvider as any;
|
||||
}
|
||||
|
||||
@ -238,7 +260,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created Ruxa Image generation provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("ruxa-image", resolvedBaseUrl);
|
||||
return ruxaImageProvider as any;
|
||||
}
|
||||
|
||||
@ -248,7 +270,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created Fal Image generation provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("fal-image", resolvedBaseUrl);
|
||||
return falImageProvider as any;
|
||||
}
|
||||
|
||||
@ -257,7 +279,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created OpenAI Image generation provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("openai-image", resolvedBaseUrl);
|
||||
return openAIImageProvider as any;
|
||||
}
|
||||
|
||||
@ -266,7 +288,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created StepFun Image generation provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("stepfun-image", resolvedBaseUrl);
|
||||
return stepfunImageProvider as any;
|
||||
}
|
||||
|
||||
@ -275,7 +297,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created Midjourney generation provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("midjourney", resolvedBaseUrl);
|
||||
return midjourneyProvider as any;
|
||||
}
|
||||
|
||||
@ -284,7 +306,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created Runway provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("runway", resolvedBaseUrl);
|
||||
return runwayProvider as any;
|
||||
}
|
||||
|
||||
@ -293,7 +315,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created Krea provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("krea", resolvedBaseUrl);
|
||||
return kreaProvider as any;
|
||||
}
|
||||
|
||||
@ -304,7 +326,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(`[Provider] Created BLTCY unified video provider: ${resolvedBaseUrl}`);
|
||||
logProviderCreated("bltcy-video", resolvedBaseUrl);
|
||||
return bltcyVideoProvider as any;
|
||||
}
|
||||
if (isVolcanoMultimodalBaseUrl(resolvedBaseUrl)) {
|
||||
@ -312,9 +334,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl,
|
||||
apiKey: provider.apiKey,
|
||||
});
|
||||
console.log(
|
||||
`[Provider] Created Volcano Multimodal provider via Responses API: ${resolvedBaseUrl}`
|
||||
);
|
||||
logProviderCreated("volcano-multimodal", resolvedBaseUrl);
|
||||
return volcanoMultimodalProvider as any;
|
||||
}
|
||||
// OpenAI 兼容的第三方 API(如 GPT-5 Nano、Claude via OpenAI proxy 等)
|
||||
@ -325,9 +345,7 @@ function getOrCreateProvider(provider: Pick<AiProvider, "id" | "type" | "baseUrl
|
||||
baseURL: resolvedBaseUrl || provider.baseUrl,
|
||||
fetch: getOpenAICompatibleFetch(resolvedBaseUrl || provider.baseUrl),
|
||||
});
|
||||
console.log(
|
||||
`[Provider] Created custom OpenAI-compatible provider: ${resolvedBaseUrl || provider.baseUrl}`
|
||||
);
|
||||
logProviderCreated("custom", resolvedBaseUrl || provider.baseUrl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -344,13 +362,13 @@ export async function getDynamicModel(
|
||||
try {
|
||||
const model = await getAiModelById({ id: modelId });
|
||||
if (!model || !model.isEnabled) {
|
||||
console.warn(`[getDynamicModel] Model ${modelId} not found or disabled`);
|
||||
logger.warn("model unavailable", { modelId });
|
||||
return null;
|
||||
}
|
||||
|
||||
const provider = await getAiProviderById({ id: model.providerId });
|
||||
if (!provider || !provider.isEnabled) {
|
||||
console.warn(`[getDynamicModel] Provider for model ${modelId} not found or disabled`);
|
||||
logger.warn("provider unavailable", { modelId, providerId: model.providerId });
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -363,14 +381,21 @@ export async function getDynamicModel(
|
||||
});
|
||||
|
||||
if (!providerInstance) {
|
||||
console.error(`[getDynamicModel] Failed to create provider instance for ${provider.type}`);
|
||||
logger.error("provider instance creation failed", {
|
||||
providerType: provider.type,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
const resolvedModelId = String(overrideModelId || "").trim() || model.modelId;
|
||||
|
||||
// 创建基础模型
|
||||
console.log(`[getDynamicModel] Creating model: ${resolvedModelId} (${model.displayName}) using provider: ${provider.name} (${provider.type})`);
|
||||
logger.debug("model creation started", {
|
||||
modelId,
|
||||
resolvedModelId,
|
||||
providerId: provider.id,
|
||||
providerType: provider.type,
|
||||
});
|
||||
|
||||
// 根据 provider 类型选择正确的方法和模型ID
|
||||
// customProvider (gemini, local) 使用 .languageModel()
|
||||
@ -379,105 +404,84 @@ export async function getDynamicModel(
|
||||
if (provider.type === "gemini" || provider.type === "grsai-gpt-image") {
|
||||
const imageProviderLabel = provider.type === "grsai-gpt-image" ? "Grsai GPT Image" : "Gemini image";
|
||||
// 图片生成 provider 使用 chat() 方法(与 local-qwen 相同的调用方式)
|
||||
console.log(`[getDynamicModel] Getting ${imageProviderLabel} chat model...`); // 调试日志
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log(`[getDynamicModel] ${imageProviderLabel} model retrieved:`, baseModel ? "success" : "failed"); // 调试日志
|
||||
console.log(`[getDynamicModel] ${imageProviderLabel} model type:`, typeof baseModel); // 调试
|
||||
console.log(`[getDynamicModel] ${imageProviderLabel} model keys:`, baseModel ? Object.keys(baseModel).join(', ') : 'N/A'); // 调试
|
||||
logChatModelResult(imageProviderLabel, baseModel);
|
||||
} else if (provider.type === "local") {
|
||||
// 本地模型使用 chat() 方法
|
||||
console.log("[getDynamicModel] Getting local chat model..."); // 调试日志
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] Local model retrieved:", baseModel ? "success" : "failed"); // 调试日志
|
||||
logChatModelResult("local", baseModel);
|
||||
} else if (provider.type === "qianwen-video") {
|
||||
// 千问视频生成使用 chat() 方法
|
||||
console.log("[getDynamicModel] Getting Qianwen Video chat model..."); // 调试日志
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] Qianwen Video model retrieved:", baseModel ? "success" : "failed"); // 调试日志
|
||||
logChatModelResult("qianwen-video", baseModel);
|
||||
} else if (provider.type === "fal-video") {
|
||||
// FAL 视频生成使用 chat() 方法
|
||||
console.log("[getDynamicModel] Getting Fal Video chat model..."); // 调试日志
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] Fal Video model retrieved:", baseModel ? "success" : "failed"); // 调试日志
|
||||
logChatModelResult("fal-video", baseModel);
|
||||
} else if (provider.type === "ruxa-video") {
|
||||
// RUXA 视频生成使用 chat() 方法
|
||||
console.log("[getDynamicModel] Getting Ruxa Video chat model..."); // 调试日志
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] Ruxa Video model retrieved:", baseModel ? "success" : "failed"); // 调试日志
|
||||
logChatModelResult("ruxa-video", baseModel);
|
||||
} else if (provider.type === "volcano-vision") {
|
||||
// 火山引擎视觉生成使用 chat() 方法
|
||||
console.log("[getDynamicModel] Getting Volcano Vision chat model..."); // 调试日志
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] Volcano Vision model retrieved:", baseModel ? "success" : "failed"); // 调试日志
|
||||
logChatModelResult("volcano-vision", baseModel);
|
||||
} else if (provider.type === "alibaba-image") {
|
||||
// 阿里云千问图片生成使用 chat() 方法
|
||||
console.log("[getDynamicModel] Getting Alibaba Image chat model..."); // 调试日志
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] Alibaba Image model retrieved:", baseModel ? "success" : "failed"); // 调试日志
|
||||
logChatModelResult("alibaba-image", baseModel);
|
||||
} else if (provider.type === "bfl-image") {
|
||||
console.log("[getDynamicModel] Getting BFL Image chat model...");
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] BFL Image model retrieved:", baseModel ? "success" : "failed");
|
||||
logChatModelResult("bfl-image", baseModel);
|
||||
} else if (provider.type === "ruxa-image") {
|
||||
// RUXA 图片编辑生成使用 chat() 方法
|
||||
console.log("[getDynamicModel] Getting Ruxa Image chat model..."); // 调试日志
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] Ruxa Image model retrieved:", baseModel ? "success" : "failed"); // 调试日志
|
||||
logChatModelResult("ruxa-image", baseModel);
|
||||
} else if (provider.type === "fal-image") {
|
||||
// FAL 图片编辑生成使用 chat() 方法
|
||||
console.log("[getDynamicModel] Getting Fal Image chat model..."); // 调试日志
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] Fal Image model retrieved:", baseModel ? "success" : "failed"); // 调试日志
|
||||
logChatModelResult("fal-image", baseModel);
|
||||
} else if (provider.type === "openai-image") {
|
||||
// OpenAI Images 兼容图片生成/编辑使用 chat() 方法
|
||||
console.log("[getDynamicModel] Getting OpenAI Image chat model..."); // 调试日志
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] OpenAI Image model retrieved:", baseModel ? "success" : "failed"); // 调试日志
|
||||
logChatModelResult("openai-image", baseModel);
|
||||
} else if (provider.type === "stepfun-image") {
|
||||
console.log("[getDynamicModel] Getting StepFun Image chat model...");
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] StepFun Image model retrieved:", baseModel ? "success" : "failed");
|
||||
logChatModelResult("stepfun-image", baseModel);
|
||||
} else if (provider.type === "midjourney") {
|
||||
console.log("[getDynamicModel] Getting Midjourney chat model..."); // 调试日志
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] Midjourney model retrieved:", baseModel ? "success" : "failed"); // 调试日志
|
||||
logChatModelResult("midjourney", baseModel);
|
||||
} else if (provider.type === "runway") {
|
||||
console.log("[getDynamicModel] Getting Runway chat model..."); // 调试日志
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] Runway model retrieved:", baseModel ? "success" : "failed"); // 调试日志
|
||||
logChatModelResult("runway", baseModel);
|
||||
} else if (provider.type === "krea") {
|
||||
console.log("[getDynamicModel] Getting Krea chat model...");
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] Krea model retrieved:", baseModel ? "success" : "failed");
|
||||
logChatModelResult("krea", baseModel);
|
||||
} else if (provider.type === "huanke-gemini") {
|
||||
// 环科 Gemini 原生格式使用 chat() 方法
|
||||
console.log("[getDynamicModel] Getting Huanke Gemini chat model..."); // 调试日志
|
||||
baseModel = providerInstance.chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] Huanke Gemini model retrieved:", baseModel ? "success" : "failed"); // 调试日志
|
||||
console.log("[getDynamicModel] Huanke Gemini model type:", typeof baseModel); // 调试
|
||||
console.log("[getDynamicModel] Huanke Gemini model keys:", baseModel ? Object.keys(baseModel).join(', ') : 'N/A'); // 调试
|
||||
logChatModelResult("huanke-gemini", baseModel);
|
||||
} else {
|
||||
// OpenAI-compatible providers
|
||||
console.log("[getDynamicModel] Getting OpenAI-compatible model..."); // 调试日志
|
||||
baseModel = (providerInstance as any).chat(resolvedModelId);
|
||||
console.log("[getDynamicModel] OpenAI model retrieved:", baseModel ? "success" : "failed"); // 调试日志
|
||||
logChatModelResult("openai-compatible", baseModel);
|
||||
}
|
||||
|
||||
// 如果模型名称包含特定关键词,可以添加推理中间件
|
||||
// 例如,为推理模型添加思考过程提取
|
||||
if (model.displayName.toLowerCase().includes("reasoning") ||
|
||||
model.displayName.toLowerCase().includes("推理")) {
|
||||
console.log("[getDynamicModel] Applying reasoning middleware..."); // 调试日志
|
||||
logger.debug("reasoning middleware applied", { modelId, resolvedModelId });
|
||||
return wrapLanguageModel({
|
||||
model: baseModel,
|
||||
middleware: extractReasoningMiddleware({ tagName: "think" }),
|
||||
});
|
||||
}
|
||||
|
||||
console.log("[getDynamicModel] Returning base model"); // 调试日志
|
||||
logger.debug("base model returned", { modelId, resolvedModelId });
|
||||
return baseModel;
|
||||
} catch (error) {
|
||||
console.error("[getDynamicModel] Failed to get dynamic model:", error);
|
||||
logger.error("dynamic model resolution failed", error, { modelId });
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -506,7 +510,7 @@ export async function getAvailableModels() {
|
||||
providerType: provider.type,
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error("Failed to get available models:", error);
|
||||
logger.error("available models load failed", error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@ -527,7 +531,12 @@ export async function getSystemModel(
|
||||
|
||||
if (defaultModelData) {
|
||||
const { model, provider } = defaultModelData;
|
||||
console.log(`[getSystemModel] Using default model for ${purpose}: ${model.displayName} (${provider.name})`);
|
||||
logger.debug("system model default selected", {
|
||||
purpose,
|
||||
modelId: model.id,
|
||||
providerId: provider.id,
|
||||
providerType: provider.type,
|
||||
});
|
||||
|
||||
const providerInstance = getOrCreateProvider({
|
||||
id: provider.id,
|
||||
@ -542,7 +551,7 @@ export async function getSystemModel(
|
||||
}
|
||||
|
||||
// 如果没有找到数据库配置,回退到环境变量配置
|
||||
console.warn(`[getSystemModel] No default model found in database for ${purpose}, falling back to env config`);
|
||||
logger.warn("system model default missing, using env fallback", { purpose });
|
||||
if (process.env.DASHSCOPE_API_KEY && process.env.DASHSCOPE_BASE_URL) {
|
||||
const fallbackProvider = createOpenAI({
|
||||
apiKey: process.env.DASHSCOPE_API_KEY,
|
||||
@ -551,10 +560,10 @@ export async function getSystemModel(
|
||||
return fallbackProvider.chat("qwen-turbo");
|
||||
}
|
||||
|
||||
console.error(`[getSystemModel] No model configuration found for ${purpose}`);
|
||||
logger.error("system model configuration missing", { purpose });
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error(`[getSystemModel] Failed to get system model for ${purpose}:`, error);
|
||||
logger.error("system model resolution failed", error, { purpose });
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ const files = [
|
||||
"lib/ai/providers/gemini-image.ts",
|
||||
"lib/ai/providers/volcano-vision.ts",
|
||||
"lib/ai/providers/qianwen-video.ts",
|
||||
"lib/ai/dynamic-provider.ts",
|
||||
"services/canvas/index.ts",
|
||||
"components/image-annotator.tsx",
|
||||
"app/api/canvas/auto-title/route.ts",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user