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 +191 -0
- c3_charm-0.1.0/PKG-INFO +392 -0
- c3_charm-0.1.0/README.md +345 -0
- c3_charm-0.1.0/pyproject.toml +78 -0
- c3_charm-0.1.0/src/charm/__init__.py +55 -0
- c3_charm-0.1.0/src/charm/client.py +1399 -0
- c3_charm-0.1.0/src/charm/errors.py +98 -0
- c3_charm-0.1.0/src/charm/models.py +99 -0
- c3_charm-0.1.0/src/charm/utils.py +168 -0
- c3_charm-0.1.0/src/charm_toolkit/BaseTimesSeries.py +536 -0
- c3_charm-0.1.0/src/charm_toolkit/Data.py +192 -0
- c3_charm-0.1.0/src/charm_toolkit/Datasets.py +357 -0
- c3_charm-0.1.0/src/charm_toolkit/EmbeddingUtils.py +142 -0
- c3_charm-0.1.0/src/charm_toolkit/Plots.py +193 -0
- c3_charm-0.1.0/src/charm_toolkit/Trainer.py +252 -0
- c3_charm-0.1.0/src/charm_toolkit/__init__.py +33 -0
- c3_charm-0.1.0/src/charm_toolkit/models.py +757 -0
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.
|
c3_charm-0.1.0/PKG-INFO
ADDED
|
@@ -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
|
+
[](https://pypi.org/project/c3-charm/)
|
|
50
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
51
|
+
[](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
|
+
|