ia-tracker-qca 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. ia_tracker_qca-0.1.0/LICENCE +21 -0
  2. ia_tracker_qca-0.1.0/MANIFEST.in +4 -0
  3. ia_tracker_qca-0.1.0/PKG-INFO +140 -0
  4. ia_tracker_qca-0.1.0/README.md +109 -0
  5. ia_tracker_qca-0.1.0/pyproject.toml +46 -0
  6. ia_tracker_qca-0.1.0/requirements.txt +4 -0
  7. ia_tracker_qca-0.1.0/setup.cfg +4 -0
  8. ia_tracker_qca-0.1.0/setup.py +6 -0
  9. ia_tracker_qca-0.1.0/src/ia_cost_tracker/__init__.py +27 -0
  10. ia_tracker_qca-0.1.0/src/ia_cost_tracker/database.py +290 -0
  11. ia_tracker_qca-0.1.0/src/ia_cost_tracker/exceptions.py +26 -0
  12. ia_tracker_qca-0.1.0/src/ia_cost_tracker/models.py +72 -0
  13. ia_tracker_qca-0.1.0/src/ia_cost_tracker/providers/__init__.py +11 -0
  14. ia_tracker_qca-0.1.0/src/ia_cost_tracker/providers/anthropic.py +81 -0
  15. ia_tracker_qca-0.1.0/src/ia_cost_tracker/providers/base.py +55 -0
  16. ia_tracker_qca-0.1.0/src/ia_cost_tracker/providers/maritaca.py +142 -0
  17. ia_tracker_qca-0.1.0/src/ia_cost_tracker/tracker.py +357 -0
  18. ia_tracker_qca-0.1.0/src/ia_tracker_qca.egg-info/PKG-INFO +140 -0
  19. ia_tracker_qca-0.1.0/src/ia_tracker_qca.egg-info/SOURCES.txt +24 -0
  20. ia_tracker_qca-0.1.0/src/ia_tracker_qca.egg-info/dependency_links.txt +1 -0
  21. ia_tracker_qca-0.1.0/src/ia_tracker_qca.egg-info/requires.txt +10 -0
  22. ia_tracker_qca-0.1.0/src/ia_tracker_qca.egg-info/top_level.txt +1 -0
  23. ia_tracker_qca-0.1.0/tests/test_anthropic_integration.py +201 -0
  24. ia_tracker_qca-0.1.0/tests/test_anthropic_real.py +180 -0
  25. ia_tracker_qca-0.1.0/tests/test_completo.py +134 -0
  26. ia_tracker_qca-0.1.0/tests/test_maritaca_integration.py +157 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Elison Felipe Santos
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,4 @@
1
+ include README.md
2
+ include LICENSE
3
+ include requirements.txt
4
+ recursive-include src *.py
@@ -0,0 +1,140 @@
1
+ Metadata-Version: 2.4
2
+ Name: ia_tracker_qca
3
+ Version: 0.1.0
4
+ Summary: Biblioteca para rastreamento e auditoria de custos de APIs de IA
5
+ Author-email: Sua Equipe <contato@suaempresa.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/suaempresa/ia-cost-tracker
8
+ Project-URL: Documentation, https://github.com/suaempresa/ia-cost-tracker#readme
9
+ Project-URL: Repository, https://github.com/suaempresa/ia-cost-tracker
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Requires-Python: >=3.8
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENCE
21
+ Requires-Dist: psycopg2-binary>=2.9.0
22
+ Requires-Dist: requests>=2.28.0
23
+ Requires-Dist: python-dotenv>=0.19.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
26
+ Requires-Dist: pytest-cov>=3.0.0; extra == "dev"
27
+ Requires-Dist: black>=22.0.0; extra == "dev"
28
+ Requires-Dist: isort>=5.10.0; extra == "dev"
29
+ Requires-Dist: flake8>=4.0.0; extra == "dev"
30
+ Dynamic: license-file
31
+
32
+ # IA Cost Tracker
33
+
34
+ [![PyPI version](https://badge.fury.io/py/ia-cost-tracker.svg)](https://badge.fury.io/py/ia-cost-tracker)
35
+ [![Python Versions](https://img.shields.io/pypi/pyversions/ia-cost-tracker.svg)](https://pypi.org/project/ia-cost-tracker/)
36
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
37
+ [![Downloads](https://pepy.tech/badge/ia-cost-tracker)](https://pepy.tech/project/ia-cost-tracker)
38
+
39
+ Rastreie custos de APIs de IA (Maritaca, Anthropic) automaticamente.
40
+
41
+ Biblioteca Python para rastreamento e auditoria de custos de APIs de IA (Maritaca, Anthropic).
42
+
43
+ ## Instalação
44
+
45
+ ```bash
46
+ pip install pip install ia_tracker_qca
47
+
48
+ ```
49
+
50
+ Uso básico (não recomendado pois demora mais por causa que busca os valores atualizados na hora!):
51
+
52
+ ```python
53
+ from ia_cost_tracker import IATracker
54
+
55
+ # Inicializar
56
+ tracker = IATracker(
57
+ db_connection_string="postgresql://user:pass@localhost/db",
58
+ maritaca_api_key="sua-chave",
59
+ anthropic_api_key="sua-chave"
60
+ )
61
+
62
+ # Sincronizar preços dos modelos
63
+ tracker.sincronizar_precos_maritaca() #essa chamada a api demora uns 10segs as vezes.
64
+ tracker.sincronizar_precos_anthropic()
65
+
66
+ # Registrar uma chamada
67
+ tracker.registrar_chamada(
68
+ provedor="maritaca",
69
+ modelo="sabia-2-medium",
70
+ tokens_input=150,
71
+ tokens_output=75,
72
+ aplicacao="meu-app",
73
+ tag_funcionalidade="chat",
74
+ usuario="usuario@email.com"
75
+ )
76
+
77
+ # Obter estatísticas
78
+ stats = tracker.obter_estatisticas_aplicacao("meu-app")
79
+ print(f"Custo total: R$ {stats['custo_total']}")
80
+ print(f"Total de chamadas: {stats['total_chamadas']}")
81
+
82
+ ```
83
+
84
+
85
+ Exemplo de uso em uma aplicação em produção:
86
+ ```python
87
+ from ia_cost_tracker import IATracker
88
+
89
+ tracker = IATracker(db_connection_string=os.getenv("DB_CONNECTION_STRING"))
90
+
91
+ # Após chamar a IA
92
+ tracker.registrar_chamada(
93
+ provedor="maritaca", # ou "anthropic"
94
+ modelo="sabia-4",
95
+ tokens_input=150,
96
+ tokens_output=75,
97
+ aplicacao="meu-app",
98
+ tag_funcionalidade="chat",
99
+ usuario="user@email.com" # opcional
100
+ )
101
+ ```
102
+
103
+ Desenvolvimento:
104
+
105
+ ```bash
106
+ # Clonar repositório
107
+ git clone https://github.com/suaempresa/ia-cost-tracker
108
+ cd ia-cost-tracker
109
+
110
+ # Instalar em modo desenvolvimento
111
+ pip install -e ".[dev]"
112
+
113
+ # Rodar testes
114
+ pytest
115
+
116
+ # Formatar código
117
+ black src/
118
+ isort src/
119
+ ```
120
+
121
+ Consultar Custos:
122
+
123
+ ```python
124
+ from datetime import datetime, timedelta
125
+
126
+ # Últimos 7 dias
127
+ data_inicio = datetime.now() - timedelta(days=7)
128
+ stats = tracker.obter_estatisticas_aplicacao(
129
+ aplicacao="meu-app",
130
+ data_inicio=data_inicio
131
+ )
132
+
133
+ # Listar modelos disponíveis
134
+ modelos = tracker.listar_modelos(provedor="maritaca")
135
+ for modelo in modelos:
136
+ print(f"{modelo.nome_modelo}: "
137
+ f"R$ {modelo.custo_input_por_1k}/1k input, "
138
+ f"R$ {modelo.custo_output_por_1k}/1k output")
139
+
140
+ ```
@@ -0,0 +1,109 @@
1
+ # IA Cost Tracker
2
+
3
+ [![PyPI version](https://badge.fury.io/py/ia-cost-tracker.svg)](https://badge.fury.io/py/ia-cost-tracker)
4
+ [![Python Versions](https://img.shields.io/pypi/pyversions/ia-cost-tracker.svg)](https://pypi.org/project/ia-cost-tracker/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![Downloads](https://pepy.tech/badge/ia-cost-tracker)](https://pepy.tech/project/ia-cost-tracker)
7
+
8
+ Rastreie custos de APIs de IA (Maritaca, Anthropic) automaticamente.
9
+
10
+ Biblioteca Python para rastreamento e auditoria de custos de APIs de IA (Maritaca, Anthropic).
11
+
12
+ ## Instalação
13
+
14
+ ```bash
15
+ pip install pip install ia_tracker_qca
16
+
17
+ ```
18
+
19
+ Uso básico (não recomendado pois demora mais por causa que busca os valores atualizados na hora!):
20
+
21
+ ```python
22
+ from ia_cost_tracker import IATracker
23
+
24
+ # Inicializar
25
+ tracker = IATracker(
26
+ db_connection_string="postgresql://user:pass@localhost/db",
27
+ maritaca_api_key="sua-chave",
28
+ anthropic_api_key="sua-chave"
29
+ )
30
+
31
+ # Sincronizar preços dos modelos
32
+ tracker.sincronizar_precos_maritaca() #essa chamada a api demora uns 10segs as vezes.
33
+ tracker.sincronizar_precos_anthropic()
34
+
35
+ # Registrar uma chamada
36
+ tracker.registrar_chamada(
37
+ provedor="maritaca",
38
+ modelo="sabia-2-medium",
39
+ tokens_input=150,
40
+ tokens_output=75,
41
+ aplicacao="meu-app",
42
+ tag_funcionalidade="chat",
43
+ usuario="usuario@email.com"
44
+ )
45
+
46
+ # Obter estatísticas
47
+ stats = tracker.obter_estatisticas_aplicacao("meu-app")
48
+ print(f"Custo total: R$ {stats['custo_total']}")
49
+ print(f"Total de chamadas: {stats['total_chamadas']}")
50
+
51
+ ```
52
+
53
+
54
+ Exemplo de uso em uma aplicação em produção:
55
+ ```python
56
+ from ia_cost_tracker import IATracker
57
+
58
+ tracker = IATracker(db_connection_string=os.getenv("DB_CONNECTION_STRING"))
59
+
60
+ # Após chamar a IA
61
+ tracker.registrar_chamada(
62
+ provedor="maritaca", # ou "anthropic"
63
+ modelo="sabia-4",
64
+ tokens_input=150,
65
+ tokens_output=75,
66
+ aplicacao="meu-app",
67
+ tag_funcionalidade="chat",
68
+ usuario="user@email.com" # opcional
69
+ )
70
+ ```
71
+
72
+ Desenvolvimento:
73
+
74
+ ```bash
75
+ # Clonar repositório
76
+ git clone https://github.com/suaempresa/ia-cost-tracker
77
+ cd ia-cost-tracker
78
+
79
+ # Instalar em modo desenvolvimento
80
+ pip install -e ".[dev]"
81
+
82
+ # Rodar testes
83
+ pytest
84
+
85
+ # Formatar código
86
+ black src/
87
+ isort src/
88
+ ```
89
+
90
+ Consultar Custos:
91
+
92
+ ```python
93
+ from datetime import datetime, timedelta
94
+
95
+ # Últimos 7 dias
96
+ data_inicio = datetime.now() - timedelta(days=7)
97
+ stats = tracker.obter_estatisticas_aplicacao(
98
+ aplicacao="meu-app",
99
+ data_inicio=data_inicio
100
+ )
101
+
102
+ # Listar modelos disponíveis
103
+ modelos = tracker.listar_modelos(provedor="maritaca")
104
+ for modelo in modelos:
105
+ print(f"{modelo.nome_modelo}: "
106
+ f"R$ {modelo.custo_input_por_1k}/1k input, "
107
+ f"R$ {modelo.custo_output_por_1k}/1k output")
108
+
109
+ ```
@@ -0,0 +1,46 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ia_tracker_qca"
7
+ version = "0.1.0"
8
+ description = "Biblioteca para rastreamento e auditoria de custos de APIs de IA"
9
+ readme = "README.md"
10
+ authors = [
11
+ {name = "Sua Equipe", email = "contato@suaempresa.com"}
12
+ ]
13
+ license = {text = "MIT"}
14
+ requires-python = ">=3.8"
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.8",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ ]
25
+ dependencies = [
26
+ "psycopg2-binary>=2.9.0",
27
+ "requests>=2.28.0",
28
+ "python-dotenv>=0.19.0",
29
+ ]
30
+
31
+ [project.optional-dependencies]
32
+ dev = [
33
+ "pytest>=7.0.0",
34
+ "pytest-cov>=3.0.0",
35
+ "black>=22.0.0",
36
+ "isort>=5.10.0",
37
+ "flake8>=4.0.0",
38
+ ]
39
+
40
+ [project.urls]
41
+ Homepage = "https://github.com/suaempresa/ia-cost-tracker"
42
+ Documentation = "https://github.com/suaempresa/ia-cost-tracker#readme"
43
+ Repository = "https://github.com/suaempresa/ia-cost-tracker"
44
+
45
+ [tool.setuptools.packages.find]
46
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ dotenv
2
+ psycopg2-binary>=2.9.0
3
+ requests>=2.28.0
4
+ python-dotenv>=0.19.0
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,6 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ packages=find_packages(where="src"),
5
+ package_dir={"": "src"},
6
+ )
@@ -0,0 +1,27 @@
1
+ """
2
+ IA Cost Tracker - Biblioteca para rastreamento de custos de APIs de IA.
3
+
4
+ Esta biblioteca permite rastrear e auditar custos de chamadas a APIs de IA
5
+ como Maritaca e Anthropic, salvando informações detalhadas em banco de dados.
6
+
7
+ Para Maritaca: sincroniza preços via API
8
+ Para Anthropic: usa preços mantidos no banco de dados
9
+ """
10
+
11
+ __version__ = "0.1.0"
12
+
13
+ from .tracker import IATracker
14
+ from .exceptions import (
15
+ IATrackerError,
16
+ DatabaseError,
17
+ ProviderError,
18
+ ModelNotFoundError,
19
+ )
20
+
21
+ __all__ = [
22
+ "IATracker",
23
+ "IATrackerError",
24
+ "DatabaseError",
25
+ "ProviderError",
26
+ "ModelNotFoundError",
27
+ ]
@@ -0,0 +1,290 @@
1
+ """Gerenciador de conexões e operações com banco de dados."""
2
+
3
+ import psycopg2
4
+ from psycopg2.extras import RealDictCursor
5
+ from typing import List, Optional, Dict, Any
6
+ from contextlib import contextmanager
7
+ from decimal import Decimal
8
+ import logging
9
+
10
+ from .models import ModeloIA, UsoToken
11
+ from .exceptions import DatabaseError, ModelNotFoundError
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class DatabaseManager:
17
+ """
18
+ Gerenciador de conexões e operações com PostgreSQL.
19
+
20
+ Esta classe gerencia todas as interações com o banco de dados,
21
+ incluindo operações CRUD para modelos e registros de uso.
22
+ """
23
+
24
+ def __init__(self, connection_string: str):
25
+ """
26
+ Inicializa o gerenciador de banco de dados.
27
+
28
+ Args:
29
+ connection_string: String de conexão PostgreSQL
30
+ (ex: "postgresql://user:pass@localhost/dbname")
31
+
32
+ Raises:
33
+ DatabaseError: Se houver erro na conexão com o banco
34
+ """
35
+ self.connection_string = connection_string
36
+ self._test_connection()
37
+
38
+ def _test_connection(self) -> None:
39
+ """Testa a conexão com o banco de dados."""
40
+ try:
41
+ with self._get_connection() as conn:
42
+ with conn.cursor() as cur:
43
+ cur.execute("SELECT 1")
44
+ except Exception as e:
45
+ raise DatabaseError(f"Erro ao conectar ao banco de dados: {str(e)}")
46
+
47
+ @contextmanager
48
+ def _get_connection(self):
49
+ """
50
+ Context manager para conexões com o banco.
51
+
52
+ Yields:
53
+ psycopg2.connection: Conexão com o banco de dados
54
+ """
55
+ conn = None
56
+ try:
57
+ conn = psycopg2.connect(self.connection_string)
58
+ yield conn
59
+ conn.commit()
60
+ except Exception as e:
61
+ if conn:
62
+ conn.rollback()
63
+ raise DatabaseError(f"Erro na operação do banco: {str(e)}")
64
+ finally:
65
+ if conn:
66
+ conn.close()
67
+
68
+ @staticmethod
69
+ def _convert_decimal_to_float(row_dict: Dict) -> Dict:
70
+ """
71
+ Converte valores Decimal para float no dicionário.
72
+
73
+ Args:
74
+ row_dict: Dicionário com dados do banco
75
+
76
+ Returns:
77
+ Dicionário com Decimals convertidos para float
78
+ """
79
+ converted = {}
80
+ for key, value in row_dict.items():
81
+ if isinstance(value, Decimal):
82
+ converted[key] = float(value)
83
+ else:
84
+ converted[key] = value
85
+ return converted
86
+
87
+ def buscar_modelo(self, provedor: str, nome_modelo: str) -> Optional[ModeloIA]:
88
+ """
89
+ Busca um modelo específico no banco de dados.
90
+
91
+ Args:
92
+ provedor: Nome do provedor (ex: 'maritaca', 'anthropic')
93
+ nome_modelo: Nome do modelo
94
+
95
+ Returns:
96
+ ModeloIA se encontrado, None caso contrário
97
+
98
+ Raises:
99
+ DatabaseError: Se houver erro na consulta
100
+ """
101
+ query = """
102
+ SELECT id_modelo, provedor, nome_modelo, custo_input_por_1k,
103
+ custo_output_por_1k, ativo, criado_em
104
+ FROM dim_modelo_ia
105
+ WHERE provedor = %s AND nome_modelo = %s AND ativo = true
106
+ """
107
+
108
+ with self._get_connection() as conn:
109
+ with conn.cursor(cursor_factory=RealDictCursor) as cur:
110
+ cur.execute(query, (provedor, nome_modelo))
111
+ row = cur.fetchone()
112
+
113
+ if row:
114
+ row_dict = self._convert_decimal_to_float(dict(row))
115
+ return ModeloIA(**row_dict)
116
+ return None
117
+
118
+ def listar_modelos(self, provedor: Optional[str] = None,
119
+ apenas_ativos: bool = True) -> List[ModeloIA]:
120
+ """
121
+ Lista modelos do banco de dados.
122
+
123
+ Args:
124
+ provedor: Filtrar por provedor específico (opcional)
125
+ apenas_ativos: Se True, retorna apenas modelos ativos
126
+
127
+ Returns:
128
+ Lista de ModeloIA
129
+
130
+ Raises:
131
+ DatabaseError: Se houver erro na consulta
132
+ """
133
+ query = """
134
+ SELECT id_modelo, provedor, nome_modelo, custo_input_por_1k,
135
+ custo_output_por_1k, ativo, criado_em
136
+ FROM dim_modelo_ia
137
+ WHERE 1=1
138
+ """
139
+ params = []
140
+
141
+ if provedor:
142
+ query += " AND provedor = %s"
143
+ params.append(provedor)
144
+
145
+ if apenas_ativos:
146
+ query += " AND ativo = true"
147
+
148
+ query += " ORDER BY provedor, nome_modelo"
149
+
150
+ with self._get_connection() as conn:
151
+ with conn.cursor(cursor_factory=RealDictCursor) as cur:
152
+ cur.execute(query, params)
153
+ rows = cur.fetchall()
154
+ modelos = []
155
+ for row in rows:
156
+ row_dict = self._convert_decimal_to_float(dict(row))
157
+ modelos.append(ModeloIA(**row_dict))
158
+ return modelos
159
+
160
+ def inserir_ou_atualizar_modelo(self, modelo: ModeloIA) -> int:
161
+ """
162
+ Insere um novo modelo ou atualiza se já existir.
163
+
164
+ Args:
165
+ modelo: Objeto ModeloIA a ser inserido/atualizado
166
+
167
+ Returns:
168
+ ID do modelo inserido/atualizado
169
+
170
+ Raises:
171
+ DatabaseError: Se houver erro na operação
172
+ """
173
+ query = """
174
+ INSERT INTO dim_modelo_ia
175
+ (provedor, nome_modelo, custo_input_por_1k, custo_output_por_1k, ativo)
176
+ VALUES (%s, %s, %s, %s, %s)
177
+ ON CONFLICT (provedor, nome_modelo)
178
+ DO UPDATE SET
179
+ custo_input_por_1k = EXCLUDED.custo_input_por_1k,
180
+ custo_output_por_1k = EXCLUDED.custo_output_por_1k,
181
+ ativo = EXCLUDED.ativo
182
+ RETURNING id_modelo
183
+ """
184
+
185
+ with self._get_connection() as conn:
186
+ with conn.cursor() as cur:
187
+ cur.execute(query, (
188
+ modelo.provedor,
189
+ modelo.nome_modelo,
190
+ modelo.custo_input_por_1k,
191
+ modelo.custo_output_por_1k,
192
+ modelo.ativo
193
+ ))
194
+ id_modelo = cur.fetchone()[0]
195
+ logger.info(f"Modelo {modelo.provedor}/{modelo.nome_modelo} "
196
+ f"inserido/atualizado com ID {id_modelo}")
197
+ return id_modelo
198
+
199
+ def registrar_uso(self, uso: UsoToken) -> int:
200
+ """
201
+ Registra um uso de tokens no banco de dados.
202
+
203
+ Args:
204
+ uso: Objeto UsoToken com os dados do uso
205
+
206
+ Returns:
207
+ ID do registro de uso criado
208
+
209
+ Raises:
210
+ DatabaseError: Se houver erro na inserção
211
+ """
212
+ query = """
213
+ INSERT INTO fato_uso_tokens (
214
+ id_modelo, tokens_input, tokens_output,
215
+ custo_input, custo_output, tag_funcionalidade,
216
+ aplicacao, usuario, tempo_resposta_ms,
217
+ erro, mensagem_erro, timestamp_uso
218
+ ) VALUES (
219
+ %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
220
+ ) RETURNING id_uso
221
+ """
222
+
223
+ with self._get_connection() as conn:
224
+ with conn.cursor() as cur:
225
+ cur.execute(query, (
226
+ uso.id_modelo,
227
+ uso.tokens_input,
228
+ uso.tokens_output,
229
+ uso.custo_input,
230
+ uso.custo_output,
231
+ uso.tag_funcionalidade,
232
+ uso.aplicacao,
233
+ uso.usuario,
234
+ uso.tempo_resposta_ms,
235
+ uso.erro,
236
+ uso.mensagem_erro,
237
+ uso.timestamp_uso
238
+ ))
239
+ id_uso = cur.fetchone()[0]
240
+ logger.info(f"Uso registrado com ID {id_uso} - "
241
+ f"Custo total: R$ {uso.custo_total:.6f}")
242
+ return id_uso
243
+
244
+ def buscar_custos_por_aplicacao(self, aplicacao: str,
245
+ data_inicio: Optional[Any] = None,
246
+ data_fim: Optional[Any] = None) -> Dict[str, Any]:
247
+ """
248
+ Busca estatísticas de custo para uma aplicação específica.
249
+
250
+ Args:
251
+ aplicacao: Nome da aplicação
252
+ data_inicio: Data inicial do período (opcional)
253
+ data_fim: Data final do período (opcional)
254
+
255
+ Returns:
256
+ Dicionário com estatísticas de uso e custo
257
+
258
+ Raises:
259
+ DatabaseError: Se houver erro na consulta
260
+ """
261
+ query = """
262
+ SELECT
263
+ COUNT(*) as total_chamadas,
264
+ SUM(tokens_input) as total_tokens_input,
265
+ SUM(tokens_output) as total_tokens_output,
266
+ SUM(tokens_total) as total_tokens,
267
+ SUM(custo_total) as custo_total,
268
+ AVG(custo_total) as custo_medio,
269
+ AVG(tempo_resposta_ms) as tempo_medio_resposta_ms,
270
+ SUM(CASE WHEN erro = true THEN 1 ELSE 0 END) as total_erros
271
+ FROM fato_uso_tokens
272
+ WHERE aplicacao = %s
273
+ """
274
+ params = [aplicacao]
275
+
276
+ if data_inicio:
277
+ query += " AND timestamp_uso >= %s"
278
+ params.append(data_inicio)
279
+
280
+ if data_fim:
281
+ query += " AND timestamp_uso <= %s"
282
+ params.append(data_fim)
283
+
284
+ with self._get_connection() as conn:
285
+ with conn.cursor(cursor_factory=RealDictCursor) as cur:
286
+ cur.execute(query, params)
287
+ resultado = cur.fetchone()
288
+ if resultado:
289
+ return self._convert_decimal_to_float(dict(resultado))
290
+ return {}
@@ -0,0 +1,26 @@
1
+ """Exceções personalizadas para o IA Cost Tracker."""
2
+
3
+
4
+ class IATrackerError(Exception):
5
+ """Exceção base para erros do IA Cost Tracker."""
6
+ pass
7
+
8
+
9
+ class DatabaseError(IATrackerError):
10
+ """Exceção para erros relacionados ao banco de dados."""
11
+ pass
12
+
13
+
14
+ class ProviderError(IATrackerError):
15
+ """Exceção para erros relacionados aos provedores de IA."""
16
+ pass
17
+
18
+
19
+ class ModelNotFoundError(IATrackerError):
20
+ """Exceção quando um modelo não é encontrado no banco de dados."""
21
+ pass
22
+
23
+
24
+ class ConfigurationError(IATrackerError):
25
+ """Exceção para erros de configuração."""
26
+ pass