mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-20 15:33:54 +00:00
feat(agent): add Fireworks pricing entries + routing branch
Fireworks-hosted sessions previously showed estimated_cost_usd = 0 because (a) _OFFICIAL_DOCS_PRICING had no Fireworks entries and (b) resolve_billing_route() had no branch for provider="fireworks", falling through to billing_mode="unknown". Adds entries for the three Fireworks models hermes operators are most likely to route through (Kimi K2.6, DeepSeek V4 Pro, Qwen3.6-Plus) and a routing branch that triggers on either explicit provider="fireworks" or api.fireworks.ai base_url match. Mirrors the recently-merged MiniMax addition pattern; pricing snapshot sourced from https://docs.fireworks.ai/serverless/pricing and the per-model pages on fireworks.ai. Tests cover: (a) full Fireworks model id resolves to the snapshot entry, (b) base_url alone is sufficient to route, (c) end-to-end estimate returns "estimated" status with the expected dollar amount. A follow-up upstream issue is open proposing a dynamic pricing source (e.g. litellm's pricing JSON) as a permanent fix to the PR-per-model treadmill that this snapshot keeps adding to.
This commit is contained in:
parent
5a39f0501c
commit
365620ab28
2 changed files with 83 additions and 0 deletions
|
|
@ -609,6 +609,43 @@ _OFFICIAL_DOCS_PRICING: Dict[tuple[str, str], PricingEntry] = {
|
|||
source="official_docs_snapshot",
|
||||
pricing_version="minimax-pricing-2026-04",
|
||||
),
|
||||
# Fireworks AI — serverless pricing for the models hermes typically routes
|
||||
# through when configured with provider="fireworks". Fireworks publishes a
|
||||
# cached_input rate per model alongside input/output, which maps to
|
||||
# cache_read_cost_per_million. No separately published cache_write rate.
|
||||
(
|
||||
"fireworks",
|
||||
"kimi-k2p6",
|
||||
): PricingEntry(
|
||||
input_cost_per_million=Decimal("0.95"),
|
||||
output_cost_per_million=Decimal("4.00"),
|
||||
cache_read_cost_per_million=Decimal("0.16"),
|
||||
source="official_docs_snapshot",
|
||||
source_url="https://docs.fireworks.ai/serverless/pricing",
|
||||
pricing_version="fireworks-pricing-2026-05",
|
||||
),
|
||||
(
|
||||
"fireworks",
|
||||
"deepseek-v4-pro",
|
||||
): PricingEntry(
|
||||
input_cost_per_million=Decimal("1.74"),
|
||||
output_cost_per_million=Decimal("3.48"),
|
||||
cache_read_cost_per_million=Decimal("0.145"),
|
||||
source="official_docs_snapshot",
|
||||
source_url="https://docs.fireworks.ai/serverless/pricing",
|
||||
pricing_version="fireworks-pricing-2026-05",
|
||||
),
|
||||
(
|
||||
"fireworks",
|
||||
"qwen3p6-plus",
|
||||
): PricingEntry(
|
||||
input_cost_per_million=Decimal("0.50"),
|
||||
output_cost_per_million=Decimal("3.00"),
|
||||
cache_read_cost_per_million=Decimal("0.10"),
|
||||
source="official_docs_snapshot",
|
||||
source_url="https://fireworks.ai/models/fireworks/qwen3p6-plus",
|
||||
pricing_version="fireworks-pricing-2026-05",
|
||||
),
|
||||
}
|
||||
|
||||
# GPT-5.6 "-pro" high-effort variants bill at the same per-token rates as
|
||||
|
|
@ -672,6 +709,10 @@ def resolve_billing_route(
|
|||
# the OpenAI-compat endpoint requires so the pricing key matches.
|
||||
if provider_name == "vertex" or base_url_host_matches(base_url or "", "aiplatform.googleapis.com"):
|
||||
return BillingRoute(provider="gemini", model=model.split("/")[-1], base_url=base_url or "", billing_mode="official_docs_snapshot")
|
||||
if provider_name == "fireworks" or base_url_host_matches(base_url or "", "api.fireworks.ai"):
|
||||
# Fireworks model ids look like accounts/fireworks/models/<name>;
|
||||
# rsplit("/", 1)[-1] yields just <name> which is what the dict keys on.
|
||||
return BillingRoute(provider="fireworks", model=model.rsplit("/", 1)[-1], base_url=base_url or "", billing_mode="official_docs_snapshot")
|
||||
if provider_name in {"custom", "local"} or (base and "localhost" in base):
|
||||
return BillingRoute(provider=provider_name or "custom", model=model, base_url=base_url or "", billing_mode="unknown")
|
||||
return BillingRoute(provider=provider_name or "unknown", model=model.split("/")[-1] if model else "", base_url=base_url or "", billing_mode="unknown")
|
||||
|
|
|
|||
|
|
@ -322,3 +322,45 @@ def test_bedrock_claude_cached_session_estimates_cost_not_unknown():
|
|||
)
|
||||
assert result.status == "estimated"
|
||||
assert result.amount_usd is not None
|
||||
|
||||
def test_fireworks_kimi_k2p6_resolves_with_full_model_path():
|
||||
"""Fireworks model ids look like accounts/fireworks/models/<name>;
|
||||
the routing layer must strip the prefix so the dict lookup succeeds."""
|
||||
entry = get_pricing_entry(
|
||||
"accounts/fireworks/models/kimi-k2p6",
|
||||
provider="fireworks",
|
||||
base_url="https://api.fireworks.ai/inference/v1",
|
||||
)
|
||||
|
||||
assert entry is not None
|
||||
assert float(entry.input_cost_per_million) == 0.95
|
||||
assert float(entry.output_cost_per_million) == 4.00
|
||||
assert float(entry.cache_read_cost_per_million) == 0.16
|
||||
assert entry.source == "official_docs_snapshot"
|
||||
|
||||
|
||||
def test_fireworks_base_url_host_match_alone_routes_to_pricing():
|
||||
"""Provider not explicitly passed; routing infers fireworks from the host."""
|
||||
entry = get_pricing_entry(
|
||||
"accounts/fireworks/models/deepseek-v4-pro",
|
||||
base_url="https://api.fireworks.ai/inference/v1",
|
||||
)
|
||||
|
||||
assert entry is not None
|
||||
assert float(entry.input_cost_per_million) == 1.74
|
||||
assert float(entry.output_cost_per_million) == 3.48
|
||||
|
||||
|
||||
def test_fireworks_qwen3p6_plus_estimate_usage_cost():
|
||||
"""End-to-end: Fireworks Qwen3.6-Plus sessions report a dollar estimate."""
|
||||
result = estimate_usage_cost(
|
||||
"accounts/fireworks/models/qwen3p6-plus",
|
||||
CanonicalUsage(input_tokens=1_000_000, output_tokens=500_000),
|
||||
provider="fireworks",
|
||||
base_url="https://api.fireworks.ai/inference/v1",
|
||||
)
|
||||
|
||||
assert result.status == "estimated"
|
||||
assert result.amount_usd is not None
|
||||
# 1M input × $0.50/M + 500K output × $3.00/M = $0.50 + $1.50 = $2.00
|
||||
assert float(result.amount_usd) == 2.00
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue