将 Comfy Router 与 LiteLLM 配合使用
将 Comfy Router 置于 LiteLLM Proxy 之后作为直通端点,并从 x-litellm-response-cost 响应头中记录每次运行的确切美元成本。
将 Comfy Router 与 LiteLLM 配合使用
将 Comfy Router 置于 LiteLLM Proxy 之后作为直通端点,并从 x-litellm-response-cost 响应头中记录每次运行的确切美元成本。
如果你已经使用 LiteLLM Proxy 跟踪支出,就可以把 Comfy Router 作为又一个透传端点添加进来。调用方继续使用自己的 LiteLLM 密钥,而你的 Comfy API 密钥则保留在代理上。
对于会反馈每次运行 Comfy 点数价格的模型(参见不反馈成本的运行),Router 会在 x-litellm-response-cost 响应头中以美元为单位反馈一次运行的成本:同步运行体现在运行响应上,已排队的运行则体现在结果收集响应上。LiteLLM 会在每个透传响应中读取该响应头,并将其记录为该请求的支出,因此你无需为这些模型维护价格表。
[!NOTE] LiteLLM 内置的 fal_ai/ 提供商仅涵盖图像生成。若要通过 LiteLLM 路由常规工作负载,请使用此处所示的透传端点,而不是原生提供商。
配置透传
1. 创建 Comfy API 密钥
在你的 Comfy 工作区中创建密钥,并使其可供 LiteLLM Proxy 进程使用:
export COMFY_API_KEY="comfyui-..."
2. 将 Router 添加到 config.yaml
general_settings:
pass_through_endpoints:
# 运行和队列提交。同步运行会报告其确切费用,
# 该费用会替换该行的 cost_per_request。队列提交不会;
# 参见下方“队列交付”。
- path: "/comfy/v2/models"
target: "https://api.comfy.org/v2/models"
include_subpath: true
methods: ["POST"]
headers:
X-API-Key: "os.environ/COMFY_API_KEY"
content-type: application/json
cost_per_request: 0.10 # 你的回退估算值,单位为 USD
timeout: 660 # 高于 Router 的运行截止时间(默认 10 分钟)
# 模型目录、队列状态轮询和结果收集。排队运行的
# 结果收集会报告其确切费用,该费用会替换下方
# 该行的 0。
- path: "/comfy/v2/models"
target: "https://api.comfy.org/v2/models"
include_subpath: true
methods: ["GET"]
headers:
X-API-Key: "os.environ/COMFY_API_KEY"
cost_per_request: 0
include_subpath: true会将/comfy/v2/models/{provider}/{model}转发到https://api.comfy.org/v2/models/{provider}/{model},因此一对条目即可覆盖所有 Router 模型。- 请将
path和target限定在/v2/models范围内。若将透传指向 API 根路径,任何持有 LiteLLM 密钥的调用方都能在其他所有 Comfy API 路由上使用你的 Comfy 密钥,从而绕过 LiteLLM 的支出跟踪。 methods用于在同一路径上区分这两个条目。它需要 LiteLLM Proxy 的透传端点支持methods的版本;本页面是基于 v1.103.0 检查的。X-API-Key携带你的comfyui-密钥。Router 也接受以Authorization: Bearer comfyui-...形式提供的同一密钥。- 请勿开启
forward_headers。开启后,LiteLLM 会将所有传入的请求头转发给 Router,包括调用方的 LiteLLM 密钥。关闭时,调用方以x-pass-Idempotency-Key传递Idempotency-Key:LiteLLM 会去掉x-pass-前缀并将其转发。普通的Idempotency-Key请求头不会到达 Router,因此重试会再次运行并产生第二次生成的计费。 - 将
timeout设置得高于 Router 的运行截止时间,以便 Router 能在 LiteLLM 放弃之前返回自己的504和请求 ID。截止时间默认为 10 分钟,与 LiteLLM 默认的透传超时 600 秒相同。
3. 通过代理调用 Router
调用方使用其 LiteLLM 密钥进行身份验证。请求体是模型自身的输入,与 Comfy Router 参考中完全相同:
curl --max-time 660 \
http://localhost:4000/comfy/v2/models/byteplus/dreamina-seedance-2-5-260628 \
-H "Authorization: Bearer $LITELLM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content": [{"text": "A red fox trotting through a snowy pine forest", "type": "text"}], "duration": 5, "ratio": "16:9", "resolution": "720p"}'
支出如何记录
报告成本的运行会携带以下响应头:对于同步运行,这些响应头出现在运行响应中;对于已排队运行,它们出现在结果收集响应中:
X-Comfy-Credits-Used: 12.5
X-Litellm-Response-Cost: 0.0592417062
X-Litellm-Total-Tokens: 0
X-Comfy-Credits-Used 是该次运行以 Comfy 积分表示的价格,四舍五入到两位小数。X-Litellm-Response-Cost 是将同一价格从未舍入的积分数量换算成美元后得到的金额,因此用显示的积分数除以换算比率,所得结果可能在最后几位上与之不同。响应头名称不区分大小写,所以 LiteLLM 会将其读取为 x-litellm-response-cost。LiteLLM 会原样记录它,并用它替代你的 cost_per_request。x-litellm-total-tokens 始终为 0,因为媒体类运行不按 token 计量。
与 X-Comfy-Credits-Used 一样,该响应头报告的是价格,而不是已结算的扣费。请以工作区计费为准核对,而不是以 LiteLLM 的合计为准。
不报告成本的运行
有些运行不会携带 x-litellm-response-cost。在大多数这类情况下,X-Comfy-Credits-Used 也会缺失:
- 使用你自己的提供商密钥计费、而不是从你的 Comfy 积分中扣费的运行
- 尚未列入 Router 会报告每次运行积分价格的模型列表中的模型。该列表较为保守,有些提供商完全不在其中
- 未进入 Comfy 计费环节的扣费
有一种情况不同:错误响应。来自 billing.charges_on_policy_rejection 为 yes 的模型的同步 content_policy_violation,可以携带 X-Comfy-Credits-Used,其中包含 Comfy 为被拒绝的生成记录的使用量;即便如此,它也绝不会携带 x-litellm-response-cost,因为错误不是 LiteLLM 应当记账的结果。
当 Router 针对使用相同 Idempotency-Key 的重试(通过代理发送时为 x-pass-Idempotency-Key)重放已存储的结果时,该响应头也会缺失。该重试不会再次计费,因此这次重放不会第二次报告该次运行的确切成本。出于同样的原因,已排队运行的结果收集中只有一次会携带该响应头,即该次运行的价格被记录后的第一次收集;再次收集同一结果仍会返回 X-Comfy-Credits-Used,但不会返回 x-litellm-response-cost。
当该响应头缺失时,LiteLLM 会回退到端点的 cost_per_request。这适用于上述所有情况。因此,错误响应、使用你自己的提供商密钥计费的运行以及幂等重放,都会按你的估值记录。这些记录大多并未从你的积分中扣费,但并非全部如此:携带 X-Comfy-Credits-Used 的内容策略拒绝已被定价,因此应从该响应头读取其成本;另外少数失败,例如 Router 无法返回给你的生成结果,可能会在未报告成本的情况下产生计费。请以工作区的使用记录为准核对。请将 cost_per_request 设置为对典型运行的合理估值,而不是 0,这样不报告成本的运行就不会在你的支出报告中显示为免费,同时也要预期这些记录会使 LiteLLM 的合计高于你的 Comfy 账单。一次已被定价且确实没有任何花费的运行会报告 x-litellm-response-cost: 0,LiteLLM 会将其记录为零。
队列投递
使用队列投递时,一次生成会以多个请求的形式到达 LiteLLM,每个请求各自单独成行计入消费:
| 请求 | 方法 | 使用上述配置时的行费用 |
|---|---|---|
提交:/v2/models/{provider}/{model}/requests | POST | 你的 cost_per_request 估算值 |
每次状态轮询:.../requests/{request_id}/status | GET | 0 |
结果收集:.../requests/{request_id} | GET | 该次运行的确切价格,在首次上报该价格的收集请求上 |
取消:.../requests/{request_id}/cancel | POST | 你的 cost_per_request 估算值 |
提交响应中的 status_url、response_url 和 cancel_url 都是绝对的 https://api.comfy.org/... URL,而 LiteLLM 不会重写响应体。要通过代理调用它们,请将 https://api.comfy.org 替换为代理的 /comfy 前缀,例如 http://localhost:4000/comfy/v2/models/...。如果直接发送给 Comfy,你的 LiteLLM 密钥会被拒绝。
结果收集请求只会在该次运行的价格记录后的第一次收集时携带一次 x-litellm-response-cost。对大多数模型来说,那就是第一次收集。对某些模型,价格会在结果就绪后才记录,因此较早的收集可能返回时不带该字段,而同一请求的后续收集会上报它。
Router 在响应该次收集时会将价格标记为已上报。如果响应没有到达 LiteLLM(例如请求超时或连接中断),后续收集也不会携带 x-litellm-response-cost,LiteLLM 就会按 GET 条目的费用记录该次运行。
提交行仍会记录你的 cost_per_request 估算值,因此在使用上述配置时,一次排队运行会被计算两次:一次按你的估算值,一次按它的确切价格。如果你只使用队列投递,请将 POST 条目的 cost_per_request 设为 0,这样每次排队运行只会按其确切价格记录一次。这样,对于你从未收集结果的运行,它不会出现在 LiteLLM 的总计中,但仍会计费到你的工作区。当两个条目都为 0 时,未上报任何费用的运行会被记录为 0。这包括以下情况:某次运行的价格在其结果就绪后才记录,而你只在该价格记录之前收集该结果一次;以及上述收集请求未上报该价格的情况。如果你的客户端只在每个结果就绪时收集一次,请保留 POST 的估算值。
说明
- LiteLLM 会记录消费额,但不会改变计费。无论是否使用该代理,Comfy 都按相同方式为你的工作区计费。
- 每个模型的完整请求与响应 schema 都在 Comfy Router 参考 中。截止时间、重试及其他限制见能力与限制。