mirror of
https://github.com/we-promise/sure.git
synced 2026-05-29 23:39:03 +00:00
- LlmUsage.infer_provider now returns "anthropic" for Bedrock / Vertex shaped IDs (anthropic.* and anthropic/*), so cost-ledger filtering by provider stays correct even when no per-MTok rate is stored. Previously these IDs fell through to the "openai" default. - AutoCategorizer drops the redundant nil sentinel from the category_name enum — the union type [string, null] already permits null, and some JSON Schema validators reject nil literals inside enum arrays.
52 lines
2.1 KiB
Ruby
52 lines
2.1 KiB
Ruby
require "test_helper"
|
|
|
|
class LlmUsageTest < ActiveSupport::TestCase
|
|
test "infer_provider returns anthropic for claude models" do
|
|
assert_equal "anthropic", LlmUsage.infer_provider("claude-sonnet-4-6")
|
|
assert_equal "anthropic", LlmUsage.infer_provider("claude-opus-4-7")
|
|
assert_equal "anthropic", LlmUsage.infer_provider("claude-haiku-4-5")
|
|
end
|
|
|
|
test "infer_provider still returns openai for gpt models" do
|
|
assert_equal "openai", LlmUsage.infer_provider("gpt-4.1")
|
|
assert_equal "openai", LlmUsage.infer_provider("gpt-5")
|
|
end
|
|
|
|
test "infer_provider attributes Bedrock and Vertex prefixed IDs to anthropic" do
|
|
assert_equal "anthropic", LlmUsage.infer_provider("anthropic.claude-sonnet-4-5-20250929-v1:0")
|
|
assert_equal "anthropic", LlmUsage.infer_provider("anthropic.claude-opus-4-20250514-v1:0")
|
|
assert_equal "anthropic", LlmUsage.infer_provider("anthropic/claude-3-5-sonnet@20240620")
|
|
end
|
|
|
|
test "calculate_cost returns nil for Bedrock IDs (no per-token rate stored)" do
|
|
# Bedrock bills through AWS not Anthropic — we don't store a per-MTok rate,
|
|
# but the row must still attribute to anthropic for provider filtering.
|
|
assert_nil LlmUsage.calculate_cost(
|
|
model: "anthropic.claude-sonnet-4-5-20250929-v1:0",
|
|
prompt_tokens: 1000,
|
|
completion_tokens: 500
|
|
)
|
|
end
|
|
|
|
test "calculate_cost returns Anthropic pricing for Claude models" do
|
|
cost = LlmUsage.calculate_cost(model: "claude-sonnet-4-6", prompt_tokens: 1_000_000, completion_tokens: 100_000)
|
|
|
|
# 1M input * $3/MTok + 100K output * $15/MTok = $3.00 + $1.50 = $4.50
|
|
assert_in_delta 4.5, cost, 0.0001
|
|
end
|
|
|
|
test "calculate_cost uses higher pricing for Opus" do
|
|
cost = LlmUsage.calculate_cost(model: "claude-opus-4-7", prompt_tokens: 1_000_000, completion_tokens: 0)
|
|
|
|
# 1M input * $15/MTok = $15.00
|
|
assert_in_delta 15.0, cost, 0.0001
|
|
end
|
|
|
|
test "calculate_cost uses lower pricing for Haiku" do
|
|
cost = LlmUsage.calculate_cost(model: "claude-haiku-4-5", prompt_tokens: 1_000_000, completion_tokens: 1_000_000)
|
|
|
|
# $1 in + $5 out = $6.00
|
|
assert_in_delta 6.0, cost, 0.0001
|
|
end
|
|
end
|