添加模型

使用 AIChannel 和 AIService 注册模型。

创建 AIChannel,实现 Downcity Model Protocol stream,再注册 AIModelSpec:

import {
  AIChannel,
  AIService,
  stream_openai_compatible_model,
  type AIChannelStreamInput,
  type AIChannelStreamResult,
} from "@downcity/federation";

class DeepSeekChannel extends AIChannel {
  constructor() {
    super({
      id: "deepseek",
      env: { DEEPSEEK_API_KEY: "DeepSeek API Key" },
      base_url: "https://api.deepseek.com/v1",
    });
  }

  protected async stream(
    input: AIChannelStreamInput,
  ): Promise<AIChannelStreamResult> {
    const api_key = input.env("DEEPSEEK_API_KEY");
    if (!api_key) throw new Error("DEEPSEEK_API_KEY is required");
    return stream_openai_compatible_model(input, {
      api_key,
      base_url: this.base_url ?? "https://api.deepseek.com/v1",
    });
  }
}

const channel = new DeepSeekChannel();
const ai = new AIService();

ai.use(channel.model({
  id: "deepseek-v4-flash",
  upstream_model: "deepseek-chat",
  name: "DeepSeek V4 Flash",
  context_window: 128_000,
}));

federation.use(ai);

这一个 stream() 同时支持 city.ai.stream()、CityModel 和 /v1/ai/chat/completions。

reasoning、fallback、计费和 provider_options 详见 AIChannel 与模型注册。

结构化价格

模型可以通过 pricing 提供机器可读的价格方案。unit 表示计费对象,scale 表示每个价格对应的单位数量;多个方案可通过 dimensions 表达时段或档位。

pricing: {
  currency: "USD",
  unit: "token",
  scale: 1_000_000,
  rates: { input: 1.6, output: 9.6, cached_input: 0.16 },
}

旧版 price 字段仅作为兼容投影,新增模型不应单独维护价格文案。