README.md 3.56 KB

@drama/llm

多厂商 LLM 网关。公共面(src/index.js)导出 createLLM、createStaticKeyProvider、LLMError 和 provider 注册表;协议差异全部圈在 src/providers/llm.<apiType>.js 子类,基类(src/base.js)零厂商分支。生产、诊断和验收都只调用真实 provider,不提供 fake provider 或 fetch 注入缝。

运行时会计链由 composition root 成组注入供应商成本、审计和积分结算端口。成功响应先严格构造 token 用量并记录价格快照与人民币 micros 成本,再按显式策略结算用户积分;运营探针可以三者全部省略,但不得只省略其中一部分。

OpenAI 兼容文本能力零文件接入

接入一个 OpenAI 兼容新厂商(DeepSeek 等)= 配置厂商主体、文本能力、key 和模型,零代码、零新文件:

INSERT INTO model_provider (code, display_name) VALUES ('deepseek', 'DeepSeek');
INSERT INTO model_provider_capability
  (provider_id, code, capability, adapter, credential_source, base_url)
SELECT id, 'deepseek', 'text', 'openai', 'key_pool', 'https://api.deepseek.com/v1'
FROM model_provider WHERE code = 'deepseek';
INSERT INTO llm_key (vendor, api_key) VALUES ('llm:deepseek', '<key>');
INSERT INTO llm_model (provider_capability_id, model, pricing)
SELECT id, 'deepseek-chat', '<pricing-json>'
FROM model_provider_capability WHERE code = 'deepseek' AND capability = 'text';

装配从文本能力行构造实例:createLLM({ provider: row.adapter, vendor: row.name })。

  • adapter 决定复用哪个 provider 子类(openai = Chat Completions 适配器)。
  • base_url 经 lease.baseUrl 承载厂商端点,永远优先于 defaultBaseUrl()。
  • vendor 使 key 池按厂商身份隔离(同用 openai 适配器的两个厂商各命中自己的 key 池,详见任务 07 的 vendor 选项)。

仅当帧形态或多模态形态有厂商差异时才需新增 llm.<x>.js(如 gemini/volcengine);纯 OpenAI 兼容厂商只配置数据。

两套 OpenAI 适配器定位

同一 OpenAI 生态的两套协议收敛为两个适配器文件,经 model_provider_capability.adapter 二选一,不建平行体系:

adapter 文件 端点 用途
openai_responses providers/llm.openai_responses.js POST /responses OpenAI 厂商默认适配器(Responses API,store:false、独立 prompt_cache_key、缓存读写用量)
openai providers/llm.openai.js POST /chat/completions OpenAI 兼容厂商(Moonshot / DeepSeek / Azure / 兼容网关)

Visual Game 持续 Agent 通过独立 prompt_cache_key 固定缓存身份。模型参数提供 prompt_cache_options: { mode: 'implicit' | 'explicit', ttl?: '30m' } 时,static 消息同时发送 prompt_cache_breakpoint;未提供时不发送这两个公开缓存控制字段。Responses usage 统一构造 cached_tokens 和 cache_write_tokens,供应商未报告的可选明细在第三方响应入口构造为 0。

视频支持面

视频落地/拒绝由基类 supportsVideo() 能力钩子驱动(base.js 的 request() 单点护栏),基类零厂商分支:

provider 视频
gemini 支持(inline_data base64 / file_data url)
volcengine 支持(video_url 块)
openai / openai_responses / anthropic / moonshot / azure_foundry 收到 videos 抛 LLMError{ reason:'badRequest', retryable:false }

扩展视频厂商 = 在子类覆写 supportsVideo() 返回 true,并在 chat/_toOpenAIMessages 落该厂商的视频块。