enprompta 1.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.
Potentially problematic release.
This version of enprompta might be problematic. Click here for more details.
- enprompta-1.0.0/.gitignore +61 -0
- enprompta-1.0.0/PKG-INFO +388 -0
- enprompta-1.0.0/README.md +354 -0
- enprompta-1.0.0/enprompta/__init__.py +103 -0
- enprompta-1.0.0/enprompta/client.py +355 -0
- enprompta-1.0.0/enprompta/decorators.py +515 -0
- enprompta-1.0.0/enprompta/exceptions.py +132 -0
- enprompta-1.0.0/enprompta/middleware/__init__.py +78 -0
- enprompta-1.0.0/enprompta/middleware/base.py +164 -0
- enprompta-1.0.0/enprompta/middleware/logging.py +212 -0
- enprompta-1.0.0/enprompta/resources/__init__.py +19 -0
- enprompta-1.0.0/enprompta/resources/executions.py +110 -0
- enprompta-1.0.0/enprompta/resources/prompts.py +219 -0
- enprompta-1.0.0/enprompta/resources/teams.py +107 -0
- enprompta-1.0.0/enprompta/resources/templates.py +65 -0
- enprompta-1.0.0/enprompta/resources/traces.py +555 -0
- enprompta-1.0.0/enprompta/resources/webhooks.py +156 -0
- enprompta-1.0.0/enprompta/types.py +518 -0
- enprompta-1.0.0/pyproject.toml +67 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
2
|
+
|
|
3
|
+
# dependencies
|
|
4
|
+
/node_modules
|
|
5
|
+
/.pnp
|
|
6
|
+
.pnp.*
|
|
7
|
+
.yarn/*
|
|
8
|
+
!.yarn/patches
|
|
9
|
+
!.yarn/plugins
|
|
10
|
+
!.yarn/releases
|
|
11
|
+
!.yarn/versions
|
|
12
|
+
|
|
13
|
+
# testing
|
|
14
|
+
/coverage
|
|
15
|
+
|
|
16
|
+
# next.js
|
|
17
|
+
/.next/
|
|
18
|
+
/out/
|
|
19
|
+
|
|
20
|
+
# production
|
|
21
|
+
/build
|
|
22
|
+
|
|
23
|
+
# misc
|
|
24
|
+
.DS_Store
|
|
25
|
+
*.pem
|
|
26
|
+
nul
|
|
27
|
+
|
|
28
|
+
# debug
|
|
29
|
+
npm-debug.log*
|
|
30
|
+
yarn-debug.log*
|
|
31
|
+
yarn-error.log*
|
|
32
|
+
.pnpm-debug.log*
|
|
33
|
+
|
|
34
|
+
# env files (can opt-in for committing if needed)
|
|
35
|
+
.env*
|
|
36
|
+
|
|
37
|
+
# vercel
|
|
38
|
+
.vercel
|
|
39
|
+
|
|
40
|
+
# typescript
|
|
41
|
+
*.tsbuildinfo
|
|
42
|
+
next-env.d.ts
|
|
43
|
+
|
|
44
|
+
/src/generated/prisma
|
|
45
|
+
|
|
46
|
+
.vercel
|
|
47
|
+
.env*.local
|
|
48
|
+
|
|
49
|
+
.vercel
|
|
50
|
+
node_modules/
|
|
51
|
+
dist/
|
|
52
|
+
.next/
|
|
53
|
+
playwright-report/
|
|
54
|
+
test-results/
|
|
55
|
+
# Visual-regression baselines are tracked — they ARE the test contract.
|
|
56
|
+
# Only the captured-actual screenshots from a failed run live in test-results/.
|
|
57
|
+
*.zip
|
|
58
|
+
__pycache__/
|
|
59
|
+
*.pyc
|
|
60
|
+
temp_ext/
|
|
61
|
+
temp_extension/
|
enprompta-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: enprompta
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Official Python SDK for the Enprompta API
|
|
5
|
+
Project-URL: Homepage, https://enprompta.com
|
|
6
|
+
Project-URL: Documentation, https://enprompta.com/docs/sdk/python
|
|
7
|
+
Project-URL: Repository, https://github.com/igwebupower/enprompta
|
|
8
|
+
Project-URL: Issues, https://github.com/igwebupower/enprompta/issues
|
|
9
|
+
Author-email: Enprompta <support@enprompta.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
Keywords: ai,api,enprompta,llm,prompts,sdk
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Requires-Dist: httpx>=0.25.0
|
|
26
|
+
Requires-Dist: pydantic>=2.0.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-httpx>=0.21.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# enprompta
|
|
36
|
+
|
|
37
|
+
Official Python SDK for the Enprompta API.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install enprompta
|
|
43
|
+
# or
|
|
44
|
+
poetry add enprompta
|
|
45
|
+
# or
|
|
46
|
+
pipenv install enprompta
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Requirements
|
|
50
|
+
|
|
51
|
+
- Python 3.8+
|
|
52
|
+
- httpx 0.25+
|
|
53
|
+
- pydantic 2.0+
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
import asyncio
|
|
59
|
+
from enprompta import Enprompta
|
|
60
|
+
|
|
61
|
+
async def main():
|
|
62
|
+
# Initialize with API key
|
|
63
|
+
client = Enprompta(api_key="ep_your_api_key")
|
|
64
|
+
|
|
65
|
+
# List prompts
|
|
66
|
+
prompts = await client.prompts.list()
|
|
67
|
+
for prompt in prompts.data:
|
|
68
|
+
print(prompt.title)
|
|
69
|
+
|
|
70
|
+
# Create a prompt
|
|
71
|
+
prompt = await client.prompts.create(
|
|
72
|
+
title="Email Writer",
|
|
73
|
+
content="Write a professional email about {{topic}}",
|
|
74
|
+
visibility="PRIVATE"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# Execute a prompt
|
|
78
|
+
result = await client.prompts.execute(
|
|
79
|
+
prompt.id,
|
|
80
|
+
variables={"topic": "project update"},
|
|
81
|
+
provider="openai",
|
|
82
|
+
model="gpt-4"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
print(result.output)
|
|
86
|
+
|
|
87
|
+
asyncio.run(main())
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Authentication
|
|
91
|
+
|
|
92
|
+
### API Key
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from enprompta import Enprompta
|
|
96
|
+
|
|
97
|
+
client = Enprompta(api_key="ep_your_api_key")
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### OAuth2 Client Credentials
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
client = Enprompta(
|
|
104
|
+
client_id="your_client_id",
|
|
105
|
+
client_secret="your_client_secret",
|
|
106
|
+
scopes=["prompts:read", "prompts:write"]
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Environment Variables
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
# Set these environment variables:
|
|
114
|
+
# ENPROMPTA_API_KEY
|
|
115
|
+
# ENPROMPTA_CLIENT_ID
|
|
116
|
+
# ENPROMPTA_CLIENT_SECRET
|
|
117
|
+
|
|
118
|
+
client = Enprompta() # Auto-reads from environment
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Features
|
|
122
|
+
|
|
123
|
+
### Prompts
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
# List with pagination
|
|
127
|
+
response = await client.prompts.list(limit=20, visibility="PRIVATE")
|
|
128
|
+
for prompt in response.data:
|
|
129
|
+
print(prompt.title)
|
|
130
|
+
|
|
131
|
+
# Auto-pagination
|
|
132
|
+
async for prompt in client.prompts.list_all():
|
|
133
|
+
print(prompt.title)
|
|
134
|
+
|
|
135
|
+
# Create
|
|
136
|
+
prompt = await client.prompts.create(
|
|
137
|
+
title="My Prompt",
|
|
138
|
+
content="Hello {{name}}",
|
|
139
|
+
variables=[{"name": "name", "type": "text", "required": True}]
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# Get
|
|
143
|
+
prompt = await client.prompts.get("prompt_id")
|
|
144
|
+
|
|
145
|
+
# Update
|
|
146
|
+
await client.prompts.update("prompt_id", title="New Title")
|
|
147
|
+
|
|
148
|
+
# Delete
|
|
149
|
+
await client.prompts.delete("prompt_id")
|
|
150
|
+
|
|
151
|
+
# Execute
|
|
152
|
+
result = await client.prompts.execute(
|
|
153
|
+
"prompt_id",
|
|
154
|
+
variables={"name": "World"},
|
|
155
|
+
provider="openai",
|
|
156
|
+
model="gpt-4"
|
|
157
|
+
)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Executions
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
# List executions
|
|
164
|
+
response = await client.executions.list(
|
|
165
|
+
prompt_id="prompt_id",
|
|
166
|
+
start_date="2024-01-01"
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
# Get statistics
|
|
170
|
+
stats = await client.executions.get_stats(group_by="day")
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Teams
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
teams = await client.teams.list()
|
|
177
|
+
team = await client.teams.create(name="Engineering")
|
|
178
|
+
await client.teams.update("team_id", name="New Name")
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Webhooks
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
webhook = await client.webhooks.create(
|
|
185
|
+
name="My Webhook",
|
|
186
|
+
url="https://example.com/webhook",
|
|
187
|
+
events=["prompt.created", "execution.completed"]
|
|
188
|
+
)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Synchronous Client
|
|
192
|
+
|
|
193
|
+
For non-async code:
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
from enprompta import EnpromptaSync
|
|
197
|
+
|
|
198
|
+
client = EnpromptaSync(api_key="ep_your_api_key")
|
|
199
|
+
|
|
200
|
+
# All methods work without await
|
|
201
|
+
prompts = client.prompts.list()
|
|
202
|
+
prompt = client.prompts.create(title="My Prompt", content="Hello")
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Context Manager
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
# Async
|
|
209
|
+
async with Enprompta(api_key="ep_your_api_key") as client:
|
|
210
|
+
prompts = await client.prompts.list()
|
|
211
|
+
|
|
212
|
+
# Sync
|
|
213
|
+
with EnpromptaSync(api_key="ep_your_api_key") as client:
|
|
214
|
+
prompts = client.prompts.list()
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Error Handling
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
from enprompta.exceptions import (
|
|
221
|
+
EnpromptaError,
|
|
222
|
+
AuthenticationError,
|
|
223
|
+
RateLimitError,
|
|
224
|
+
ValidationError,
|
|
225
|
+
NotFoundError
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
try:
|
|
229
|
+
await client.prompts.get("invalid_id")
|
|
230
|
+
except NotFoundError:
|
|
231
|
+
print("Prompt not found")
|
|
232
|
+
except RateLimitError as e:
|
|
233
|
+
print(f"Retry after {e.retry_after}s")
|
|
234
|
+
except EnpromptaError as e:
|
|
235
|
+
print(f"Error {e.code}: {e.message}")
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## LLM Observability & Tracing
|
|
239
|
+
|
|
240
|
+
### @trace Decorator
|
|
241
|
+
|
|
242
|
+
Automatically trace any LLM function with the `@trace` decorator:
|
|
243
|
+
|
|
244
|
+
```python
|
|
245
|
+
from enprompta import Enprompta, trace
|
|
246
|
+
import openai
|
|
247
|
+
|
|
248
|
+
client = Enprompta(api_key="ep_your_api_key")
|
|
249
|
+
|
|
250
|
+
@trace(client, provider="openai", model="gpt-4")
|
|
251
|
+
def generate_response(prompt: str) -> str:
|
|
252
|
+
response = openai.chat.completions.create(
|
|
253
|
+
model="gpt-4",
|
|
254
|
+
messages=[{"role": "user", "content": prompt}]
|
|
255
|
+
)
|
|
256
|
+
return response.choices[0].message.content
|
|
257
|
+
|
|
258
|
+
# Traces are automatically recorded with timing, tokens, and cost
|
|
259
|
+
result = generate_response("Explain quantum computing")
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Async Support
|
|
263
|
+
|
|
264
|
+
```python
|
|
265
|
+
@trace(client, provider="anthropic", model="claude-3-sonnet", session_id="user-123")
|
|
266
|
+
async def async_chat(prompt: str) -> str:
|
|
267
|
+
response = await anthropic.messages.create(
|
|
268
|
+
model="claude-3-sonnet-20240229",
|
|
269
|
+
messages=[{"role": "user", "content": prompt}]
|
|
270
|
+
)
|
|
271
|
+
return response.content[0].text
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Auto-traced OpenAI Client
|
|
275
|
+
|
|
276
|
+
Wrap your OpenAI client for zero-code tracing:
|
|
277
|
+
|
|
278
|
+
```python
|
|
279
|
+
from enprompta import Enprompta, traced_openai
|
|
280
|
+
from openai import OpenAI
|
|
281
|
+
|
|
282
|
+
enprompta = Enprompta(api_key="ep_...")
|
|
283
|
+
openai = traced_openai(enprompta, OpenAI())
|
|
284
|
+
|
|
285
|
+
# All calls are now automatically traced!
|
|
286
|
+
response = openai.chat.completions.create(
|
|
287
|
+
model="gpt-4",
|
|
288
|
+
messages=[{"role": "user", "content": "Hello"}]
|
|
289
|
+
)
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Context Manager (Manual Tracing)
|
|
293
|
+
|
|
294
|
+
For more control, use the context manager:
|
|
295
|
+
|
|
296
|
+
```python
|
|
297
|
+
with client.traces.wrap(
|
|
298
|
+
provider="openai",
|
|
299
|
+
model="gpt-4",
|
|
300
|
+
input="Hello"
|
|
301
|
+
) as ctx:
|
|
302
|
+
response = openai.chat.completions.create(
|
|
303
|
+
model="gpt-4",
|
|
304
|
+
messages=[{"role": "user", "content": "Hello"}]
|
|
305
|
+
)
|
|
306
|
+
ctx.set_output(
|
|
307
|
+
output=response.choices[0].message.content,
|
|
308
|
+
input_tokens=response.usage.prompt_tokens,
|
|
309
|
+
output_tokens=response.usage.completion_tokens
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
print(f"Trace ID: {ctx.trace_id}")
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Nested Spans for Complex Pipelines
|
|
316
|
+
|
|
317
|
+
Track multi-step operations like RAG:
|
|
318
|
+
|
|
319
|
+
```python
|
|
320
|
+
# Record the main trace
|
|
321
|
+
result = client.traces.record(
|
|
322
|
+
provider="openai",
|
|
323
|
+
model="gpt-4",
|
|
324
|
+
input="What are our refund policies?",
|
|
325
|
+
output="Based on our documentation...",
|
|
326
|
+
latency_ms=2500
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
# Add spans for each step
|
|
330
|
+
client.traces.create_span(
|
|
331
|
+
result["trace_id"],
|
|
332
|
+
name="vector_search",
|
|
333
|
+
span_type=SpanType.RETRIEVAL,
|
|
334
|
+
input={"query": "refund policies", "top_k": 5},
|
|
335
|
+
output={"document_ids": ["doc1", "doc2"]},
|
|
336
|
+
duration_ms=150
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
client.traces.create_span(
|
|
340
|
+
result["trace_id"],
|
|
341
|
+
name="embedding",
|
|
342
|
+
span_type=SpanType.EMBEDDING,
|
|
343
|
+
tokens=8,
|
|
344
|
+
duration_ms=50
|
|
345
|
+
)
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
## Webhook Signature Verification
|
|
349
|
+
|
|
350
|
+
```python
|
|
351
|
+
from enprompta.webhooks import verify_signature
|
|
352
|
+
|
|
353
|
+
# In your webhook handler (FastAPI example)
|
|
354
|
+
@app.post("/webhooks/enprompta")
|
|
355
|
+
async def handle_webhook(request: Request):
|
|
356
|
+
payload = await request.body()
|
|
357
|
+
signature = request.headers.get("X-Enprompta-Signature")
|
|
358
|
+
|
|
359
|
+
if not verify_signature(payload, signature, webhook_secret):
|
|
360
|
+
raise HTTPException(status_code=401)
|
|
361
|
+
|
|
362
|
+
event = json.loads(payload)
|
|
363
|
+
print(f"Received: {event['event']}")
|
|
364
|
+
return {"status": "ok"}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Type Hints
|
|
368
|
+
|
|
369
|
+
Full type hint support:
|
|
370
|
+
|
|
371
|
+
```python
|
|
372
|
+
from enprompta.types import (
|
|
373
|
+
Prompt,
|
|
374
|
+
Execution,
|
|
375
|
+
Team,
|
|
376
|
+
Webhook,
|
|
377
|
+
CreatePromptParams,
|
|
378
|
+
ExecutePromptParams
|
|
379
|
+
)
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
## Documentation
|
|
383
|
+
|
|
384
|
+
Full documentation: https://enprompta.com/docs/sdk/python
|
|
385
|
+
|
|
386
|
+
## License
|
|
387
|
+
|
|
388
|
+
MIT
|