# llm-kit **Repository Path**: thzxx/llm-kit ## Basic Information - **Project Name**: llm-kit - **Description**: 🧰 统一 LLM API 客户端 — 一套 API 同时支持 DeepSeek、Ollama、Kimi、MiniMax、MiMo、智谱 GLM、OpenAI 兼容。TypeScript,零依赖,ESM+CJS 双格式,Node/Deno/Bun/浏览器同构。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-19 - **Last Updated**: 2026-05-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README
# 🧰 llm-kit **统一的大语言模型 API 客户端** 一个库同时支持 **Anthropic** · **DeepSeek** · **Ollama** · **Kimi** · **MiniMax** · **MiMo** · **智谱** · **OpenAI 兼容** API [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![TypeScript](https://img.shields.io/badge/TypeScript-5.5+-3178c6.svg)](https://www.typescriptlang.org/) [![Node.js](https://img.shields.io/badge/Node.js-≥18-339933.svg)](https://nodejs.org/) [![ESM + CJS](https://img.shields.io/badge/ESM%20%2B%20CJS-Dual%20Format-yellow.svg)](#安装) [快速开始](#快速开始) · [架构](#架构) · [API 文档](#api-参考) · [中间件](#中间件) · [扩展 Provider](#扩展新-provider) · [Gitee](https://gitee.com/thzxx/llm-kit)
--- ## ✨ 特性 | 特性 | 说明 | |------|------| | 🔮 **统一接口** | `createClient('deepseek')` 同一套 API,切换 Provider 零成本 | | 🧩 **组合式架构** | 策略对象 + 中间件链 | | 🌊 **原生流式** | TransformStream 管道,零中间层 AsyncGenerator 包装 | | 🔧 **函数调用** | 8 个 Provider 全部支持 Tool Calling | | 🧠 **思考模式** | Anthropic / DeepSeek / Ollama / Kimi / MiniMax / MiMo / 智谱 7 个 Provider | | 📄 **结构化输出** | JSON 模式 + Schema,全部 Provider 支持 | | 🖼️ **多模态** | 图片 · 视频 · 音频 · 文件 | | 🔌 **中间件** | 日志、指标、缓存、限流 — 可组合的横切关注点 | | ⚡ **韧性** | 可配重试(指数退避)、超时、自定义 fetch | | 🛡️ **错误体系** | `AuthError` · `RateLimitError` · `TimeoutError` · `ValidationError` · `ConnectionError` | | 📦 **双格式** | ESM + CJS + TypeScript 声明文件 | | 🌐 **同构** | Node 18+ · Deno · Bun · 现代浏览器 | --- ## 📦 安装 ```bash npm install llm-kit # or yarn add llm-kit # or pnpm add llm-kit ``` 从 Git 安装: ```bash npm install git+https://gitee.com/thzxx/llm-kit.git ``` --- ## ⚡ 快速开始 ### 30 秒上手 ```ts import { createClient } from 'llm-kit'; const client = createClient('deepseek', { apiKey: process.env.DEEPSEEK_API_KEY, }); const response = await client.chat({ model: 'deepseek-v4-pro', messages: [{ role: 'user', content: '解释 JavaScript 事件循环' }], stream: false, }); console.log(response.choices[0].message.content); ``` ### 切换 Provider 改一个字符串,其余代码不变: ```ts // OpenAI(官方) const client = createClient('openai', { apiKey: 'sk-...' }); // OpenAI 兼容(vLLM / LiteLLM 等) const client = createClient('openai-compatible', { baseURL: 'http://localhost:8000' }); // Anthropic(官方) const client = createClient('anthropic', { apiKey: 'sk-ant-...' }); // Anthropic 兼容(国内厂商 Anthropic 格式 API) const client = createClient('anthropic-compatible', { apiKey: 'sk-...', baseURL: 'https://api.xiaomimimo.com/v1', }); // DeepSeek const client = createClient('deepseek', { apiKey: 'sk-...' }); // Ollama(本地) const client = createClient('ollama'); // Kimi const client = createClient('kimi', { apiKey: 'sk-...' }); ``` ### 支持的 Provider | Provider | 创建方式 | 默认 baseURL | |----------|----------|-------------| | OpenAI | `createClient('openai', { apiKey })` | `https://api.openai.com/v1` | | OpenAI 兼容 | `createClient('openai-compatible', { baseURL })` | 需指定 | | Anthropic | `createClient('anthropic', { apiKey })` | `https://api.anthropic.com` | | Anthropic 兼容 | `createClient('anthropic-compatible', { apiKey, baseURL })` | 需指定 | | DeepSeek | `createClient('deepseek', { apiKey })` | `https://api.deepseek.com` | | Ollama | `createClient('ollama')` | `http://localhost:11434` | | Kimi | `createClient('kimi', { apiKey })` | `https://api.moonshot.cn` | | MiniMax | `createClient('minimax', { apiKey })` | `https://api.minimaxi.com` | | MiMo | `createClient('mimo', { apiKey })` | `https://api.xiaomimimo.com/v1` | | 智谱 | `createClient('zhipu', { apiKey })` | `https://open.bigmodel.cn/api/paas/v4` | --- ## 🏗️ 架构 llm-kit 采用**组合式架构**,通过策略对象和中间件链构建行为。 ### 设计原则 1. **组合优于继承** — 行为来自策略对象 2. **依赖注入** — HTTP 层可替换,便于测试 3. **中间件** — 横切关注点独立于核心逻辑 4. **开闭原则** — 新增 Provider 只需注册,不改已有代码 ### 架构图 ``` ┌─────────────────────────────────────────────────────────┐ │ ComposableClient │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │ │ │ Auth │ │ Request │ │ Response │ │ Stream │ │ │ │ Strategy │ │ Builder │ │Normalizer│ │ Parser │ │ │ └──────────┘ └──────────┘ └──────────┘ └─────────┘ │ │ │ │ ┌──────────────────────────────────────────────────┐ │ │ │ Middleware Chain │ │ │ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────────────┐ │ │ │ │ │Logger│→ │Metric│→ │Cache │→ │ HTTP Layer │ │ │ │ │ └──────┘ └──────┘ └──────┘ └──────────────┘ │ │ │ └──────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ ``` ### 策略层 每个职责独立为可替换的策略对象: | 策略 | 职责 | 内置实现 | |------|------|---------| | `AuthStrategy` | 认证头生成 | `BearerAuth` / `ApiKeyHeaderAuth` / `NoAuth` | | `ErrorMappingStrategy` | HTTP 错误映射 | `DefaultErrorMapping` / `ChainedErrorMapping` | | `StreamParserStrategy` | 流格式解析 | `SSEStreamParser` / `NDJSONStreamParser` | | `RequestBuilderStrategy` | 请求体构建 | 各 Provider 独立实现 | | `ResponseNormalizerStrategy` | 响应归一化 | 各 Provider 独立实现 | ### 流式管道 使用 TransformStream 实现零中间层的流式处理: ``` 字节流 → parseTransform → mapTransform → ReadableStream ``` --- ## 🌊 流式输出 ### 方式一:逐 chunk 读取 ```ts const stream = await client.chat({ model: 'deepseek-v4-pro', messages: [{ role: 'user', content: '写一首诗' }], stream: true, }); for await (const chunk of stream) { process.stdout.write(chunk.choices[0]?.delta?.content ?? ''); } ``` ### 方式二:统一事件流(推荐) ```ts const eventStream = await client.chatStream({ model: 'deepseek-v4-pro', messages: [{ role: 'user', content: '写一首诗' }], }); const reader = eventStream.getReader(); while (true) { const { done, value } = await reader.read(); if (done) break; switch (value.type) { case 'content': process.stdout.write(value.text); break; case 'reasoning': console.log('[思考]', value.text); break; case 'tool_call': console.log('[工具]', value.tool_call); break; case 'usage': console.log('[统计]', value.usage); break; case 'done': console.log('[完成]', value.finish_reason); break; } } ``` --- ## 🔌 中间件 中间件采用洋葱模型,请求从外到内,响应从内到外: ```ts import { createClient, loggerMiddleware, metricsMiddleware, createMetrics } from 'llm-kit'; const metrics = createMetrics(); const client = createClient('deepseek', { apiKey: 'sk-...', middlewares: [ loggerMiddleware(), metricsMiddleware(metrics), ], }); // 使用后查看指标 console.log(`请求: ${metrics.requests}, 错误: ${metrics.errors}`); ``` ### 自定义中间件 ```ts import type { Middleware } from 'llm-kit'; const rateLimiter: Middleware = async (ctx, next) => { await waitForQuota(); // 你的限流逻辑 return next(); }; const cache: Middleware = async (ctx, next) => { const key = `${ctx.method}:${ctx.path}:${JSON.stringify(ctx.body)}`; const cached = cacheStore.get(key); if (cached) return cached; const res = await next(); cacheStore.set(key, res); return res; }; client.use(rateLimiter); client.use(cache); ``` ### 内置中间件 | 中间件 | 功能 | |--------|------| | `loggerMiddleware()` | 请求/响应日志 | | `metricsMiddleware(metrics)` | 请求计数、延迟、错误率 | --- ## 🧠 思考模式 6 个 Provider 支持思考模式,统一通过 `reasoning_content` 字段输出: ```ts const response = await client.chat({ model: 'deepseek-v4-pro', messages: [{ role: 'user', content: '9.11 和 9.8 哪个更大?' }], thinking: { type: 'enabled' }, stream: false, }); console.log('[思考]', response.choices[0].reasoning_content); console.log('[回答]', response.choices[0].message.content); ``` --- ## 🔧 函数调用 ```ts const tools = [{ type: 'function', function: { name: 'get_weather', description: '获取指定城市的天气', parameters: { type: 'object', properties: { city: { type: 'string' } }, required: ['city'], }, }, }]; const response = await client.chat({ model: 'deepseek-v4-pro', messages: [{ role: 'user', content: '北京天气怎么样?' }], tools, stream: false, }); if (response.choices[0].message.tool_calls) { for (const call of response.choices[0].message.tool_calls) { console.log(`${call.function.name}(${call.function.arguments})`); } } ``` --- ## 📄 结构化输出 ```ts const response = await client.chat({ model: 'deepseek-v4-pro', messages: [ { role: 'system', content: '以 JSON 格式输出 name 和 age 字段' }, { role: 'user', content: '小明今年 25 岁' }, ], response_format: { type: 'json_object' }, stream: false, }); const data = JSON.parse(response.choices[0].message.content); // { name: "小明", age: 25 } ``` --- ## 🖼️ 多模态 ```ts // 图片 const response = await client.chat({ model: 'mimo-v2.5', messages: [{ role: 'user', content: [ { type: 'text', text: '描述这张图片' }, { type: 'image_url', image_url: { url: 'https://example.com/photo.jpg' } }, ], }], stream: false, }); ``` ### 多模态支持矩阵 | Provider | 图片 | 视频 | 音频 | 文件 | |----------|:----:|:----:|:----:|:----:| | Anthropic | ✅ | ❌ | ❌ | ✅ | | DeepSeek | ❌ | ❌ | ❌ | ❌ | | Ollama | ✅ | ❌ | ❌ | ❌ | | Kimi | ✅ | ✅ | ❌ | ❌ | | MiniMax | ✅ | ❌ | ❌ | ❌ | | MiMo | ✅ | ✅ | ✅ | ❌ | | 智谱 | ✅ | ✅ | ✅ | ✅ | --- ## 🛡️ 错误处理 ```ts import { createClient, LLMError, RateLimitError, AuthError, TimeoutError } from 'llm-kit'; try { await client.chat({ ... }); } catch (err) { if (err instanceof RateLimitError) { await sleep(err.retryAfter * 1000); } else if (err instanceof AuthError) { console.error('API Key 无效'); } else if (err instanceof TimeoutError) { console.error('请求超时'); } else if (err instanceof LLMError) { console.error(`[${err.provider}] ${err.code}: ${err.message}`); } } ``` ### 错误层级 ``` LLMError (基类) ├── RateLimitError — 429 限流 ├── AuthError — 401/403 认证失败 ├── TimeoutError — 请求超时 ├── ValidationError — 参数校验失败 └── ConnectionError — 网络连接失败 ``` --- ## 🔄 重试与超时 ```ts const client = createClient('deepseek', { apiKey: 'sk-...', retries: 3, // 最多重试 3 次 retryDelay: 1000, // 基础延迟 1s(指数退避) timeout: 60000, // 单次请求超时 60s }); ``` --- ## 🧩 扩展新 Provider 通过 `registerProvider()` 注册新 Provider,无需修改任何已有代码: ```ts import { registerProvider, ComposableClient } from 'llm-kit'; import { BearerAuth, DefaultErrorMapping, SSEStreamParser } from 'llm-kit'; import { OpenAICompatibleRequestBuilder, OpenAICompatibleResponseNormalizer } from 'llm-kit'; registerProvider('my-provider', { createConfig: () => ({ name: 'my-provider', defaultBaseURL: 'https://api.my-provider.com', defaultTimeout: 120_000, capabilities: { chat: true, streaming: true, thinking: false, toolCalling: true, structuredOutput: true, generate: false, embed: false, models: true, balance: false, imageInput: false, fim: false, }, auth: new BearerAuth(), errorMapping: new DefaultErrorMapping(), chatStreamParser: new SSEStreamParser(), requestBuilder: new OpenAICompatibleRequestBuilder({ providerName: 'my-provider', chatEndpoint: '/v1/chat/completions', }), responseNormalizer: new OpenAICompatibleResponseNormalizer({ providerName: 'my-provider', }), }), requiresApiKey: true, }); // 使用 const client = createClient('my-provider', { apiKey: 'sk-...' }); ``` --- ## 📂 项目结构 ``` llm-kit/ ├── src/ │ ├── index.ts # 主入口 │ ├── core/ │ │ ├── types.ts # 统一类型定义 │ │ ├── composable-client.ts # 组合式客户端 │ │ ├── errors.ts # 错误体系 │ │ ├── middleware.ts # 中间件系统 │ │ └── registry.ts # 注册式工厂 │ ├── strategies/ │ │ ├── auth.ts # 认证策略 │ │ ├── error-mapping.ts # 错误映射策略 │ │ ├── stream-parser.ts # 流解析策略 │ │ ├── request-builder.ts # 请求构建策略 │ │ ├── response-normalizer.ts # 响应归一化策略 │ │ └── openai-compatible-base.ts # OpenAI 兼容共享基类 │ ├── adapters/ │ │ ├── anthropic.ts # Anthropic (Claude) 适配器 │ │ ├── deepseek.ts # DeepSeek 适配器 │ │ ├── ollama.ts # Ollama 适配器 │ │ └── providers.ts # Kimi/MiniMax/MiMo/智谱/OpenAI兼容 │ └── utils/ │ ├── fetch.ts # 跨环境 HTTP │ ├── stream.ts # SSE/NDJSON 解析器 + TransformStream 管道 │ └── validator.ts # 参数校验 ├── tests/ │ ├── core.test.ts # 核心测试 │ ├── composable.test.ts # 架构测试 │ └── strategies.test.ts # 策略层测试 ├── package.json └── tsconfig.json ``` --- ## 📋 API 参考 ### 工厂函数 ```ts createClient('anthropic', options?) // → AnthropicClient createClient('deepseek', options?) // → DeepSeekClient createClient('ollama', options?) // → OllamaClient createClient('kimi', options?) // → KimiClient createClient('minimax', options?) // → MiniMaxClient createClient('mimo', options?) // → MiMoClient createClient('zhipu', options?) // → ZhipuClient createClient('openai-compatible', options?) // → OpenAICompatibleClient ``` ### ClientOptions | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | `apiKey` | `string` | - | API 密钥 | | `baseURL` | `string` | Provider 默认 | API 地址 | | `timeout` | `number` | 120000/300000 | 请求超时(ms) | | `headers` | `Record` | `{}` | 自定义请求头 | | `fetch` | `typeof fetch` | 全局 fetch | 自定义 fetch | | `retries` | `number` | `0` | 重试次数 | | `retryDelay` | `number` | `1000` | 重试基础延迟(ms) | | `middlewares` | `Middleware[]` | `[]` | 请求中间件 | ### Client 方法 | 方法 | 返回值 | 说明 | |------|--------|------| | `chat(request)` | `ChatResponse \| ReadableStream` | 对话补全 | | `chatStream(request)` | `ReadableStream` | 统一事件流 | | `generate(request)` | `GenerateResponse \| ReadableStream` | FIM 补全 | | `embed(request)` | `EmbedResponse` | 文本嵌入 | | `models()` | `ModelListResponse` | 列出模型 | | `use(middleware)` | `this` | 添加中间件 | --- ## 🧪 开发 ```bash # 安装依赖 npm install # 构建(ESM + CJS + Types) npm run build # 运行测试(120 个) npm test # 类型检查 npx tsc --noEmit ``` --- ## 📄 许可证 [MIT](LICENSE) © [thzxx](https://gitee.com/thzxx)