浏览代码

feat(core): wire createLLMClient into providers lookup + deprecation warning

fanghanjun 6 月之前
父节点
当前提交
7cee9d265f
共有 1 个文件被更改,包括 33 次插入 和 10 次删除
  1. 33 10
      packages/core/src/llm/provider.ts

+ 33 - 10
packages/core/src/llm/provider.ts

@@ -15,6 +15,19 @@ import type {
   ToolCall as PiToolCall,
   ToolCall as PiToolCall,
 } from "@mariozechner/pi-ai";
 } from "@mariozechner/pi-ai";
 import { resolveServicePreset } from "./service-presets.js";
 import { resolveServicePreset } from "./service-presets.js";
+import { getProvider } from "./providers/index.js";
+import { lookupModel } from "./providers/lookup.js";
+
+let providersDeprecationWarnedOnce = false;
+function warnOnceAboutMaxTokensDeprecation(): void {
+  if (providersDeprecationWarnedOnce) return;
+  providersDeprecationWarnedOnce = true;
+  console.warn(
+    "[inkos] config.maxTokens / maxTokensCap 已被 providers 接管:" +
+      "各模型的真实 maxOutput / contextWindow 来自 providers/<name>.ts。" +
+      "2.0.0 将彻底删除 LLMConfig.maxTokens / maxTokensCap 字段。",
+  );
+}
 
 
 // === Streaming Monitor Types ===
 // === Streaming Monitor Types ===
 
 
@@ -141,10 +154,12 @@ export interface ChatWithToolsResult {
 // === Factory ===
 // === Factory ===
 
 
 export function createLLMClient(config: LLMConfig): LLMClient {
 export function createLLMClient(config: LLMConfig): LLMClient {
+  // 提前查一次 modelCard 以便给 defaults.maxTokens 做 fallback(A 组过渡期逻辑,见下面 piModel 再查一次是幂等的)
+  const _earlyCard = lookupModel(config.service ?? "custom", config.model);
   const defaults = {
   const defaults = {
     temperature: config.temperature ?? 0.7,
     temperature: config.temperature ?? 0.7,
-    // fallback: agent 没传 per-call 时用这个
-    maxTokens: config.maxTokens ?? 8192,
+    // fallback: agent 没传 per-call 时用这个。优先 config.maxTokens(过渡期兼容),否则 modelCard.maxOutput,否则 8192
+    maxTokens: config.maxTokens ?? _earlyCard?.maxOutput ?? 8192,
     // cap: 只在用户显式配 maxTokensCap 时生效;默认 null = 不封顶 per-call。
     // cap: 只在用户显式配 maxTokensCap 时生效;默认 null = 不封顶 per-call。
     // **禁止**改成 `config.maxTokens ?? null` —— 那样会让 architect 的 per-call
     // **禁止**改成 `config.maxTokens ?? null` —— 那样会让 architect 的 per-call
     // 16384 被用户 config.maxTokens=8192 自动裁剪,基础设定输出会被截断。
     // 16384 被用户 config.maxTokens=8192 自动裁剪,基础设定输出会被截断。
@@ -159,23 +174,31 @@ export function createLLMClient(config: LLMConfig): LLMClient {
   // --- Build pi-ai Model object ---
   // --- Build pi-ai Model object ---
   const serviceName = config.service ?? "custom";
   const serviceName = config.service ?? "custom";
   const preset = resolveServicePreset(serviceName);
   const preset = resolveServicePreset(serviceName);
-  const piApi = resolvePiApi(serviceName, config.apiFormat, preset?.api) as PiApi;
-  const baseUrl = config.baseUrl || preset?.baseUrl || "";
+  const inkosProvider = getProvider(serviceName);
+  const modelCard = lookupModel(serviceName, config.model);
+
+  // A 组过渡期:命中 modelCard 时打一次性 warning(表示用户的 maxTokens 配置已被 providers 接管)
+  if (modelCard) {
+    warnOnceAboutMaxTokensDeprecation();
+  }
+
+  const piApi = resolvePiApi(serviceName, config.apiFormat, (inkosProvider?.api ?? preset?.api) as PiApi) as PiApi;
+  const baseUrl = config.baseUrl || inkosProvider?.baseUrl || preset?.baseUrl || "";
   const extraHeaders = config.headers ?? parseEnvHeaders();
   const extraHeaders = config.headers ?? parseEnvHeaders();
 
 
   const provider = config.provider === "anthropic" ? "anthropic" : "openai";
   const provider = config.provider === "anthropic" ? "anthropic" : "openai";
 
 
   const piModel: PiModel<PiApi> = {
   const piModel: PiModel<PiApi> = {
-    id: config.model,
-    name: config.model,
+    id: modelCard?.deploymentName ?? config.model,
+    name: modelCard?.displayName ?? config.model,
     api: piApi,
     api: piApi,
     provider,
     provider,
     baseUrl,
     baseUrl,
-    reasoning: (config.thinkingBudget ?? 0) > 0,
-    input: ["text"] as ("text" | "image")[],
+    reasoning: modelCard?.abilities?.reasoning ?? (config.thinkingBudget ?? 0) > 0,
+    input: modelCard?.abilities?.vision ? ["text", "image"] : ["text"],
     cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
     cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
-    contextWindow: 128_000,
-    maxTokens: config.maxTokens ?? 8192,
+    contextWindow: modelCard?.contextWindowTokens ?? 128_000,
+    maxTokens: modelCard?.maxOutput ?? config.maxTokens ?? 8192,
     ...(extraHeaders ? { headers: extraHeaders } : {}),
     ...(extraHeaders ? { headers: extraHeaders } : {}),
   };
   };