cmpnd 0.1.0__tar.gz → 0.2.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.
Files changed (117) hide show
  1. cmpnd-0.2.0/.gitignore +43 -0
  2. cmpnd-0.2.0/CLAUDE.md +24 -0
  3. cmpnd-0.2.0/PKG-INFO +269 -0
  4. cmpnd-0.2.0/README.md +233 -0
  5. cmpnd-0.2.0/cmpnd/__init__.py +338 -0
  6. cmpnd-0.2.0/cmpnd/callback.py +985 -0
  7. cmpnd-0.2.0/cmpnd/cli/__init__.py +132 -0
  8. cmpnd-0.2.0/cmpnd/cli/api_client.py +87 -0
  9. cmpnd-0.2.0/cmpnd/cli/commands/auth.py +19 -0
  10. cmpnd-0.2.0/cmpnd/cli/commands/datasets.py +31 -0
  11. cmpnd-0.2.0/cmpnd/cli/commands/deployments.py +58 -0
  12. cmpnd-0.2.0/cmpnd/cli/commands/evals.py +42 -0
  13. cmpnd-0.2.0/cmpnd/cli/commands/optimizations.py +60 -0
  14. cmpnd-0.2.0/cmpnd/cli/commands/programs.py +55 -0
  15. cmpnd-0.2.0/cmpnd/cli/commands/top.py +676 -0
  16. cmpnd-0.2.0/cmpnd/cli/commands/traces.py +63 -0
  17. cmpnd-0.2.0/cmpnd/config.py +160 -0
  18. cmpnd-0.2.0/cmpnd/context.py +118 -0
  19. cmpnd-0.2.0/cmpnd/dataset_sync.py +128 -0
  20. cmpnd-0.2.0/cmpnd/datasets.py +219 -0
  21. cmpnd-0.2.0/cmpnd/decorators.py +144 -0
  22. cmpnd-0.2.0/cmpnd/deploy.py +212 -0
  23. cmpnd-0.2.0/cmpnd/eval_handler.py +384 -0
  24. cmpnd-0.2.0/cmpnd/execute.py +132 -0
  25. cmpnd-0.2.0/cmpnd/exporter.py +601 -0
  26. cmpnd-0.2.0/cmpnd/helpers.py +220 -0
  27. cmpnd-0.2.0/cmpnd/identity.py +433 -0
  28. cmpnd-0.2.0/cmpnd/models.py +755 -0
  29. cmpnd-0.2.0/cmpnd/optimizers/__init__.py +31 -0
  30. cmpnd-0.2.0/cmpnd/optimizers/gepa.py +390 -0
  31. cmpnd-0.2.0/cmpnd/optimizers/gepa_callback.py +472 -0
  32. cmpnd-0.2.0/cmpnd/optimizers/tracker.py +903 -0
  33. cmpnd-0.2.0/cmpnd/packaging.py +331 -0
  34. cmpnd-0.2.0/docs/2026-04-02-code-review.md +280 -0
  35. cmpnd-0.2.0/docs/plans/2026-04-05-train-val-dataset-capture-design.md +91 -0
  36. cmpnd-0.2.0/docs/plans/2026-04-05-train-val-dataset-capture.md +727 -0
  37. cmpnd-0.2.0/examples/local_ollama.py +40 -0
  38. cmpnd-0.2.0/pyproject.toml +90 -0
  39. cmpnd-0.2.0/tests/__init__.py +1 -0
  40. cmpnd-0.2.0/tests/e2e/__init__.py +0 -0
  41. cmpnd-0.2.0/tests/e2e/conftest.py +280 -0
  42. cmpnd-0.2.0/tests/e2e/test_capture_prompts.py +129 -0
  43. cmpnd-0.2.0/tests/e2e/test_composite_module.py +86 -0
  44. cmpnd-0.2.0/tests/e2e/test_dataset_auto_creation.py +271 -0
  45. cmpnd-0.2.0/tests/e2e/test_deploy_execute.py +311 -0
  46. cmpnd-0.2.0/tests/e2e/test_edge_cases.py +62 -0
  47. cmpnd-0.2.0/tests/e2e/test_example_hash.py +150 -0
  48. cmpnd-0.2.0/tests/e2e/test_gepa_optimization.py +92 -0
  49. cmpnd-0.2.0/tests/e2e/test_lm_accuracy.py +99 -0
  50. cmpnd-0.2.0/tests/e2e/test_module_tracing.py +205 -0
  51. cmpnd-0.2.0/tests/e2e/test_optimization_metric_identity.py +111 -0
  52. cmpnd-0.2.0/tests/e2e/test_parallel_export.py +104 -0
  53. cmpnd-0.2.0/tests/e2e/test_project_attribution.py +147 -0
  54. cmpnd-0.2.0/tests/e2e/test_react_tool_spans.py +79 -0
  55. cmpnd-0.2.0/tests/e2e/test_span_thinning.py +67 -0
  56. cmpnd-0.2.0/tests/e2e/test_trace_structure.py +180 -0
  57. cmpnd-0.2.0/tests/e2e/test_user_attribution.py +181 -0
  58. cmpnd-0.2.0/tests/integration/__init__.py +0 -0
  59. cmpnd-0.2.0/tests/integration/conftest.py +76 -0
  60. cmpnd-0.2.0/tests/integration/test_cli_deploy_smoketest.py +124 -0
  61. cmpnd-0.2.0/tests/integration/test_logs_renders_traces.py +152 -0
  62. cmpnd-0.2.0/tests/integration/test_optimizing_progress.py +135 -0
  63. cmpnd-0.2.0/tests/integration/test_unhappy_path.py +196 -0
  64. cmpnd-0.2.0/tests/test_callback.py +1856 -0
  65. cmpnd-0.2.0/tests/test_cli/__init__.py +0 -0
  66. cmpnd-0.2.0/tests/test_cli/conftest.py +15 -0
  67. cmpnd-0.2.0/tests/test_cli/test_api_client.py +123 -0
  68. cmpnd-0.2.0/tests/test_cli/test_auth.py +16 -0
  69. cmpnd-0.2.0/tests/test_cli/test_datasets.py +23 -0
  70. cmpnd-0.2.0/tests/test_cli/test_deployments.py +51 -0
  71. cmpnd-0.2.0/tests/test_cli/test_evals.py +33 -0
  72. cmpnd-0.2.0/tests/test_cli/test_main.py +44 -0
  73. cmpnd-0.2.0/tests/test_cli/test_optimizations.py +52 -0
  74. cmpnd-0.2.0/tests/test_cli/test_programs.py +50 -0
  75. cmpnd-0.2.0/tests/test_cli/test_top.py +480 -0
  76. cmpnd-0.2.0/tests/test_cli/test_traces.py +51 -0
  77. cmpnd-0.2.0/tests/test_clustering/__init__.py +6 -0
  78. cmpnd-0.2.0/tests/test_clustering/conftest.py +153 -0
  79. cmpnd-0.2.0/tests/test_clustering/test_edge_cases.py +324 -0
  80. cmpnd-0.2.0/tests/test_clustering/test_hash_consistency.py +265 -0
  81. cmpnd-0.2.0/tests/test_clustering/test_type_conversion.py +214 -0
  82. cmpnd-0.2.0/tests/test_config.py +178 -0
  83. cmpnd-0.2.0/tests/test_context.py +226 -0
  84. cmpnd-0.2.0/tests/test_context_propagation.py +49 -0
  85. cmpnd-0.2.0/tests/test_dataset_sync.py +497 -0
  86. cmpnd-0.2.0/tests/test_datasets.py +568 -0
  87. cmpnd-0.2.0/tests/test_decorators.py +302 -0
  88. cmpnd-0.2.0/tests/test_deploy.py +279 -0
  89. cmpnd-0.2.0/tests/test_eval.py +564 -0
  90. cmpnd-0.2.0/tests/test_exception_paths.py +302 -0
  91. cmpnd-0.2.0/tests/test_execute.py +160 -0
  92. cmpnd-0.2.0/tests/test_exporter.py +428 -0
  93. cmpnd-0.2.0/tests/test_exporter_real.py +461 -0
  94. cmpnd-0.2.0/tests/test_gepa_callback.py +1743 -0
  95. cmpnd-0.2.0/tests/test_gepa_integration.py +241 -0
  96. cmpnd-0.2.0/tests/test_identity.py +476 -0
  97. cmpnd-0.2.0/tests/test_integration.py +397 -0
  98. cmpnd-0.2.0/tests/test_models.py +457 -0
  99. cmpnd-0.2.0/tests/test_packaging.py +179 -0
  100. cmpnd-0.2.0/tests/test_project_payload.py +147 -0
  101. cmpnd-0.2.0/tests/test_repro_reactv2_bugs.py +195 -0
  102. cmpnd-0.2.0/tests/test_schemas.py +132 -0
  103. cmpnd-0.2.0/tests/test_span_thinning.py +183 -0
  104. cmpnd-0.2.0/tests/test_stats_export.py +118 -0
  105. cmpnd-0.2.0/tests/test_tracked_gepa.py +1015 -0
  106. cmpnd-0.2.0/tests/test_truncation.py +167 -0
  107. cmpnd-0.2.0/todo.md +45 -0
  108. cmpnd-0.2.0/uv.lock +3276 -0
  109. cmpnd-0.1.0/PKG-INFO +0 -6
  110. cmpnd-0.1.0/cmpnd.egg-info/PKG-INFO +0 -6
  111. cmpnd-0.1.0/cmpnd.egg-info/SOURCES.txt +0 -7
  112. cmpnd-0.1.0/cmpnd.egg-info/dependency_links.txt +0 -1
  113. cmpnd-0.1.0/cmpnd.egg-info/top_level.txt +0 -1
  114. cmpnd-0.1.0/main.py +0 -6
  115. cmpnd-0.1.0/pyproject.toml +0 -7
  116. cmpnd-0.1.0/setup.cfg +0 -4
  117. /cmpnd-0.1.0/README.md → /cmpnd-0.2.0/cmpnd/cli/commands/__init__.py +0 -0
cmpnd-0.2.0/.gitignore ADDED
@@ -0,0 +1,43 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ parts/
14
+ sdist/
15
+ var/
16
+ wheels/
17
+ *.egg-info/
18
+ .installed.cfg
19
+ *.egg
20
+
21
+ # Virtual environments
22
+ .env
23
+ .venv
24
+ env/
25
+ venv/
26
+ ENV/
27
+
28
+ # IDE
29
+ .idea/
30
+ .vscode/
31
+ *.swp
32
+ *.swo
33
+
34
+ # Testing
35
+ .pytest_cache/
36
+ .coverage
37
+ htmlcov/
38
+ .tox/
39
+ .nox/
40
+
41
+ # Misc
42
+ *.log
43
+ .DS_Store
cmpnd-0.2.0/CLAUDE.md ADDED
@@ -0,0 +1,24 @@
1
+ # Claude Code Instructions
2
+
3
+ Part of the CMPND monorepo. See `../CLAUDE.md` for cross-cutting rules (hash architecture, null handling, testing philosophy).
4
+
5
+ ## Running Tests & Checks
6
+
7
+ ```bash
8
+ python -m pytest tests/ # all tests (excluding e2e)
9
+ python -m pytest tests/ -k "not e2e" # skip e2e explicitly
10
+ ruff check . # lint
11
+ ruff format --check . # format check
12
+ ```
13
+
14
+ ## Key Files
15
+
16
+ - `cmpnd/identity.py` - Unified hash computations (xxhash, SHA256)
17
+ - `cmpnd/callback.py` - DSPy instrumentation, signature extraction
18
+ - `cmpnd/optimizers/tracker.py` - Optimization tracking
19
+ - `cmpnd/packaging.py` - Source ZIP generation for deploy (ported from deploy/local_cmpnd.py)
20
+ - `cmpnd/deploy.py` - `deploy()` function: SDK -> Rails -> AWS deploy stack
21
+
22
+ ## Release
23
+
24
+ See the "PyPI SDK release" section in [`docs/deployment.md`](../docs/deployment.md). Short version: `git tag sdk-v<version> && git push origin sdk-v<version>`. Version is derived from the git tag at build time (dynamic versioning).
cmpnd-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,269 @@
1
+ Metadata-Version: 2.4
2
+ Name: cmpnd
3
+ Version: 0.2.0
4
+ Summary: DSPy observability and deployment SDK for cmpnd
5
+ Project-URL: Homepage, https://cmpnd.ai
6
+ Author-email: cmpnd <hello@cmpnd.io>
7
+ License: MIT
8
+ Keywords: dspy,llm,observability,tracing
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: dspy>=3.1.3
21
+ Requires-Dist: httpx>=0.27.0
22
+ Requires-Dist: pydantic>=2.0
23
+ Requires-Dist: xxhash>=3.0.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: jsonschema>=4.0; extra == 'dev'
26
+ Requires-Dist: mypy>=1.0; extra == 'dev'
27
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
28
+ Requires-Dist: pytest>=8.0; extra == 'dev'
29
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
30
+ Provides-Extra: stub
31
+ Requires-Dist: cmpnd-deploy; (python_version >= '3.11') and extra == 'stub'
32
+ Requires-Dist: fastapi>=0.110; extra == 'stub'
33
+ Requires-Dist: python-multipart>=0.0.9; extra == 'stub'
34
+ Requires-Dist: uvicorn[standard]>=0.27; extra == 'stub'
35
+ Description-Content-Type: text/markdown
36
+
37
+ # cmpnd
38
+
39
+ DSPy observability and deployment SDK for cmpnd.
40
+
41
+ Automatically trace your DSPy programs with one line of code, and deploy them with one more.
42
+
43
+ ## Installation
44
+
45
+ ```bash
46
+ pip install cmpnd
47
+ ```
48
+
49
+ ## Quick Start
50
+
51
+ ```python
52
+ import cmpnd
53
+
54
+ # Configure with your API key
55
+ cmpnd.configure(api_key="ct_xxx", project="my-project")
56
+
57
+ # Enable automatic DSPy instrumentation
58
+ cmpnd.auto_instrument()
59
+
60
+ # Your DSPy code is now automatically traced!
61
+ import dspy
62
+
63
+ lm = dspy.LM("openai/gpt-4o-mini")
64
+ dspy.configure(lm=lm)
65
+
66
+ cot = dspy.ChainOfThought("question -> answer")
67
+ result = cot(question="What is DSPy?")
68
+ # Trace is automatically sent to cmpnd
69
+ ```
70
+
71
+ ## Configuration
72
+
73
+ ### Using environment variables
74
+
75
+ ```bash
76
+ export CMPND_API_KEY="ct_your_api_key"
77
+ export CMPND_ENDPOINT="https://platform.cmpnd.ai" # optional
78
+ ```
79
+
80
+ ```python
81
+ import cmpnd
82
+
83
+ cmpnd.configure() # Reads from environment
84
+ cmpnd.auto_instrument()
85
+ ```
86
+
87
+ ### Configuration options
88
+
89
+ ```python
90
+ cmpnd.configure(
91
+ api_key="ct_xxx", # Required: API key
92
+ endpoint="https://platform.cmpnd.ai", # Optional: Backend URL
93
+ project="my-project", # Optional: Project name
94
+ batch_size=100, # Optional: Batch size for export
95
+ flush_interval_seconds=5.0, # Optional: Flush interval
96
+ capture_inputs=True, # Optional: Capture function inputs
97
+ capture_outputs=True, # Optional: Capture function outputs
98
+ default_tags={"env": "prod"}, # Optional: Tags for all traces
99
+ )
100
+ ```
101
+
102
+ ## Deployment
103
+
104
+ Deploy a DSPy module to the cmpnd platform for server-side execution:
105
+
106
+ ```python
107
+ import cmpnd
108
+ import dspy
109
+
110
+ cmpnd.configure(api_key="ct_xxx")
111
+
112
+ lm = dspy.LM("groq/llama-3.1-8b-instant", temperature=0.0, max_tokens=16384)
113
+ dspy.configure(lm=lm)
114
+
115
+ module = dspy.Predict("question -> answer")
116
+ deployment_id = cmpnd.deploy(module)
117
+ ```
118
+
119
+ The SDK packages the module's source code into a ZIP, uploads it to the platform, and polls until the server-side parser finishes. Returns a `deployment_id` for future use with `cmpnd.execute()` (coming soon).
120
+
121
+ ### With a metric (for optimization)
122
+
123
+ ```python
124
+ def accuracy(example, pred, trace=None):
125
+ return example.answer == pred.answer
126
+
127
+ deployment_id = cmpnd.deploy(module, metric=accuracy)
128
+ ```
129
+
130
+ ### Options
131
+
132
+ ```python
133
+ cmpnd.deploy(
134
+ module, # Required: a DSPy module
135
+ metric=None, # Optional: metric callable for optimization support
136
+ timeout=300, # Optional: seconds to wait for parsing (default 300)
137
+ )
138
+ ```
139
+
140
+ ### How it works
141
+
142
+ 1. The SDK generates source code from the live module (LM config, signature, types)
143
+ 2. `POST /api/v1/deployments` creates a deployment and returns a presigned S3 upload URL
144
+ 3. The source ZIP is uploaded directly to S3
145
+ 4. The server-side parser extracts the program and LM configuration
146
+ 5. The SDK polls until status is `ready`, then returns the `deployment_id`
147
+
148
+ The deployed program's LM model string (e.g. `groq/llama-3.1-8b-instant`) and configuration (temperature, max_tokens) are extracted automatically from the source.
149
+
150
+ ## Custom Spans
151
+
152
+ Add custom spans to trace non-DSPy code:
153
+
154
+ ### Using the decorator
155
+
156
+ ```python
157
+ from cmpnd import trace, SpanType
158
+
159
+ @trace(name="fetch_documents", span_type=SpanType.RETRIEVE)
160
+ def fetch_documents(query: str) -> list[str]:
161
+ # Your retrieval logic
162
+ return documents
163
+ ```
164
+
165
+ ### Using the context manager
166
+
167
+ ```python
168
+ from cmpnd import start_span, SpanType
169
+
170
+ def run_pipeline(query: str):
171
+ with start_span("vector_search", span_type=SpanType.RETRIEVE) as span:
172
+ span.set_attribute("index", "my-faiss-index")
173
+ docs = search(query)
174
+ span.set_outputs({"doc_count": len(docs)})
175
+
176
+ return generate(query, docs)
177
+ ```
178
+
179
+ ## What Gets Traced
180
+
181
+ The SDK automatically captures:
182
+
183
+ ### Module Execution
184
+ - Module type (Predict, ChainOfThought, ReAct, etc.)
185
+ - Signature name and instructions
186
+ - Input/output field names
187
+ - Demo count
188
+
189
+ ### LM Calls
190
+ - Model name and provider
191
+ - Token usage (prompt, completion, total)
192
+ - Request/response content
193
+
194
+ ### Adapters
195
+ - Format and parse operations
196
+ - Input/output transformations
197
+
198
+ ### Tools
199
+ - Tool name and description
200
+ - Invocation inputs/outputs
201
+
202
+ ### Evaluations
203
+ - Evaluation scores
204
+ - Program being evaluated
205
+
206
+ ## Span Types
207
+
208
+ Available span types for categorization:
209
+
210
+ - `SpanType.MODULE` - Generic DSPy module
211
+ - `SpanType.PREDICT` - Predict module
212
+ - `SpanType.CHAIN_OF_THOUGHT` - ChainOfThought module
213
+ - `SpanType.REACT` - ReAct agent
214
+ - `SpanType.RETRIEVE` - Retrieval operations
215
+ - `SpanType.LM_CALL` - Language model calls
216
+ - `SpanType.ADAPTER_FORMAT` - Adapter formatting
217
+ - `SpanType.ADAPTER_PARSE` - Adapter parsing
218
+ - `SpanType.TOOL` - Tool invocations
219
+ - `SpanType.EVALUATION` - Evaluation runs
220
+
221
+ ## API Reference
222
+
223
+ ### `cmpnd.configure()`
224
+
225
+ Initialize the SDK with your API key and options.
226
+
227
+ ### `cmpnd.auto_instrument()`
228
+
229
+ Automatically register the callback with DSPy.
230
+
231
+ ### `cmpnd.CmpndCallback`
232
+
233
+ The callback class for manual registration:
234
+
235
+ ```python
236
+ import dspy
237
+ import cmpnd
238
+
239
+ cmpnd.configure(api_key="ct_xxx")
240
+ dspy.configure(callbacks=[cmpnd.CmpndCallback()])
241
+ ```
242
+
243
+ ### `cmpnd.deploy()`
244
+
245
+ Deploy a DSPy module to the cmpnd platform. Returns the `deployment_id`.
246
+
247
+ ### `cmpnd.trace()`
248
+
249
+ Decorator for custom traced functions.
250
+
251
+ ### `cmpnd.start_span()`
252
+
253
+ Context manager for custom spans.
254
+
255
+ ### `cmpnd.get_current_trace()`
256
+
257
+ Get the current trace (if any).
258
+
259
+ ### `cmpnd.get_current_span()`
260
+
261
+ Get the current span (if any).
262
+
263
+ ### `cmpnd.shutdown_exporter()`
264
+
265
+ Gracefully shutdown the background exporter.
266
+
267
+ ## License
268
+
269
+ MIT
cmpnd-0.2.0/README.md ADDED
@@ -0,0 +1,233 @@
1
+ # cmpnd
2
+
3
+ DSPy observability and deployment SDK for cmpnd.
4
+
5
+ Automatically trace your DSPy programs with one line of code, and deploy them with one more.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pip install cmpnd
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```python
16
+ import cmpnd
17
+
18
+ # Configure with your API key
19
+ cmpnd.configure(api_key="ct_xxx", project="my-project")
20
+
21
+ # Enable automatic DSPy instrumentation
22
+ cmpnd.auto_instrument()
23
+
24
+ # Your DSPy code is now automatically traced!
25
+ import dspy
26
+
27
+ lm = dspy.LM("openai/gpt-4o-mini")
28
+ dspy.configure(lm=lm)
29
+
30
+ cot = dspy.ChainOfThought("question -> answer")
31
+ result = cot(question="What is DSPy?")
32
+ # Trace is automatically sent to cmpnd
33
+ ```
34
+
35
+ ## Configuration
36
+
37
+ ### Using environment variables
38
+
39
+ ```bash
40
+ export CMPND_API_KEY="ct_your_api_key"
41
+ export CMPND_ENDPOINT="https://platform.cmpnd.ai" # optional
42
+ ```
43
+
44
+ ```python
45
+ import cmpnd
46
+
47
+ cmpnd.configure() # Reads from environment
48
+ cmpnd.auto_instrument()
49
+ ```
50
+
51
+ ### Configuration options
52
+
53
+ ```python
54
+ cmpnd.configure(
55
+ api_key="ct_xxx", # Required: API key
56
+ endpoint="https://platform.cmpnd.ai", # Optional: Backend URL
57
+ project="my-project", # Optional: Project name
58
+ batch_size=100, # Optional: Batch size for export
59
+ flush_interval_seconds=5.0, # Optional: Flush interval
60
+ capture_inputs=True, # Optional: Capture function inputs
61
+ capture_outputs=True, # Optional: Capture function outputs
62
+ default_tags={"env": "prod"}, # Optional: Tags for all traces
63
+ )
64
+ ```
65
+
66
+ ## Deployment
67
+
68
+ Deploy a DSPy module to the cmpnd platform for server-side execution:
69
+
70
+ ```python
71
+ import cmpnd
72
+ import dspy
73
+
74
+ cmpnd.configure(api_key="ct_xxx")
75
+
76
+ lm = dspy.LM("groq/llama-3.1-8b-instant", temperature=0.0, max_tokens=16384)
77
+ dspy.configure(lm=lm)
78
+
79
+ module = dspy.Predict("question -> answer")
80
+ deployment_id = cmpnd.deploy(module)
81
+ ```
82
+
83
+ The SDK packages the module's source code into a ZIP, uploads it to the platform, and polls until the server-side parser finishes. Returns a `deployment_id` for future use with `cmpnd.execute()` (coming soon).
84
+
85
+ ### With a metric (for optimization)
86
+
87
+ ```python
88
+ def accuracy(example, pred, trace=None):
89
+ return example.answer == pred.answer
90
+
91
+ deployment_id = cmpnd.deploy(module, metric=accuracy)
92
+ ```
93
+
94
+ ### Options
95
+
96
+ ```python
97
+ cmpnd.deploy(
98
+ module, # Required: a DSPy module
99
+ metric=None, # Optional: metric callable for optimization support
100
+ timeout=300, # Optional: seconds to wait for parsing (default 300)
101
+ )
102
+ ```
103
+
104
+ ### How it works
105
+
106
+ 1. The SDK generates source code from the live module (LM config, signature, types)
107
+ 2. `POST /api/v1/deployments` creates a deployment and returns a presigned S3 upload URL
108
+ 3. The source ZIP is uploaded directly to S3
109
+ 4. The server-side parser extracts the program and LM configuration
110
+ 5. The SDK polls until status is `ready`, then returns the `deployment_id`
111
+
112
+ The deployed program's LM model string (e.g. `groq/llama-3.1-8b-instant`) and configuration (temperature, max_tokens) are extracted automatically from the source.
113
+
114
+ ## Custom Spans
115
+
116
+ Add custom spans to trace non-DSPy code:
117
+
118
+ ### Using the decorator
119
+
120
+ ```python
121
+ from cmpnd import trace, SpanType
122
+
123
+ @trace(name="fetch_documents", span_type=SpanType.RETRIEVE)
124
+ def fetch_documents(query: str) -> list[str]:
125
+ # Your retrieval logic
126
+ return documents
127
+ ```
128
+
129
+ ### Using the context manager
130
+
131
+ ```python
132
+ from cmpnd import start_span, SpanType
133
+
134
+ def run_pipeline(query: str):
135
+ with start_span("vector_search", span_type=SpanType.RETRIEVE) as span:
136
+ span.set_attribute("index", "my-faiss-index")
137
+ docs = search(query)
138
+ span.set_outputs({"doc_count": len(docs)})
139
+
140
+ return generate(query, docs)
141
+ ```
142
+
143
+ ## What Gets Traced
144
+
145
+ The SDK automatically captures:
146
+
147
+ ### Module Execution
148
+ - Module type (Predict, ChainOfThought, ReAct, etc.)
149
+ - Signature name and instructions
150
+ - Input/output field names
151
+ - Demo count
152
+
153
+ ### LM Calls
154
+ - Model name and provider
155
+ - Token usage (prompt, completion, total)
156
+ - Request/response content
157
+
158
+ ### Adapters
159
+ - Format and parse operations
160
+ - Input/output transformations
161
+
162
+ ### Tools
163
+ - Tool name and description
164
+ - Invocation inputs/outputs
165
+
166
+ ### Evaluations
167
+ - Evaluation scores
168
+ - Program being evaluated
169
+
170
+ ## Span Types
171
+
172
+ Available span types for categorization:
173
+
174
+ - `SpanType.MODULE` - Generic DSPy module
175
+ - `SpanType.PREDICT` - Predict module
176
+ - `SpanType.CHAIN_OF_THOUGHT` - ChainOfThought module
177
+ - `SpanType.REACT` - ReAct agent
178
+ - `SpanType.RETRIEVE` - Retrieval operations
179
+ - `SpanType.LM_CALL` - Language model calls
180
+ - `SpanType.ADAPTER_FORMAT` - Adapter formatting
181
+ - `SpanType.ADAPTER_PARSE` - Adapter parsing
182
+ - `SpanType.TOOL` - Tool invocations
183
+ - `SpanType.EVALUATION` - Evaluation runs
184
+
185
+ ## API Reference
186
+
187
+ ### `cmpnd.configure()`
188
+
189
+ Initialize the SDK with your API key and options.
190
+
191
+ ### `cmpnd.auto_instrument()`
192
+
193
+ Automatically register the callback with DSPy.
194
+
195
+ ### `cmpnd.CmpndCallback`
196
+
197
+ The callback class for manual registration:
198
+
199
+ ```python
200
+ import dspy
201
+ import cmpnd
202
+
203
+ cmpnd.configure(api_key="ct_xxx")
204
+ dspy.configure(callbacks=[cmpnd.CmpndCallback()])
205
+ ```
206
+
207
+ ### `cmpnd.deploy()`
208
+
209
+ Deploy a DSPy module to the cmpnd platform. Returns the `deployment_id`.
210
+
211
+ ### `cmpnd.trace()`
212
+
213
+ Decorator for custom traced functions.
214
+
215
+ ### `cmpnd.start_span()`
216
+
217
+ Context manager for custom spans.
218
+
219
+ ### `cmpnd.get_current_trace()`
220
+
221
+ Get the current trace (if any).
222
+
223
+ ### `cmpnd.get_current_span()`
224
+
225
+ Get the current span (if any).
226
+
227
+ ### `cmpnd.shutdown_exporter()`
228
+
229
+ Gracefully shutdown the background exporter.
230
+
231
+ ## License
232
+
233
+ MIT