mirror of
https://github.com/we-promise/sure.git
synced 2026-05-29 15:34:58 +00:00
fix(ai): attribute Bedrock model IDs to anthropic + clean nil enum
- 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.
This commit is contained in:
@@ -92,6 +92,13 @@ class LlmUsage < ApplicationRecord
|
||||
def self.infer_provider(model)
|
||||
return "openai" if model.blank?
|
||||
|
||||
# Bedrock + Vertex prefix model IDs with "anthropic." regardless of
|
||||
# whether the Claude family is in the local PRICING map. Attribute them
|
||||
# to the Anthropic provider so cost-ledger filtering by provider is
|
||||
# correct even when we can't compute a per-token rate (custom endpoints
|
||||
# bill via their own provider, not Anthropic directly).
|
||||
return "anthropic" if model.start_with?("anthropic.", "anthropic/")
|
||||
|
||||
# Check each provider to see if they have pricing for this model
|
||||
PRICING.each do |provider_name, provider_pricing|
|
||||
# Try exact match first
|
||||
|
||||
@@ -77,7 +77,7 @@ class Provider::Anthropic::AutoCategorizer
|
||||
category_name: {
|
||||
type: [ "string", "null" ],
|
||||
description: "Matched category name from the user's categories, or null when uncertain.",
|
||||
enum: [ *user_categories.map { |c| c[:name] }, nil ]
|
||||
enum: user_categories.map { |c| c[:name] }
|
||||
}
|
||||
},
|
||||
required: [ "transaction_id", "category_name" ],
|
||||
|
||||
@@ -12,6 +12,22 @@ class LlmUsageTest < ActiveSupport::TestCase
|
||||
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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user