mono项目开发模板,内置cli管理构建
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

12 KiB

@dm/xllm — 面向大模型 / Agent 的使用说明

本文档供 大模型、代码助手、自动化 Agent 在编写或修改调用代码时作为单一事实来源。API 以当前包导出为准(入口:packages/xllm/src/index.ts)。


1. 包与运行时

  • 包名@dm/xllm
  • 模块:ESM("type": "module"
  • 运行环境:需存在全局 fetch(现代 Node、浏览器、Bun 等)。无 fetch 时抛 XllmErrorNETWORK_ERROR)。
  • 安装(monorepo):在依赖包中 bun add @dm/xllm@workspace:* 或等价 workspace 引用。

2. 入口与导出

2.1 运行时导出

import { createXllm, XllmError } from "@dm/xllm";

2.2 类型导出(export type

XClientOptions, XRequest, XResponse, XStreamEvent, XMessage, XContentPart, XProviderName, XThinkingMode, XReasoningEffortInput, XToolDefinition, XToolCall, XToolChoice, XToolExecutor, XToolExecutorMap, XToolErrorStrategy, XChatWithToolsOptions, XChatWithToolsResult, XUsage


3. 客户端:createXllmXllmClient

const xllm = createXllm(options?: XClientOptions): XllmClient;

3.1 XllmClient 方法

方法 签名 用途
generate (request: XRequest) => Promise<XResponse> 非流式,一次返回完整结构
stream (request: XRequest) => AsyncIterable<XStreamEvent> 流式 SSE,用 for await 消费
chatWithTools (request: XChatWithToolsOptions, executors: XToolExecutorMap) => Promise<XChatWithToolsResult> 非流式 + 自动工具闭环
streamWithTools 同上,返回 AsyncIterable<XStreamEvent> 流式 + 自动工具闭环
with (overrides: Partial<XClientOptions>) => XllmClient 复制客户端并合并默认配置

4. 配置合并与环境变量

4.1 优先级(从高到低)

  1. 单次请求 XRequest / XChatWithToolsOptions 上的字段(provider, model, apiKey, baseURL 等)
  2. createXllm 传入的 XClientOptions
  3. 环境变量(仅 Node 等存在 process.env 时)

实现位置:packages/xllm/src/runtime/config.ts

4.2 环境变量

变量 作用
XLLM_API_KEY 通用 API Key 兜底
OPENAI_API_KEY provider === "openai-compatible" 时兜底
DEEPSEEK_API_KEY provider === "deepseek" 时兜底
XLLM_BASE_URL 通用 base URL 兜底

4.3 默认 provider / model / baseURL

未指定时:

  • provider 默认为 "openai-compatible"
  • modelopenai-compatiblegpt-4o-minideepseekdeepseek-chat
  • baseURLhttps://api.openai.com/v1https://api.deepseek.com

5. 供应商(XProviderName

当前内置:

  • "openai-compatible":OpenAI Chat Completions 兼容 HTTP 形态(/chat/completions
  • "deepseek":在兼容层之上设置 DeepSeek 默认 baseURL,其余映射与 openai-compatible 一致

接入其它「OpenAI 兼容」网关:不必新增枚举;使用 provider: "openai-compatible",并设置 baseURL(及可选 headers)指向该网关。

非兼容协议:须在库内新增 ProviderAdapter 并注册(见第 11 节)。


5.1 思考模式(Thinking / CoT)— 非全供应商通用

thinking / reasoningEffort 不是抽象意义上的「全市场通用配置」:它们对应 OpenAI Chat Completions 兼容 JSON 里部分厂商采用的字段名(DeepSeek 官方文档中的 OpenAI 形态即如此)。其它供应商若使用不同字段名、不同嵌套路径或不同 API,有两种做法:

  1. providerExtras(推荐先做):在 XRequest.providerExtras 里写入任意键值,库会在构建完标准字段后 Object.assign 合并进请求体根对象后合并者可覆盖同名标准字段)。用于传入厂商文档要求的专有参数,而无需立刻新增适配器。
  2. ProviderAdapter:协议差异大(路径、鉴权、流式格式都不同)时,在 packages/xllm 内实现并注册适配器。

与 DeepSeek 文档一致的字段映射如下(兼容体):

XRequest 字段 请求体字段 说明
thinking?: { type: "enabled" | "disabled" } thinking 思考开关;不传则由服务端默认(一般为 enabled)
reasoningEffort?: "low" | "medium" | "high" | "max" | "xhigh" reasoning_effort 仅发送 highmaxlow / mediumhighxhighmax

流式:若供应商在 SSE 的 choices[].delta 中返回 reasoning_content(或 reasoning 字符串),库会发出 XStreamEvent{ type: "reasoning.delta", text: string },与 { type: "text.delta", ... } 区分。

非流式:若 message 中含 reasoning_contentreasoning,会填入 XResponse.reasoning;正文仍在 XResponse.text

provider: "deepseek"provider: "openai-compatible" 均走同一适配器请求体逻辑;其它 同形态 网关若支持相同字段,亦可使用 thinking / reasoningEffort;否则请用 providerExtras


6. 请求与消息模型

6.1 XRequest(核心字段)

  • messages: XMessage[](必填)
  • tools?: XToolDefinition[]
  • toolChoice?: "auto" | "none" | { name: string }
  • temperature?, topP?, maxTokens?, metadata?
  • 可覆盖:provider?, model?, apiKey?, baseURL?
  • thinking?, reasoningEffort?:见 §5.1(非通用,部分兼容厂商)
  • providerExtras?:合并进 Chat Completions 请求 JSON 根对象(见 §5.1)
  • stream?:由 generate/stream 内部控制,调用方一般不必依赖此字段语义

6.2 XMessage

  • system | user | assistantcontent: XContentPart[]assistant 可选 toolCalls?: XToolCall[]协议要求:在 role: "tool" 之前,assistant 需带对应 tool_calls;使用 chatWithTools / streamWithTools 时由库自动写入);assistant 还可选 reasoningContent?: string,序列化为 reasoning_content(思考模式 + 工具调用时,部分供应商要求后续轮完整回传)
  • tool必须包含 toolCallId: string,且与上一轮 assistant 的 tool_calls[].id 对应

6.3 XContentPart

  • { type: "text"; text: string }
  • { type: "image"; image: { url: string } }(http(s) 或 data URL;模型是否支持多模态由供应商决定,库只做字段映射)

6.4 XToolDefinition

  • name, 可选 description, parameters(通常为 JSON Schema 风格对象,会原样进入供应商请求体)

7. 响应与流式事件

7.1 XResponse

  • text, toolCalls, usage?, provider, model, finishReason?, raw?

7.2 XStreamEvent(判别联合,按 event.type 收窄)

type 含义
response.start 流开始,含 provider, model, requestId?
text.delta 文本增量
reasoning.delta 思考链增量(如 reasoning_content
tool_call.delta 工具参数增量
tool_call.done 单个工具调用片段结束
response.usage 用量
response.done 本轮流结束;finishReason 可能为空(例如仅 [DONE] 收尾时)

消费建议:直出场景主要处理 text.delta;工具场景监听 tool_call.done;结束可用 response.done(注意可能与适配器在 finish_reason[DONE] 路径上的去重逻辑配合,避免重复收尾业务状态)。


8. 工具调用

8.1 仅单次模型调用(手动处理工具)

  1. generate / streamtools + toolChoice: "auto"
  2. XResponse.toolCalls 或流式 tool_call.doneid, name, argumentsarguments 为 JSON 字符串)
  3. 本地执行后,追加 role: "tool"toolCallId 对齐,再发下一轮请求;assistant 侧需带 toolCalls推荐直接用 chatWithTools / streamWithTools 避免协议错误

8.2 chatWithTools(非流式闭环)

  • 额外选项:maxRounds?(默认 5),toolErrorStrategy?(默认 "throw"
  • 返回:{ response, rounds, toolCallsExecuted }
  • 行为:每轮 generate;若有 toolCalls,执行 executors[name],将结果写入 tool 消息并追加历史,直到无工具调用或超出 maxRounds
  • 思考模式 + 工具调用(DeepSeek):若本轮 XResponse.reasoning 有值(来自 message.reasoning_content),库会把同一全文写入历史 assistant 的 reasoningContent,下一轮请求序列化为 reasoning_content,满足「后续请求须完整回传」的要求。

8.3 streamWithTools(流式闭环)

  • 每轮消费完整 stream;收集 tool_call.done 与拼接的 assistantText同时拼接本轮全部 reasoning.deltareasoningContent;执行工具后追加 assistant(含 toolCalls 与可选 reasoningContent)与 tool 消息,再进入下一轮
  • 事件仍原样 yield 给调用方

8.4 XToolExecutorXToolExecutorMap

type XToolExecutor = (args: unknown, toolCall: XToolCall) => Promise<unknown> | unknown;
type XToolExecutorMap = Record<string, XToolExecutor>;
  • args 由库对 toolCall.argumentsJSON.parse 失败时回退为 { raw: string }

8.5 toolErrorStrategy

行为
throw 工具不存在或执行抛错 → 抛 XllmError
return_tool_error_message 将错误封装为 tool 消息内容(JSON),让模型继续
skip 跳过该工具,不追加 tool 消息

9. 错误:XllmError

  • code: AUTH_ERROR | RATE_LIMIT | NETWORK_ERROR | INVALID_REQUEST | PROVIDER_ERROR
  • provider, message, 可选 statusCode, requestId, raw
  • HTTP 非 2xx 时由适配器 normalizeError 映射

10. 自定义 fetch 与测试

const xllm = createXllm({
  apiKey: "test",
  fetch: mockFetch as typeof fetch,
});

用于单测或代理;generate/stream 使用合并后的 fetchImpl


11. 新增内置供应商(需改库)

  1. 扩展 XProviderNamepackages/xllm/src/core/types.ts
  2. 实现 ProviderAdapterpackages/xllm/src/providers/types.ts
  3. registry.ts 注册
  4. runtime/config.ts 补充默认 model / baseURL / resolveApiKey 分支
  5. 增加 index.test.ts 用 mock fetch 覆盖

OpenAI 兼容第三方:通常只需 openai-compatible + baseURL,无需新枚举。


12. 实现文件索引(供维护者 / Agent 定位)

职责 路径
对外导出 src/index.ts
客户端 src/client/create-xllm.ts, generate.ts, stream.ts, chat-with-tools.ts, stream-with-tools.ts, tool-loop-shared.ts
类型 src/core/types.ts, src/core/errors.ts
配置 src/runtime/config.ts, http.ts, sse.ts
适配器 src/providers/openai-compatible.adapter.ts, deepseek.adapter.ts, registry.ts

13. 生成代码时的检查清单(给大模型)

  • 是否设置了 apiKey 或对应环境变量?
  • 兼容网关是否使用 openai-compatible + 正确 baseURL
  • 流式是否用 for await 遍历 XStreamEvent 并收窄 type
  • 工具闭环是否优先使用 chatWithTools / streamWithTools,避免手写 tool_calls 顺序错误?
  • 多模态是否确认目标模型支持,否则仅发 text
  • 工具失败策略是否为生产环境显式选择 toolErrorStrategy
  • 思考类参数是否确认与供应商文档一致?否则是否改用 providerExtras

文档与 packages/xllm 源码同步维护;若行为与代码不一致,以源码为准。