膜
@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)。适配器读取第三列中的环境变量,除非您在其配置中通过相同的设置.
| 适配器 | 会谈 | 环境 |
|---|---|---|
AnthropicAdapter | Anthropic's Messages API. (原始内容存档于2018-10-12). | ANTHROPIC_API_KEY |
BedrockAdapter | Anthropic在AWS Bedrock上的克洛德模型. | AWS_ACCESS_KEY_ID, (中文(简体) ), AWS_SECRET_ACCESS_KEY,可选 AWS_SESSION_TOKEN,以及 AWS_REGION (默认) us-west-2(中文(简体) ) |
OpenAIAdapter | OpenAI的"聊天补全"API. | OPENAI_API_KEY |
OpenAIResponsesAPIAdapter | OpenAI的反应API. | OPENAI_API_KEY |
OpenAICompatibleAdapter | 任意OpenAI相容的聊天补全端点,例如Ollama或vLLM. | 无:通过 apiKey 如果终点需要的话 |
OpenAICompletionsAdapter | A 类 /v1/completions 端点,用于基础模型. | 无:通过 apiKey 如果终点需要的话 |
OpenRouterAdapter | 开出鲁特. | OPENROUTER_API_KEY |
GeminiAdapter | 谷歌双子座API. | GOOGLE_API_KEY |
OpenAIResponsesAdapter | OpenAI的图像 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_tokens87个令牌,一秒钟开始, 大约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
捐款额 包括改变土地、拉动请求应包含什么、改变日志碎片和释放. 变动情况 列出每次发布更改的内容.
许可证
麻省理工学院. 见 自由主义。 。 。 .