basalt_sdk 1.1.1__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.
- basalt_sdk-1.1.1/.gitignore +20 -0
- basalt_sdk-1.1.1/PKG-INFO +560 -0
- basalt_sdk-1.1.1/README.md +468 -0
- basalt_sdk-1.1.1/basalt/__init__.py +40 -0
- basalt_sdk-1.1.1/basalt/_internal/__init__.py +6 -0
- basalt_sdk-1.1.1/basalt/_internal/base_client.py +121 -0
- basalt_sdk-1.1.1/basalt/_internal/http.py +404 -0
- basalt_sdk-1.1.1/basalt/_version.py +1 -0
- basalt_sdk-1.1.1/basalt/client.py +164 -0
- basalt_sdk-1.1.1/basalt/config.py +15 -0
- basalt_sdk-1.1.1/basalt/datasets/__init__.py +25 -0
- basalt_sdk-1.1.1/basalt/datasets/client.py +387 -0
- basalt_sdk-1.1.1/basalt/datasets/file_upload.py +501 -0
- basalt_sdk-1.1.1/basalt/datasets/models.py +159 -0
- basalt_sdk-1.1.1/basalt/experiments/__init__.py +13 -0
- basalt_sdk-1.1.1/basalt/experiments/client.py +147 -0
- basalt_sdk-1.1.1/basalt/experiments/models.py +62 -0
- basalt_sdk-1.1.1/basalt/observability/__init__.py +75 -0
- basalt_sdk-1.1.1/basalt/observability/api.py +1176 -0
- basalt_sdk-1.1.1/basalt/observability/config.py +227 -0
- basalt_sdk-1.1.1/basalt/observability/context_managers.py +921 -0
- basalt_sdk-1.1.1/basalt/observability/decorators.py +98 -0
- basalt_sdk-1.1.1/basalt/observability/evaluators.py +118 -0
- basalt_sdk-1.1.1/basalt/observability/instrumentation.py +519 -0
- basalt_sdk-1.1.1/basalt/observability/processors.py +428 -0
- basalt_sdk-1.1.1/basalt/observability/request_tracing.py +131 -0
- basalt_sdk-1.1.1/basalt/observability/resilient_exporters.py +72 -0
- basalt_sdk-1.1.1/basalt/observability/semconv.py +645 -0
- basalt_sdk-1.1.1/basalt/observability/spans.py +71 -0
- basalt_sdk-1.1.1/basalt/observability/trace.py +165 -0
- basalt_sdk-1.1.1/basalt/observability/trace_context.py +222 -0
- basalt_sdk-1.1.1/basalt/observability/types.py +27 -0
- basalt_sdk-1.1.1/basalt/observability/utils.py +409 -0
- basalt_sdk-1.1.1/basalt/prompts/__init__.py +49 -0
- basalt_sdk-1.1.1/basalt/prompts/client.py +694 -0
- basalt_sdk-1.1.1/basalt/prompts/models.py +662 -0
- basalt_sdk-1.1.1/basalt/types/__init__.py +43 -0
- basalt_sdk-1.1.1/basalt/types/cache.py +16 -0
- basalt_sdk-1.1.1/basalt/types/common.py +13 -0
- basalt_sdk-1.1.1/basalt/types/exceptions.py +67 -0
- basalt_sdk-1.1.1/basalt/utils/__init__.py +0 -0
- basalt_sdk-1.1.1/basalt/utils/memcache.py +48 -0
- basalt_sdk-1.1.1/docs/01-introduction.md +236 -0
- basalt_sdk-1.1.1/docs/02-getting-started.md +169 -0
- basalt_sdk-1.1.1/docs/03-prompts.md +772 -0
- basalt_sdk-1.1.1/docs/04-datasets.md +417 -0
- basalt_sdk-1.1.1/docs/05-observability.md +274 -0
- basalt_sdk-1.1.1/docs/06-advanced-tracing.md +85 -0
- basalt_sdk-1.1.1/docs/06-manual-tracing.md +488 -0
- basalt_sdk-1.1.1/docs/07-llm-tracing.md +55 -0
- basalt_sdk-1.1.1/docs/08-async-observability.md +156 -0
- basalt_sdk-1.1.1/docs/09-auto-instrumentation.md +236 -0
- basalt_sdk-1.1.1/docs/10-evaluators.md +539 -0
- basalt_sdk-1.1.1/docs/11-experiments.md +125 -0
- basalt_sdk-1.1.1/docs/12-user-org-tracking.md +223 -0
- basalt_sdk-1.1.1/docs/13-trace-context.md +577 -0
- basalt_sdk-1.1.1/pyproject.toml +215 -0
- basalt_sdk-1.1.1/tests/__init__.py +0 -0
- basalt_sdk-1.1.1/tests/conftest.py +44 -0
- basalt_sdk-1.1.1/tests/datasets/__init__.py +1 -0
- basalt_sdk-1.1.1/tests/datasets/test_client.py +370 -0
- basalt_sdk-1.1.1/tests/datasets/test_file_upload.py +627 -0
- basalt_sdk-1.1.1/tests/experiments/__init__.py +1 -0
- basalt_sdk-1.1.1/tests/experiments/test_client.py +301 -0
- basalt_sdk-1.1.1/tests/internal/__init__.py +1 -0
- basalt_sdk-1.1.1/tests/internal/test_http.py +414 -0
- basalt_sdk-1.1.1/tests/observability/__init__.py +1 -0
- basalt_sdk-1.1.1/tests/observability/test_api.py +541 -0
- basalt_sdk-1.1.1/tests/observability/test_config.py +35 -0
- basalt_sdk-1.1.1/tests/observability/test_context_managers.py +574 -0
- basalt_sdk-1.1.1/tests/observability/test_decorators.py +70 -0
- basalt_sdk-1.1.1/tests/observability/test_evaluators.py +86 -0
- basalt_sdk-1.1.1/tests/observability/test_instrumentation.py +266 -0
- basalt_sdk-1.1.1/tests/observability/test_multi_exporters.py +298 -0
- basalt_sdk-1.1.1/tests/observability/test_processors.py +316 -0
- basalt_sdk-1.1.1/tests/observability/test_request_tracing.py +76 -0
- basalt_sdk-1.1.1/tests/observability/test_resilient_exporters.py +149 -0
- basalt_sdk-1.1.1/tests/observability/test_should_evaluate_propagation.py +454 -0
- basalt_sdk-1.1.1/tests/observability/test_trace.py +419 -0
- basalt_sdk-1.1.1/tests/observability/utils.py +35 -0
- basalt_sdk-1.1.1/tests/otel/__init__.py +3 -0
- basalt_sdk-1.1.1/tests/otel/conftest.py +45 -0
- basalt_sdk-1.1.1/tests/otel/example_otlp_export.py +151 -0
- basalt_sdk-1.1.1/tests/otel/generate_sample_otlp_json.py +127 -0
- basalt_sdk-1.1.1/tests/otel/otlp_utils.py +177 -0
- basalt_sdk-1.1.1/tests/otel/test_llm_instrumentation.py +791 -0
- basalt_sdk-1.1.1/tests/prompts/__init__.py +0 -0
- basalt_sdk-1.1.1/tests/prompts/test_client.py +937 -0
- basalt_sdk-1.1.1/tests/prompts/test_context_manager.py +233 -0
- basalt_sdk-1.1.1/tests/test_client_telemetry.py +48 -0
- basalt_sdk-1.1.1/tests/test_observe_decorators.py +87 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
basalt*.egg-info/
|
|
2
|
+
build/
|
|
3
|
+
dist/
|
|
4
|
+
__pycache__/
|
|
5
|
+
test.py
|
|
6
|
+
.DS_Store
|
|
7
|
+
.idea/
|
|
8
|
+
venv/
|
|
9
|
+
.github/instructions/*.md
|
|
10
|
+
.copilot-tracking
|
|
11
|
+
.env*
|
|
12
|
+
requirements*
|
|
13
|
+
.serena
|
|
14
|
+
.hatch/
|
|
15
|
+
*.pyc
|
|
16
|
+
.pytest_cache/
|
|
17
|
+
.ruff_cache/
|
|
18
|
+
coverage.xml
|
|
19
|
+
.coverage
|
|
20
|
+
htmlcov/
|
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: basalt_sdk
|
|
3
|
+
Version: 1.1.1
|
|
4
|
+
Summary: Basalt SDK for python
|
|
5
|
+
Project-URL: Homepage, https://github.com/basalt-ai/basalt-python
|
|
6
|
+
Author-email: Basalt <support@getbasalt.ai>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Keywords: ai,basalt,python,sdk
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Requires-Dist: black>=26.1.0
|
|
13
|
+
Requires-Dist: httpx>=0.28.1
|
|
14
|
+
Requires-Dist: jinja2>=3.1.6
|
|
15
|
+
Requires-Dist: opentelemetry-api~=1.39.1
|
|
16
|
+
Requires-Dist: opentelemetry-exporter-otlp~=1.39.1
|
|
17
|
+
Requires-Dist: opentelemetry-instrumentation-httpx~=0.59b0
|
|
18
|
+
Requires-Dist: opentelemetry-instrumentation~=0.59b0
|
|
19
|
+
Requires-Dist: opentelemetry-sdk~=1.39.1
|
|
20
|
+
Requires-Dist: opentelemetry-semantic-conventions~=0.59b0
|
|
21
|
+
Requires-Dist: typing-extensions>=4.10.0
|
|
22
|
+
Requires-Dist: wrapt~=1.17.3
|
|
23
|
+
Provides-Extra: all
|
|
24
|
+
Requires-Dist: opentelemetry-instrumentation-anthropic~=0.51.0; extra == 'all'
|
|
25
|
+
Requires-Dist: opentelemetry-instrumentation-bedrock~=0.51.0; extra == 'all'
|
|
26
|
+
Requires-Dist: opentelemetry-instrumentation-chromadb~=0.51.0; extra == 'all'
|
|
27
|
+
Requires-Dist: opentelemetry-instrumentation-google-generativeai~=0.51.0; extra == 'all'
|
|
28
|
+
Requires-Dist: opentelemetry-instrumentation-langchain~=0.51.0; extra == 'all'
|
|
29
|
+
Requires-Dist: opentelemetry-instrumentation-llamaindex~=0.51.0; extra == 'all'
|
|
30
|
+
Requires-Dist: opentelemetry-instrumentation-mistralai~=0.51.0; extra == 'all'
|
|
31
|
+
Requires-Dist: opentelemetry-instrumentation-openai~=0.51.0; extra == 'all'
|
|
32
|
+
Requires-Dist: opentelemetry-instrumentation-pinecone~=0.51.0; extra == 'all'
|
|
33
|
+
Requires-Dist: opentelemetry-instrumentation-qdrant~=0.51.0; extra == 'all'
|
|
34
|
+
Requires-Dist: opentelemetry-instrumentation-vertexai~=0.51.0; extra == 'all'
|
|
35
|
+
Provides-Extra: anthropic
|
|
36
|
+
Requires-Dist: opentelemetry-instrumentation-anthropic~=0.51.0; extra == 'anthropic'
|
|
37
|
+
Provides-Extra: bedrock
|
|
38
|
+
Requires-Dist: opentelemetry-instrumentation-bedrock~=0.51.0; extra == 'bedrock'
|
|
39
|
+
Provides-Extra: chromadb
|
|
40
|
+
Requires-Dist: opentelemetry-instrumentation-chromadb~=0.51.0; extra == 'chromadb'
|
|
41
|
+
Provides-Extra: dev
|
|
42
|
+
Requires-Dist: anthropic; extra == 'dev'
|
|
43
|
+
Requires-Dist: coverage; extra == 'dev'
|
|
44
|
+
Requires-Dist: google-genai; extra == 'dev'
|
|
45
|
+
Requires-Dist: mistralai; extra == 'dev'
|
|
46
|
+
Requires-Dist: openai; extra == 'dev'
|
|
47
|
+
Requires-Dist: opentelemetry-instrumentation-anthropic; extra == 'dev'
|
|
48
|
+
Requires-Dist: opentelemetry-instrumentation-google-genai; extra == 'dev'
|
|
49
|
+
Requires-Dist: opentelemetry-instrumentation-google-generativeai; extra == 'dev'
|
|
50
|
+
Requires-Dist: opentelemetry-instrumentation-openai; extra == 'dev'
|
|
51
|
+
Requires-Dist: opentelemetry-instrumentation-vertexai; extra == 'dev'
|
|
52
|
+
Requires-Dist: parameterized; extra == 'dev'
|
|
53
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
54
|
+
Requires-Dist: pytest-asyncio; extra == 'dev'
|
|
55
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
56
|
+
Requires-Dist: requests; extra == 'dev'
|
|
57
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
58
|
+
Requires-Dist: setuptools; extra == 'dev'
|
|
59
|
+
Requires-Dist: twine; extra == 'dev'
|
|
60
|
+
Requires-Dist: wheel; extra == 'dev'
|
|
61
|
+
Provides-Extra: framework-all
|
|
62
|
+
Requires-Dist: opentelemetry-instrumentation-langchain~=0.51.0; extra == 'framework-all'
|
|
63
|
+
Requires-Dist: opentelemetry-instrumentation-llamaindex~=0.51.0; extra == 'framework-all'
|
|
64
|
+
Provides-Extra: google-generativeai
|
|
65
|
+
Requires-Dist: opentelemetry-instrumentation-google-generativeai~=0.51.0; extra == 'google-generativeai'
|
|
66
|
+
Provides-Extra: langchain
|
|
67
|
+
Requires-Dist: opentelemetry-instrumentation-langchain~=0.51.0; extra == 'langchain'
|
|
68
|
+
Provides-Extra: llamaindex
|
|
69
|
+
Requires-Dist: opentelemetry-instrumentation-llamaindex~=0.51.0; extra == 'llamaindex'
|
|
70
|
+
Provides-Extra: llm-all
|
|
71
|
+
Requires-Dist: opentelemetry-instrumentation-anthropic~=0.51.0; extra == 'llm-all'
|
|
72
|
+
Requires-Dist: opentelemetry-instrumentation-bedrock~=0.51.0; extra == 'llm-all'
|
|
73
|
+
Requires-Dist: opentelemetry-instrumentation-google-generativeai~=0.51.0; extra == 'llm-all'
|
|
74
|
+
Requires-Dist: opentelemetry-instrumentation-mistralai~=0.51.0; extra == 'llm-all'
|
|
75
|
+
Requires-Dist: opentelemetry-instrumentation-openai~=0.51.0; extra == 'llm-all'
|
|
76
|
+
Requires-Dist: opentelemetry-instrumentation-vertexai~=0.51.0; extra == 'llm-all'
|
|
77
|
+
Provides-Extra: mistralai
|
|
78
|
+
Requires-Dist: opentelemetry-instrumentation-mistralai~=0.51.0; extra == 'mistralai'
|
|
79
|
+
Provides-Extra: openai
|
|
80
|
+
Requires-Dist: opentelemetry-instrumentation-openai~=0.51.0; extra == 'openai'
|
|
81
|
+
Provides-Extra: pinecone
|
|
82
|
+
Requires-Dist: opentelemetry-instrumentation-pinecone~=0.51.0; extra == 'pinecone'
|
|
83
|
+
Provides-Extra: qdrant
|
|
84
|
+
Requires-Dist: opentelemetry-instrumentation-qdrant~=0.51.0; extra == 'qdrant'
|
|
85
|
+
Provides-Extra: vector-all
|
|
86
|
+
Requires-Dist: opentelemetry-instrumentation-chromadb~=0.51.0; extra == 'vector-all'
|
|
87
|
+
Requires-Dist: opentelemetry-instrumentation-pinecone~=0.51.0; extra == 'vector-all'
|
|
88
|
+
Requires-Dist: opentelemetry-instrumentation-qdrant~=0.51.0; extra == 'vector-all'
|
|
89
|
+
Provides-Extra: vertex-ai
|
|
90
|
+
Requires-Dist: opentelemetry-instrumentation-vertexai~=0.51.0; extra == 'vertex-ai'
|
|
91
|
+
Description-Content-Type: text/markdown
|
|
92
|
+
|
|
93
|
+
# Basalt SDK
|
|
94
|
+
|
|
95
|
+
Basalt is a powerful tool for managing AI prompts, monitoring AI applications, and their release workflows. This SDK is the official Python package for interacting with your Basalt prompts and monitoring your AI applications.
|
|
96
|
+
|
|
97
|
+
## Installation
|
|
98
|
+
|
|
99
|
+
Install the Basalt SDK via pip:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
pip install basalt-sdk
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Optional Instrumentation Dependencies
|
|
106
|
+
|
|
107
|
+
The SDK includes optional OpenTelemetry instrumentation packages for various LLM providers, vector databases, and frameworks. You can install only the instrumentations you need:
|
|
108
|
+
|
|
109
|
+
#### LLM Provider Instrumentations
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Individual providers (10 available)
|
|
113
|
+
pip install basalt-sdk[openai]
|
|
114
|
+
pip install basalt-sdk[anthropic]
|
|
115
|
+
pip install basalt-sdk[google-generativeai] # Google Gemini
|
|
116
|
+
pip install basalt-sdk[bedrock]
|
|
117
|
+
pip install basalt-sdk[vertex-ai]
|
|
118
|
+
pip install basalt-sdk[ollama]
|
|
119
|
+
...
|
|
120
|
+
|
|
121
|
+
# Multiple providers
|
|
122
|
+
pip install basalt-sdk[openai,anthropic]
|
|
123
|
+
|
|
124
|
+
# All LLM providers (10 providers)
|
|
125
|
+
pip install basalt-sdk[llm-all]
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Note:** The NEW Google GenAI SDK instrumentation is not yet available on PyPI. Use `google-generativeai` for Gemini for now.
|
|
129
|
+
|
|
130
|
+
#### Vector Database Instrumentations
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Individual vector databases
|
|
134
|
+
pip install basalt-sdk[chromadb]
|
|
135
|
+
pip install basalt-sdk[pinecone]
|
|
136
|
+
pip install basalt-sdk[qdrant]
|
|
137
|
+
|
|
138
|
+
# All vector databases
|
|
139
|
+
pip install basalt-sdk[vector-all]
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
#### Framework Instrumentations
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Individual frameworks
|
|
146
|
+
pip install basalt-sdk[langchain]
|
|
147
|
+
pip install basalt-sdk[llamaindex]
|
|
148
|
+
|
|
149
|
+
# All frameworks
|
|
150
|
+
pip install basalt-sdk[framework-all]
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### Install Everything
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Install all available instrumentations
|
|
157
|
+
pip install basalt-sdk[all]
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Note:** These instrumentation packages are automatically activated when you enable telemetry in the Basalt SDK. They provide automatic tracing for your LLM provider calls, vector database operations, and framework usage.
|
|
161
|
+
|
|
162
|
+
## Usage
|
|
163
|
+
|
|
164
|
+
### Importing and Initializing the SDK
|
|
165
|
+
|
|
166
|
+
To get started, import the `Basalt` class and initialize it with your API key. Telemetry is enabled by default via OpenTelemetry, but can be configured or disabled:
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
from basalt import Basalt, TelemetryConfig
|
|
170
|
+
|
|
171
|
+
# Basic initialization with API key
|
|
172
|
+
basalt = Basalt(api_key="my-dev-api-key")
|
|
173
|
+
|
|
174
|
+
# Disable all telemetry
|
|
175
|
+
basalt = Basalt(api_key="my-dev-api-key", enable_telemetry=False)
|
|
176
|
+
|
|
177
|
+
# Advanced telemetry configuration
|
|
178
|
+
telemetry = TelemetryConfig(
|
|
179
|
+
service_name="my-app",
|
|
180
|
+
environment="staging",
|
|
181
|
+
enabled_providers=["openai", "anthropic"], # Optional: selective instrumentation
|
|
182
|
+
)
|
|
183
|
+
basalt = Basalt(api_key="my-dev-api-key", telemetry_config=telemetry)
|
|
184
|
+
|
|
185
|
+
# Or use client-level parameters (simpler)
|
|
186
|
+
basalt = Basalt(
|
|
187
|
+
api_key="my-dev-api-key",
|
|
188
|
+
enabled_instruments=["openai", "anthropic"]
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# Configure global metadata when constructing the client
|
|
192
|
+
basalt = Basalt(
|
|
193
|
+
api_key="my-dev-api-key",
|
|
194
|
+
observability_metadata={"env": "staging"},
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# Don't forget to shutdown the client when done
|
|
198
|
+
# This flushes any pending telemetry data
|
|
199
|
+
basalt.shutdown()
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
See `examples/telemetry_example.py` for a more complete walkthrough covering decorators, context managers, and custom exporters.
|
|
203
|
+
|
|
204
|
+
### Telemetry & Observability
|
|
205
|
+
|
|
206
|
+
The SDK includes comprehensive OpenTelemetry integration for observability:
|
|
207
|
+
|
|
208
|
+
- `TelemetryConfig` centralizes all observability options including:
|
|
209
|
+
- Service name/version and deployment environment
|
|
210
|
+
- Custom exporter configuration
|
|
211
|
+
- Lightweight tracing wrappers for Basalt API calls (bring your own HTTP instrumentation if you need transport-level spans)
|
|
212
|
+
- LLM provider instrumentation with fine-grained control over which providers to instrument
|
|
213
|
+
- Quick disable via `enable_telemetry=False` bypasses all instrumentation without touching application code.
|
|
214
|
+
- Built-in decorators and context managers simplify manual span creation:
|
|
215
|
+
- **Root Spans**: `@start_observe` - Creates trace entry point with identity and experiment tracking
|
|
216
|
+
- **Nested Spans**: `@observe` with `kind` parameter - For generation, retrieval, tool, event, function spans
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
from basalt.observability import observe, start_observe
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
# Root span with identity tracking
|
|
223
|
+
@start_observe(
|
|
224
|
+
feature_slug="dataset-processing",
|
|
225
|
+
name="process_workflow",
|
|
226
|
+
identity={
|
|
227
|
+
"organization": {"id": "123", "name": "ACME"},
|
|
228
|
+
"user": {"id": "456", "name": "John Doe"}
|
|
229
|
+
},
|
|
230
|
+
metadata={"environment": "production"}
|
|
231
|
+
)
|
|
232
|
+
def process_dataset(slug: str, user_id: str) -> str:
|
|
233
|
+
# Identity automatically propagates to child spans
|
|
234
|
+
observe.set_input({"slug": slug})
|
|
235
|
+
result = f"processed:{slug}"
|
|
236
|
+
observe.set_output({"result": result})
|
|
237
|
+
return result
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
# Nested LLM span
|
|
241
|
+
@observe(kind="generation", name="llm.generate")
|
|
242
|
+
def generate_summary(model: str, prompt: str) -> dict:
|
|
243
|
+
# Your LLM call here
|
|
244
|
+
return {"choices": [{"message": {"content": "Summary"}}]}
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
**Supported environment variables:**
|
|
252
|
+
|
|
253
|
+
| Variable | Description |
|
|
254
|
+
| --- | --- |
|
|
255
|
+
| `BASALT_API_KEY` | API key for authentication (can also be passed to `Basalt()` constructor). |
|
|
256
|
+
| `BASALT_TELEMETRY_ENABLED` | Master switch to enable/disable telemetry (default: `true`). |
|
|
257
|
+
| `BASALT_SERVICE_NAME` | Overrides the OTEL `service.name`. |
|
|
258
|
+
| `BASALT_ENVIRONMENT` | Sets `deployment.environment`. |
|
|
259
|
+
| `BASALT_OTEL_EXPORTER_OTLP_ENDPOINT` | Custom OTLP HTTP endpoint for traces. Overrides the default Basalt OTEL collector endpoint. |
|
|
260
|
+
| `BASALT_BUILD` | SDK build mode - set to `development` for local OTEL collector testing (default: `production`). |
|
|
261
|
+
| `TRACELOOP_TRACE_CONTENT` | Controls whether prompts/completions are logged. **Note:** Set automatically by `TelemetryConfig.trace_content` - you typically don't need to set this manually. |
|
|
262
|
+
| `BASALT_ENABLED_INSTRUMENTS` | Comma-separated list of instruments to enable (e.g., `openai,anthropic`). |
|
|
263
|
+
| `BASALT_DISABLED_INSTRUMENTS` | Comma-separated list of instruments to disable (e.g., `langchain,llamaindex`). |
|
|
264
|
+
|
|
265
|
+
**Default OTLP Exporter:**
|
|
266
|
+
|
|
267
|
+
By default, the SDK automatically sends traces to Basalt's OTEL collector:
|
|
268
|
+
- **Production**: `https://otel.getbasalt.ai/v1/traces`
|
|
269
|
+
- **Development**: `http://localhost:4318/v1/traces` (when `BASALT_BUILD=development`)
|
|
270
|
+
|
|
271
|
+
You can override this by:
|
|
272
|
+
1. Providing a custom `exporter` in `TelemetryConfig`
|
|
273
|
+
2. Setting the `BASALT_OTEL_EXPORTER_OTLP_ENDPOINT` environment variable
|
|
274
|
+
3. Disabling telemetry with `enable_telemetry=False`
|
|
275
|
+
|
|
276
|
+
## Prompt SDK
|
|
277
|
+
|
|
278
|
+
The Prompt SDK allows you to interact with your Basalt prompts using an exception-based API for clear error handling.
|
|
279
|
+
|
|
280
|
+
For a complete working example, check out:
|
|
281
|
+
- [Prompt API Example](./examples/prompt_api_example.py) - Detailed examples with error handling
|
|
282
|
+
- [Prompt SDK Demo Notebook](./examples/prompt_sdk_demo.ipynb) - Interactive notebook
|
|
283
|
+
|
|
284
|
+
### Available Methods
|
|
285
|
+
|
|
286
|
+
#### Prompts
|
|
287
|
+
Your Basalt instance exposes a `prompts` property for interacting with your Basalt prompts:
|
|
288
|
+
|
|
289
|
+
- **List Prompts**
|
|
290
|
+
|
|
291
|
+
Retrieve all available prompts.
|
|
292
|
+
|
|
293
|
+
**Example Usage:**
|
|
294
|
+
|
|
295
|
+
```python
|
|
296
|
+
from basalt import Basalt
|
|
297
|
+
from basalt.types.exceptions import BasaltAPIError, UnauthorizedError
|
|
298
|
+
|
|
299
|
+
basalt = Basalt(api_key="your-api-key")
|
|
300
|
+
|
|
301
|
+
try:
|
|
302
|
+
prompts = basalt.prompts.list_sync()
|
|
303
|
+
for prompt in prompts:
|
|
304
|
+
print(f"{prompt.slug} - {prompt.name}")
|
|
305
|
+
except UnauthorizedError:
|
|
306
|
+
print("Invalid API key")
|
|
307
|
+
except BasaltAPIError as e:
|
|
308
|
+
print(f"API error: {e}")
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
- **Get a Prompt**
|
|
312
|
+
|
|
313
|
+
Retrieve a specific prompt using a slug, and optional filters `tag` and `version`. Without tag or version, the production version of your prompt is selected by default.
|
|
314
|
+
|
|
315
|
+
**Example Usage:**
|
|
316
|
+
|
|
317
|
+
```python
|
|
318
|
+
from basalt import Basalt
|
|
319
|
+
from basalt.types.exceptions import NotFoundError, BasaltAPIError
|
|
320
|
+
|
|
321
|
+
basalt = Basalt(api_key="your-api-key")
|
|
322
|
+
|
|
323
|
+
try:
|
|
324
|
+
# Get the production version
|
|
325
|
+
prompt = basalt.prompts.get_sync('prompt-slug')
|
|
326
|
+
print(prompt.text)
|
|
327
|
+
|
|
328
|
+
# With optional tag or version parameters
|
|
329
|
+
prompt = basalt.prompts.get_sync(slug='prompt-slug', tag='latest')
|
|
330
|
+
prompt = basalt.prompts.get_sync(slug='prompt-slug', version='1.0.0')
|
|
331
|
+
|
|
332
|
+
# If your prompt has variables, pass them when fetching
|
|
333
|
+
prompt = basalt.prompts.get_sync(
|
|
334
|
+
slug='prompt-slug',
|
|
335
|
+
variables={'name': 'John Doe', 'role': 'engineer'}
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
# Use the prompt with your AI provider of choice
|
|
339
|
+
# Example: OpenAI
|
|
340
|
+
import openai
|
|
341
|
+
client = openai.OpenAI()
|
|
342
|
+
|
|
343
|
+
response = client.chat.completions.create(
|
|
344
|
+
model='gpt-4',
|
|
345
|
+
messages=[{'role': 'user', 'content': prompt.text}]
|
|
346
|
+
)
|
|
347
|
+
print(response.choices[0].message.content)
|
|
348
|
+
|
|
349
|
+
except NotFoundError:
|
|
350
|
+
print('Prompt not found')
|
|
351
|
+
except BasaltAPIError as e:
|
|
352
|
+
print(f'API error: {e}')
|
|
353
|
+
finally:
|
|
354
|
+
basalt.shutdown()
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
- **Context Managers for Observability** (Recommended)
|
|
358
|
+
|
|
359
|
+
Use prompts as context managers to automatically nest LLM calls under a prompt span for better trace organization and observability:
|
|
360
|
+
|
|
361
|
+
**Sync Example:**
|
|
362
|
+
|
|
363
|
+
```python
|
|
364
|
+
from basalt import Basalt
|
|
365
|
+
import openai
|
|
366
|
+
|
|
367
|
+
basalt = Basalt(api_key="your-api-key")
|
|
368
|
+
client = openai.OpenAI()
|
|
369
|
+
|
|
370
|
+
# Use context manager for automatic span nesting
|
|
371
|
+
with basalt.prompts.get_sync('summary-prompt', tag='production') as prompt:
|
|
372
|
+
response = client.chat.completions.create(
|
|
373
|
+
model=prompt.model.model,
|
|
374
|
+
messages=[{'role': 'user', 'content': prompt.text}]
|
|
375
|
+
)
|
|
376
|
+
print(response.choices[0].message.content)
|
|
377
|
+
|
|
378
|
+
basalt.shutdown()
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
**Async Example:**
|
|
382
|
+
|
|
383
|
+
```python
|
|
384
|
+
import asyncio
|
|
385
|
+
from basalt import Basalt
|
|
386
|
+
import openai
|
|
387
|
+
|
|
388
|
+
async def generate():
|
|
389
|
+
basalt = Basalt(api_key="your-api-key")
|
|
390
|
+
client = openai.AsyncOpenAI()
|
|
391
|
+
|
|
392
|
+
async with await basalt.prompts.get('summary-prompt', tag='production') as prompt:
|
|
393
|
+
response = await client.chat.completions.create(
|
|
394
|
+
model=prompt.model.model,
|
|
395
|
+
messages=[{'role': 'user', 'content': prompt.text}]
|
|
396
|
+
)
|
|
397
|
+
print(response.choices[0].message.content)
|
|
398
|
+
|
|
399
|
+
basalt.shutdown()
|
|
400
|
+
|
|
401
|
+
asyncio.run(generate())
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
See the [Prompts guide](./docs/03-prompts.md#observability-with-context-managers) for complete details.
|
|
405
|
+
|
|
406
|
+
- **Describe a Prompt**
|
|
407
|
+
|
|
408
|
+
Get metadata about a prompt including available versions and tags.
|
|
409
|
+
|
|
410
|
+
**Example Usage:**
|
|
411
|
+
|
|
412
|
+
```python
|
|
413
|
+
try:
|
|
414
|
+
description = basalt.prompts.describe_sync('prompt-slug')
|
|
415
|
+
print(f"Available versions: {description.available_versions}")
|
|
416
|
+
print(f"Available tags: {description.available_tags}")
|
|
417
|
+
except NotFoundError:
|
|
418
|
+
print('Prompt not found')
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
- **Async Operations**
|
|
422
|
+
|
|
423
|
+
All methods have async variants using `_async` suffix:
|
|
424
|
+
|
|
425
|
+
```python
|
|
426
|
+
import asyncio
|
|
427
|
+
|
|
428
|
+
async def fetch_prompts():
|
|
429
|
+
basalt = Basalt(api_key="your-api-key")
|
|
430
|
+
|
|
431
|
+
try:
|
|
432
|
+
# List prompts asynchronously
|
|
433
|
+
prompts = await basalt.prompts.list_async()
|
|
434
|
+
|
|
435
|
+
# Get a specific prompt asynchronously
|
|
436
|
+
prompt = await basalt.prompts.get_async('prompt-slug')
|
|
437
|
+
|
|
438
|
+
# Describe a prompt asynchronously
|
|
439
|
+
description = await basalt.prompts.describe_async('prompt-slug')
|
|
440
|
+
|
|
441
|
+
finally:
|
|
442
|
+
basalt.shutdown()
|
|
443
|
+
|
|
444
|
+
asyncio.run(fetch_prompts())
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## Dataset SDK
|
|
448
|
+
|
|
449
|
+
The Dataset SDK allows you to interact with your Basalt datasets using an exception-based API for clear error handling.
|
|
450
|
+
|
|
451
|
+
For a complete working example, check out:
|
|
452
|
+
- [Dataset API Example](./examples/dataset_api_example.py) - Detailed examples with error handling
|
|
453
|
+
- [Dataset SDK Demo Notebook](./examples/dataset_sdk_demo.ipynb) - Interactive notebook
|
|
454
|
+
|
|
455
|
+
### Available Methods
|
|
456
|
+
|
|
457
|
+
#### Datasets
|
|
458
|
+
Your Basalt instance exposes a `datasets` property for interacting with your Basalt datasets:
|
|
459
|
+
|
|
460
|
+
- **List Datasets**
|
|
461
|
+
|
|
462
|
+
Retrieve all available datasets.
|
|
463
|
+
|
|
464
|
+
**Example Usage:**
|
|
465
|
+
|
|
466
|
+
```python
|
|
467
|
+
from basalt import Basalt
|
|
468
|
+
from basalt.types.exceptions import BasaltAPIError
|
|
469
|
+
|
|
470
|
+
basalt = Basalt(api_key="your-api-key")
|
|
471
|
+
|
|
472
|
+
try:
|
|
473
|
+
datasets = basalt.datasets.list_sync()
|
|
474
|
+
for dataset in datasets:
|
|
475
|
+
print(f"{dataset.slug} - {dataset.name}")
|
|
476
|
+
print(f"Columns: {dataset.columns}")
|
|
477
|
+
except BasaltAPIError as e:
|
|
478
|
+
print(f"API error: {e}")
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
- **Get a Dataset**
|
|
482
|
+
|
|
483
|
+
Retrieve a specific dataset by slug.
|
|
484
|
+
|
|
485
|
+
**Example Usage:**
|
|
486
|
+
|
|
487
|
+
```python
|
|
488
|
+
from basalt.types.exceptions import NotFoundError
|
|
489
|
+
|
|
490
|
+
try:
|
|
491
|
+
dataset = basalt.datasets.get_sync('dataset-slug')
|
|
492
|
+
print(f"Dataset: {dataset.name}")
|
|
493
|
+
print(f"Rows: {len(dataset.rows)}")
|
|
494
|
+
|
|
495
|
+
# Access dataset rows
|
|
496
|
+
for row in dataset.rows:
|
|
497
|
+
print(row)
|
|
498
|
+
|
|
499
|
+
except NotFoundError:
|
|
500
|
+
print('Dataset not found')
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
- **Async Operations**
|
|
504
|
+
|
|
505
|
+
All methods have async variants using `_async` suffix:
|
|
506
|
+
|
|
507
|
+
```python
|
|
508
|
+
import asyncio
|
|
509
|
+
|
|
510
|
+
async def fetch_datasets():
|
|
511
|
+
basalt = Basalt(api_key="your-api-key")
|
|
512
|
+
|
|
513
|
+
try:
|
|
514
|
+
# List datasets asynchronously
|
|
515
|
+
datasets = await basalt.datasets.list_async()
|
|
516
|
+
|
|
517
|
+
# Get a specific dataset asynchronously
|
|
518
|
+
dataset = await basalt.datasets.get_async('dataset-slug')
|
|
519
|
+
|
|
520
|
+
finally:
|
|
521
|
+
basalt.shutdown()
|
|
522
|
+
|
|
523
|
+
asyncio.run(fetch_datasets())
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
## Error Handling
|
|
527
|
+
|
|
528
|
+
The SDK uses exception-based error handling for clarity and pythonic patterns:
|
|
529
|
+
|
|
530
|
+
```python
|
|
531
|
+
from basalt import Basalt
|
|
532
|
+
from basalt.types.exceptions import (
|
|
533
|
+
BasaltAPIError, # Base exception for all API errors
|
|
534
|
+
NotFoundError, # Resource not found (404)
|
|
535
|
+
UnauthorizedError, # Authentication failed (401)
|
|
536
|
+
NetworkError, # Network/connection errors
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
basalt = Basalt(api_key="your-api-key")
|
|
540
|
+
|
|
541
|
+
try:
|
|
542
|
+
prompt = basalt.prompts.get_sync('my-prompt')
|
|
543
|
+
# Use the prompt
|
|
544
|
+
except NotFoundError:
|
|
545
|
+
print("Prompt doesn't exist")
|
|
546
|
+
except UnauthorizedError:
|
|
547
|
+
print("Check your API key")
|
|
548
|
+
except NetworkError:
|
|
549
|
+
print("Network connection failed")
|
|
550
|
+
except BasaltAPIError as e:
|
|
551
|
+
print(f"Other API error: {e}")
|
|
552
|
+
finally:
|
|
553
|
+
basalt.shutdown()
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
## License
|
|
559
|
+
|
|
560
|
+
MIT
|