baabakk/llm-ports

GitHub: baabakk/llm-ports

一个面向多供应商 LLM 系统的 TypeScript 抽象架构层,通过统一接口、成本管控与失败降级机制解决业务逻辑与特定模型 SDK 深度耦合的问题。

Stars: 2 | Forks: 0

# llm-ports:用于多 Provider AI 系统的 TypeScript LLM 抽象层 Provider 无关的 TypeScript LLM 架构。 无需修改代码即可切换 Provider。 避免供应商锁定。 控制成本。 将 prompt 作为可复用能力。 多 Provider 路由 • fallback 链 • USD 成本限制 • 能力工厂 • tool-use 安全 • 可观测性 [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![状态](https://img.shields.io/badge/status-pre--release-orange) ![TypeScript](https://img.shields.io/badge/TypeScript-first-blue) ## 问题所在 大多数 LLM 应用程序都会以可预见的方式出错: - SDK 升级会涉及过多文件 - 切换 Provider 需要重构 - Prompt 逻辑在各个功能中重复存在 - 成本和路由逻辑分散各处 - 业务逻辑变得与特定 Provider 的 SDK 耦合 这不仅仅是 SDK 的问题。 **这是架构问题。** ## 解决方案 `llm-ports` 将端口和适配器模式应用于 LLM 系统。 其他所有部分都与类型化接口通信。 您的应用程序不再直接调用模型,而是使用可复用的能力: - classify - draft - score - summarize - extract - plan - analyze LLM 不再是您需要管理的依赖项。 它变成了您可以配置的基础设施。 ## 您将获得什么 - 跨 OpenAI、Anthropic、Ollama、Vercel AI SDK 及兼容 Provider 的**多 Provider LLM 路由** - 当 Provider 失败或超出预算时的 **fallback 链** - 具有每小时、每天和每月限制的**基于 USD 的成本限制** - **可复用的 prompt 能力**,使 prompt 定义一次即可在处处复用 - 针对结构化输出失败的**验证恢复** - 用于破坏性或需要确认的操作的 **tool-use 安全原语** - 用于成本、延迟、质量和结果的**可观测性钩子** - 提供完整类型支持的 **TypeScript 优先 API** - **不依赖 LangChain、LlamaIndex 或繁重框架的运行时** ## 60 秒设置 ### 1. 在 `.env` 中配置 Provider ``` LLM_PROVIDER_FAST=anthropic||cost:50/day LLM_PROVIDER_SMART=anthropic||cost:200/day LLM_TASK_ROUTE_TRIAGE=fast,smart ``` ### 2. 创建一次 port ``` import { createRegistryFromEnv } from "@llm-ports/core"; import { createAnthropicAdapter } from "@llm-ports/adapter-anthropic"; export const llm = createRegistryFromEnv({ adapters: { anthropic: createAnthropicAdapter({ apiKey: process.env.ANTHROPIC_API_KEY!, }), }, }).getPort(); ``` ### 3. 在任何地方使用它,无需导入 SDK ``` const result = await llm.generateText({ taskType: "triage", prompt: "Classify this email...", }); ``` Registry 将: - 为任务选择合适的模型 - 执行成本限制 - 在失败时通过 Provider 链进行 fallback - 记录使用情况、成本和延迟 ## 能力:可复用的 LLM 操作 无需在各个文件中复制 prompt 逻辑,只需定义一次能力并复用它。 ``` import { createClassifier } from "@llm-ports/capabilities"; import { z } from "zod"; const IntentSchema = z.object({ intent: z.enum(["question", "request", "complaint", "feedback", "other"]), urgency: z.enum(["low", "normal", "high"]), reasoning: z.string(), }); export const classifyIntent = createClassifier({ port: llm, schema: IntentSchema, schemaName: "user-intent", rubric: ` question: asking for information request: wants something done complaint: reports a problem feedback: opinion only other: anything else `, }); ``` 现在可以在任何地方调用它: ``` const result = await classifyIntent({ content: userMessage }); ``` 输出示例: ``` { intent: "request", urgency: "high", reasoning: "The user is asking for a concrete action." } ``` 为什么这很重要: - 改进一次 prompt,所有调用处都会受益 - 保持整个系统行为一致 - 让调试和评估更容易 - 让业务逻辑摆脱特定于 Provider 的 SDK 细节 ## 架构概述 之前: ``` Application code ├─ direct SDK call ├─ direct SDK call ├─ direct SDK call └─ model router leaking SDK types ``` 之后: ``` Application code ↓ Capabilities ↓ LLM Port ↓ Adapters and Provider Registry ↓ LLM providers ``` 关键转变在于: ## 软件包 | 软件包 | 用途 | |--------|---------| | `@llm-ports/core` | Port 接口、registry、路由、成本限制、验证策略、内容块 | | `@llm-ports/capabilities` | 可复用的 LLM 操作工厂 | | `@llm-ports/adapter-openai` | OpenAI SDK 适配器,支持兼容 Provider 的 `baseURL` | | `@llm-ports/adapter-anthropic` | Anthropic SDK 适配器 | | `@llm-ports/adapter-google` | Google Gemini 原生适配器 (@google/genai SDK) — 完整多模态,内置定价 | | `@llm-ports/adapter-ollama` | Ollama 原生适配器,支持模型管理 | | `@llm-ports/adapter-vercel` | 用于迁移和兼容性的 Vercel AI SDK 适配器 | ## 示例 [`examples/`](examples/) 中有七个可运行的示例,每个都是独立的 pnpm workspace 软件包,并附带 README 解释代码: | 示例 | 展示内容 | |---|---| | [`basic`](examples/basic/) | 最基础的端到端实现。一个适配器,一种任务类型,一次 `generateText` 调用。即 60 秒设置演示。 | | [`multi-provider`](examples/multi-provider/) | Fallback 链(Anthropic 主力 → OpenAI 备用),每个 Provider 的 USD 成本限制,能力工厂。 | | [`email-triage`](examples/email-triage/) | 最常见的生产用例,浓缩在约 150 行代码中。入站邮件 → 分类(意图 + 紧急度 + 情感)→ 策略门控 → 起草符合品牌语气的回复 → 排队等待人工审核。能力组合的故事。 | | [`streaming-chat`](examples/streaming-chat/) | 包含三个路由的 Express 服务端:`POST /chat`(一次性)、`POST /chat/stream`(Server-Sent Events)、`POST /chat/agent`(tool-augmented)。仅用约 30 行胶水代码实现最常见的 LLM UX 模式。 | | [`extract-from-pdf`](examples/extract-from-pdf/) | 文档提取:原始 OCR 发票文本 → 通过 Zod 转换为完全类型化的结构化对象。演示 `generateStructured`、带反馈的验证重试以及 `createExtractor` 工厂。 | | [`agent-with-approval`](examples/agent-with-approval/) | 具有一流安全原语的 tool-use Agent。`destructive`、`requiresConfirmation`、`maxOutputBytes` 标志 + 审批门控包装器。差异化的示例。 | | [`migrate-from-vercel-ai`](examples/migrate-from-vercel-ai/) | 针对 Vercel AI SDK 用户的两种迁移路径:(a) 使用 `@llm-ports/adapter-vercel` 包装现有的模型工厂,(b) 用原生的 llm-ports 适配器替换 `@ai-sdk/*`。并排展示前后的差异。 | 每个示例都可以从 monorepo 根目录运行: ``` pnpm --filter @llm-ports/example- start ``` 运行前请设置相关的 API key(`ANTHROPIC_API_KEY`、`OPENAI_API_KEY`)。每个示例的 README 记录了其所需的 key。 ## 支持的用例 在以下情况时使用 `llm-ports`: - 需要 多 Provider LLM 路由 - 需要 LLM fallback 链 - 需要 TypeScript LLM 抽象 - 需要 OpenAI 和 Anthropic Provider 切换 - 需要为生产 LLM 应用程序控制成本 - 需要 可复用的 prompt 能力 - 需要 结构化输出验证和恢复 - 需要 agent 工作流中的 tool-use 安全 - 需要 LLM 成本、延迟和质量的 可观测性 - 需要 供应商中立的 AI 架构 ## 何时使用 如果满足以下条件,请使用 `llm-ports`: - 您使用 2 个或更多 LLM Provider - 您以后可能会切换 Provider - SDK 升级引起了多文件改动 - Prompt 逻辑存在重复 - 成本控制很重要 - 您希望将业务逻辑与 Provider SDK 解耦 如果有以下情况,请跳过它: - 您只有 1 到 2 次 LLM 调用 - 您只是在进行原型设计 - 您是故意围绕某个特定 Provider 的特性进行构建 - 您想要一个完整的 agent 框架、记忆层、RAG 框架或托管网关 ## 相关工具 | 工具 | `llm-ports` 与它们的关系 | |------|--------------------------| | Vercel AI SDK | Vercel 统一了 Provider 调用。`llm-ports` 在此基础上增加了 registry、fallback 链、USD 成本限制、验证恢复和能力工厂。 | | LiteLLM | LiteLLM 是一个 Python 优先的 HTTP 代理。`llm-ports` 是 TypeScript 的,且在进程内运行,没有额外的网络跳转。 | | Portkey | Portkey 是一个商业托管网关。`llm-ports` 是 MIT 许可、进程内运行的,且没有托管依赖。 | | LangChain.js | LangChain 是一个框架。`llm-ports` 是一个轻量级的架构和控制层。 | | LlamaIndex.TS | LlamaIndex 是检索优先的。`llm-ports` 处理 LLM 调用、路由、fallback 和成本控制。 | | Mastra | Mastra 是 agent 优先的,内置了记忆和工作流原语。`llm-ports` 在该层之下提供了更底层的 LLM 原语。 | ## Alpha 阶段的已知限制 `llm-ports` 处于预发布状态。核心架构已经稳定,离线回归测试套件非常全面(250+ 测试,p99 延迟低于 1 ms,在 110+ 代码片段中未检测到文档陈旧)。一些适配器和 agent 路径仍在加固中。 十四个中等影响的 alpha 测试问题([#1](https://github.com/baabakk/llm-ports/issues/1), [#3](https://github.com/baabakk/llm-ports/issues/3), [#4](https://github.com/baabakk/llm-ports/issues/4), [#5](https://github.com/baabakk/llm-ports/issues/5), [#6](https://github.com/baabakk/llm-ports/issues/6), [#9](https://github.com/baabakk/llm-ports/issues/9), [#12](https://github.com/baabakk/llm-ports/issues/12), [#14](https://github.com/baabakk/llm-ports/issues/14), [#16](https://github.com/baabakk/llm-ports/issues/16), [#19](https://github.com/baabakk/llm-ports/issues/19), [#20](https://github.com/baabakk/llm-ports/issues/20), [#21](https://github.com/baabakk/llm-ports/issues/21), [#24](https://github.com/baabakk/llm-ports/issues/24), [#32](https://github.com/baabakk/llm-ports/issues/32))已在 `0.1.0-alpha.1` → `0.1.0-alpha.13` 中修复并现已关闭。Alpha 系列完成了 v0.1 表面:Gemini 多轮对话 `runAgent` + 原生 `responseSchema`,运行时模型发现(跨 4 个适配器的 `LLMPort.listModels()` + `Registry.checkPricingFreshness()`),`adapter-openai` 上的 `useStrictResponseFormat` 用于 Cerebras 的 strict-JSON,openai + anthropic 上的 `dangerouslyAllowBrowser` 选项,用于 o-series / gpt-5-nano / Groq gpt-oss-120b 推理深度控制的 `reasoningEffort` 参数,能力工厂向底层 port 调用传递 `reasoningEffort` + `signal` + `forceProviderAlias`,以及扩展后的 `attemptValidationRepair` 过程,该过程可捕获 markdown 包裹的枚举、尾随标点、字符串化 JSON 作为对象以及包含单个对象的数组等误读情况。完整的各项功能清单详见 [v0.1 状态页](https://baabakk.github.io/llm-ports/v0-1-status)。 仍然悬而未决的问题: - 某些兼容 Provider 的模型(Groq、Together AI、Fireworks、Clarifai、SambaNova)可能需要配置 `pricingOverrides` 条目,以满足 registry 的定价验证步骤。默认情况下,内置的定价表涵盖 OpenAI、Anthropic、Google 和 Ollama。关于 Clarifai 的 Qwen3.6 35B A3B FP8 和 SambaNova 的 MiniMax-M2.7 的操作示例在 [openai 适配器文档](https://baabakk.github.io/llm-ports/adapters/openai)中。 - Vercel 适配器的 `runAgent` 仅支持单轮(多轮将在 v0.2 中实现)。 - Registry 在**预算限制**和**运行时错误**时都会遍历 Provider 链(alpha.7+,默认谓词:`ProviderUnavailableError`)。可通过 `runtimeFallback: "none" | "default" | { shouldFallback }` 进行配置。流式方法仅在流创建失败时遍历,而不是在迭代过程中。 如果您遇到了此处未列出的问题,请[提交一个 issue](https://github.com/baabakk/llm-ports/issues/new/choose) —— bug 报告模板会捕获我们所需的确切版本和复现步骤。 ## 安装 `llm-ports` 处于 alpha 阶段。所有 7 个软件包以及新的 `@llm-ports/migrate` codemod 均发布在 `v0.1.0-alpha.20.1`。经过短暂的 alpha 测试后,稳定的 v0.1 将正式发布 —— 请访问 [v0.1 状态页](https://baabakk.github.io/llm-ports/v0-1-status) 查看哪些部分目前已经稳定,哪些仍在加固中。 ``` npm install @llm-ports/core@0.1.0-alpha.20.1 ``` 根据需要安装适配器: ``` npm install @llm-ports/adapter-anthropic@0.1.0-alpha.20.1 npm install @llm-ports/adapter-openai@0.1.0-alpha.20.1 npm install @llm-ports/adapter-google@0.1.0-alpha.20.1 npm install @llm-ports/adapter-ollama@0.1.0-alpha.20.1 npm install @llm-ports/adapter-vercel@0.1.0-alpha.20.1 npm install @llm-ports/capabilities@0.1.0-alpha.20.1 ``` (作用域在 `@llm-ports` 下。通过 changesets 统一进行版本控制。) Peer dependency:`zod >=3.24.0 <5`。请自带 SDK(`@anthropic-ai/sdk`、`openai`、`ollama`、`ai`)。 ### Alpha 系列期间的版本锁定 **建议:锁定到确切的 alpha 版本**,而不是 `@alpha` dist-tag,因为我们仍在锁定核心结构。`@` 标签会跟踪最新发布的预发布版本;因此,执行 `pnpm install` 或 `npm update` 可能会默默跨过多个破坏性变更进行升级。精确锁定会在您手动升级之前保持版本不变,届时您可以阅读 [MIGRATION.md](./MIGRATION.md) 并应用各版本的迁移指南。 ``` // package.json — recommended during alphas { "dependencies": { "@llm-ports/core": "0.1.0-alpha.20.1", "@llm-ports/adapter-anthropic": "0.1.0-alpha.20.1" } } ``` `@alpha` 标签适合用于实验: ``` npm install @llm-ports/core@alpha ``` 当您升级时,`@llm-ports/core` 的 postinstall 会输出一行指向迁移页面的横幅。要通过自动化方式跨多个 alpha 版本升级,请使用内置的 codemod: ``` npx @llm-ports/migrate@alpha alpha-19-to-alpha-20 --dry-run # preview npx @llm-ports/migrate@alpha alpha-19-to-alpha-20 --write # apply ``` ## 文档 文档站点(每次推送到 `main` 时从 `docs/` 自动部署): https://baabakk.github.io/llm-ports/ 页面: - 入门指南 - 概念:ports、adapters、任务路由、成本限制、内容块、验证策略 - 指南:多 Provider 路由、本地到云端、成本控制、自定义适配器、可观测性、安全性 - 能力:每种能力一个页面 - 适配器:每个适配器一个页面及功能对比矩阵 - 迁移:从 Vercel AI SDK、LangChain.js 和直接 Provider SDK 迁移 ## 安全性 没有威胁模型的 tool use 是危险的。 `llm-ports` 将安全性视为 API 的重要组成部分: - 破坏性工具标记 - 需要确认的操作 - 最大输出字节限制 - 脱敏能力 - 针对提示词注入和工具滥用的明确指导 请参阅 [SECURITY.md](./SECURITY.md)。 ## 贡献 在初始的 v0.1 脚手架落地后,欢迎各界贡献。 请参阅 [CONTRIBUTING.md](./CONTRIBUTING.md)。 ## 许可证 MIT。请参阅 [LICENSE](./LICENSE)。 ## 状态 预发布版。 当前目标: - v0.1:core、adapters、成本限制、7 个能力工厂 - v0.2:扩展的能力和可观测性包 - v0.3:额外的适配器和 markdown 技能格式评估 ## 关注发布 `llm-ports` 处于预发布阶段。若要在 v0.1 发布到 `latest` 标签时(以及之后每个次要版本发布时)收到通知: 1. 点击 [GitHub 仓库](https://github.com/baabakk/llm-ports) 顶部的 **Watch** 按钮 2. 选择 **Custom** 3. 勾选 **Releases** 只有在真正发布新版本时,您才会收到电子邮件或通知。不会有 PR 或 commit 的干扰噪音。
标签:AI, DLL 劫持, MITM代理, TypeScript, 多供应商路由, 大语言模型, 安全插件, 架构设计, 自动化代码审查, 自动化攻击