c3-charm 0.1.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.
c3_charm-0.1.0/LICENSE ADDED
@@ -0,0 +1,191 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to the Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by the Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding any notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ Copyright 2025 C3 AI, Inc.
180
+
181
+ Licensed under the Apache License, Version 2.0 (the "License");
182
+ you may not use this file except in compliance with the License.
183
+ You may obtain a copy of the License at
184
+
185
+ http://www.apache.org/licenses/LICENSE-2.0
186
+
187
+ Unless required by applicable law or agreed to in writing, software
188
+ distributed under the License is distributed on an "AS IS" BASIS,
189
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190
+ See the License for the specific language governing permissions and
191
+ limitations under the License.
@@ -0,0 +1,392 @@
1
+ Metadata-Version: 2.3
2
+ Name: c3-charm
3
+ Version: 0.1.0
4
+ Summary: Python SDK for the CHARM time-series foundation model — embeddings, forecasting, and a downstream-task toolkit.
5
+ License: Apache-2.0
6
+ Keywords: time-series,embeddings,forecasting,foundation-model,anomaly-detection
7
+ Author: C3 AI
8
+ Author-email: opensource@c3.ai
9
+ Requires-Python: >=3.10
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
20
+ Classifier: Typing :: Typed
21
+ Provides-Extra: toolkit
22
+ Requires-Dist: datasetsforecast (>=0.1.0) ; extra == "toolkit"
23
+ Requires-Dist: dill (>=0.3.7) ; extra == "toolkit"
24
+ Requires-Dist: gin-config (>=0.5.0) ; extra == "toolkit"
25
+ Requires-Dist: httpx[http2] (>=0.25.0)
26
+ Requires-Dist: lightgbm (>=4.0.0) ; extra == "toolkit"
27
+ Requires-Dist: matplotlib (>=3.7.0) ; extra == "toolkit"
28
+ Requires-Dist: minisom (>=2.3.1) ; extra == "toolkit"
29
+ Requires-Dist: numpy (>=1.24.0) ; extra == "toolkit"
30
+ Requires-Dist: optuna (>=3.0.0) ; extra == "toolkit"
31
+ Requires-Dist: pandas (>=2.0.0) ; extra == "toolkit"
32
+ Requires-Dist: pyarrow (>=14.0.0) ; extra == "toolkit"
33
+ Requires-Dist: python-dotenv (>=1.0.0)
34
+ Requires-Dist: requests (>=2.31.0)
35
+ Requires-Dist: scienceplots (>=2.0.0) ; extra == "toolkit"
36
+ Requires-Dist: scikit-learn (>=1.3.0) ; extra == "toolkit"
37
+ Requires-Dist: seaborn (>=0.13.0) ; extra == "toolkit"
38
+ Requires-Dist: tensordict (>=0.1.0) ; extra == "toolkit"
39
+ Requires-Dist: torch (>=2.0.0) ; extra == "toolkit"
40
+ Requires-Dist: tqdm (>=4.60.0)
41
+ Project-URL: Documentation, https://github.com/c3ai/c3-charm#readme
42
+ Project-URL: Homepage, https://c3.ai
43
+ Project-URL: Issues, https://github.com/c3ai/c3-charm/issues
44
+ Project-URL: Repository, https://github.com/c3ai/c3-charm
45
+ Description-Content-Type: text/markdown
46
+
47
+ # c3-charm
48
+
49
+ [![PyPI version](https://img.shields.io/pypi/v/c3-charm.svg)](https://pypi.org/project/c3-charm/)
50
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
51
+ [![Python](https://img.shields.io/pypi/pyversions/c3-charm.svg)](https://pypi.org/project/c3-charm/)
52
+
53
+ A Python SDK for interacting with the CHARM time-series API. It provides a simple interface for **embeddings** (multivariate time series → vectors) and **forecast/backcast** (predict future or reconstruct past steps).
54
+
55
+ ## What is CHARM?
56
+
57
+ CHARM (CHannel Aware Representation Model) is a foundation model specifically designed for multi-variate time series data. It generates high-quality embeddings that capture the semantic essence of time series segments, making them ideal for various downstream applications:
58
+
59
+ - **Anomaly detection**: Identify unusual patterns in time series data
60
+ - **Clustering**: Group similar time series together
61
+ - **Classification**: Categorize time series into predefined classes
62
+ - **Forecasting**: Improve time series predictions
63
+ - **Similarity search**: Find similar patterns across large datasets
64
+
65
+ ## Data shapes and API reference
66
+
67
+ Use this section to shape your inputs and interpret outputs. The API has two endpoints; both expect the same **time series format**.
68
+
69
+ ### Shared input format (embeddings and forecast/backcast)
70
+
71
+ Every request uses:
72
+
73
+ - **`descriptions`**: List of **channel names** per time series.
74
+ - Type: `list[list[str]]`.
75
+ - Shape: **(N, C)** — N samples, each with C channel names.
76
+ - Example: `[["engine", "temperature"], ["fan", "speed"]]` for N=2, C=2.
77
+
78
+ - **`ts_array`**: List of **time series values** (one per sample).
79
+ - Type: `list[list[list[float]]]`.
80
+ - Shape: **(N, T, C)** — N samples, each of T timesteps × C channels.
81
+ - **All samples in a single request must have the same T and the same C.**
82
+ - Example: one sample with 10 timesteps and 2 channels → a list of 10 rows, each row a list of 2 floats.
83
+
84
+ **Conventions:**
85
+
86
+ - **N** = batch size (number of time series in the call).
87
+ - **T** = timesteps per series (same for all). Must be **≥ 1** and **< 1500** (SDK enforces T < 1500).
88
+ - **C** = channels per series (same for all). Must be **< 1500**.
89
+ - **N × C × T ≤ 500,000** per request (client may split into multiple requests via batching).
90
+
91
+ ### 1. Embeddings — `client.embeddings.create` / `client.embeddings.async_create`
92
+
93
+ **Endpoint:** `POST {base_url}/predict`
94
+
95
+ | | |
96
+ |--|--|
97
+ | **Input** | `descriptions` (N×C), `ts_array` (N×T×C). See shared format above. |
98
+ | **Output** | `response.embeds`: one vector per time series. Shape **(N, D)** where D = embedding dimension (model-dependent). |
99
+ | **Return type** | `EmbeddingsResponse`: `.embeds`, `.model`, `.usage`, `.raw`. |
100
+
101
+ Use `return_tensors="list"`, `"np"`, or `"torch"` to get lists, a NumPy array, or a PyTorch tensor.
102
+
103
+ ### 2. Forecast — `client.prediction.create` / `client.prediction.async_create`
104
+
105
+ **Endpoint:** `POST {base_url}/forecast`
106
+
107
+ **Input:** Same `descriptions` and `ts_array` as above, plus:
108
+
109
+ - **`target_len`** (int, required, non-zero):
110
+ - **Positive** → forecast that many steps **ahead** (e.g. `10` = next 10 steps).
111
+ - **Negative** → backcast that many steps **in the past** (e.g. `-8` = last 8 steps).
112
+
113
+ | | |
114
+ |--|--|
115
+ | **Output** | `response.denormalized_predictions`: predictions in original scale. Shape **(N, abs(target_len), C, Q)** where Q = number of quantiles (e.g. 21). |
116
+ | **Also** | `response.predictions` (normalized), `response.data` (input echo). Same batch dimension N. |
117
+ | **Return type** | `ForecastResponse`: `.denormalized_predictions`, `.predictions`, `.data`, `.target_len`, `.mode` (`"forecast"` or `"backcast"`), `.raw`. |
118
+
119
+ Use `return_tensors="list"`, `"np"`, or `"torch"` for all tensor fields.
120
+
121
+ ### Quick reference
122
+
123
+ | Functionality | Method | Input | Output shape (main) |
124
+ |---------------|--------|--------|---------------------|
125
+ | Embeddings | `embeddings.create` / `async_create` | `descriptions` (N×C), `ts_array` (N×T×C) | **(N, D)** |
126
+ | Forecast | `prediction.create` / `async_create` | Same + `target_len` > 0 | **(N, target_len, C, Q)** |
127
+ | Backcast | `prediction.create` / `async_create` | Same + `target_len` < 0 | **(N, abs(target_len), C, Q)** |
128
+
129
+ ## Installation
130
+
131
+ Install from PyPI:
132
+
133
+ ```bash
134
+ pip install c3-charm
135
+ ```
136
+
137
+ To include the downstream-task toolkit (models, trainers, datasets):
138
+
139
+ ```bash
140
+ pip install c3-charm[toolkit]
141
+ ```
142
+
143
+ Or install from source with Poetry:
144
+
145
+ ```bash
146
+ git clone https://github.com/c3ai/c3-charm.git
147
+ cd c3-charm
148
+ poetry install # core SDK only
149
+ poetry install --with toolkit # include toolkit dependencies
150
+ ```
151
+
152
+ ## Dependencies
153
+
154
+ **Core** (installed by default):
155
+ - `requests` — synchronous HTTP client
156
+ - `httpx[http2]` — asynchronous HTTP/2 client
157
+ - `python-dotenv` — `.env` file loading
158
+ - `tqdm` — progress bars
159
+
160
+ **Toolkit** (optional, `pip install c3-charm[toolkit]`):
161
+ - `torch`, `tensordict` — tensor operations
162
+ - `numpy`, `pandas` — data manipulation
163
+ - `matplotlib`, `seaborn`, `scienceplots` — visualization
164
+ - `scikit-learn` — ML utilities
165
+ - `lightgbm`, `optuna` — gradient boosting & hyperparameter tuning
166
+ - `gin-config` — experiment configuration
167
+
168
+ ## Quick Start
169
+
170
+ ```python
171
+ from charm import CharmClient
172
+ from dotenv import load_dotenv
173
+ import os
174
+
175
+ # Load environment variables from .env file
176
+ load_dotenv()
177
+
178
+ # Get API key and base URL from environment variables
179
+ api_key = os.getenv("CHARM_API_KEY", "your-api-key")
180
+ base_url = os.getenv("CHARM_BASE_URL", "http://your-server-url:8080")
181
+
182
+ # Create a client
183
+ client = CharmClient(
184
+ base_url=base_url,
185
+ api_key=api_key,
186
+ timeout=30, # Increased timeout for potentially large requests
187
+ max_retries=3, # Automatically retry failed requests
188
+ http2=True, # Enable HTTP/2 for async requests (default)
189
+ )
190
+
191
+ # Generate embeddings for time series data (synchronous with progress bar)
192
+ response = client.embeddings.create(
193
+ descriptions=[["engine", "temperature"], ["fan", "speed"]],
194
+ ts_array=[
195
+ # First time series (10 timesteps, 2 channels)
196
+ [
197
+ [0.1, 0.2], [0.3, 0.4], [0.5, 0.6], [0.7, 0.8], [0.9, 1.0],
198
+ [1.1, 1.2], [1.3, 1.4], [1.5, 1.6], [1.7, 1.8], [1.9, 2.0]
199
+ ],
200
+ # Second time series (10 timesteps, 2 channels)
201
+ [
202
+ [2.1, 2.2], [2.3, 2.4], [2.5, 2.6], [2.7, 2.8], [2.9, 3.0],
203
+ [3.1, 3.2], [3.3, 3.4], [3.5, 3.6], [3.7, 3.8], [3.9, 4.0]
204
+ ]
205
+ ],
206
+ batch_size=32, # Process in batches of 32 (for large datasets)
207
+ return_tensors="np", # Options: "list", "np", "torch"
208
+ progress=True # Show progress bar (default: True)
209
+ )
210
+
211
+ # Access the embeddings
212
+ embeddings = response.embeds
213
+ print(f"Model: {response.model}")
214
+ print(f"Embeddings shape: {embeddings.shape}")
215
+
216
+ # Asynchronous processing (much faster for large datasets)
217
+ import asyncio
218
+
219
+ async def generate_embeddings_async():
220
+ response = await client.embeddings.async_create(
221
+ descriptions=[["engine", "temperature"], ["fan", "speed"]],
222
+ ts_array=[
223
+ # Same time series data as above
224
+ [
225
+ [0.1, 0.2], [0.3, 0.4], [0.5, 0.6], [0.7, 0.8], [0.9, 1.0],
226
+ [1.1, 1.2], [1.3, 1.4], [1.5, 1.6], [1.7, 1.8], [1.9, 2.0]
227
+ ],
228
+ [
229
+ [2.1, 2.2], [2.3, 2.4], [2.5, 2.6], [2.7, 2.8], [2.9, 3.0],
230
+ [3.1, 3.2], [3.3, 3.4], [3.5, 3.6], [3.7, 3.8], [3.9, 4.0]
231
+ ]
232
+ ],
233
+ max_B_per_request=32, # Process 32 time series per API call
234
+ concurrency_per_call=8, # Run up to 8 concurrent API calls
235
+ return_tensors="np", # Options: "list", "np", "torch"
236
+ progress=True # Show progress bar (default: True)
237
+ )
238
+ return response
239
+
240
+ # Run the async function
241
+ response_async = asyncio.run(generate_embeddings_async())
242
+ ```
243
+
244
+ ### Time Series Forecasting
245
+
246
+ The CHARM SDK also supports time series forecasting through the `/forecast` endpoint:
247
+
248
+ ```python
249
+ # Forecasting (predict future values)
250
+ response = client.prediction.create(
251
+ descriptions=[["sensor_A", "sensor_B"]],
252
+ ts_array=[[
253
+ [1.0, 2.0],
254
+ [1.1, 2.1],
255
+ [1.2, 2.2],
256
+ [1.3, 2.3],
257
+ [1.4, 2.4],
258
+ [1.5, 2.5],
259
+ [1.6, 2.6],
260
+ [1.7, 2.7],
261
+ [1.8, 2.8],
262
+ [1.9, 2.9],
263
+ ]],
264
+ target_len=10, # Forecast 10 steps ahead
265
+ return_tensors="np"
266
+ )
267
+
268
+ # Access the denormalized predictions
269
+ forecast = response.denormalized_predictions
270
+ print(f"Forecast shape: {forecast.shape}") # e.g., (1, 10, 2, Q) where Q is number of quantiles
271
+ print(f"Mode: {response.mode}") # "forecast"
272
+
273
+ # Backcasting (reconstruct past values)
274
+ response = client.prediction.create(
275
+ descriptions=[["sensor_A", "sensor_B"]],
276
+ ts_array=[[
277
+ [1.0, 2.0],
278
+ [1.1, 2.1],
279
+ [1.2, 2.2],
280
+ [1.3, 2.3],
281
+ [1.4, 2.4],
282
+ [1.5, 2.5],
283
+ [1.6, 2.6],
284
+ [1.7, 2.7],
285
+ [1.8, 2.8],
286
+ [1.9, 2.9],
287
+ ]],
288
+ target_len=-8, # Reconstruct last 8 steps
289
+ return_tensors="np"
290
+ )
291
+
292
+ reconstructed = response.denormalized_predictions
293
+ print(f"Mode: {response.mode}") # "backcast"
294
+ ```
295
+
296
+ **Note:** `target_len` is required and must be non-zero:
297
+ - **Positive values**: Forecast future timesteps (e.g., `target_len=10`)
298
+ - **Negative values**: Reconstruct past timesteps (e.g., `target_len=-8`)
299
+
300
+ ### Using a .env file
301
+
302
+ You can create a `.env` file in your project directory with the following content:
303
+
304
+ ```
305
+ CHARM_API_KEY=your-api-key
306
+ CHARM_BASE_URL=http://your-server-url:8080
307
+ ```
308
+
309
+ This allows you to keep your credentials separate from your code and avoid hardcoding sensitive information.
310
+
311
+ ## Features
312
+
313
+ - OpenAI-style SDK for CHARM time-series embeddings
314
+ - API key authentication
315
+ - Automatic retries with exponential backoff
316
+ - Configurable timeouts
317
+ - Client-side batching for large datasets
318
+ - Flexible return types (Python lists, NumPy arrays, or PyTorch tensors)
319
+ - Both synchronous and asynchronous methods in a single client:
320
+ - `client.embeddings.create()` - Synchronous method with progress tracking
321
+ - `await client.embeddings.async_create()` - Asynchronous method with concurrent batch processing
322
+ - `client.prediction.create()` - Synchronous prediction method
323
+ - `await client.prediction.async_create()` - Asynchronous prediction method
324
+ - Progress tracking with tqdm for both sync and async methods
325
+ - HTTP/2 support for asynchronous requests
326
+ - Comprehensive error handling with specific exception types
327
+ - Binary protocol for efficient data transfer (handles raw fp16 bytes from server)
328
+
329
+ ## Performance Considerations
330
+
331
+ - **Synchronous Method** (`client.embeddings.create`): Suitable for smaller datasets or when simplicity is preferred. Processes batches sequentially, which can be slow for large datasets. Now includes progress tracking with tqdm. Avoid sending very large batches (>100 samples) in a single request to prevent timeouts.
332
+
333
+ - **Asynchronous Method** (`client.embeddings.async_create`): Recommended for large datasets. Significantly faster due to concurrent processing with features like:
334
+ - Parallel batch processing
335
+ - Bounded concurrency to avoid overwhelming the server
336
+ - Progress tracking for long-running operations
337
+ - HTTP/2 support for efficient connections
338
+
339
+ ## Payload limitations
340
+
341
+ The SDK and API enforce:
342
+
343
+ - **Timesteps per series:** T ≥ 1 and **T < 1500** (enforced by SDK).
344
+ - **Channels per series:** **C < 1500** (see [usage guide](./usage.md)).
345
+ - **Per-request size:** **N × C × T ≤ 500,000** (client-side batching can split larger jobs).
346
+ - **Batch consistency:** All time series in a single request must have the **same T** and the **same C**.
347
+
348
+ See the [Data shapes and API reference](#data-shapes-and-api-reference) section above for input/output shapes.
349
+
350
+ ## Requirements
351
+
352
+ - Python 3.10+
353
+ - See [Installation](#installation) for dependency details
354
+
355
+ ## Testing
356
+
357
+ The CHARM SDK uses pytest for testing. To run the tests:
358
+
359
+ ```bash
360
+ # Install pytest if not already installed
361
+ pip install pytest
362
+
363
+ # Run all tests
364
+ python -m pytest tests/
365
+
366
+ # Run specific test file
367
+ python -m pytest tests/test_utils.py
368
+
369
+ # Run with verbose output
370
+ python -m pytest -v tests/
371
+ ```
372
+
373
+ ## Documentation
374
+
375
+ For detailed documentation, see the [examples](./docs/notebooks) directory, the [usage guide](./usage.md), the [quickstart guide](./quickstart.md), and the docstrings in the code.
376
+
377
+ ## Example Applications
378
+
379
+ The CHARM SDK can be used for various time series applications:
380
+
381
+ 1. **Anomaly Detection**: Identify unusual patterns in sensor data, network traffic, or financial transactions
382
+ 2. **Time Series Clustering**: Group similar time series patterns for market segmentation or behavior analysis
383
+ 3. **Classification**: Categorize time series data for predictive maintenance or activity recognition
384
+ 4. **Similarity Search**: Find similar patterns across large datasets for pattern discovery
385
+ 5. **Forecasting**: Predict future values or reconstruct past values in time series data
386
+
387
+ Check out the notebooks in the `docs/notebooks` directory for detailed examples of these applications.
388
+
389
+ ## License
390
+
391
+ This project is licensed under the Apache License 2.0 — see the [LICENSE](LICENSE) file for details.
392
+