@animalabs/membrane

中文文档
0.9.0发布于 2026/10/30MITTypeScriptES Module构建来源已验证近 30 天下载 2.7万

LLM 中间软件 - 一个可选择的边界, 改变通过的东西

中文使用文档
文档目录9 节
  1. 安装
  2. 快开始
  3. 流程和工具
  4. 供应商
  5. 格式化器
  6. 其他值得了解的行为
  7. 设计说明
  8. 发展
  9. 许可证

膜

@animalabs/membrane 通过一个请求和响应格式向许多提供者发送 LLM 请求. 请求是指定参与者的电文清单,例如: User, (中文(简体) ), Alice 或者说 Claude,带有系统即时,工具和生成设置. 膜将其转化为提供者所期望的,用回转来发送,并解析答案,无论是否流出,分为内容块,工具调用和使用,估计成本.

它坐落于康涅狄格堆栈的底部. 代理框架, (中文(简体) ), 上下文管理器 财务报告和审定财务报表 连接主机 都建立在它之上。 上下文管理器将代理商的历史编译为膜的信息格式,代理架构发送每个通过膜.

安装

npm install @animalabs/membrane

它需要节点22.12或后. 它的一次性依赖是 @anthropic-ai/sdk。 。 。 .

快开始

import { Membrane, AnthropicAdapter } from '@animalabs/membrane';

// The adapter reads ANTHROPIC_API_KEY unless you pass apiKey or other credentials.
const membrane = new Membrane(new AnthropicAdapter());

const response = await membrane.complete({
  system: 'You are a helpful assistant.',
  messages: [
    { participant: 'User', content: [{ type: 'text', text: 'Hello!' }] },
  ],
  config: { model: 'claude-sonnet-4-5', maxTokens: 1024 },
});

console.log(response.content);    // content blocks, e.g. [{ type: 'text', text: '…' }]
console.log(response.stopReason); // e.g. 'end_turn'
console.log(response.usage);      // input and output tokens
console.log(response.details.usage.estimatedCost); // absent for a model membrane has no prices for

参加者的名字 Claude 是默认的助手。 设定 assistantParticipant 应请求或 Membrane 配置, 以使用另一个名称 .

流程和工具

stream() 接受相同的请求,并在回合结束时返回相同的响应,或者 AbortedResponse 如果它被取消, 通过你的信号或超时。 供应商失败以 MembraneError,因为它从 complete()。 。 。 . onChunk 接收到每个块, 元数据显示它属于哪个块, 以及它是否是可见文本而不是思维或工具内容。 与 onToolCalls,膜会运行工具回合内线:它通过每个回合的工具调用来调用功能,发送返回的结果,并持续到模型解答而不调用工具. 子弹在深处停了 maxToolDepth (10),从0计数, 最后一轮的结果回来 toolResults 而不是去模型. complete() 没有工具循环,返回任何工具调用 response.toolCalls。 。 。 .

import { isAbortedResponse } from '@animalabs/membrane';

const controller = new AbortController();
const result = await membrane.stream(
  {
    messages: [
      { participant: 'User', content: [{ type: 'text', text: 'What time is it?' }] },
    ],
    tools: [{
      name: 'get_time',
      description: 'The current time, as an ISO string.',
      inputSchema: { type: 'object', properties: {} },
    }],
    config: { model: 'claude-sonnet-4-5', maxTokens: 1024 },
  },
  {
    onChunk: (text, meta) => { if (meta.visible) process.stdout.write(text); },
    onToolCalls: async (calls) =>
      calls.map((call) => ({ toolUseId: call.id, content: new Date().toISOString() })),
    signal: controller.signal,
  },
);

if (isAbortedResponse(result)) {
  // Cancelled: result.reason says why ('user' when it was your signal),
  // and result.rawAssistantText holds any text that had arrived.
}

供应商

每个供应商都是你传递给的适配器 new Membrane(adapter, config)。适配器读取第三列中的环境变量,除非您在其配置中通过相同的设置.

适配器会谈环境
AnthropicAdapterAnthropic's Messages API. (原始内容存档于2018-10-12).ANTHROPIC_API_KEY
BedrockAdapterAnthropic在AWS Bedrock上的克洛德模型.AWS_ACCESS_KEY_ID, (中文(简体) ), AWS_SECRET_ACCESS_KEY,可选 AWS_SESSION_TOKEN,以及 AWS_REGION (默认) us-west-2(中文(简体) )
OpenAIAdapterOpenAI的"聊天补全"API.OPENAI_API_KEY
OpenAIResponsesAPIAdapterOpenAI的反应API.OPENAI_API_KEY
OpenAICompatibleAdapter任意OpenAI相容的聊天补全端点,例如Ollama或vLLM.无:通过 apiKey 如果终点需要的话
OpenAICompletionsAdapterA 类 /v1/completions 端点,用于基础模型.无:通过 apiKey 如果终点需要的话
OpenRouterAdapter开出鲁特.OPENROUTER_API_KEY
GeminiAdapter谷歌双子座API.GOOGLE_API_KEY
OpenAIResponsesAdapterOpenAI的图像 API,尽管它的名字.OPENAI_API_KEY
MockAdapter无:供测试使用的罐装或反射反应(createCannedAdapter, (中文(简体) ), createEchoAdapter) (中文(简体) ).无

格式化器

A formatter 将参与者转换为提供者的信息格式并解析答案. Membrane配置中有一个是 formatter。 。 。 .

  • AnthropicXmlFormatter,默认值,支持本地工具和XML记录模式。 在 XML 模式中, 对话变成一个参与者标记的记录, 工具调用 <function_calls> 财务报告和审定财务报表 <function_results>,模型继续作为预填.
  • NativeFormatter 将参与者映射到提供者自己的用户和助理角色.
  • CompletionsFormatter 制作一个用于完成终点的单个快速字符串.
  • OpenAIResponsesFormatter 构建响应 API 输入, 重放从该 API 导入的项目 .

膜构建出一个本土请求,带有本土工具,每当地物支持一个时,就像默认地物一样. 一个请求 toolMode: 'xml',或为 XML 配置的文件,选择 XML 笔录. 文件/格式 涵盖选择和每个主题的选择.

其他值得了解的行为

  • 复问. 膜是重试的一层: AnthropicAdapter'SDK客户端在每次请求时都会做一次尝试,只有它的缓存保存器的背景回放保留了SDK自己的回放. 提供商的电话在发送任何信息之前 都会出现可重试的错误, 在每一个入口和任何一轮的工具循环中, 都会出现故障。 已经发送的不是, 因为那会重播你已经拥有的东西。 每次尝试都唤作你 onRequest,所以一个请求的膜重试再次称它为";一个证书解析器在401后被重发是它接下来的尝试的一部分. 向超载供应商(529个)提出的要求达到 retry.overloaded.maxRetries 尝试,7次默认,或 retry.maxRetries 如果这是更多的。 它们之间的延迟从10秒翻倍到5分钟的上限,每个等由一半的延迟和全部延迟之间随机抽取,或者在时间更长时是提供者的再试. 没有重试之后, 大约5到10分钟。 限速请求 (429) 最多有5次尝试,或 retry.maxRetries 如果更多的话,其他可重试的失败(a 5xx,一个提供者的408,一个连接失败)会得到 retry.maxRetries 尝试,默认三次,等待1秒和2秒。 最多一分钟的重试等待,或者在时间更长的地方等待时间上限(529小时为5分钟);更长的时间不是:错误一时降临到你们身上,上面所说的等待是: retryAfterMs已发出请求的最后期限也没有被重审: AnthropicAdapter闲置和第一事件监督,undici的头 和身体超时, Bun的取出超时, 和每一次超时 AnthropicAdapterSDK客户端报告 包括一个连接超时, 因为SDK报告的方式都一样。 呼叫结束为可重试 timeout 让你重试与否。 在其他适配器上,在节点上,连接超时像任何连接故障一样被重试;Bun的取出超时没有说哪个阶段耗出,所以在Bun上,一个被停顿的连接也留给了您. 如果只有你自己的重试层,通过 retry: false 改为 complete(), (中文(简体) ), stream() 或者说 streamYielding():膜后再回覆无一失信请求,不论出错,失败如来,由提供商对此提供建议(出错)retryable,并声明等待 retryAfterMs) (中文(简体) ). 二个发送停留: 拒绝 重新发出你要求的 refusalRetries 打开 complete(),或打开 streamYielding() 在本地工具模式下,以及一个带有证书解析器的适配器在401后所制作的带有刷新证书的重发版本. 一层你的复试 可以接受膜本身的决定 @animalabs/membrane/retry,带有自己的号码: classifyFailure 给失败的课,和 retryDecision 在这么多次尝试之后是否再发送 以及等待多久.
  • 进展范围. 过 progressBounds: true 改为 stream() 或者说 streamYielding() 以结束一个停止进步的流式电话, 即使提供商保持其连接 。 他们被默认关闭。 在内容之前,一个呼叫在发送60秒后结束,或者,一旦一个思维障碍开始,则在后半段和该障碍的允许:请求的 max_tokens 87个令牌,一秒钟开始, 大约3分钟16,000个令牌,24.5分钟128,000个。 一旦内容开始,一个呼叫在150秒后结束,没有提供商事件,或者,当最后一个事件是一个思维障碍的起步时,如果这个障碍更长,则在该障碍的允许后结束. 当请求要求总结思考时,总结是内容,所以一个打开反应的总结会得到60秒到第一个三角洲. 数值是 PROGRESS_BOUNDS从 @animalabs/membrane/progress-bounds对象 { beforeContentMs: 90_000 } 替换其中任何一个。 他们申请 AnthropicAdapter 财务报告和审定财务报表 BedrockAdapter他们的溪流 报告他们的内容, 并运行在旁边 progressTimeoutMs 和Anthropic适配器自己的最后期限, 第一个用完电话。 结束为终止的有理性的流 'timeout' (单位:千美元) message 命名束缚,膜不会再次发送。 默认值是在生产路由器流传的Anthropic呼叫中测量到的 claude-opus-5-5 财务报告和审定财务报表 claude-haiku-5-5,从每次尝试的发送中计时。 等待内容或思维屏障的起步时间在 Opus 和 Haiku 的 第 99. 9 分之一时达到 25 秒, 随时间推移而增长: Opus 上, 百分位从 14 秒 不到 10 万 个令牌升至 29 秒 超过 70 万 个, 路由器自己 的 30 秒 的 剪接 使 开始速度变得不见踪影。 87个符号的一秒是 Opus 思维速度的第1分之1 超过30秒或以上的思维区块(Haiku's was 175),在呼叫中发出一个 max_tokens 在16 000或128 000人中,没有成功的思维障碍使用了一半的津贴。 内容后事件间最长的间隔为140秒. 贝德洛克,没有流传的电话, 和其他模型, claude-opus-4-6 在其中,没有测量, 所以检查值 根据你自己的呼声,然后启动那里.
  • 快速缓冲. 在 Anthropic 和 Bedrok 上, 请求带有缓存标记, 除非请求设置 promptCaching: false。带 cacheBreakpoint: true 得到一个。 Anthropic在一次请求中接受四个标记,而膜会掉入最浅的后方. 一个请求 cacheTtl: '1h' 询问 Anthropic 为更长的缓存; Bedrock 保留了自己的默认寿命 . AnthropicAdapter 也保持了闲置代理的一小时缓存的温度. 内容 CacheKeepalive默认情况下,重放最后一个带有一小时缓存标记的流出请求 max_tokens: 0,一旦缓存 走了45分钟未动, 最多一天后最后一次真正的请求。 它只持有一个请求 当提供者已知 开始它的信息,在一个流 message_start 或一旦SDK有非流回音,那么在那时之前失败的电话,如一个拒绝或从未交付,就永远不会被重播. 重放在请求最后一个一小时的标记之后,除了一个用户结束时需要结束什么:没有一个小时的缓存条目会保留它们,所以重放它们只会作为输入计费,或者在5分钟的标记覆盖它们的地方再写. 该标记上或之后没有用户消息的请求会被全部重放 。 请求只有5分钟缓存,或者形状无法重放,没有刷新. 因此,一个长寿命的过程在闲置时发出这些刷新请求. new AnthropicAdapter({ cacheKeepalive: { enabled: false } }) 关掉.
  • 系统改变. 只保存信件 system_change 块更改模型提供的工具,以及其系统文本,从谈话开始,不编辑请求 tools 或者说 system,所以在它保持前的即时缓存. NativeFormatter 财务报告和审定财务报表 AnthropicAdapter 把它当作中间的谈话 role: 'system' 消息: 每个 removeTools 作为工具去除,每个 defineTools 作为工具定义和每项 addSystem 值不仅仅是文本的白空间,在修改工具时内置工具为β。 它在它的位置或之后的第一个点开始,API接受:在用户转弯后,包含一个工具-结果转弯,在助手转弯之前或结尾. 携带一个请求失败 MembraneError 谁 systemChangeRefused 当它的位置之后没有一点接受它时,当前题或适配器是另一个时,当模型没有接受中间对口系统消息时,才是真实的. 前两出出出事前出事. 通过另一个前题, 一个请求 它不能携带任何工具(tools 由于请求的更改留下了它们)首先失败,没有了旗帜,因为同样的更改是在 tools 也会遇到拒绝 同样的改动是: tools 财务报告和审定财务报表 system 虽然一个以助手转弯结束的请求 仍然能满足模特儿拒绝预填的要求.
  • 错误. 提供商或运输故障 MembraneError,其 type 财务报告和审定财务报表 retryable 说出发生了什么 随附了原始请求 从您自己的代码中错误地显示, 膜运行在调用旁, 而调用请求的再端无法修复, 结束调用时没有调用: 钩子, 请求或流回调用, 收件消费者, Anthropic适配器 dynamicHeaders,一个已配置的日志 warn() 或登记处 getPricing()它到达你作为一个 MembraneError 与 retryable: false: 你扔的那个,如果它已经说 retryable: false,或者从您错误中被归类为膜的一个新的将其它任何分类,而您的错误作为它的 cause 并且没有 HTTP 状态, 提供者代码或等待自己的 。 你的一个错误命名 AbortError 保留类型 abort,所以膜将它当作 任何其他流产 扔在同一点。 如何构建、发送或读取该呼叫,将保持自己的分类:适配器和传送、证书解析器、前题及其解析器。 如果响应适配器 onFastModeFallback 抛出,膜记录出出错和反应。 请求的膜因自身错误类型而拒绝构建失败而未被发送. 与 NativeFormatter,或本地模式下的默认物质,使用未发光的工具块的历史会被修复而不是拒绝:没有结果的调用得到一个 [pending] 结果,没有呼叫的结果就变成文字.

设计说明

docs/ 保留更长的注:

  • formatters.md: 格式化器,工具模式及其默认值.
  • prefill-formatter-architecture.md: 预填格式是如何工作的.
  • anthropic-credentials.md:旋转Anthropic无记名证书.
  • subscription-responses.md: ChatGPT订阅回放传输.

发展

npm ci
npm run build
npm test           # vitest
npm run typecheck

捐款额 包括改变土地、拉动请求应包含什么、改变日志碎片和释放. 变动情况 列出每次发布更改的内容.

许可证

麻省理工学院. 见 自由主义。 。 。 .

版本与发布记录

@animalabs/membrane 共发布 115 个版本,首次发布于 2026/01/26;过去 12 个月发布了 115 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.9.0latest2026/10/308 天前
0.8.02026/10/2612 天前
0.7.22026/10/2612 天前
0.6.1release-0.62026/10/2315 天前
0.7.12026/10/2315 天前
0.7.02026/10/2216 天前

关于 @animalabs/membrane 的常见问题

@animalabs/membrane 是什么?

LLM 中间软件 - 一个可选择的边界, 改变通过的东西

如何安装 @animalabs/membrane?

在项目目录运行 npm install @animalabs/membrane,或使用 pnpm add / yarn add / bun add。

@animalabs/membrane 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@animalabs/membrane 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@animalabs/membrane 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.12.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@animalabs/membrane 可以商用吗?

@animalabs/membrane 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@animalabs/membrane 的下载量有多少?

根据 npm 官方下载统计,@animalabs/membrane 在 2026/10/06 – 2026/11/04 这 30 天内被下载 27,116 次,日均约 904 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@animalabs/membrane 还在维护吗?

最新版本 0.9.0 发布于 2026/10/30(8 天前);至今共发布 115 个版本,其中过去 12 个月发布了 115 个;首次发布于 2026/01/26。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。