discourse/plugins/discourse-ai/app/models/ai_api_audit_log.rb

86 lines
3 KiB
Ruby
Vendored

# frozen_string_literal: true
class AiApiAuditLog < ActiveRecord::Base
self.ignored_columns = %w[cached_tokens] # TODO: Remove when 20251118000500_drop_cached_tokens_from_ai_api_audit_logs has been promoted to pre-deploy
belongs_to :post
belongs_to :topic
belongs_to :user
belongs_to :llm_model, foreign_key: :llm_id, optional: true
module Provider
OpenAI = 1
Anthropic = 2
HuggingFaceTextGeneration = 3
Gemini = 4
Vllm = 5
Cohere = 6
Ollama = 7
SambaNova = 8
Mistral = 9
OpenRouter = 10
BedrockConverse = 11
end
def self.token_and_spending_stats(scope)
spending_expr = LlmModel.spending_sql(table_name)
request_tokens, response_tokens, cache_read_tokens, cache_write_tokens, spending, model_count =
scope.joins("LEFT JOIN llm_models ON llm_models.id = #{table_name}.llm_id").pick(
Arel.sql("COALESCE(SUM(COALESCE(#{table_name}.request_tokens, 0)), 0)"),
Arel.sql("COALESCE(SUM(COALESCE(#{table_name}.response_tokens, 0)), 0)"),
Arel.sql("COALESCE(SUM(COALESCE(#{table_name}.cache_read_tokens, 0)), 0)"),
Arel.sql("COALESCE(SUM(COALESCE(#{table_name}.cache_write_tokens, 0)), 0)"),
Arel.sql("COALESCE(SUM(#{spending_expr}), 0) / 1000000.0"),
Arel.sql("COUNT(llm_models.id)"),
)
{
request_tokens: request_tokens.to_i,
response_tokens: response_tokens.to_i,
cache_read_tokens: cache_read_tokens.to_i,
cache_write_tokens: cache_write_tokens.to_i,
spending: model_count.to_i.positive? ? spending.to_f.round(6) : nil,
}
end
def next_log_id
self.class.where("id > ?", id).where(topic_id: topic_id).order(id: :asc).pluck(:id).first
end
def prev_log_id
self.class.where("id < ?", id).where(topic_id: topic_id).order(id: :desc).pluck(:id).first
end
end
# == Schema Information
#
# Table name: ai_api_audit_logs
#
# id :bigint not null, primary key
# cache_read_tokens :integer
# cache_write_tokens :integer
# duration_msecs :integer
# feature_context :jsonb
# feature_name :string(255)
# language_model :string(255)
# raw_request_payload :string
# raw_response_payload :string
# request_tokens :integer
# response_status :integer
# response_tokens :integer
# created_at :datetime not null
# updated_at :datetime not null
# llm_id :bigint
# post_id :integer
# provider_id :integer not null
# topic_id :integer
# user_id :integer
#
# Indexes
#
# index_ai_api_audit_logs_on_created_at_and_feature_name (created_at,feature_name)
# index_ai_api_audit_logs_on_created_at_and_language_model (created_at,language_model)
# index_ai_api_audit_logs_on_created_at_and_user_id (created_at,user_id)
# index_ai_api_audit_logs_on_llm_id (llm_id)
# index_ai_api_audit_logs_on_post_id (post_id)
# index_ai_api_audit_logs_on_topic_id (topic_id)
#