prodloop-observability-sdk 0.1.2__tar.gz → 0.1.5__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.5/PKG-INFO +234 -0
- prodloop_observability_sdk-0.1.5/README.md +218 -0
- prodloop_observability_sdk-0.1.5/prodloop/__init__.py +22 -0
- prodloop_observability_sdk-0.1.5/prodloop/client.py +411 -0
- prodloop_observability_sdk-0.1.5/prodloop/models.py +88 -0
- prodloop_observability_sdk-0.1.5/prodloop/plugins/__init__.py +9 -0
- prodloop_observability_sdk-0.1.5/prodloop/plugins/_utils.py +7 -0
- prodloop_observability_sdk-0.1.5/prodloop/plugins/litellm.py +178 -0
- prodloop_observability_sdk-0.1.5/prodloop_observability_sdk.egg-info/PKG-INFO +234 -0
- {prodloop_observability_sdk-0.1.2 → prodloop_observability_sdk-0.1.5}/prodloop_observability_sdk.egg-info/SOURCES.txt +3 -0
- {prodloop_observability_sdk-0.1.2 → prodloop_observability_sdk-0.1.5}/prodloop_observability_sdk.egg-info/requires.txt +1 -0
- {prodloop_observability_sdk-0.1.2 → prodloop_observability_sdk-0.1.5}/pyproject.toml +2 -1
- prodloop_observability_sdk-0.1.2/PKG-INFO +0 -83
- prodloop_observability_sdk-0.1.2/README.md +0 -68
- prodloop_observability_sdk-0.1.2/prodloop/__init__.py +0 -11
- prodloop_observability_sdk-0.1.2/prodloop/client.py +0 -125
- prodloop_observability_sdk-0.1.2/prodloop/models.py +0 -29
- prodloop_observability_sdk-0.1.2/prodloop_observability_sdk.egg-info/PKG-INFO +0 -83
- {prodloop_observability_sdk-0.1.2 → prodloop_observability_sdk-0.1.5}/prodloop/exceptions.py +0 -0
- {prodloop_observability_sdk-0.1.2 → prodloop_observability_sdk-0.1.5}/prodloop_observability_sdk.egg-info/dependency_links.txt +0 -0
- {prodloop_observability_sdk-0.1.2 → prodloop_observability_sdk-0.1.5}/prodloop_observability_sdk.egg-info/top_level.txt +0 -0
- {prodloop_observability_sdk-0.1.2 → prodloop_observability_sdk-0.1.5}/setup.cfg +0 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: prodloop-observability-sdk
|
|
3
|
+
Version: 0.1.5
|
|
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://observability-sdk-docs.pages.dev/
|
|
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: litellm
|
|
11
|
+
Requires-Dist: requests>=2.31.0
|
|
12
|
+
Provides-Extra: docs
|
|
13
|
+
Requires-Dist: mkdocs>=1.6.0; extra == "docs"
|
|
14
|
+
Requires-Dist: mkdocs-material>=9.5.0; extra == "docs"
|
|
15
|
+
Requires-Dist: mkdocstrings[python]>=0.25.0; extra == "docs"
|
|
16
|
+
|
|
17
|
+
# Prodloop Observability SDK
|
|
18
|
+
|
|
19
|
+
Python SDK to evaluate AI voice bot calls through the Prodloop evaluation service.
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install prodloop-observability-sdk
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Quickstart
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from prodloop import ProdloopClient, EvaluationParameter
|
|
31
|
+
|
|
32
|
+
client = ProdloopClient(api_key="sk_live_...")
|
|
33
|
+
|
|
34
|
+
result = client.evaluate_call(
|
|
35
|
+
audio_file_path="call.mp3",
|
|
36
|
+
parameters=[
|
|
37
|
+
EvaluationParameter.E2E_RESPONSE_TIME,
|
|
38
|
+
EvaluationParameter.HALLUCINATION,
|
|
39
|
+
],
|
|
40
|
+
thresholds={"e2e_response_time_max_ms": 800},
|
|
41
|
+
input_prompt="Bot instructions used during this call...",
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
print(result)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Extraction Validation
|
|
48
|
+
|
|
49
|
+
To validate extraction quality, pass both `extraction_schema` and `bot_captured_variables`:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
result = client.evaluate_call(
|
|
53
|
+
audio_file_path="call.mp3",
|
|
54
|
+
parameters=[EvaluationParameter.EXTRACTION_VARIABLES],
|
|
55
|
+
extraction_schema={"customer_name": "string"},
|
|
56
|
+
bot_captured_variables={"customer_name": "ram"},
|
|
57
|
+
)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Response includes:
|
|
61
|
+
|
|
62
|
+
- `extraction_variables`
|
|
63
|
+
- `extraction_validation`
|
|
64
|
+
|
|
65
|
+
## Hallucination Input Requirement
|
|
66
|
+
|
|
67
|
+
When requesting `hallucination`, pass the bot's original call prompt as `input_prompt`:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
result = client.evaluate_call(
|
|
71
|
+
audio_file_path="call.mp3",
|
|
72
|
+
parameters=[EvaluationParameter.HALLUCINATION],
|
|
73
|
+
input_prompt="You are a polite admissions bot. Never invent course details.",
|
|
74
|
+
)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Supported Parameters
|
|
78
|
+
|
|
79
|
+
- `e2e_response_time`
|
|
80
|
+
- `turn_by_turn_latency`
|
|
81
|
+
- `pause_profile`
|
|
82
|
+
- `audio_artifacts`
|
|
83
|
+
- `hallucination`
|
|
84
|
+
- `extraction_variables`
|
|
85
|
+
- `interruption_behavior`
|
|
86
|
+
|
|
87
|
+
## Parameter Purpose
|
|
88
|
+
|
|
89
|
+
- `e2e_response_time`: average response latency in milliseconds.
|
|
90
|
+
- `turn_by_turn_latency`: per-turn latency series with `turn_index` and `latency_ms`.
|
|
91
|
+
- `pause_profile`: deterministic pause summary (`pause_count`, `total_pause_time_ms`, `longest_pause_ms`).
|
|
92
|
+
- `audio_artifacts`: deterministic audio-signal checks (`clipping_ratio`, `dc_offset`, clipping/DC flags).
|
|
93
|
+
- `hallucination`: whether the bot produced fabricated or incorrect claims.
|
|
94
|
+
- `extraction_variables`: structured variable extraction from call audio.
|
|
95
|
+
- `interruption_behavior`: whether the bot handled interruptions gracefully.
|
|
96
|
+
|
|
97
|
+
Deterministic parameters are computed directly from the audio signal:
|
|
98
|
+
`e2e_response_time`, `turn_by_turn_latency`, `pause_profile`, `audio_artifacts`.
|
|
99
|
+
|
|
100
|
+
## Authentication
|
|
101
|
+
|
|
102
|
+
Pass your Prodloop API key in the SDK constructor.
|
|
103
|
+
The SDK sends it as a `Bearer` token in the `Authorization` header.
|
|
104
|
+
|
|
105
|
+
## Errors
|
|
106
|
+
|
|
107
|
+
- `ValidationError`: invalid local inputs (file path, parameters, etc.)
|
|
108
|
+
- `APIError`: backend/API-level failures (`status_code`, `message`)
|
|
109
|
+
|
|
110
|
+
## Documentation Site
|
|
111
|
+
|
|
112
|
+
Live documentation: https://observability-sdk-docs.pages.dev/
|
|
113
|
+
|
|
114
|
+
## Prompt Simulation
|
|
115
|
+
|
|
116
|
+
The SDK can test a bot prompt without an audio file by simulating a text conversation between a tester LLM and your bot.
|
|
117
|
+
|
|
118
|
+
There are two modes:
|
|
119
|
+
|
|
120
|
+
- `self_simulation`: Prodloop backend runs the tester and bot conversation. You select the bot model route, but Prodloop-owned backend credentials are used. No bot credentials are sent from your code.
|
|
121
|
+
- `user_orchestrated`: Prodloop backend runs the tester and grader. Your SDK process runs the bot locally with your own credentials and sends only bot replies/latency back to Prodloop.
|
|
122
|
+
|
|
123
|
+
Simulation currently accepts exactly one parameter per request. To test multiple parameters, start one simulation per parameter. `max_turns` is configurable from `1` to `10`.
|
|
124
|
+
|
|
125
|
+
Discover currently enabled simulation parameters at runtime:
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
params = client.get_simulation_parameters()
|
|
129
|
+
print(params["parameters"]) # [{"key": "hallucination"}, ...]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The response intentionally exposes only public parameter keys. Whether a parameter is LLM-judged or deterministic is backend implementation detail.
|
|
133
|
+
|
|
134
|
+
For prompt simulation, `turn_by_turn_latency` is the only timing parameter exposed. It is also emitted in every simulation result automatically at no extra LLM cost, even when you select another parameter such as `hallucination`. Older audio-evaluation parameters like `e2e_response_time` and `pause_profile` remain relevant for call-audio evaluation, but they are not separate prompt-simulation parameters.
|
|
135
|
+
|
|
136
|
+
### Self Simulation
|
|
137
|
+
|
|
138
|
+
Use the generic LiteLLM connector. The currently supported backend model routes are `vertex_ai/gemini-2.5-pro` for Gemini on Vertex AI and `azure/<deployment-name>` for Azure OpenAI deployments.
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
import os
|
|
142
|
+
import time
|
|
143
|
+
from prodloop import EvaluationParameter, ProdloopClient, SimulationMode, plugins
|
|
144
|
+
|
|
145
|
+
client = ProdloopClient(api_key=os.environ["PRODLOOP_API_KEY"])
|
|
146
|
+
|
|
147
|
+
start = client.simulate_prompt(
|
|
148
|
+
simulation_mode=SimulationMode.SELF_SIMULATION,
|
|
149
|
+
prompt="You are a concise support bot. Do not invent policy details.",
|
|
150
|
+
parameters=[EvaluationParameter.HALLUCINATION],
|
|
151
|
+
bot_llm=plugins.LiteLLM(
|
|
152
|
+
model="vertex_ai/gemini-2.5-pro",
|
|
153
|
+
temperature=0.2,
|
|
154
|
+
max_tokens=512,
|
|
155
|
+
),
|
|
156
|
+
max_turns=5,
|
|
157
|
+
scenario="A customer reports a delayed order and asks about compensation.",
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
chat_id = start["chat_id"]
|
|
161
|
+
print("chat_id:", chat_id)
|
|
162
|
+
|
|
163
|
+
while True:
|
|
164
|
+
result = client.get_simulation(chat_id)
|
|
165
|
+
print(result["status"])
|
|
166
|
+
if result["status"] in {"completed", "failed"}:
|
|
167
|
+
print(result)
|
|
168
|
+
break
|
|
169
|
+
time.sleep(2)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Backend provider configuration is required for `self_simulation`. Examples:
|
|
173
|
+
|
|
174
|
+
- Vertex AI: `VERTEX_PROJECT`, `VERTEX_LOCATION`, and the deployed service account permissions.
|
|
175
|
+
- Azure OpenAI: `AZURE_API_BASE`, `AZURE_API_VERSION`, and `AZURE_API_KEY` or `AZURE_AD_TOKEN`. You can also derive the base URL from a resource name in your own deployment setup.
|
|
176
|
+
|
|
177
|
+
If the backend is not configured for the selected route, the API returns a safe user-facing error asking you to configure provider credentials or use `user_orchestrated` mode.
|
|
178
|
+
|
|
179
|
+
### User Orchestrated Simulation
|
|
180
|
+
|
|
181
|
+
Use `user_orchestrated` when the bot must run in your own process with your own credentials. Prodloop never receives your bot provider credentials.
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
import os
|
|
185
|
+
from prodloop import EvaluationParameter, ProdloopClient, SimulationMode, plugins
|
|
186
|
+
|
|
187
|
+
bot = plugins.LiteLLMBot(
|
|
188
|
+
model="azure/<deployment-name>",
|
|
189
|
+
system_prompt="You are a concise support bot. Do not invent policy details.",
|
|
190
|
+
options={"temperature": 0.2, "max_tokens": 256},
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
client = ProdloopClient(api_key=os.environ["PRODLOOP_API_KEY"])
|
|
194
|
+
|
|
195
|
+
result = client.simulate_prompt(
|
|
196
|
+
simulation_mode=SimulationMode.USER_ORCHESTRATED,
|
|
197
|
+
prompt="You are a concise support bot. Do not invent policy details.",
|
|
198
|
+
parameters=[EvaluationParameter.HALLUCINATION],
|
|
199
|
+
max_turns=5,
|
|
200
|
+
scenario="A customer pressures the bot to confirm a fake policy.",
|
|
201
|
+
bot_turn_handler=bot,
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
print(result)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
For `user_orchestrated`, configure bot credentials locally for either Vertex AI or Azure OpenAI. For Vertex AI, use ADC/service-account configuration and project/location. For Azure OpenAI, use your Azure endpoint, API version, and API key/token locally. The SDK sends only bot response text and bot LLM processing latency to Prodloop.
|
|
208
|
+
|
|
209
|
+
### Result Shape
|
|
210
|
+
|
|
211
|
+
Simulation responses include:
|
|
212
|
+
|
|
213
|
+
- `chat_id`: stable simulation identifier.
|
|
214
|
+
- `status`: `running`, `completed`, or `failed`.
|
|
215
|
+
- `turns`: tester message, bot response, `turn_id`, grading result, and per-turn timing.
|
|
216
|
+
- `final_result`: overall pass/fail, per-parameter result, summary, and prompt patch suggestions when a test fails.
|
|
217
|
+
|
|
218
|
+
If a parameter fails, `final_result.parameter_results[*].prompt_patch_lines` and `prompt_patch_location` provide copy-paste prompt guidance.
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
## Credit Balance
|
|
223
|
+
|
|
224
|
+
Check the credits left on the API key without running an evaluation:
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
balance = client.get_credit_balance()
|
|
228
|
+
print(balance["credits_remaining"])
|
|
229
|
+
|
|
230
|
+
# Alias with the same response
|
|
231
|
+
balance = client.get_credits_remaining()
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
This endpoint authenticates the API key but does not debit credits.
|
|
@@ -0,0 +1,218 @@
|
|
|
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
|
+
input_prompt="Bot instructions used during this call...",
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
print(result)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Extraction Validation
|
|
32
|
+
|
|
33
|
+
To validate extraction quality, pass both `extraction_schema` and `bot_captured_variables`:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
result = client.evaluate_call(
|
|
37
|
+
audio_file_path="call.mp3",
|
|
38
|
+
parameters=[EvaluationParameter.EXTRACTION_VARIABLES],
|
|
39
|
+
extraction_schema={"customer_name": "string"},
|
|
40
|
+
bot_captured_variables={"customer_name": "ram"},
|
|
41
|
+
)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Response includes:
|
|
45
|
+
|
|
46
|
+
- `extraction_variables`
|
|
47
|
+
- `extraction_validation`
|
|
48
|
+
|
|
49
|
+
## Hallucination Input Requirement
|
|
50
|
+
|
|
51
|
+
When requesting `hallucination`, pass the bot's original call prompt as `input_prompt`:
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
result = client.evaluate_call(
|
|
55
|
+
audio_file_path="call.mp3",
|
|
56
|
+
parameters=[EvaluationParameter.HALLUCINATION],
|
|
57
|
+
input_prompt="You are a polite admissions bot. Never invent course details.",
|
|
58
|
+
)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Supported Parameters
|
|
62
|
+
|
|
63
|
+
- `e2e_response_time`
|
|
64
|
+
- `turn_by_turn_latency`
|
|
65
|
+
- `pause_profile`
|
|
66
|
+
- `audio_artifacts`
|
|
67
|
+
- `hallucination`
|
|
68
|
+
- `extraction_variables`
|
|
69
|
+
- `interruption_behavior`
|
|
70
|
+
|
|
71
|
+
## Parameter Purpose
|
|
72
|
+
|
|
73
|
+
- `e2e_response_time`: average response latency in milliseconds.
|
|
74
|
+
- `turn_by_turn_latency`: per-turn latency series with `turn_index` and `latency_ms`.
|
|
75
|
+
- `pause_profile`: deterministic pause summary (`pause_count`, `total_pause_time_ms`, `longest_pause_ms`).
|
|
76
|
+
- `audio_artifacts`: deterministic audio-signal checks (`clipping_ratio`, `dc_offset`, clipping/DC flags).
|
|
77
|
+
- `hallucination`: whether the bot produced fabricated or incorrect claims.
|
|
78
|
+
- `extraction_variables`: structured variable extraction from call audio.
|
|
79
|
+
- `interruption_behavior`: whether the bot handled interruptions gracefully.
|
|
80
|
+
|
|
81
|
+
Deterministic parameters are computed directly from the audio signal:
|
|
82
|
+
`e2e_response_time`, `turn_by_turn_latency`, `pause_profile`, `audio_artifacts`.
|
|
83
|
+
|
|
84
|
+
## Authentication
|
|
85
|
+
|
|
86
|
+
Pass your Prodloop API key in the SDK constructor.
|
|
87
|
+
The SDK sends it as a `Bearer` token in the `Authorization` header.
|
|
88
|
+
|
|
89
|
+
## Errors
|
|
90
|
+
|
|
91
|
+
- `ValidationError`: invalid local inputs (file path, parameters, etc.)
|
|
92
|
+
- `APIError`: backend/API-level failures (`status_code`, `message`)
|
|
93
|
+
|
|
94
|
+
## Documentation Site
|
|
95
|
+
|
|
96
|
+
Live documentation: https://observability-sdk-docs.pages.dev/
|
|
97
|
+
|
|
98
|
+
## Prompt Simulation
|
|
99
|
+
|
|
100
|
+
The SDK can test a bot prompt without an audio file by simulating a text conversation between a tester LLM and your bot.
|
|
101
|
+
|
|
102
|
+
There are two modes:
|
|
103
|
+
|
|
104
|
+
- `self_simulation`: Prodloop backend runs the tester and bot conversation. You select the bot model route, but Prodloop-owned backend credentials are used. No bot credentials are sent from your code.
|
|
105
|
+
- `user_orchestrated`: Prodloop backend runs the tester and grader. Your SDK process runs the bot locally with your own credentials and sends only bot replies/latency back to Prodloop.
|
|
106
|
+
|
|
107
|
+
Simulation currently accepts exactly one parameter per request. To test multiple parameters, start one simulation per parameter. `max_turns` is configurable from `1` to `10`.
|
|
108
|
+
|
|
109
|
+
Discover currently enabled simulation parameters at runtime:
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
params = client.get_simulation_parameters()
|
|
113
|
+
print(params["parameters"]) # [{"key": "hallucination"}, ...]
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The response intentionally exposes only public parameter keys. Whether a parameter is LLM-judged or deterministic is backend implementation detail.
|
|
117
|
+
|
|
118
|
+
For prompt simulation, `turn_by_turn_latency` is the only timing parameter exposed. It is also emitted in every simulation result automatically at no extra LLM cost, even when you select another parameter such as `hallucination`. Older audio-evaluation parameters like `e2e_response_time` and `pause_profile` remain relevant for call-audio evaluation, but they are not separate prompt-simulation parameters.
|
|
119
|
+
|
|
120
|
+
### Self Simulation
|
|
121
|
+
|
|
122
|
+
Use the generic LiteLLM connector. The currently supported backend model routes are `vertex_ai/gemini-2.5-pro` for Gemini on Vertex AI and `azure/<deployment-name>` for Azure OpenAI deployments.
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
import os
|
|
126
|
+
import time
|
|
127
|
+
from prodloop import EvaluationParameter, ProdloopClient, SimulationMode, plugins
|
|
128
|
+
|
|
129
|
+
client = ProdloopClient(api_key=os.environ["PRODLOOP_API_KEY"])
|
|
130
|
+
|
|
131
|
+
start = client.simulate_prompt(
|
|
132
|
+
simulation_mode=SimulationMode.SELF_SIMULATION,
|
|
133
|
+
prompt="You are a concise support bot. Do not invent policy details.",
|
|
134
|
+
parameters=[EvaluationParameter.HALLUCINATION],
|
|
135
|
+
bot_llm=plugins.LiteLLM(
|
|
136
|
+
model="vertex_ai/gemini-2.5-pro",
|
|
137
|
+
temperature=0.2,
|
|
138
|
+
max_tokens=512,
|
|
139
|
+
),
|
|
140
|
+
max_turns=5,
|
|
141
|
+
scenario="A customer reports a delayed order and asks about compensation.",
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
chat_id = start["chat_id"]
|
|
145
|
+
print("chat_id:", chat_id)
|
|
146
|
+
|
|
147
|
+
while True:
|
|
148
|
+
result = client.get_simulation(chat_id)
|
|
149
|
+
print(result["status"])
|
|
150
|
+
if result["status"] in {"completed", "failed"}:
|
|
151
|
+
print(result)
|
|
152
|
+
break
|
|
153
|
+
time.sleep(2)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Backend provider configuration is required for `self_simulation`. Examples:
|
|
157
|
+
|
|
158
|
+
- Vertex AI: `VERTEX_PROJECT`, `VERTEX_LOCATION`, and the deployed service account permissions.
|
|
159
|
+
- Azure OpenAI: `AZURE_API_BASE`, `AZURE_API_VERSION`, and `AZURE_API_KEY` or `AZURE_AD_TOKEN`. You can also derive the base URL from a resource name in your own deployment setup.
|
|
160
|
+
|
|
161
|
+
If the backend is not configured for the selected route, the API returns a safe user-facing error asking you to configure provider credentials or use `user_orchestrated` mode.
|
|
162
|
+
|
|
163
|
+
### User Orchestrated Simulation
|
|
164
|
+
|
|
165
|
+
Use `user_orchestrated` when the bot must run in your own process with your own credentials. Prodloop never receives your bot provider credentials.
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
import os
|
|
169
|
+
from prodloop import EvaluationParameter, ProdloopClient, SimulationMode, plugins
|
|
170
|
+
|
|
171
|
+
bot = plugins.LiteLLMBot(
|
|
172
|
+
model="azure/<deployment-name>",
|
|
173
|
+
system_prompt="You are a concise support bot. Do not invent policy details.",
|
|
174
|
+
options={"temperature": 0.2, "max_tokens": 256},
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
client = ProdloopClient(api_key=os.environ["PRODLOOP_API_KEY"])
|
|
178
|
+
|
|
179
|
+
result = client.simulate_prompt(
|
|
180
|
+
simulation_mode=SimulationMode.USER_ORCHESTRATED,
|
|
181
|
+
prompt="You are a concise support bot. Do not invent policy details.",
|
|
182
|
+
parameters=[EvaluationParameter.HALLUCINATION],
|
|
183
|
+
max_turns=5,
|
|
184
|
+
scenario="A customer pressures the bot to confirm a fake policy.",
|
|
185
|
+
bot_turn_handler=bot,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
print(result)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
For `user_orchestrated`, configure bot credentials locally for either Vertex AI or Azure OpenAI. For Vertex AI, use ADC/service-account configuration and project/location. For Azure OpenAI, use your Azure endpoint, API version, and API key/token locally. The SDK sends only bot response text and bot LLM processing latency to Prodloop.
|
|
192
|
+
|
|
193
|
+
### Result Shape
|
|
194
|
+
|
|
195
|
+
Simulation responses include:
|
|
196
|
+
|
|
197
|
+
- `chat_id`: stable simulation identifier.
|
|
198
|
+
- `status`: `running`, `completed`, or `failed`.
|
|
199
|
+
- `turns`: tester message, bot response, `turn_id`, grading result, and per-turn timing.
|
|
200
|
+
- `final_result`: overall pass/fail, per-parameter result, summary, and prompt patch suggestions when a test fails.
|
|
201
|
+
|
|
202
|
+
If a parameter fails, `final_result.parameter_results[*].prompt_patch_lines` and `prompt_patch_location` provide copy-paste prompt guidance.
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
## Credit Balance
|
|
207
|
+
|
|
208
|
+
Check the credits left on the API key without running an evaluation:
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
balance = client.get_credit_balance()
|
|
212
|
+
print(balance["credits_remaining"])
|
|
213
|
+
|
|
214
|
+
# Alias with the same response
|
|
215
|
+
balance = client.get_credits_remaining()
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
This endpoint authenticates the API key but does not debit credits.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import prodloop.plugins as plugins
|
|
2
|
+
from prodloop.client import ProdloopClient
|
|
3
|
+
from prodloop.exceptions import APIError, ProdloopError, ValidationError
|
|
4
|
+
from prodloop.models import (
|
|
5
|
+
BotLLMConnection,
|
|
6
|
+
EvaluationParameter,
|
|
7
|
+
SimulationMode,
|
|
8
|
+
)
|
|
9
|
+
from prodloop.plugins import LiteLLM, LiteLLMBot
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"ProdloopClient",
|
|
13
|
+
"BotLLMConnection",
|
|
14
|
+
"LiteLLM",
|
|
15
|
+
"LiteLLMBot",
|
|
16
|
+
"EvaluationParameter",
|
|
17
|
+
"SimulationMode",
|
|
18
|
+
"plugins",
|
|
19
|
+
"ProdloopError",
|
|
20
|
+
"ValidationError",
|
|
21
|
+
"APIError",
|
|
22
|
+
]
|