epi-recorder 1.0.0__py3-none-any.whl → 1.1.0__py3-none-any.whl
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.
- epi_cli/keys.py +3 -3
- epi_cli/ls.py +160 -0
- epi_cli/main.py +73 -8
- epi_cli/record.py +10 -3
- epi_cli/run.py +318 -0
- epi_cli/verify.py +20 -20
- epi_cli/view.py +68 -13
- epi_core/redactor.py +14 -1
- epi_core/schemas.py +34 -3
- epi_recorder/api.py +217 -20
- epi_recorder/environment.py +21 -0
- epi_recorder/patcher.py +88 -7
- epi_recorder-1.1.0.dist-info/METADATA +569 -0
- epi_recorder-1.1.0.dist-info/RECORD +27 -0
- epi_viewer_static/app.js +77 -1
- epi_recorder-1.0.0.dist-info/METADATA +0 -503
- epi_recorder-1.0.0.dist-info/RECORD +0 -25
- {epi_recorder-1.0.0.dist-info → epi_recorder-1.1.0.dist-info}/WHEEL +0 -0
- {epi_recorder-1.0.0.dist-info → epi_recorder-1.1.0.dist-info}/entry_points.txt +0 -0
- {epi_recorder-1.0.0.dist-info → epi_recorder-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {epi_recorder-1.0.0.dist-info → epi_recorder-1.1.0.dist-info}/top_level.txt +0 -0
epi_recorder/environment.py
CHANGED
|
@@ -214,3 +214,24 @@ def get_environment_summary() -> str:
|
|
|
214
214
|
lines.append(f"Working Directory: {env['working_directory']['path']}")
|
|
215
215
|
|
|
216
216
|
return "\n".join(lines)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
# Backward compatibility alias
|
|
220
|
+
def capture_environment(
|
|
221
|
+
include_all_env_vars: bool = False,
|
|
222
|
+
redact_env_vars: bool = True
|
|
223
|
+
) -> Dict[str, Any]:
|
|
224
|
+
"""
|
|
225
|
+
Alias for capture_full_environment for backward compatibility.
|
|
226
|
+
|
|
227
|
+
Args:
|
|
228
|
+
include_all_env_vars: Whether to include all environment variables
|
|
229
|
+
redact_env_vars: Whether to redact sensitive env vars
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
dict: Complete environment snapshot
|
|
233
|
+
"""
|
|
234
|
+
return capture_full_environment(
|
|
235
|
+
include_all_env_vars=include_all_env_vars,
|
|
236
|
+
redact_env_vars=redact_env_vars
|
|
237
|
+
)
|
epi_recorder/patcher.py
CHANGED
|
@@ -32,7 +32,7 @@ class RecordingContext:
|
|
|
32
32
|
enable_redaction: Whether to redact secrets (default: True)
|
|
33
33
|
"""
|
|
34
34
|
self.output_dir = output_dir
|
|
35
|
-
self.steps: List[StepModel] = []
|
|
35
|
+
# self.steps: List[StepModel] = [] # Removed for scalability
|
|
36
36
|
self.step_index = 0
|
|
37
37
|
self.enable_redaction = enable_redaction
|
|
38
38
|
self.redactor = get_default_redactor() if enable_redaction else None
|
|
@@ -83,8 +83,8 @@ class RecordingContext:
|
|
|
83
83
|
# Write to file
|
|
84
84
|
self._write_step(step)
|
|
85
85
|
|
|
86
|
-
# Store in memory
|
|
87
|
-
self.steps.append(step)
|
|
86
|
+
# Store in memory - REMOVED for scalability
|
|
87
|
+
# self.steps.append(step)
|
|
88
88
|
self.step_index += 1
|
|
89
89
|
|
|
90
90
|
def _write_step(self, step: StepModel) -> None:
|
|
@@ -325,9 +325,91 @@ def _patch_openai_legacy() -> bool:
|
|
|
325
325
|
return False
|
|
326
326
|
|
|
327
327
|
|
|
328
|
+
return results
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def patch_requests() -> bool:
|
|
332
|
+
"""
|
|
333
|
+
Patch the requests library to intercept all HTTP calls.
|
|
334
|
+
|
|
335
|
+
Returns:
|
|
336
|
+
bool: True if patching succeeded, False otherwise
|
|
337
|
+
"""
|
|
338
|
+
try:
|
|
339
|
+
import requests
|
|
340
|
+
from requests.sessions import Session
|
|
341
|
+
|
|
342
|
+
# Store original method
|
|
343
|
+
original_request = Session.request
|
|
344
|
+
|
|
345
|
+
@wraps(original_request)
|
|
346
|
+
def wrapped_request(self, method, url, *args, **kwargs):
|
|
347
|
+
"""Wrapped requests.Session.request with recording."""
|
|
348
|
+
|
|
349
|
+
# Only record if context is active
|
|
350
|
+
if not is_recording():
|
|
351
|
+
return original_request(self, method, url, *args, **kwargs)
|
|
352
|
+
|
|
353
|
+
context = get_recording_context()
|
|
354
|
+
start_time = time.time()
|
|
355
|
+
|
|
356
|
+
# Capture request
|
|
357
|
+
# We don't capture full body by default to avoid massive logs,
|
|
358
|
+
# but we capture metadata
|
|
359
|
+
request_data = {
|
|
360
|
+
"provider": "http",
|
|
361
|
+
"method": method,
|
|
362
|
+
"url": url,
|
|
363
|
+
"headers": dict(kwargs.get("headers", {})),
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
# Log request step
|
|
367
|
+
context.add_step("http.request", request_data)
|
|
368
|
+
|
|
369
|
+
# Execute original call
|
|
370
|
+
try:
|
|
371
|
+
response = original_request(self, method, url, *args, **kwargs)
|
|
372
|
+
elapsed = time.time() - start_time
|
|
373
|
+
|
|
374
|
+
# Capture response
|
|
375
|
+
response_data = {
|
|
376
|
+
"provider": "http",
|
|
377
|
+
"status_code": response.status_code,
|
|
378
|
+
"reason": response.reason,
|
|
379
|
+
"url": response.url,
|
|
380
|
+
"headers": dict(response.headers),
|
|
381
|
+
"latency_seconds": round(elapsed, 3)
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
# Log response step
|
|
385
|
+
context.add_step("http.response", response_data)
|
|
386
|
+
|
|
387
|
+
return response
|
|
388
|
+
|
|
389
|
+
except Exception as e:
|
|
390
|
+
# Log error step
|
|
391
|
+
context.add_step("http.error", {
|
|
392
|
+
"provider": "http",
|
|
393
|
+
"error": str(e),
|
|
394
|
+
"error_type": type(e).__name__,
|
|
395
|
+
"url": url
|
|
396
|
+
})
|
|
397
|
+
raise
|
|
398
|
+
|
|
399
|
+
# Apply patch
|
|
400
|
+
Session.request = wrapped_request
|
|
401
|
+
return True
|
|
402
|
+
|
|
403
|
+
except ImportError:
|
|
404
|
+
return False
|
|
405
|
+
except Exception as e:
|
|
406
|
+
print(f"Warning: Failed to patch requests: {e}")
|
|
407
|
+
return False
|
|
408
|
+
|
|
409
|
+
|
|
328
410
|
def patch_all() -> Dict[str, bool]:
|
|
329
411
|
"""
|
|
330
|
-
Patch all supported LLM providers.
|
|
412
|
+
Patch all supported LLM providers and HTTP libraries.
|
|
331
413
|
|
|
332
414
|
Returns:
|
|
333
415
|
dict: Provider name -> success status
|
|
@@ -337,9 +419,8 @@ def patch_all() -> Dict[str, bool]:
|
|
|
337
419
|
# Patch OpenAI
|
|
338
420
|
results["openai"] = patch_openai()
|
|
339
421
|
|
|
340
|
-
#
|
|
341
|
-
|
|
342
|
-
# results["gemini"] = patch_gemini()
|
|
422
|
+
# Patch generic requests (covers LangChain, Anthropic, etc.)
|
|
423
|
+
results["requests"] = patch_requests()
|
|
343
424
|
|
|
344
425
|
return results
|
|
345
426
|
|
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: epi-recorder
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: Executable Package for AI workflows - Record, Verify, and Replay AI runs
|
|
5
|
+
Author-email: Mohd Ibrahim Afridi <epitechforworld@outlook.com>
|
|
6
|
+
Maintainer-email: Mohd Ibrahim Afridi <epitechforworld@outlook.com>
|
|
7
|
+
License: Apache-2.0
|
|
8
|
+
Project-URL: Homepage, https://github.com/mohdibrahimaiml/EPI-V1.1
|
|
9
|
+
Project-URL: Documentation, https://github.com/mohdibrahimaiml/EPI-V1.1#readme
|
|
10
|
+
Project-URL: Repository, https://github.com/mohdibrahimaiml/EPI-V1.1
|
|
11
|
+
Project-URL: Issues, https://github.com/mohdibrahimaiml/EPI-V1.1/issues
|
|
12
|
+
Keywords: ai,reproducibility,verification,llm,evidence,openai,cryptography,workflow,audit
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Classifier: Topic :: Security :: Cryptography
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Python: >=3.11
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: pydantic>=2.0.0
|
|
28
|
+
Requires-Dist: cryptography>=41.0.0
|
|
29
|
+
Requires-Dist: cbor2>=5.6.0
|
|
30
|
+
Requires-Dist: typer[all]>=0.12.0
|
|
31
|
+
Requires-Dist: rich>=13.0.0
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
36
|
+
Requires-Dist: black>=24.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: ruff>=0.3.0; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# EPI - Evidence Packaged Infrastructure
|
|
41
|
+
|
|
42
|
+
**Evidence Packaged Infrastructure (EPI)** - The "PDF for AI Workflows"
|
|
43
|
+
|
|
44
|
+
Self-contained, cryptographically verified evidence packages for AI systems.
|
|
45
|
+
|
|
46
|
+
[](LICENSE)
|
|
47
|
+
[](https://www.python.org/downloads/)
|
|
48
|
+
[](https://pypi.org/project/epi-recorder/)
|
|
49
|
+
[](https://pypi.org/project/epi-recorder/)
|
|
50
|
+
[](https://github.com/mohdibrahimaiml/EPI-V1.1)
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 🚀 Quick Start
|
|
55
|
+
|
|
56
|
+
### Python API (Recommended for Developers)
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from epi_recorder import record
|
|
60
|
+
|
|
61
|
+
# Wrap your AI code with a context manager
|
|
62
|
+
with record("my_workflow.epi", workflow_name="Demo"):
|
|
63
|
+
# Your AI code runs normally - automatically recorded!
|
|
64
|
+
response = openai.chat.completions.create(
|
|
65
|
+
model="gpt-4",
|
|
66
|
+
messages=[{"role": "user", "content": "Hello!"}]
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# Optionally log custom events
|
|
70
|
+
session.log_step("calculation", {"result": 42})
|
|
71
|
+
|
|
72
|
+
# .epi file is automatically created, signed, and ready to verify!
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### CLI (For Shell Scripts & CI/CD)
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Install
|
|
79
|
+
pip install epi-recorder
|
|
80
|
+
|
|
81
|
+
# Record a workflow
|
|
82
|
+
epi run my_ai_script.py
|
|
83
|
+
|
|
84
|
+
# Verify integrity and authenticity
|
|
85
|
+
epi verify recording.epi
|
|
86
|
+
|
|
87
|
+
# View in browser
|
|
88
|
+
epi view recording.epi
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
That's it! Your AI workflow is now captured, signed, and viewable.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 🆕 What's New in v1.1.0
|
|
96
|
+
|
|
97
|
+
✅ **Windows Compatibility** - Full support for Windows CMD and PowerShell
|
|
98
|
+
✅ **Unicode Fixes** - Clean ASCII output, no encoding errors
|
|
99
|
+
✅ **Enhanced CLI** - All 11 commands work perfectly on Windows
|
|
100
|
+
✅ **Improved Metadata** - Better support for goal, notes, metrics, tags
|
|
101
|
+
✅ **Bug Fixes** - Resolved redaction edge cases and error handling
|
|
102
|
+
|
|
103
|
+
**Note:** File format remains backward compatible (spec version 1.0-keystone)
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 🎯 What is EPI?
|
|
108
|
+
|
|
109
|
+
**EPI (Evidence Packaged Infrastructure)** captures **everything** that happens during an AI workflow:
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
- 🤖 **LLM API calls** - Prompts, responses, tokens, latency
|
|
113
|
+
- 🔒 **Secrets redacted** - Automatically (15+ patterns)
|
|
114
|
+
- 📦 **Files and artifacts** - Content-addressed storage
|
|
115
|
+
- 🖥️ **Environment snapshot** - OS, Python version, packages
|
|
116
|
+
- ✅ **Cryptographically signed** - Ed25519 signatures
|
|
117
|
+
- 📊 **Beautiful timeline viewer** - Interactive HTML interface
|
|
118
|
+
|
|
119
|
+
All packaged into a **single .epi file** that anyone can verify and replay.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 🌟 Why EPI?
|
|
124
|
+
|
|
125
|
+
### The Problem
|
|
126
|
+
|
|
127
|
+
❌ **70% of AI research cannot be reproduced**
|
|
128
|
+
❌ **AI models fail mysteriously in production**
|
|
129
|
+
❌ **Cannot prove how AI decisions were made**
|
|
130
|
+
❌ **"It worked on my machine" debugging nightmare**
|
|
131
|
+
|
|
132
|
+
### The Solution
|
|
133
|
+
|
|
134
|
+
✅ **Record** - Capture complete AI workflows with one command
|
|
135
|
+
✅ **Verify** - Cryptographic proof of authenticity
|
|
136
|
+
✅ **Share** - Single file contains everything
|
|
137
|
+
✅ **Replay** - Deterministic reproduction (offline mode)
|
|
138
|
+
✅ **Audit** - Full transparency for compliance
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 📖 Core Features
|
|
143
|
+
|
|
144
|
+
### 🎬 Recording
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
epi run train.py
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Automatically captures:
|
|
151
|
+
- OpenAI API calls (GPT-4, GPT-3.5, etc.)
|
|
152
|
+
- Shell commands and outputs
|
|
153
|
+
- Python execution context
|
|
154
|
+
- Generated files and artifacts
|
|
155
|
+
- Environment variables (redacted)
|
|
156
|
+
|
|
157
|
+
### 🔐 Security by Default
|
|
158
|
+
|
|
159
|
+
- **Auto-redacts secrets:** API keys, tokens, credentials
|
|
160
|
+
- **Ed25519 signatures:** Cryptographic proof of authenticity
|
|
161
|
+
- **Frictionless:** Auto-generates keypair on first run
|
|
162
|
+
- **No secret leakage:** 15+ regex patterns protect sensitive data
|
|
163
|
+
|
|
164
|
+
### ✅ Verification
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
epi verify experiment.epi
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Three-level verification:
|
|
171
|
+
1. **Structural** - Valid ZIP format and schema
|
|
172
|
+
2. **Integrity** - SHA-256 file hashes match
|
|
173
|
+
3. **Authenticity** - Ed25519 signature valid
|
|
174
|
+
|
|
175
|
+
### 👁️ Beautiful Viewer
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
epi view experiment.epi
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Opens in your browser with:
|
|
182
|
+
- Interactive timeline of all steps
|
|
183
|
+
- LLM chat bubbles (prompts & responses)
|
|
184
|
+
- Trust badges (signed/unsigned)
|
|
185
|
+
- Artifact previews
|
|
186
|
+
- Zero code execution (pure JSON rendering)
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## 🎓 Use Cases
|
|
191
|
+
|
|
192
|
+
### AI Researchers
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Submit verifiable research
|
|
196
|
+
epi run reproduce.py
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
✅ 100% reproducible methodology
|
|
200
|
+
✅ Eliminates "it worked on my machine"
|
|
201
|
+
✅ Speeds up peer review
|
|
202
|
+
|
|
203
|
+
### Enterprise AI Teams
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# Capture production AI runs
|
|
207
|
+
epi run deploy_model.py
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
✅ Audit trails for compliance (EU AI Act, SOC 2)
|
|
211
|
+
✅ Debug production failures instantly
|
|
212
|
+
✅ Version control for AI systems
|
|
213
|
+
|
|
214
|
+
### Software Engineers
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
# Perfect bug reproduction
|
|
218
|
+
epi run flaky_test.py
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
✅ Share exact failing conditions
|
|
222
|
+
✅ Debug AI features faster
|
|
223
|
+
✅ Stable CI/CD for AI features
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## 🛠️ Installation
|
|
228
|
+
|
|
229
|
+
### From PyPI (Recommended)
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
pip install epi-recorder
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### From Source
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
git clone https://github.com/mohdibrahimaiml/EPI-V1.1.git
|
|
239
|
+
cd EPI-V1.1
|
|
240
|
+
pip install -e .
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Requirements
|
|
244
|
+
|
|
245
|
+
- **Python:** 3.11 or higher
|
|
246
|
+
- **OS:** Windows, macOS, Linux
|
|
247
|
+
- **Dependencies:** Automatically installed
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## 📚 Commands
|
|
252
|
+
|
|
253
|
+
### `epi run` - Record and Auto-Verify
|
|
254
|
+
|
|
255
|
+
Record a Python script (easiest way):
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
epi run script.py
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Options:
|
|
262
|
+
- `--no-verify` - Skip verification step
|
|
263
|
+
- `--no-open` - Don't open browser
|
|
264
|
+
- `--goal "text"` - Set workflow goal
|
|
265
|
+
- `--metrics '{"key": value}'` - Add metrics (JSON)
|
|
266
|
+
|
|
267
|
+
### `epi verify` - Check Integrity
|
|
268
|
+
|
|
269
|
+
Verify .epi file integrity and authenticity:
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
epi verify recording.epi
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Output:
|
|
276
|
+
```
|
|
277
|
+
+-------------- [OK] EPI Verification Report --------------+
|
|
278
|
+
| File: recording.epi |
|
|
279
|
+
| Trust Level: HIGH |
|
|
280
|
+
| Message: Cryptographically verified and integrity intact |
|
|
281
|
+
+----------------------------------------------------------+
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### `epi view` - Open in Browser
|
|
285
|
+
|
|
286
|
+
View recording in interactive HTML viewer:
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
epi view recording.epi
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### `epi ls` - List Recordings
|
|
293
|
+
|
|
294
|
+
Show all recordings in `./epi-recordings/`:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
epi ls
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### `epi keys` - Manage Keys
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
epi keys generate --name mykey
|
|
304
|
+
epi keys list
|
|
305
|
+
epi keys export --name mykey
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## 🐍 Python API
|
|
311
|
+
|
|
312
|
+
### Why Use the Python API?
|
|
313
|
+
|
|
314
|
+
The Python API is the **recommended way** to integrate EPI into your AI applications:
|
|
315
|
+
|
|
316
|
+
✅ **Zero CLI overhead** - No shell commands needed
|
|
317
|
+
✅ **Seamless integration** - Just wrap your code with `with record()`
|
|
318
|
+
✅ **Auto-captures OpenAI** - Automatically records all LLM calls
|
|
319
|
+
✅ **Custom logging** - Manually log steps and artifacts
|
|
320
|
+
✅ **Auto-signed** - Cryptographic signatures by default
|
|
321
|
+
|
|
322
|
+
### Basic Usage
|
|
323
|
+
|
|
324
|
+
```python
|
|
325
|
+
from epi_recorder import record
|
|
326
|
+
|
|
327
|
+
with record("experiment.epi", workflow_name="My Experiment"):
|
|
328
|
+
# Your code here - automatically recorded
|
|
329
|
+
result = train_model()
|
|
330
|
+
print(f"Result: {result}")
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### With Custom Logging
|
|
334
|
+
|
|
335
|
+
```python
|
|
336
|
+
from epi_recorder import record
|
|
337
|
+
from pathlib import Path
|
|
338
|
+
|
|
339
|
+
with record("workflow.epi",
|
|
340
|
+
workflow_name="Data Processing",
|
|
341
|
+
tags=["v1.0", "prod"]) as session:
|
|
342
|
+
# Process data
|
|
343
|
+
data = load_data("input.csv")
|
|
344
|
+
|
|
345
|
+
# Log custom steps
|
|
346
|
+
session.log_step("data.loaded", {
|
|
347
|
+
"rows": len(data),
|
|
348
|
+
"columns": list(data.columns)
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
# Process...
|
|
352
|
+
results = process(data)
|
|
353
|
+
|
|
354
|
+
# Save output
|
|
355
|
+
results.to_csv("output.csv")
|
|
356
|
+
|
|
357
|
+
# Capture the output file
|
|
358
|
+
session.log_artifact(Path("output.csv"))
|
|
359
|
+
|
|
360
|
+
# Log summary
|
|
361
|
+
session.log_step("processing.complete", {
|
|
362
|
+
"status": "success",
|
|
363
|
+
"output_rows": len(results)
|
|
364
|
+
})
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### With OpenAI (Auto-Recorded)
|
|
368
|
+
|
|
369
|
+
```python
|
|
370
|
+
from epi_recorder import record
|
|
371
|
+
import openai
|
|
372
|
+
|
|
373
|
+
with record("chat_session.epi", workflow_name="Customer Support"):
|
|
374
|
+
# OpenAI calls are automatically captured!
|
|
375
|
+
response = openai.chat.completions.create(
|
|
376
|
+
model="gpt-4",
|
|
377
|
+
messages=[
|
|
378
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
379
|
+
{"role": "user", "content": "What is quantum computing?"}
|
|
380
|
+
]
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
print(response.choices[0].message.content)
|
|
384
|
+
|
|
385
|
+
# API keys are automatically redacted in the recording!
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Advanced Options
|
|
389
|
+
|
|
390
|
+
```python
|
|
391
|
+
from epi_recorder import record
|
|
392
|
+
|
|
393
|
+
with record(
|
|
394
|
+
"advanced.epi",
|
|
395
|
+
goal="Train ML model",
|
|
396
|
+
notes="Testing with new hyperparameters",
|
|
397
|
+
metrics={"accuracy": 0.96, "latency_ms": 150},
|
|
398
|
+
approved_by="lead_scientist@company.com",
|
|
399
|
+
metadata_tags=["production", "v2.1"],
|
|
400
|
+
auto_sign=True, # Sign with default key
|
|
401
|
+
redact=True # Redact secrets
|
|
402
|
+
) as session:
|
|
403
|
+
# Your workflow
|
|
404
|
+
pass
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## 🔒 Security
|
|
410
|
+
|
|
411
|
+
### Automatic Redaction
|
|
412
|
+
|
|
413
|
+
EPI automatically removes:
|
|
414
|
+
- OpenAI API keys (`sk-...`)
|
|
415
|
+
- Anthropic API keys (`sk-ant-...`)
|
|
416
|
+
- AWS credentials (`AKIA...`)
|
|
417
|
+
- GitHub tokens (`ghp_...`)
|
|
418
|
+
- Bearer tokens, JWT tokens
|
|
419
|
+
- Database connection strings
|
|
420
|
+
- Private keys (PEM format)
|
|
421
|
+
|
|
422
|
+
### Cryptographic Signing
|
|
423
|
+
|
|
424
|
+
- **Algorithm:** Ed25519 (RFC 8032)
|
|
425
|
+
- **Key Size:** 256 bits
|
|
426
|
+
- **Hash:** SHA-256 with canonical CBOR
|
|
427
|
+
- **Storage:** `~/.epi/keys/` (secure permissions)
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## 🧪 Example
|
|
432
|
+
|
|
433
|
+
```python
|
|
434
|
+
# chat_example.py
|
|
435
|
+
from openai import OpenAI
|
|
436
|
+
|
|
437
|
+
client = OpenAI()
|
|
438
|
+
|
|
439
|
+
response = client.chat.completions.create(
|
|
440
|
+
model="gpt-3.5-turbo",
|
|
441
|
+
messages=[
|
|
442
|
+
{"role": "user", "content": "Explain quantum computing"}
|
|
443
|
+
]
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
print(response.choices[0].message.content)
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
```bash
|
|
450
|
+
# Record it
|
|
451
|
+
epi run chat_example.py
|
|
452
|
+
|
|
453
|
+
# Verify it
|
|
454
|
+
epi verify chat_example_*.epi
|
|
455
|
+
# ✅ Trust Level: HIGH
|
|
456
|
+
|
|
457
|
+
# View it
|
|
458
|
+
epi view chat_example_*.epi
|
|
459
|
+
# Opens timeline in browser
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
464
|
+
## 🧑💻 Development
|
|
465
|
+
|
|
466
|
+
### Running Tests
|
|
467
|
+
|
|
468
|
+
```bash
|
|
469
|
+
pytest tests/ -v --cov=epi_core --cov=epi_cli
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Project Structure
|
|
473
|
+
|
|
474
|
+
```
|
|
475
|
+
epi-recorder/
|
|
476
|
+
├── epi_core/ # Core logic
|
|
477
|
+
├── epi_cli/ # CLI commands
|
|
478
|
+
├── epi_recorder/ # Runtime capture
|
|
479
|
+
├── tests/ # Test suite
|
|
480
|
+
└── docs/ # Specification
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## 📊 Project Status
|
|
486
|
+
|
|
487
|
+
✅ **Phase 0:** Foundation (complete)
|
|
488
|
+
✅ **Phase 1:** Trust Layer (complete)
|
|
489
|
+
✅ **Phase 2:** Recorder MVP (complete)
|
|
490
|
+
✅ **Phase 3:** Viewer MVP (complete)
|
|
491
|
+
✅ **Phase 4:** Polish & Production (complete)
|
|
492
|
+
|
|
493
|
+
**Current Release:** v1.1.0 - Production Ready
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
## 📞 Contact & Support
|
|
498
|
+
|
|
499
|
+
**Project:** Evidence Packaged Infrastructure (EPI)
|
|
500
|
+
**Founder:** Mohd Ibrahim Afridi
|
|
501
|
+
**Project Email:** epitechforworld@outlook.com
|
|
502
|
+
**Personal Email:** mohdibrahimaiml@outlook.com
|
|
503
|
+
|
|
504
|
+
**Links:**
|
|
505
|
+
- **GitHub Repository:** https://github.com/mohdibrahimaiml/EPI-V1.1
|
|
506
|
+
- **Issues:** https://github.com/mohdibrahimaiml/EPI-V1.1/issues
|
|
507
|
+
- **PyPI:** https://pypi.org/project/epi-recorder/
|
|
508
|
+
- **Documentation:** [Coming Soon]
|
|
509
|
+
|
|
510
|
+
---
|
|
511
|
+
|
|
512
|
+
## 📄 License
|
|
513
|
+
|
|
514
|
+
Apache License 2.0
|
|
515
|
+
|
|
516
|
+
Copyright (c) 2024 Mohd Ibrahim Afridi
|
|
517
|
+
|
|
518
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
519
|
+
you may not use this file except in compliance with the License.
|
|
520
|
+
You may obtain a copy of the License at
|
|
521
|
+
|
|
522
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
523
|
+
|
|
524
|
+
Unless required by applicable law or agreed to in writing, software
|
|
525
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
526
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
527
|
+
See the License for the specific language governing permissions and
|
|
528
|
+
limitations under the License.
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
## 🙏 Acknowledgments
|
|
533
|
+
|
|
534
|
+
Built with:
|
|
535
|
+
- [Pydantic](https://pydantic.dev/) - Data validation
|
|
536
|
+
- [Typer](https://typer.tiangolo.com/) - CLI framework
|
|
537
|
+
- [Rich](https://rich.readthedocs.io/) - Terminal formatting
|
|
538
|
+
- [cryptography](https://cryptography.io/) - Ed25519 signatures
|
|
539
|
+
|
|
540
|
+
---
|
|
541
|
+
|
|
542
|
+
## 🌟 Made with ❤️ for the AI community
|
|
543
|
+
|
|
544
|
+
**Turning opaque AI runs into transparent, portable digital proofs.**
|
|
545
|
+
|
|
546
|
+
EPI makes AI workflows reproducible, verifiable, and auditable.
|
|
547
|
+
|
|
548
|
+
---
|
|
549
|
+
|
|
550
|
+
**Get started today:**
|
|
551
|
+
|
|
552
|
+
```bash
|
|
553
|
+
pip install epi-recorder
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
**Record your first AI workflow:**
|
|
557
|
+
|
|
558
|
+
```python
|
|
559
|
+
from epi_recorder import record
|
|
560
|
+
|
|
561
|
+
@record
|
|
562
|
+
def hello_epi():
|
|
563
|
+
print("Hello, EPI!")
|
|
564
|
+
return "success"
|
|
565
|
+
|
|
566
|
+
hello_epi()
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
**Welcome to the future of AI transparency!** 🚀
|