Ver Fonte

feat(core): add providers/lookup with two-layer strategy + priority sort

fanghanjun há 6 meses atrás
pai
commit
4191d91278
1 ficheiros alterados com 56 adições e 0 exclusões
  1. 56 0
      packages/core/src/llm/providers/lookup.ts

+ 56 - 0
packages/core/src/llm/providers/lookup.ts

@@ -0,0 +1,56 @@
+import type { InkosModel } from "./types.js";
+import { getAllProviders, getProvider } from "./index.js";
+
+/**
+ * provider id 优先级。Layer 2 全局扫时同 id 多条匹配按这个顺序取第一条,
+ * 保证结果确定性。白名单外的 provider 视同 999(排最后)。
+ */
+const PROVIDER_PRIORITY: readonly string[] = [
+  "anthropic", "openai", "google", "deepseek", "qwen", "moonshot",
+  "zhipu", "minimax", "xai",
+  "siliconcloud", "ppio", "bailian",
+  "openrouter", "aihubmix", "novita",
+];
+
+/**
+ * 两层 lookup:
+ * - Layer 1: 已知 provider 精确查(整串比较,不拆斜线)
+ * - Layer 2: 全局扫所有 provider 的 models,按 provider id 优先级取第一条
+ * - 都 miss: 返回 undefined,调用方走保守默认
+ *
+ * 不做斜线前缀拆分。lobe 的 processModelList 证实了"靠调用入口带 provider 消歧"
+ * 是对的做法,斜线拆分对 PPIO / SiliconCloud 原生命名会误匹配。
+ */
+export function lookupModel(
+  serviceId: string,
+  modelId: string,
+): InkosModel | undefined {
+  const lowerId = modelId.toLowerCase();
+
+  const provider = getProvider(serviceId);
+  if (provider) {
+    const hit = provider.models.find((m) => m.id.toLowerCase() === lowerId);
+    if (hit) return hit;
+  }
+
+  const matches: Array<{ model: InkosModel; providerId: string }> = [];
+  for (const p of getAllProviders()) {
+    const hit = p.models.find((m) => m.id.toLowerCase() === lowerId);
+    if (hit) matches.push({ model: hit, providerId: p.id });
+  }
+  if (matches.length === 0) return undefined;
+
+  matches.sort((a, b) => {
+    const ai = PROVIDER_PRIORITY.indexOf(a.providerId);
+    const bi = PROVIDER_PRIORITY.indexOf(b.providerId);
+    return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi);
+  });
+  return matches[0].model;
+}
+
+/** 某 service 下可用(enabled !== false)的模型列表 */
+export function listEnabledModels(serviceId: string): InkosModel[] {
+  const provider = getProvider(serviceId);
+  if (!provider) return [];
+  return provider.models.filter((m) => m.enabled !== false);
+}