paygent-sdk 1.0.0__tar.gz → 2.0.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.
- {paygent_sdk-1.0.0/paygent_sdk.egg-info → paygent_sdk-2.0.0}/PKG-INFO +1 -1
- paygent_sdk-2.0.0/paygent_sdk/__init__.py +100 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/paygent_sdk/client.py +16 -41
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/paygent_sdk/constants.py +84 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/paygent_sdk/models.py +28 -0
- paygent_sdk-2.0.0/paygent_sdk/voice_client.py +263 -0
- paygent_sdk-2.0.0/paygent_sdk/wrappers/__init__.py +30 -0
- paygent_sdk-2.0.0/paygent_sdk/wrappers/anthropic_wrapper.py +132 -0
- paygent_sdk-2.0.0/paygent_sdk/wrappers/gemini_wrapper.py +334 -0
- paygent_sdk-2.0.0/paygent_sdk/wrappers/langchain_wrapper.py +257 -0
- paygent_sdk-2.0.0/paygent_sdk/wrappers/mistral_wrapper.py +128 -0
- paygent_sdk-2.0.0/paygent_sdk/wrappers/openai_wrapper.py +308 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0/paygent_sdk.egg-info}/PKG-INFO +1 -1
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/paygent_sdk.egg-info/SOURCES.txt +7 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/pyproject.toml +1 -1
- paygent_sdk-1.0.0/paygent_sdk/__init__.py +0 -47
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/LICENSE +0 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/MANIFEST.in +0 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/README.md +0 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/examples/__init__.py +0 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/examples/advanced_usage.py +0 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/examples/basic_usage.py +0 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/examples/constants_usage.py +0 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/paygent_sdk.egg-info/dependency_links.txt +0 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/paygent_sdk.egg-info/requires.txt +0 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/paygent_sdk.egg-info/top_level.txt +0 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/requirements.txt +0 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/setup.cfg +0 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/setup.py +0 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/tests/__init__.py +0 -0
- {paygent_sdk-1.0.0 → paygent_sdk-2.0.0}/tests/test_client.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: paygent-sdk
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Official Python SDK for Paygent - Track AI usage and costs across multiple providers (OpenAI, Anthropic, Google, DeepSeek, etc.)
|
|
5
5
|
Home-page: https://github.com/paygent/paygent-sdk-python
|
|
6
6
|
Author: Paygent
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Paygent SDK for Python
|
|
3
|
+
|
|
4
|
+
A Python SDK for integrating with the Paygent API to track usage and costs for AI models.
|
|
5
|
+
|
|
6
|
+
For the Go SDK equivalent, see: https://github.com/paygent/paygent-sdk-go
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .client import Client
|
|
10
|
+
from .models import (
|
|
11
|
+
UsageData, UsageDataWithStrings, APIRequest, ModelPricing, MODEL_PRICING,
|
|
12
|
+
SttUsageData, TtsUsageData, SttModelPricing, TtsModelPricing
|
|
13
|
+
)
|
|
14
|
+
from .voice_client import send_stt_usage, send_tts_usage # Import to attach methods to Client
|
|
15
|
+
|
|
16
|
+
# Import wrappers with optional LangChain support
|
|
17
|
+
try:
|
|
18
|
+
from .wrappers import (
|
|
19
|
+
PaygentOpenAI,
|
|
20
|
+
PaygentAnthropic,
|
|
21
|
+
PaygentMistral,
|
|
22
|
+
PaygentGemini,
|
|
23
|
+
PaygentLangChainCallback
|
|
24
|
+
)
|
|
25
|
+
_has_langchain = True
|
|
26
|
+
except ImportError:
|
|
27
|
+
from .wrappers import (
|
|
28
|
+
PaygentOpenAI,
|
|
29
|
+
PaygentAnthropic,
|
|
30
|
+
PaygentMistral,
|
|
31
|
+
PaygentGemini
|
|
32
|
+
)
|
|
33
|
+
_has_langchain = False
|
|
34
|
+
from .constants import (
|
|
35
|
+
ServiceProvider,
|
|
36
|
+
OpenAIModels,
|
|
37
|
+
AnthropicModels,
|
|
38
|
+
GoogleDeepMindModels,
|
|
39
|
+
MetaModels,
|
|
40
|
+
AWSModels,
|
|
41
|
+
MistralAIModels,
|
|
42
|
+
CohereModels,
|
|
43
|
+
DeepSeekModels,
|
|
44
|
+
DeepgramSTTModels,
|
|
45
|
+
MicrosoftAzureSpeechSTTModels,
|
|
46
|
+
GoogleCloudSpeechSTTModels,
|
|
47
|
+
AssemblyAISTTModels,
|
|
48
|
+
AmazonPollyTTSModels,
|
|
49
|
+
MicrosoftAzureSpeechTTSModels,
|
|
50
|
+
GoogleCloudTextToSpeechTTSModels,
|
|
51
|
+
DeepgramTTSModels,
|
|
52
|
+
is_model_supported
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
__version__ = "1.0.0"
|
|
56
|
+
__all__ = [
|
|
57
|
+
# Core classes
|
|
58
|
+
"Client",
|
|
59
|
+
"UsageData",
|
|
60
|
+
"UsageDataWithStrings",
|
|
61
|
+
"APIRequest",
|
|
62
|
+
"ModelPricing",
|
|
63
|
+
"MODEL_PRICING",
|
|
64
|
+
|
|
65
|
+
# Voice data models
|
|
66
|
+
"SttUsageData",
|
|
67
|
+
"TtsUsageData",
|
|
68
|
+
"SttModelPricing",
|
|
69
|
+
"TtsModelPricing",
|
|
70
|
+
|
|
71
|
+
# Wrappers
|
|
72
|
+
"PaygentOpenAI",
|
|
73
|
+
"PaygentAnthropic",
|
|
74
|
+
"PaygentMistral",
|
|
75
|
+
"PaygentGemini",
|
|
76
|
+
|
|
77
|
+
# Constants
|
|
78
|
+
"ServiceProvider",
|
|
79
|
+
"OpenAIModels",
|
|
80
|
+
"AnthropicModels",
|
|
81
|
+
"GoogleDeepMindModels",
|
|
82
|
+
"MetaModels",
|
|
83
|
+
"AWSModels",
|
|
84
|
+
"MistralAIModels",
|
|
85
|
+
"CohereModels",
|
|
86
|
+
"DeepSeekModels",
|
|
87
|
+
|
|
88
|
+
# STT/TTS Model constants
|
|
89
|
+
"DeepgramSTTModels",
|
|
90
|
+
"MicrosoftAzureSpeechSTTModels",
|
|
91
|
+
"GoogleCloudSpeechSTTModels",
|
|
92
|
+
"AssemblyAISTTModels",
|
|
93
|
+
"AmazonPollyTTSModels",
|
|
94
|
+
"MicrosoftAzureSpeechTTSModels",
|
|
95
|
+
"GoogleCloudTextToSpeechTTSModels",
|
|
96
|
+
"DeepgramTTSModels",
|
|
97
|
+
|
|
98
|
+
# Utility functions
|
|
99
|
+
"is_model_supported"
|
|
100
|
+
]
|
|
@@ -23,20 +23,22 @@ from .models import UsageData, UsageDataWithStrings, APIRequest, ModelPricing, M
|
|
|
23
23
|
class Client:
|
|
24
24
|
"""Paygent SDK client for tracking usage and costs for AI models."""
|
|
25
25
|
|
|
26
|
-
def __init__(self, api_key: str
|
|
26
|
+
def __init__(self, api_key: str):
|
|
27
27
|
"""
|
|
28
28
|
Initialize the Paygent SDK client.
|
|
29
29
|
|
|
30
30
|
Args:
|
|
31
31
|
api_key: Your Paygent API key
|
|
32
|
-
base_url: Base URL for the Paygent API (default: http://13.201.118.45:8080)
|
|
33
32
|
"""
|
|
34
33
|
self.api_key = api_key
|
|
35
|
-
|
|
34
|
+
# Locked configuration - cannot be changed by users
|
|
35
|
+
self.base_url = "https://cp-api.withpaygent.com"
|
|
36
|
+
# self.base_url = "http://localhost:8082"
|
|
37
|
+
self.timeout = 3000
|
|
36
38
|
|
|
37
|
-
# Setup logging
|
|
39
|
+
# Setup logging with ERROR level by default (minimal logging)
|
|
38
40
|
self.logger = logging.getLogger(f"paygent_sdk.{id(self)}")
|
|
39
|
-
self.logger.setLevel(logging.
|
|
41
|
+
self.logger.setLevel(logging.ERROR)
|
|
40
42
|
|
|
41
43
|
# Add console handler if no handlers exist
|
|
42
44
|
if not self.logger.handlers:
|
|
@@ -61,13 +63,13 @@ class Client:
|
|
|
61
63
|
self.session.mount("http://", adapter)
|
|
62
64
|
self.session.mount("https://", adapter)
|
|
63
65
|
|
|
64
|
-
# Set
|
|
65
|
-
self.session.timeout =
|
|
66
|
+
# Set timeout from locked configuration
|
|
67
|
+
self.session.timeout = self.timeout
|
|
66
68
|
|
|
67
69
|
@classmethod
|
|
68
70
|
def new_client(cls, api_key: str) -> 'Client':
|
|
69
71
|
"""
|
|
70
|
-
Create a new Paygent SDK client
|
|
72
|
+
Create a new Paygent SDK client.
|
|
71
73
|
|
|
72
74
|
Args:
|
|
73
75
|
api_key: Your Paygent API key
|
|
@@ -77,20 +79,6 @@ class Client:
|
|
|
77
79
|
"""
|
|
78
80
|
return cls(api_key)
|
|
79
81
|
|
|
80
|
-
@classmethod
|
|
81
|
-
def new_client_with_url(cls, api_key: str, base_url: str) -> 'Client':
|
|
82
|
-
"""
|
|
83
|
-
Create a new Paygent SDK client with a custom base URL.
|
|
84
|
-
|
|
85
|
-
Args:
|
|
86
|
-
api_key: Your Paygent API key
|
|
87
|
-
base_url: Custom base URL for the Paygent API
|
|
88
|
-
|
|
89
|
-
Returns:
|
|
90
|
-
Client instance
|
|
91
|
-
"""
|
|
92
|
-
return cls(api_key, base_url)
|
|
93
|
-
|
|
94
82
|
def _calculate_cost(self, model: str, usage_data: UsageData) -> float:
|
|
95
83
|
"""
|
|
96
84
|
Calculate the cost based on model and usage data.
|
|
@@ -145,10 +133,7 @@ class Client:
|
|
|
145
133
|
requests.RequestException: If the HTTP request fails
|
|
146
134
|
ValueError: If the usage data is invalid
|
|
147
135
|
"""
|
|
148
|
-
|
|
149
|
-
f"Starting sendUsage for agentID={agent_id}, customerID={customer_id}, "
|
|
150
|
-
f"indicator={indicator}, model={usage_data.model}"
|
|
151
|
-
)
|
|
136
|
+
# Removed verbose logging - only log errors
|
|
152
137
|
|
|
153
138
|
# Calculate cost
|
|
154
139
|
try:
|
|
@@ -157,7 +142,7 @@ class Client:
|
|
|
157
142
|
self.logger.error(f"Failed to calculate cost: {e}")
|
|
158
143
|
raise ValueError(f"Failed to calculate cost: {e}") from e
|
|
159
144
|
|
|
160
|
-
|
|
145
|
+
# Cost calculated (no logging for performance)
|
|
161
146
|
|
|
162
147
|
# Prepare API request
|
|
163
148
|
api_request = APIRequest(
|
|
@@ -207,10 +192,7 @@ class Client:
|
|
|
207
192
|
|
|
208
193
|
# Check response status
|
|
209
194
|
if 200 <= response.status_code < 300:
|
|
210
|
-
|
|
211
|
-
f"Successfully sent usage data for agentID={agent_id}, "
|
|
212
|
-
f"customerID={customer_id}, cost={cost:.6f}"
|
|
213
|
-
)
|
|
195
|
+
# Success - no logging to minimize verbosity
|
|
214
196
|
return
|
|
215
197
|
|
|
216
198
|
# Handle error response
|
|
@@ -381,11 +363,7 @@ class Client:
|
|
|
381
363
|
requests.RequestException: If the HTTP request fails
|
|
382
364
|
ValueError: If the usage data is invalid
|
|
383
365
|
"""
|
|
384
|
-
|
|
385
|
-
f"Starting sendUsageWithTokenString for agentID={agent_id}, customerID={customer_id}, "
|
|
386
|
-
f"indicator={indicator}, serviceProvider={usage_data.service_provider}, model={usage_data.model}"
|
|
387
|
-
)
|
|
388
|
-
|
|
366
|
+
# Removed verbose logging - only log errors
|
|
389
367
|
# Calculate cost from strings
|
|
390
368
|
try:
|
|
391
369
|
cost = self._calculate_cost_from_strings(usage_data.model, usage_data)
|
|
@@ -393,7 +371,7 @@ class Client:
|
|
|
393
371
|
self.logger.error(f"Failed to calculate cost from strings: {e}")
|
|
394
372
|
raise ValueError(f"Failed to calculate cost from strings: {e}") from e
|
|
395
373
|
|
|
396
|
-
|
|
374
|
+
# Cost calculated from strings (no logging for performance)
|
|
397
375
|
|
|
398
376
|
# Calculate token counts for API request
|
|
399
377
|
prompt_tokens = self._get_token_count(usage_data.model, usage_data.prompt_string)
|
|
@@ -447,10 +425,7 @@ class Client:
|
|
|
447
425
|
|
|
448
426
|
# Check response status
|
|
449
427
|
if 200 <= response.status_code < 300:
|
|
450
|
-
|
|
451
|
-
f"Successfully sent usage data from strings for agentID={agent_id}, "
|
|
452
|
-
f"customerID={customer_id}, cost={cost:.6f}"
|
|
453
|
-
)
|
|
428
|
+
# Success - no logging to minimize verbosity
|
|
454
429
|
return
|
|
455
430
|
|
|
456
431
|
# Handle error response
|
|
@@ -19,6 +19,18 @@ class ServiceProvider:
|
|
|
19
19
|
COHERE = "Cohere"
|
|
20
20
|
DEEPSEEK = "DeepSeek"
|
|
21
21
|
CUSTOM = "Custom"
|
|
22
|
+
|
|
23
|
+
# STT Service Providers
|
|
24
|
+
DEEPGRAM = "Deepgram"
|
|
25
|
+
MICROSOFT_AZURE_SPEECH = "Microsoft Azure Speech Service"
|
|
26
|
+
GOOGLE_CLOUD_SPEECH = "Google Cloud Speech-to-Text"
|
|
27
|
+
ASSEMBLY_AI = "AssemblyAI"
|
|
28
|
+
|
|
29
|
+
# TTS Service Providers
|
|
30
|
+
AMAZON_POLLY = "Amazon Polly"
|
|
31
|
+
MICROSOFT_AZURE_SPEECH_TTS = "Microsoft Azure Speech Service"
|
|
32
|
+
GOOGLE_CLOUD_TEXT_TO_SPEECH = "Google Cloud Text-to-Speech"
|
|
33
|
+
DEEPGRAM_TTS = "Deepgram"
|
|
22
34
|
|
|
23
35
|
|
|
24
36
|
# OpenAI Models
|
|
@@ -202,6 +214,78 @@ class DeepSeekModels:
|
|
|
202
214
|
|
|
203
215
|
|
|
204
216
|
|
|
217
|
+
# Deepgram STT Models
|
|
218
|
+
class DeepgramSTTModels:
|
|
219
|
+
"""Deepgram STT model constants."""
|
|
220
|
+
FLUX = "Flux"
|
|
221
|
+
NOVA_3_MONOLINGUAL = "Nova-3 (Monolingual)"
|
|
222
|
+
NOVA_3_MULTILINGUAL = "Nova-3 (Multilingual)"
|
|
223
|
+
NOVA_1 = "Nova-1"
|
|
224
|
+
NOVA_2 = "Nova-2"
|
|
225
|
+
ENHANCED = "Enhanced"
|
|
226
|
+
BASE = "Base"
|
|
227
|
+
REDACTION = "Redaction (Add-on)"
|
|
228
|
+
KEYTERM_PROMPTING = "Keyterm Prompting (Add-on)"
|
|
229
|
+
SPEAKER_DIARIZATION = "Speaker Diarization (Add-on)"
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
# Microsoft Azure Speech Service STT Models
|
|
233
|
+
class MicrosoftAzureSpeechSTTModels:
|
|
234
|
+
"""Microsoft Azure Speech Service STT model constants."""
|
|
235
|
+
STANDARD = "Azure Speech Standard"
|
|
236
|
+
CUSTOM = "Azure Speech Custom"
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
# Google Cloud Speech-to-Text STT Models
|
|
240
|
+
class GoogleCloudSpeechSTTModels:
|
|
241
|
+
"""Google Cloud Speech-to-Text STT model constants."""
|
|
242
|
+
STANDARD = "Google Cloud Speech Standard"
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
# AssemblyAI STT Models
|
|
246
|
+
class AssemblyAISTTModels:
|
|
247
|
+
"""AssemblyAI STT model constants."""
|
|
248
|
+
UNIVERSAL_STREAMING = "Universal-Streaming"
|
|
249
|
+
UNIVERSAL_STREAMING_MULTILANG = "Universal-Streaming Multilingual"
|
|
250
|
+
KEYTERMS_PROMPTING = "Keyterms Prompting"
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
# Amazon Polly TTS Models
|
|
254
|
+
class AmazonPollyTTSModels:
|
|
255
|
+
"""Amazon Polly TTS model constants."""
|
|
256
|
+
STANDARD = "Amazon Polly Standard"
|
|
257
|
+
NEURAL = "Amazon Polly Neural"
|
|
258
|
+
LONG_FORM = "Amazon Polly Long-form"
|
|
259
|
+
GENERATIVE = "Amazon Polly Generative"
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
# Microsoft Azure Speech Service TTS Models
|
|
263
|
+
class MicrosoftAzureSpeechTTSModels:
|
|
264
|
+
"""Microsoft Azure Speech Service TTS model constants."""
|
|
265
|
+
STANDARD = "Azure TTS Standard"
|
|
266
|
+
CUSTOM = "Azure TTS Custom"
|
|
267
|
+
CUSTOM_NEURAL_HD = "Azure TTS Custom Neural HD"
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
# Google Cloud Text-to-Speech TTS Models
|
|
271
|
+
class GoogleCloudTextToSpeechTTSModels:
|
|
272
|
+
"""Google Cloud Text-to-Speech TTS model constants."""
|
|
273
|
+
CHIRP_3_HD = "Google Cloud TTS Chirp 3: HD"
|
|
274
|
+
INSTANT_CUSTOM = "Google Cloud TTS Instant custom"
|
|
275
|
+
WAVENET = "Google Cloud TTS WaveNet"
|
|
276
|
+
STUDIO = "Google Cloud TTS Studio"
|
|
277
|
+
STANDARD = "Google Cloud TTS Standard"
|
|
278
|
+
NEURAL2 = "Google Cloud TTS Neural2"
|
|
279
|
+
POLYGLOT_PREVIEW = "Google Cloud TTS Polyglot (Preview)"
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
# Deepgram TTS Models
|
|
283
|
+
class DeepgramTTSModels:
|
|
284
|
+
"""Deepgram TTS model constants."""
|
|
285
|
+
AURA_2 = "Deepgram Aura-2"
|
|
286
|
+
AURA_1 = "Deepgram Aura-1"
|
|
287
|
+
|
|
288
|
+
|
|
205
289
|
def is_model_supported(model: str) -> bool:
|
|
206
290
|
"""
|
|
207
291
|
Check if a model is supported by the SDK.
|
|
@@ -53,6 +53,34 @@ class ModelPricing:
|
|
|
53
53
|
completion_tokens_cost: float
|
|
54
54
|
|
|
55
55
|
|
|
56
|
+
@dataclass
|
|
57
|
+
class SttUsageData:
|
|
58
|
+
"""Represents the STT usage data structure."""
|
|
59
|
+
service_provider: str
|
|
60
|
+
model: str
|
|
61
|
+
audio_duration: int # Duration in seconds
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass
|
|
65
|
+
class TtsUsageData:
|
|
66
|
+
"""Represents the TTS usage data structure."""
|
|
67
|
+
service_provider: str
|
|
68
|
+
model: str
|
|
69
|
+
character_count: int # Number of characters
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass
|
|
73
|
+
class SttModelPricing:
|
|
74
|
+
"""Represents pricing information for STT models (cost per hour in USD)."""
|
|
75
|
+
cost_per_hour: float # Cost per hour in USD
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@dataclass
|
|
79
|
+
class TtsModelPricing:
|
|
80
|
+
"""Represents pricing information for TTS models (cost per 1 million characters in USD)."""
|
|
81
|
+
cost_per_million_characters: float # Cost per 1 million characters in USD
|
|
82
|
+
|
|
83
|
+
|
|
56
84
|
# Default model pricing (cost per 1000 tokens in USD)
|
|
57
85
|
MODEL_PRICING: Dict[str, ModelPricing] = {
|
|
58
86
|
# OpenAI Models (pricing per 1000 tokens)
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Voice client implementation for STT and TTS usage tracking.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from typing import Dict
|
|
7
|
+
from urllib.parse import urljoin
|
|
8
|
+
|
|
9
|
+
import requests
|
|
10
|
+
|
|
11
|
+
from .constants import (
|
|
12
|
+
DeepgramSTTModels,
|
|
13
|
+
MicrosoftAzureSpeechSTTModels,
|
|
14
|
+
GoogleCloudSpeechSTTModels,
|
|
15
|
+
AssemblyAISTTModels,
|
|
16
|
+
AmazonPollyTTSModels,
|
|
17
|
+
MicrosoftAzureSpeechTTSModels,
|
|
18
|
+
GoogleCloudTextToSpeechTTSModels,
|
|
19
|
+
DeepgramTTSModels,
|
|
20
|
+
)
|
|
21
|
+
from .models import SttModelPricing, TtsModelPricing
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# STT model pricing (cost per hour in USD)
|
|
25
|
+
STT_MODEL_PRICING: Dict[str, SttModelPricing] = {
|
|
26
|
+
# Deepgram Models
|
|
27
|
+
DeepgramSTTModels.FLUX: SttModelPricing(cost_per_hour=0.462), # $0.462 per hour
|
|
28
|
+
DeepgramSTTModels.NOVA_3_MONOLINGUAL: SttModelPricing(cost_per_hour=0.462), # $0.462 per hour
|
|
29
|
+
DeepgramSTTModels.NOVA_3_MULTILINGUAL: SttModelPricing(cost_per_hour=0.552), # $0.552 per hour
|
|
30
|
+
DeepgramSTTModels.NOVA_1: SttModelPricing(cost_per_hour=0.348), # $0.348 per hour
|
|
31
|
+
DeepgramSTTModels.NOVA_2: SttModelPricing(cost_per_hour=0.348), # $0.348 per hour
|
|
32
|
+
DeepgramSTTModels.ENHANCED: SttModelPricing(cost_per_hour=0.99), # $0.99 per hour
|
|
33
|
+
DeepgramSTTModels.BASE: SttModelPricing(cost_per_hour=0.87), # $0.87 per hour
|
|
34
|
+
DeepgramSTTModels.REDACTION: SttModelPricing(cost_per_hour=0.12), # $0.12 per hour (add-on)
|
|
35
|
+
DeepgramSTTModels.KEYTERM_PROMPTING: SttModelPricing(cost_per_hour=0.072), # $0.072 per hour (add-on)
|
|
36
|
+
DeepgramSTTModels.SPEAKER_DIARIZATION: SttModelPricing(cost_per_hour=0.12), # $0.12 per hour (add-on)
|
|
37
|
+
|
|
38
|
+
# Microsoft Azure Speech Service Models
|
|
39
|
+
MicrosoftAzureSpeechSTTModels.STANDARD: SttModelPricing(cost_per_hour=1.0), # $1.0 per hour
|
|
40
|
+
MicrosoftAzureSpeechSTTModels.CUSTOM: SttModelPricing(cost_per_hour=1.2), # $1.2 per hour
|
|
41
|
+
|
|
42
|
+
# Google Cloud Speech-to-Text Models
|
|
43
|
+
GoogleCloudSpeechSTTModels.STANDARD: SttModelPricing(cost_per_hour=0.96), # $0.96 per hour
|
|
44
|
+
|
|
45
|
+
# AssemblyAI Models
|
|
46
|
+
AssemblyAISTTModels.UNIVERSAL_STREAMING: SttModelPricing(cost_per_hour=0.15), # $0.15 per hour
|
|
47
|
+
AssemblyAISTTModels.UNIVERSAL_STREAMING_MULTILANG: SttModelPricing(cost_per_hour=0.15), # $0.15 per hour
|
|
48
|
+
AssemblyAISTTModels.KEYTERMS_PROMPTING: SttModelPricing(cost_per_hour=0.04), # $0.04 per hour
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# TTS model pricing (cost per 1 million characters in USD)
|
|
53
|
+
TTS_MODEL_PRICING: Dict[str, TtsModelPricing] = {
|
|
54
|
+
# Amazon Polly Models
|
|
55
|
+
AmazonPollyTTSModels.STANDARD: TtsModelPricing(cost_per_million_characters=0.4), # $0.4 per 1 million characters
|
|
56
|
+
AmazonPollyTTSModels.NEURAL: TtsModelPricing(cost_per_million_characters=16.0), # $16 per 1 million characters
|
|
57
|
+
AmazonPollyTTSModels.LONG_FORM: TtsModelPricing(cost_per_million_characters=100.0), # $100 per 1 million characters
|
|
58
|
+
AmazonPollyTTSModels.GENERATIVE: TtsModelPricing(cost_per_million_characters=30.0), # $30 per 1 million characters
|
|
59
|
+
|
|
60
|
+
# Microsoft Azure Speech Service TTS Models
|
|
61
|
+
MicrosoftAzureSpeechTTSModels.STANDARD: TtsModelPricing(cost_per_million_characters=15.0), # $15 per 1 million characters
|
|
62
|
+
MicrosoftAzureSpeechTTSModels.CUSTOM: TtsModelPricing(cost_per_million_characters=24.0), # $24 per 1 million characters
|
|
63
|
+
MicrosoftAzureSpeechTTSModels.CUSTOM_NEURAL_HD: TtsModelPricing(cost_per_million_characters=48.0), # $48 per 1 million characters
|
|
64
|
+
|
|
65
|
+
# Google Cloud Text-to-Speech TTS Models
|
|
66
|
+
GoogleCloudTextToSpeechTTSModels.CHIRP_3_HD: TtsModelPricing(cost_per_million_characters=30.0), # $30 per 1 million characters
|
|
67
|
+
GoogleCloudTextToSpeechTTSModels.INSTANT_CUSTOM: TtsModelPricing(cost_per_million_characters=60.0), # $60 per 1 million characters
|
|
68
|
+
GoogleCloudTextToSpeechTTSModels.WAVENET: TtsModelPricing(cost_per_million_characters=4.0), # $4 per 1 million characters
|
|
69
|
+
GoogleCloudTextToSpeechTTSModels.STUDIO: TtsModelPricing(cost_per_million_characters=160.0), # $160 per 1 million characters
|
|
70
|
+
GoogleCloudTextToSpeechTTSModels.STANDARD: TtsModelPricing(cost_per_million_characters=4.0), # $4 per 1 million characters
|
|
71
|
+
GoogleCloudTextToSpeechTTSModels.NEURAL2: TtsModelPricing(cost_per_million_characters=16.0), # $16 per 1 million characters
|
|
72
|
+
GoogleCloudTextToSpeechTTSModels.POLYGLOT_PREVIEW: TtsModelPricing(cost_per_million_characters=16.0), # $16 per 1 million characters
|
|
73
|
+
|
|
74
|
+
# Deepgram TTS Models
|
|
75
|
+
DeepgramTTSModels.AURA_2: TtsModelPricing(cost_per_million_characters=30.0), # $30 per 1 million characters
|
|
76
|
+
DeepgramTTSModels.AURA_1: TtsModelPricing(cost_per_million_characters=15.0), # $15 per 1 million characters
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _calculate_stt_cost(client_instance, model: str, audio_duration_seconds: int) -> float:
|
|
81
|
+
"""
|
|
82
|
+
Calculate the cost based on STT model and audio duration.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
client_instance: The Client instance
|
|
86
|
+
model: The STT model name
|
|
87
|
+
audio_duration_seconds: Audio duration in seconds
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Calculated cost in USD
|
|
91
|
+
"""
|
|
92
|
+
pricing = STT_MODEL_PRICING.get(model)
|
|
93
|
+
|
|
94
|
+
if not pricing:
|
|
95
|
+
client_instance.logger.warning(f"Unknown STT model '{model}', using default pricing")
|
|
96
|
+
# Use default pricing for unknown models (per hour)
|
|
97
|
+
pricing = SttModelPricing(cost_per_hour=0.5) # $0.50 per hour default
|
|
98
|
+
|
|
99
|
+
# Calculate cost: (duration in seconds / 3600) * cost per hour
|
|
100
|
+
# Convert seconds to hours and multiply by cost per hour
|
|
101
|
+
duration_hours = audio_duration_seconds / 3600.0
|
|
102
|
+
total_cost = duration_hours * pricing.cost_per_hour
|
|
103
|
+
|
|
104
|
+
client_instance.logger.debug(
|
|
105
|
+
f"STT cost calculation for model '{model}': "
|
|
106
|
+
f"duration={audio_duration_seconds} seconds ({duration_hours:.6f} hours), "
|
|
107
|
+
f"cost_per_hour={pricing.cost_per_hour:.6f}, total={total_cost:.6f}"
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
return total_cost
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _calculate_tts_cost(client_instance, model: str, character_count: int) -> float:
|
|
114
|
+
"""
|
|
115
|
+
Calculate the cost based on TTS model and character count.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
client_instance: The Client instance
|
|
119
|
+
model: The TTS model name
|
|
120
|
+
character_count: Number of characters
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Calculated cost in USD
|
|
124
|
+
"""
|
|
125
|
+
pricing = TTS_MODEL_PRICING.get(model)
|
|
126
|
+
|
|
127
|
+
if not pricing:
|
|
128
|
+
client_instance.logger.warning(f"Unknown TTS model '{model}', using default pricing")
|
|
129
|
+
# Use default pricing for unknown models (per 1 million characters)
|
|
130
|
+
pricing = TtsModelPricing(cost_per_million_characters=10.0) # $10 per 1 million characters default
|
|
131
|
+
|
|
132
|
+
# Calculate cost: (character count / 1,000,000) * cost per 1 million characters
|
|
133
|
+
# Convert character count to millions and multiply by cost per million
|
|
134
|
+
characters_in_millions = character_count / 1000000.0
|
|
135
|
+
total_cost = characters_in_millions * pricing.cost_per_million_characters
|
|
136
|
+
|
|
137
|
+
client_instance.logger.debug(
|
|
138
|
+
f"TTS cost calculation for model '{model}': "
|
|
139
|
+
f"characters={character_count} ({characters_in_millions:.6f} millions), "
|
|
140
|
+
f"cost_per_million={pricing.cost_per_million_characters:.6f}, total={total_cost:.6f}"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
return total_cost
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def send_stt_usage(client_instance, agent_id: str, customer_id: str, stt_usage_data) -> None:
|
|
147
|
+
"""
|
|
148
|
+
Send STT usage data to the Paygent API.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
client_instance: The Client instance
|
|
152
|
+
agent_id: Unique identifier for the agent
|
|
153
|
+
customer_id: Unique identifier for the customer
|
|
154
|
+
stt_usage_data: SttUsageData containing model and audio duration information
|
|
155
|
+
|
|
156
|
+
Raises:
|
|
157
|
+
requests.RequestException: If the request fails
|
|
158
|
+
"""
|
|
159
|
+
client_instance.logger.info(
|
|
160
|
+
f"Starting send_stt_usage for agentID={agent_id}, customerID={customer_id}, "
|
|
161
|
+
f"model={stt_usage_data.model}, duration={stt_usage_data.audio_duration} seconds"
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
try:
|
|
165
|
+
# Calculate cost
|
|
166
|
+
cost = _calculate_stt_cost(client_instance, stt_usage_data.model, stt_usage_data.audio_duration)
|
|
167
|
+
client_instance.logger.info(f"Calculated STT cost: {cost:.6f} for model {stt_usage_data.model}")
|
|
168
|
+
|
|
169
|
+
# Prepare API request
|
|
170
|
+
api_request = {
|
|
171
|
+
"agentId": agent_id,
|
|
172
|
+
"customerId": customer_id,
|
|
173
|
+
"indicator": "stt-usage", # Default indicator for STT usage
|
|
174
|
+
"amount": cost,
|
|
175
|
+
"audioDuration": stt_usage_data.audio_duration,
|
|
176
|
+
"model": stt_usage_data.model,
|
|
177
|
+
"serviceProvider": stt_usage_data.service_provider,
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
# Make HTTP request
|
|
181
|
+
url = urljoin(client_instance.base_url, "/api/v1/usage")
|
|
182
|
+
headers = {
|
|
183
|
+
"Content-Type": "application/json",
|
|
184
|
+
"paygent-api-key": client_instance.api_key,
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
response = client_instance.session.post(url, json=api_request, headers=headers)
|
|
188
|
+
response.raise_for_status()
|
|
189
|
+
|
|
190
|
+
client_instance.logger.info(
|
|
191
|
+
f"Successfully sent STT usage data for agentID={agent_id}, "
|
|
192
|
+
f"customerID={customer_id}, cost={cost:.6f}"
|
|
193
|
+
)
|
|
194
|
+
except requests.RequestException as e:
|
|
195
|
+
client_instance.logger.error(f"Failed to send STT usage data: {str(e)}")
|
|
196
|
+
raise
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def send_tts_usage(client_instance, agent_id: str, customer_id: str, tts_usage_data) -> None:
|
|
200
|
+
"""
|
|
201
|
+
Send TTS usage data to the Paygent API.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
client_instance: The Client instance
|
|
205
|
+
agent_id: Unique identifier for the agent
|
|
206
|
+
customer_id: Unique identifier for the customer
|
|
207
|
+
tts_usage_data: TtsUsageData containing model and character count information
|
|
208
|
+
|
|
209
|
+
Raises:
|
|
210
|
+
requests.RequestException: If the request fails
|
|
211
|
+
"""
|
|
212
|
+
client_instance.logger.info(
|
|
213
|
+
f"Starting send_tts_usage for agentID={agent_id}, customerID={customer_id}, "
|
|
214
|
+
f"model={tts_usage_data.model}, characters={tts_usage_data.character_count}"
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
try:
|
|
218
|
+
# Calculate cost
|
|
219
|
+
cost = _calculate_tts_cost(client_instance, tts_usage_data.model, tts_usage_data.character_count)
|
|
220
|
+
client_instance.logger.info(f"Calculated TTS cost: {cost:.6f} for model {tts_usage_data.model}")
|
|
221
|
+
|
|
222
|
+
# Prepare API request
|
|
223
|
+
api_request = {
|
|
224
|
+
"agentId": agent_id,
|
|
225
|
+
"customerId": customer_id,
|
|
226
|
+
"indicator": "tts-usage", # Default indicator for TTS usage
|
|
227
|
+
"amount": cost,
|
|
228
|
+
"characterCount": tts_usage_data.character_count,
|
|
229
|
+
"model": tts_usage_data.model,
|
|
230
|
+
"serviceProvider": tts_usage_data.service_provider,
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
# Make HTTP request
|
|
234
|
+
url = urljoin(client_instance.base_url, "/api/v1/usage")
|
|
235
|
+
headers = {
|
|
236
|
+
"Content-Type": "application/json",
|
|
237
|
+
"paygent-api-key": client_instance.api_key,
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
response = client_instance.session.post(url, json=api_request, headers=headers)
|
|
241
|
+
response.raise_for_status()
|
|
242
|
+
|
|
243
|
+
client_instance.logger.info(
|
|
244
|
+
f"Successfully sent TTS usage data for agentID={agent_id}, "
|
|
245
|
+
f"customerID={customer_id}, cost={cost:.6f}"
|
|
246
|
+
)
|
|
247
|
+
except requests.RequestException as e:
|
|
248
|
+
client_instance.logger.error(f"Failed to send TTS usage data: {str(e)}")
|
|
249
|
+
raise
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
# Add methods to Client class
|
|
253
|
+
def _add_voice_methods_to_client():
|
|
254
|
+
"""Dynamically add voice methods to the Client class."""
|
|
255
|
+
from .client import Client
|
|
256
|
+
|
|
257
|
+
Client.send_stt_usage = send_stt_usage
|
|
258
|
+
Client.send_tts_usage = send_tts_usage
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
# Call this function to attach methods when module is imported
|
|
262
|
+
_add_voice_methods_to_client()
|
|
263
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Wrappers for automatic usage tracking with AI provider SDKs.
|
|
3
|
+
|
|
4
|
+
This module provides wrapper classes that intercept API calls to various AI providers
|
|
5
|
+
and automatically send usage data to Paygent for tracking and billing.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .openai_wrapper import PaygentOpenAI
|
|
9
|
+
from .anthropic_wrapper import PaygentAnthropic
|
|
10
|
+
from .mistral_wrapper import PaygentMistral
|
|
11
|
+
from .gemini_wrapper import PaygentGemini
|
|
12
|
+
|
|
13
|
+
# LangChain integration (optional dependency)
|
|
14
|
+
try:
|
|
15
|
+
from .langchain_wrapper import PaygentLangChainCallback
|
|
16
|
+
__all__ = [
|
|
17
|
+
"PaygentOpenAI",
|
|
18
|
+
"PaygentAnthropic",
|
|
19
|
+
"PaygentMistral",
|
|
20
|
+
"PaygentGemini",
|
|
21
|
+
"PaygentLangChainCallback",
|
|
22
|
+
]
|
|
23
|
+
except ImportError:
|
|
24
|
+
# LangChain not installed
|
|
25
|
+
__all__ = [
|
|
26
|
+
"PaygentOpenAI",
|
|
27
|
+
"PaygentAnthropic",
|
|
28
|
+
"PaygentMistral",
|
|
29
|
+
"PaygentGemini",
|
|
30
|
+
]
|