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.
6.5 KiB
6.5 KiB
xllm 统一大模型请求库设计文档
1. 背景与目标
在 packages/xllm 新建一个可跨 Node 与浏览器使用的大模型请求库,满足以下核心诉求:
- 支持流式输出,并可直接消费增量内容
- 提供供应商适配器,将请求和响应统一为一致结构
- 开发体验简洁,支持便捷切换供应商与模型
首版范围明确为:
- 运行环境:Node + 浏览器同一套 API
- 首批供应商:OpenAI-Compatible、DeepSeek
- 流式消费方式:
for await...of - 能力范围:文本对话 + 工具调用 + 多模态输入
- 配置策略:参数优先,环境变量兜底
2. 非目标(首版不做)
- 不引入复杂重试与熔断策略(仅保留最小错误归一化能力)
- 不实现供应商专有高级能力(如某家独有推理模式)的一致化抽象
- 不做 UI 层封装,仅提供 SDK 级能力
3. 总体架构
采用“核心领域模型 + 供应商插件适配器”架构(推荐方案 A)。
3.1 模块划分
建议目录:
packages/xllm/src/core/- 统一类型定义:
XRequest、XMessage、XStreamEvent、XResponse、XToolCall、XUsage - 统一错误模型:
XllmError
- 统一类型定义:
packages/xllm/src/providers/openai-compatible.adapter.tsdeepseek.adapter.tsregistry.ts(按 provider 名称注册/获取适配器)
packages/xllm/src/client/createXllm.ts(实例创建与默认配置)stream.ts(流式执行)generate.ts(非流式执行)
packages/xllm/src/runtime/fetch.ts(跨平台请求封装)sse.ts(SSE 增量解析)env.ts(环境变量读取)
packages/xllm/src/index.ts- 对外导出 API 与类型
3.2 核心设计原则
- 业务入口稳定:调用方只面对
xllm.stream()/xllm.generate() - 差异内聚:供应商差异仅存在于 adapter 内
- 可扩展:新增供应商只需实现同一 adapter 契约并注册
4. 统一数据模型
4.1 请求模型
XRequest(逻辑结构):
messages: XMessage[]tools?: XToolDefinition[]toolChoice?: "auto" | "none" | { name: string }stream?: booleantemperature?: numbertopP?: numbermaxTokens?: numbermetadata?: Record<string, string>- 请求级覆盖字段:
provider?: "openai-compatible" | "deepseek"model?: stringapiKey?: stringbaseURL?: string
XMessage:
role: "system" | "user" | "assistant" | "tool"content: XContentPart[]toolCallId?: string(role 为tool时用于关联)
XContentPart:
{ type: "text"; text: string }{ type: "image"; image: { url: string } }
首版仅强制支持
url(包含 http(s) 与 data URL),后续可扩展 file/blob 引用。
4.2 响应模型
XResponse:
text: stringtoolCalls: XToolCall[]usage?: XUsageprovider: stringmodel: stringfinishReason?: stringraw?: unknown(可选调试字段)
5. 流式事件协议
stream() 返回 AsyncIterable<XStreamEvent>,统一事件集合:
response.start- 响应开始,包含 provider/model/requestId 等元数据
text.delta- 文本增量,用于直接输出
tool_call.delta- 工具调用参数增量
tool_call.done- 单个工具调用完成,输出完整 name/args
response.usage- token 使用统计
response.done- 完成事件,含 finish reason
说明:
- 默认将供应商 SSE 分片归一化为上述事件
- 消费侧推荐只关心
text.delta与response.done即可完成常见直出场景
6. 供应商适配器契约
定义统一接口 ProviderAdapter:
name: stringtoProviderRequest(input: XRequest, config: ResolvedConfig): ProviderHttpRequestfromProviderResponse(raw: unknown): XResponsefromProviderStreamChunk(chunk: string, state: StreamState): XStreamEvent[]normalizeError(err: unknown): XllmError
适配职责:
- 请求映射:统一字段 -> 供应商字段
- 流式映射:供应商 chunk -> 统一事件
- 错误映射:供应商错误 -> 统一错误码
7. 配置与切换策略
7.1 配置优先级
最终配置合并顺序(高到低):
- 请求级参数(
stream/generate调用时传入) - 实例默认参数(
createXllm) - 环境变量兜底
7.2 建议环境变量
XLLM_API_KEYOPENAI_API_KEYDEEPSEEK_API_KEYXLLM_BASE_URL(可选)
7.3 切换体验
createXllm({ provider, model, ... })设全局默认- 单次调用可覆写
{ provider, model, ... } - 同一业务逻辑不变,仅替换 provider/model 参数即可切换模型后端
8. 错误模型与稳定性
统一错误码建议:
AUTH_ERRORRATE_LIMITNETWORK_ERRORINVALID_REQUESTPROVIDER_ERROR
XllmError 结构包含:
codemessageproviderstatusCode?requestId?raw?
流式错误处理约定:
- 出现不可恢复错误时抛出
XllmError - 已发出的增量内容由调用方决定是否展示或回滚
9. 测试策略
9.1 单元测试
- adapter 请求映射测试
- adapter 非流式响应映射测试
- adapter 流式 chunk 解析测试(含半包、粘包、结束包)
9.2 集成测试
- mock fetch + mock SSE,覆盖
stream与generate主流程 - 断言统一事件顺序与最终响应一致性
9.3 契约测试
- 同一
XRequest在不同 provider 下返回结构都满足统一断言 - 确保新增 provider 不破坏现有统一接口语义
10. 包结构与发布约定(与仓库一致)
新包遵循现有 monorepo 规范:
- 包名建议:
@dm/xllm - 入口:
src/index.ts package.json中导出:"development": "./src/index.ts""import": "./dist/index.js""types": "./dist/index.d.ts"
- 脚本:
"dev": "dm dev"、"build": "dm build"
11. 里程碑与实施顺序
建议分 3 个小阶段:
- M1(骨架)
- 建立 core 类型、client 主入口、provider registry、基础测试框架
- M2(能力)
- 完成 openai-compatible 与 deepseek 的 stream/generate 适配
- 打通文本、多模态、工具调用映射
- M3(稳态)
- 补齐错误归一化与契约测试
- 完善 README 与示例用法
12. 验收标准
- 可在 Node 与浏览器中通过同一 API 调用
- 能通过
for await...of获取稳定的text.delta直出 - OpenAI-Compatible 与 DeepSeek 可通过仅修改 provider/model 切换
- 非流式返回结构与流式聚合结果语义一致
- 关键错误能归一化并携带可诊断信息