prodloop-observability-sdk 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.
- prodloop_observability_sdk-0.1.0/PKG-INFO +97 -0
- prodloop_observability_sdk-0.1.0/README.md +82 -0
- prodloop_observability_sdk-0.1.0/prodloop/__init__.py +11 -0
- prodloop_observability_sdk-0.1.0/prodloop/client.py +125 -0
- prodloop_observability_sdk-0.1.0/prodloop/exceptions.py +15 -0
- prodloop_observability_sdk-0.1.0/prodloop/models.py +29 -0
- prodloop_observability_sdk-0.1.0/prodloop_observability_sdk.egg-info/PKG-INFO +97 -0
- prodloop_observability_sdk-0.1.0/prodloop_observability_sdk.egg-info/SOURCES.txt +11 -0
- prodloop_observability_sdk-0.1.0/prodloop_observability_sdk.egg-info/dependency_links.txt +1 -0
- prodloop_observability_sdk-0.1.0/prodloop_observability_sdk.egg-info/requires.txt +6 -0
- prodloop_observability_sdk-0.1.0/prodloop_observability_sdk.egg-info/top_level.txt +1 -0
- prodloop_observability_sdk-0.1.0/pyproject.toml +28 -0
- prodloop_observability_sdk-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: prodloop-observability-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for evaluating AI voice bot calls via Prodloop APIs.
|
|
5
|
+
Project-URL: Homepage, https://prodloop.com
|
|
6
|
+
Project-URL: Documentation, https://prodloop.com/docs
|
|
7
|
+
Project-URL: Repository, https://github.com/prodloop/prodloop-observability-sdk
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: requests>=2.31.0
|
|
11
|
+
Provides-Extra: docs
|
|
12
|
+
Requires-Dist: mkdocs>=1.6.0; extra == "docs"
|
|
13
|
+
Requires-Dist: mkdocs-material>=9.5.0; extra == "docs"
|
|
14
|
+
Requires-Dist: mkdocstrings[python]>=0.25.0; extra == "docs"
|
|
15
|
+
|
|
16
|
+
# Prodloop Observability SDK
|
|
17
|
+
|
|
18
|
+
Python SDK to evaluate AI voice bot calls through the Prodloop evaluation service.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install prodloop-observability-sdk
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quickstart
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from prodloop import ProdloopClient, EvaluationParameter
|
|
30
|
+
|
|
31
|
+
client = ProdloopClient(api_key="sk_live_...")
|
|
32
|
+
|
|
33
|
+
result = client.evaluate_call(
|
|
34
|
+
audio_file_path="call.mp3",
|
|
35
|
+
parameters=[
|
|
36
|
+
EvaluationParameter.E2E_RESPONSE_TIME,
|
|
37
|
+
EvaluationParameter.HALLUCINATION,
|
|
38
|
+
],
|
|
39
|
+
thresholds={"e2e_response_time_max_ms": 800},
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
print(result)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Extraction Validation
|
|
46
|
+
|
|
47
|
+
To validate extraction quality, pass both `extraction_schema` and `bot_captured_variables`:
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
result = client.evaluate_call(
|
|
51
|
+
audio_file_path="call.mp3",
|
|
52
|
+
parameters=[EvaluationParameter.EXTRACTION_VARIABLES],
|
|
53
|
+
extraction_schema={"customer_name": "string"},
|
|
54
|
+
bot_captured_variables={"customer_name": "ram"},
|
|
55
|
+
)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Response includes:
|
|
59
|
+
|
|
60
|
+
- `extraction_variables`
|
|
61
|
+
- `extraction_validation`
|
|
62
|
+
|
|
63
|
+
## Supported Parameters
|
|
64
|
+
|
|
65
|
+
- `e2e_response_time`
|
|
66
|
+
- `turn_by_turn_latency`
|
|
67
|
+
- `hallucination`
|
|
68
|
+
- `extraction_variables`
|
|
69
|
+
- `interruption_behavior`
|
|
70
|
+
|
|
71
|
+
## Authentication
|
|
72
|
+
|
|
73
|
+
Pass your Prodloop API key in the SDK constructor.
|
|
74
|
+
The SDK sends it as a `Bearer` token in the `Authorization` header.
|
|
75
|
+
|
|
76
|
+
## Errors
|
|
77
|
+
|
|
78
|
+
- `ValidationError`: invalid local inputs (file path, parameters, etc.)
|
|
79
|
+
- `APIError`: backend/API-level failures (`status_code`, `message`)
|
|
80
|
+
|
|
81
|
+
## Local Demo
|
|
82
|
+
|
|
83
|
+
Use the included demo script:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
export PRODLOOP_API_KEY="sk_live_..."
|
|
87
|
+
python demo/use_sdk.py --audio-file "/absolute/path/to/call.mp3"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Documentation Site
|
|
91
|
+
|
|
92
|
+
This repo includes MkDocs docs under `docs/`.
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pip install -e ".[docs]"
|
|
96
|
+
mkdocs serve
|
|
97
|
+
```
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Prodloop Observability SDK
|
|
2
|
+
|
|
3
|
+
Python SDK to evaluate AI voice bot calls through the Prodloop evaluation service.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install prodloop-observability-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quickstart
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from prodloop import ProdloopClient, EvaluationParameter
|
|
15
|
+
|
|
16
|
+
client = ProdloopClient(api_key="sk_live_...")
|
|
17
|
+
|
|
18
|
+
result = client.evaluate_call(
|
|
19
|
+
audio_file_path="call.mp3",
|
|
20
|
+
parameters=[
|
|
21
|
+
EvaluationParameter.E2E_RESPONSE_TIME,
|
|
22
|
+
EvaluationParameter.HALLUCINATION,
|
|
23
|
+
],
|
|
24
|
+
thresholds={"e2e_response_time_max_ms": 800},
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
print(result)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Extraction Validation
|
|
31
|
+
|
|
32
|
+
To validate extraction quality, pass both `extraction_schema` and `bot_captured_variables`:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
result = client.evaluate_call(
|
|
36
|
+
audio_file_path="call.mp3",
|
|
37
|
+
parameters=[EvaluationParameter.EXTRACTION_VARIABLES],
|
|
38
|
+
extraction_schema={"customer_name": "string"},
|
|
39
|
+
bot_captured_variables={"customer_name": "ram"},
|
|
40
|
+
)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Response includes:
|
|
44
|
+
|
|
45
|
+
- `extraction_variables`
|
|
46
|
+
- `extraction_validation`
|
|
47
|
+
|
|
48
|
+
## Supported Parameters
|
|
49
|
+
|
|
50
|
+
- `e2e_response_time`
|
|
51
|
+
- `turn_by_turn_latency`
|
|
52
|
+
- `hallucination`
|
|
53
|
+
- `extraction_variables`
|
|
54
|
+
- `interruption_behavior`
|
|
55
|
+
|
|
56
|
+
## Authentication
|
|
57
|
+
|
|
58
|
+
Pass your Prodloop API key in the SDK constructor.
|
|
59
|
+
The SDK sends it as a `Bearer` token in the `Authorization` header.
|
|
60
|
+
|
|
61
|
+
## Errors
|
|
62
|
+
|
|
63
|
+
- `ValidationError`: invalid local inputs (file path, parameters, etc.)
|
|
64
|
+
- `APIError`: backend/API-level failures (`status_code`, `message`)
|
|
65
|
+
|
|
66
|
+
## Local Demo
|
|
67
|
+
|
|
68
|
+
Use the included demo script:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
export PRODLOOP_API_KEY="sk_live_..."
|
|
72
|
+
python demo/use_sdk.py --audio-file "/absolute/path/to/call.mp3"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Documentation Site
|
|
76
|
+
|
|
77
|
+
This repo includes MkDocs docs under `docs/`.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install -e ".[docs]"
|
|
81
|
+
mkdocs serve
|
|
82
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from prodloop.client import ProdloopClient
|
|
2
|
+
from prodloop.exceptions import APIError, ProdloopError, ValidationError
|
|
3
|
+
from prodloop.models import EvaluationParameter
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"ProdloopClient",
|
|
7
|
+
"EvaluationParameter",
|
|
8
|
+
"ProdloopError",
|
|
9
|
+
"ValidationError",
|
|
10
|
+
"APIError",
|
|
11
|
+
]
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import mimetypes
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any, Dict, Iterable, Mapping, Optional, Sequence
|
|
5
|
+
|
|
6
|
+
import requests
|
|
7
|
+
|
|
8
|
+
from prodloop.exceptions import APIError, ValidationError
|
|
9
|
+
from prodloop.models import EvaluationParameter, ParameterInput, coerce_parameter
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ProdloopClient:
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
api_key: str,
|
|
16
|
+
base_url: str = "https://asia-south1-prodloop.cloudfunctions.net/prodloop-evaluator-fn",
|
|
17
|
+
timeout_seconds: int = 180,
|
|
18
|
+
session: Optional[requests.Session] = None,
|
|
19
|
+
):
|
|
20
|
+
if not api_key or not api_key.strip():
|
|
21
|
+
raise ValidationError("api_key is required.")
|
|
22
|
+
if not base_url or not base_url.strip():
|
|
23
|
+
raise ValidationError("base_url is required.")
|
|
24
|
+
|
|
25
|
+
self.api_key = api_key.strip()
|
|
26
|
+
self.base_url = base_url.rstrip("/")
|
|
27
|
+
self.timeout_seconds = timeout_seconds
|
|
28
|
+
self._session = session or requests.Session()
|
|
29
|
+
|
|
30
|
+
def evaluate_call(
|
|
31
|
+
self,
|
|
32
|
+
audio_file_path: str,
|
|
33
|
+
parameters: Sequence[ParameterInput],
|
|
34
|
+
thresholds: Optional[Mapping[str, Any]] = None,
|
|
35
|
+
extraction_schema: Optional[Mapping[str, str]] = None,
|
|
36
|
+
bot_captured_variables: Optional[Mapping[str, Any]] = None,
|
|
37
|
+
timeout_seconds: Optional[int] = None,
|
|
38
|
+
) -> Dict[str, Any]:
|
|
39
|
+
normalized_parameters = self._normalize_parameters(parameters)
|
|
40
|
+
payload: Dict[str, Any] = {
|
|
41
|
+
"parameters": [param.value for param in normalized_parameters],
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if thresholds:
|
|
45
|
+
payload["thresholds"] = dict(thresholds)
|
|
46
|
+
if extraction_schema:
|
|
47
|
+
payload["extraction_schema"] = dict(extraction_schema)
|
|
48
|
+
if bot_captured_variables:
|
|
49
|
+
payload["bot_captured_variables"] = dict(bot_captured_variables)
|
|
50
|
+
|
|
51
|
+
if EvaluationParameter.EXTRACTION_VARIABLES in normalized_parameters:
|
|
52
|
+
if not extraction_schema:
|
|
53
|
+
raise ValidationError(
|
|
54
|
+
"extraction_schema is required when using 'extraction_variables'."
|
|
55
|
+
)
|
|
56
|
+
if not bot_captured_variables:
|
|
57
|
+
raise ValidationError(
|
|
58
|
+
"bot_captured_variables is required when using 'extraction_variables'."
|
|
59
|
+
)
|
|
60
|
+
missing_keys = [
|
|
61
|
+
key for key in extraction_schema.keys() if key not in bot_captured_variables
|
|
62
|
+
]
|
|
63
|
+
if missing_keys:
|
|
64
|
+
raise ValidationError(
|
|
65
|
+
"bot_captured_variables is missing keys from extraction_schema: "
|
|
66
|
+
+ ", ".join(missing_keys)
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
audio_path = Path(audio_file_path)
|
|
70
|
+
if not audio_path.exists():
|
|
71
|
+
raise ValidationError(f"Audio file not found: {audio_file_path}")
|
|
72
|
+
if not audio_path.is_file():
|
|
73
|
+
raise ValidationError(f"Audio path is not a file: {audio_file_path}")
|
|
74
|
+
|
|
75
|
+
request_timeout = timeout_seconds or self.timeout_seconds
|
|
76
|
+
url = self.base_url
|
|
77
|
+
headers = {"Authorization": f"Bearer {self.api_key}"}
|
|
78
|
+
mime_type = self._guess_mime_type(audio_path)
|
|
79
|
+
|
|
80
|
+
with audio_path.open("rb") as audio_file:
|
|
81
|
+
files = {
|
|
82
|
+
"audio_file": (audio_path.name, audio_file, mime_type),
|
|
83
|
+
"metadata": (None, json.dumps(payload), "application/json"),
|
|
84
|
+
}
|
|
85
|
+
response = self._session.post(
|
|
86
|
+
url, headers=headers, files=files, timeout=request_timeout
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
self._raise_for_api_error(response)
|
|
90
|
+
return self._safe_json(response)
|
|
91
|
+
|
|
92
|
+
@staticmethod
|
|
93
|
+
def _normalize_parameters(parameters: Iterable[ParameterInput]) -> Sequence[EvaluationParameter]:
|
|
94
|
+
normalized = [coerce_parameter(param) for param in parameters]
|
|
95
|
+
if not normalized:
|
|
96
|
+
raise ValidationError("At least one evaluation parameter is required.")
|
|
97
|
+
return normalized
|
|
98
|
+
|
|
99
|
+
@staticmethod
|
|
100
|
+
def _guess_mime_type(audio_path: Path) -> str:
|
|
101
|
+
guessed, _ = mimetypes.guess_type(str(audio_path))
|
|
102
|
+
return guessed or "application/octet-stream"
|
|
103
|
+
|
|
104
|
+
@staticmethod
|
|
105
|
+
def _safe_json(response: requests.Response) -> Dict[str, Any]:
|
|
106
|
+
try:
|
|
107
|
+
payload = response.json()
|
|
108
|
+
except ValueError as exc:
|
|
109
|
+
raise APIError(response.status_code, "Backend returned non-JSON response.") from exc
|
|
110
|
+
if not isinstance(payload, dict):
|
|
111
|
+
raise APIError(response.status_code, "Backend response must be a JSON object.")
|
|
112
|
+
return payload
|
|
113
|
+
|
|
114
|
+
@staticmethod
|
|
115
|
+
def _raise_for_api_error(response: requests.Response) -> None:
|
|
116
|
+
if response.ok:
|
|
117
|
+
return
|
|
118
|
+
|
|
119
|
+
try:
|
|
120
|
+
payload = response.json()
|
|
121
|
+
message = payload.get("error") or payload.get("message") or str(payload)
|
|
122
|
+
except ValueError:
|
|
123
|
+
message = response.text or "Unknown backend error"
|
|
124
|
+
|
|
125
|
+
raise APIError(response.status_code, message)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class ProdloopError(Exception):
|
|
2
|
+
"""Base exception for SDK errors."""
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ValidationError(ProdloopError):
|
|
6
|
+
"""Raised when request inputs are invalid."""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class APIError(ProdloopError):
|
|
10
|
+
"""Raised when backend API returns an error response."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, status_code: int, message: str):
|
|
13
|
+
super().__init__(f"Prodloop API error ({status_code}): {message}")
|
|
14
|
+
self.status_code = status_code
|
|
15
|
+
self.message = message
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Union
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EvaluationParameter(str, Enum):
|
|
6
|
+
E2E_RESPONSE_TIME = "e2e_response_time"
|
|
7
|
+
TURN_BY_TURN_LATENCY = "turn_by_turn_latency"
|
|
8
|
+
HALLUCINATION = "hallucination"
|
|
9
|
+
EXTRACTION_VARIABLES = "extraction_variables"
|
|
10
|
+
INTERRUPTION_BEHAVIOR = "interruption_behavior"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
ParameterInput = Union[EvaluationParameter, str]
|
|
14
|
+
|
|
15
|
+
SUPPORTED_PARAMETERS = tuple(param.value for param in EvaluationParameter)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def coerce_parameter(value: ParameterInput) -> EvaluationParameter:
|
|
19
|
+
if isinstance(value, EvaluationParameter):
|
|
20
|
+
return value
|
|
21
|
+
|
|
22
|
+
normalized = str(value).strip().lower()
|
|
23
|
+
for parameter in EvaluationParameter:
|
|
24
|
+
if parameter.value == normalized:
|
|
25
|
+
return parameter
|
|
26
|
+
|
|
27
|
+
raise ValueError(
|
|
28
|
+
f"Unsupported parameter '{value}'. Supported values: {', '.join(SUPPORTED_PARAMETERS)}."
|
|
29
|
+
)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: prodloop-observability-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for evaluating AI voice bot calls via Prodloop APIs.
|
|
5
|
+
Project-URL: Homepage, https://prodloop.com
|
|
6
|
+
Project-URL: Documentation, https://prodloop.com/docs
|
|
7
|
+
Project-URL: Repository, https://github.com/prodloop/prodloop-observability-sdk
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: requests>=2.31.0
|
|
11
|
+
Provides-Extra: docs
|
|
12
|
+
Requires-Dist: mkdocs>=1.6.0; extra == "docs"
|
|
13
|
+
Requires-Dist: mkdocs-material>=9.5.0; extra == "docs"
|
|
14
|
+
Requires-Dist: mkdocstrings[python]>=0.25.0; extra == "docs"
|
|
15
|
+
|
|
16
|
+
# Prodloop Observability SDK
|
|
17
|
+
|
|
18
|
+
Python SDK to evaluate AI voice bot calls through the Prodloop evaluation service.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install prodloop-observability-sdk
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quickstart
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from prodloop import ProdloopClient, EvaluationParameter
|
|
30
|
+
|
|
31
|
+
client = ProdloopClient(api_key="sk_live_...")
|
|
32
|
+
|
|
33
|
+
result = client.evaluate_call(
|
|
34
|
+
audio_file_path="call.mp3",
|
|
35
|
+
parameters=[
|
|
36
|
+
EvaluationParameter.E2E_RESPONSE_TIME,
|
|
37
|
+
EvaluationParameter.HALLUCINATION,
|
|
38
|
+
],
|
|
39
|
+
thresholds={"e2e_response_time_max_ms": 800},
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
print(result)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Extraction Validation
|
|
46
|
+
|
|
47
|
+
To validate extraction quality, pass both `extraction_schema` and `bot_captured_variables`:
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
result = client.evaluate_call(
|
|
51
|
+
audio_file_path="call.mp3",
|
|
52
|
+
parameters=[EvaluationParameter.EXTRACTION_VARIABLES],
|
|
53
|
+
extraction_schema={"customer_name": "string"},
|
|
54
|
+
bot_captured_variables={"customer_name": "ram"},
|
|
55
|
+
)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Response includes:
|
|
59
|
+
|
|
60
|
+
- `extraction_variables`
|
|
61
|
+
- `extraction_validation`
|
|
62
|
+
|
|
63
|
+
## Supported Parameters
|
|
64
|
+
|
|
65
|
+
- `e2e_response_time`
|
|
66
|
+
- `turn_by_turn_latency`
|
|
67
|
+
- `hallucination`
|
|
68
|
+
- `extraction_variables`
|
|
69
|
+
- `interruption_behavior`
|
|
70
|
+
|
|
71
|
+
## Authentication
|
|
72
|
+
|
|
73
|
+
Pass your Prodloop API key in the SDK constructor.
|
|
74
|
+
The SDK sends it as a `Bearer` token in the `Authorization` header.
|
|
75
|
+
|
|
76
|
+
## Errors
|
|
77
|
+
|
|
78
|
+
- `ValidationError`: invalid local inputs (file path, parameters, etc.)
|
|
79
|
+
- `APIError`: backend/API-level failures (`status_code`, `message`)
|
|
80
|
+
|
|
81
|
+
## Local Demo
|
|
82
|
+
|
|
83
|
+
Use the included demo script:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
export PRODLOOP_API_KEY="sk_live_..."
|
|
87
|
+
python demo/use_sdk.py --audio-file "/absolute/path/to/call.mp3"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Documentation Site
|
|
91
|
+
|
|
92
|
+
This repo includes MkDocs docs under `docs/`.
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pip install -e ".[docs]"
|
|
96
|
+
mkdocs serve
|
|
97
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
prodloop/__init__.py
|
|
4
|
+
prodloop/client.py
|
|
5
|
+
prodloop/exceptions.py
|
|
6
|
+
prodloop/models.py
|
|
7
|
+
prodloop_observability_sdk.egg-info/PKG-INFO
|
|
8
|
+
prodloop_observability_sdk.egg-info/SOURCES.txt
|
|
9
|
+
prodloop_observability_sdk.egg-info/dependency_links.txt
|
|
10
|
+
prodloop_observability_sdk.egg-info/requires.txt
|
|
11
|
+
prodloop_observability_sdk.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
prodloop
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "prodloop-observability-sdk"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python SDK for evaluating AI voice bot calls via Prodloop APIs."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"requests>=2.31.0",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[project.optional-dependencies]
|
|
16
|
+
docs = [
|
|
17
|
+
"mkdocs>=1.6.0",
|
|
18
|
+
"mkdocs-material>=9.5.0",
|
|
19
|
+
"mkdocstrings[python]>=0.25.0",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[project.urls]
|
|
23
|
+
Homepage = "https://prodloop.com"
|
|
24
|
+
Documentation = "https://prodloop.com/docs"
|
|
25
|
+
Repository = "https://github.com/prodloop/prodloop-observability-sdk"
|
|
26
|
+
|
|
27
|
+
[tool.setuptools.packages.find]
|
|
28
|
+
include = ["prodloop*"]
|