bemade-addons/ai_integration_ollama_api/models/ollama_model_stats.py
2025-05-29 21:35:47 -04:00

116 lines
4.8 KiB
Python

from odoo import models, fields, api
from datetime import datetime, timedelta
class OllamaModelStats(models.Model):
"""Tracks and stores daily usage statistics for Ollama AI models.
This model maintains detailed daily statistics for each Ollama model,
including request counts, token usage, response times, and error rates.
It inherits from ai.model.stats for base statistics functionality.
Key Features:
- Daily usage tracking per model
- Performance metrics collection
- Error rate monitoring
- Version tracking for model updates
Technical Details:
- One stat entry per model per day (enforced by SQL constraint)
- Automatic version tracking from Ollama API
- Aggregated statistics calculation
- Ordered by date for easy historical analysis
"""
_name = 'ollama.model.stats'
_description = 'Ollama Model Usage Statistics'
_inherit = ['ai.model.stats']
_order = 'date desc' # Most recent stats first
model_id = fields.Many2one('ai.model', string='Model', required=True, ondelete='cascade')
date = fields.Date(string='Date', required=True, default=fields.Date.context_today)
request_count = fields.Integer(string='Number of Requests', default=0)
token_count = fields.Integer(string='Total Tokens', default=0)
avg_response_time = fields.Float(string='Average Response Time (ms)', digits=(10, 2), default=0)
error_count = fields.Integer(string='Number of Errors', default=0)
version = fields.Char(string='Model Version', help='Version of the model when stats were recorded')
_sql_constraints = [
('unique_model_date', 'unique(model_id, date)', 'Only one stat entry per model per day is allowed.')
]
def _update_stats(self, model, tokens, response_time, error=False):
"""Update daily statistics for a specific model.
This method handles the creation or update of daily statistics entries.
It maintains running averages and cumulative counts for various metrics.
Args:
model (ai.model): The model record being tracked
tokens (int): Number of tokens in the current request
response_time (float): Response time in milliseconds
error (bool): Whether this request resulted in an error
Technical Notes:
- Creates new stat entry if none exists for today
- Updates running averages for response time
- Fetches and stores model version from Ollama API
- Maintains cumulative counts for requests and errors
"""
today = fields.Date.context_today(self)
stats = self.search([
('model_id', '=', model.id),
('date', '=', today)
])
if not stats:
# Get model version
version = self.env['ai.provider.ollama']._get_model_info(
model.provider_instance_id,
model.identifier
).get('details', {}).get('sha256', '')[:8] # First 8 chars of SHA
stats = self.create({
'model_id': model.id,
'date': today,
'version': version
})
# Update statistics
new_count = stats.request_count + 1
new_tokens = stats.token_count + tokens
new_time = ((stats.avg_response_time * stats.request_count) + response_time) / new_count
new_errors = stats.error_count + (1 if error else 0)
stats.write({
'request_count': new_count,
'token_count': new_tokens,
'avg_response_time': new_time,
'error_count': new_errors
})
@api.model
def get_model_stats(self, model_id, days=30):
"""Get statistics for a model over the specified number of days."""
start_date = fields.Date.today() - timedelta(days=days)
stats = self.search([
('model_id', '=', model_id),
('date', '>=', start_date)
])
return {
'daily_stats': [{
'date': stat.date,
'requests': stat.request_count,
'tokens': stat.token_count,
'response_time': stat.avg_response_time,
'errors': stat.error_count,
'version': stat.version
} for stat in stats],
'summary': {
'total_requests': sum(stat.request_count for stat in stats),
'total_tokens': sum(stat.token_count for stat in stats),
'avg_response_time': sum(stat.avg_response_time * stat.request_count for stat in stats) /
(sum(stat.request_count for stat in stats) if stats else 1),
'total_errors': sum(stat.error_count for stat in stats),
'versions_used': list(set(stat.version for stat in stats if stat.version))
}
}