JamJet
JamJet CloudGovernance

预算

项目级成本上限。调用前估算超限时提前抛出异常;调用后记录实际费用。

预算

budget(maxCostUsd) 为你的项目设置成本上限。JamJet 分两个阶段执行:调用前估算会在预计支出超过上限时立即抛出异常,甚至不会联系 LLM;调用后记录则根据 response.usage 的实际成本更新累计总额。

设置预算

budget() 传递一个正数美元金额。在 init() 之后,在启动时调用一次。

import { init, budget, wrap } from '@jamjet/cloud'
import OpenAI from 'openai'

init({ apiKey: process.env.JAMJET_API_KEY!, project: 'my-app' })

budget(50)   // 此项目的 $50 上限

const openai = wrap(new OpenAI())
import jamjet.cloud as jamjet
from openai import OpenAI
import os

jamjet.configure(api_key=os.environ['JAMJET_API_KEY'], project='my-app')

jamjet.budget(max_cost_usd=50)   # 此项目的 $50 上限

client = jamjet.wrap(OpenAI())

预算适用于进程中所有封装的调用。它是按进程计算的,而非按 API 密钥——使用相同密钥的不同进程各自拥有独立的上限。

调用前估算

在向 LLM 发送请求之前,JamJet 会根据提示词的 token 数量,使用模型价格表估算调用成本。如果预计总支出(进程生命周期内的累计值)超过上限,会立即抛出 JamjetBudgetExceeded 异常——不会调用 LLM,也不会产生任何费用。

import { JamjetBudgetExceeded } from '@jamjet/cloud'

try {
  const response = await openai.chat.completions.create({
    model: 'gpt-4o',
    messages: [{ role: 'user', content: 'Long prompt...' }],
  })
} catch (err) {
  if (err instanceof JamjetBudgetExceeded) {
    console.error(
      `预算已超。已用:$${err.spent.toFixed(4)},上限:$${err.limit.toFixed(2)}`
    )
  }
}
from jamjet.cloud.errors import JamjetBudgetExceeded

try:
    response = client.chat.completions.create(
        model='gpt-4o',
        messages=[{'role': 'user', 'content': 'Long prompt...'}],
    )
except JamjetBudgetExceeded as err:
    print(f'预算已超。已用:${err.spent:.4f},上限:${err.limit:.2f}')

JamjetBudgetExceeded 字段

字段类型描述
spentnumber当前进程中累计记录的 USD 消费
limitnumber通过 budget() 设置的上限

两个值均以 USD 计。spent 反映了之前调用的实际事后成本加上触发异常的调用的事前估算。

事后记录

当调用成功完成时,JamJet 从响应中读取 response.usage.input_tokensresponse.usage.output_tokens,使用相同的价格表计算实际成本,并更新累计总额。事前估算值会被跨度中的实际成本替换。

这意味着累计总额始终基于 API 的实际计费数据,而非仅仅估算值。

修改上限

随时再次调用 budget(N) 以替换当前上限。累计总额不会重置——仅上限发生变化。要有效重置,请将新上限设置为当前限额加上您希望允许的额外消费金额。

// 初始上限
budget(50)

// ... 在获得人工操作员批准后 ...

// 将上限提高至 $100
budget(100)
# 初始上限
jamjet.budget(max_cost_usd=50)

# ... 在获得人工操作员批准后 ...

# 将上限提高至 $100
jamjet.budget(max_cost_usd=100)

模型识别限制

JamJet 使用以模型名称(例如 gpt-4oclaude-3-5-sonnet-20241022)为键的内部价格表。如果请求中的模型名称不在表中——例如新发布的模型或自定义微调模型——估算成本将被视为 $0

$0 估算意味着预算门会有效允许调用,即使实际计费可能很高。事后记录仍会使用实际成本更新累计总额,因此后续调用将被准确地进行门控检查。

要验证您的模型是否被识别,请检查控制面板跨度中已完成调用的非零 cost_usd 值。如果对于应计费的模型显示 $0.0000,请打开项目设置并提交模型表更新请求。

综合示例

import OpenAI from 'openai'
import { init, budget, wrap, JamjetBudgetExceeded } from '@jamjet/cloud'

init({ apiKey: process.env.JAMJET_API_KEY!, project: 'research-pipeline' })
budget(5)   // $5 硬性上限 — 适用于开发环境

const openai = wrap(new OpenAI())

async function runResearch(prompt: string): Promise<string | null> {
  try {
    const res = await openai.chat.completions.create({
      model: 'gpt-4o',
      messages: [{ role: 'user', content: prompt }],
    })
    return res.choices[0].message.content
  } catch (err) {
    if (err instanceof JamjetBudgetExceeded) {
      console.warn(`研究已暂停 — 预算已耗尽 ($${err.spent.toFixed(4)} / $${err.limit})`)
      return null
    }
    throw err
  }
}
from openai import OpenAI
import jamjet.cloud as jamjet
from jamjet.cloud.errors import JamjetBudgetExceeded
import os

jamjet.configure(api_key=os.environ['JAMJET_API_KEY'], project='research-pipeline')
jamjet.budget(max_cost_usd=5)   # $5 硬性上限 — 适用于开发环境

client = jamjet.wrap(OpenAI())

def run_research(prompt: str) -> str | None:
    try:
        res = client.chat.completions.create(
            model='gpt-4o',
            messages=[{'role': 'user', 'content': prompt}],
        )
        return res.choices[0].message.content
    except JamjetBudgetExceeded as err:
        print(f'研究已暂停 — 预算已耗尽 (${err.spent:.4f} / ${err.limit})')
        return None

后续步骤

On this page