itstheraj commited on
Commit
3a6f8cc
·
0 Parent(s):

initial commit

Browse files
.gitattributes ADDED
@@ -0,0 +1 @@
 
 
1
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ .ruff_cache/
2
+ .venv/
3
+ __pycache__/
4
+ *.swp
5
+ *.kate-swp
6
+ *~
LICENSE ADDED
@@ -0,0 +1,474 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Lowdown Labs Lovely License 1.0 (LLLL-1.0)
2
+
3
+ Everything in this repository (the model weights, the configuration, and the code) is
4
+ released by Lowdown Labs under two licenses that apply at the same time. To use this work
5
+ you must comply with BOTH of them. Where a term in one is stricter than the other, the
6
+ stricter term controls. "Lowdown Labs Lovely License 1.0" is a convenience name for this
7
+ exact pair; it is not a new legal instrument.
8
+
9
+ SPDX-License-Identifier: CC-BY-NC-4.0 AND LicenseRef-Hippocratic-3.0
10
+
11
+ Commercial licensing. The grant below is non-commercial only. Commercial licenses are
12
+ sold separately by Lowdown Labs on a per-customer basis. To use this work, its weights, or
13
+ its outputs for any commercial purpose, contact Lowdown Labs to purchase a commercial
14
+ license. A commercial license does not remove the Hippocratic ethical-use obligations in
15
+ Part 2; those apply to commercial licensees as well.
16
+
17
+ ==============================================================================
18
+ Part 1 of 2. Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)
19
+ ==============================================================================
20
+
21
+ You may share and adapt this work for non-commercial purposes, with attribution to
22
+ Lowdown Labs. Commercial use is not granted under this license.
23
+
24
+ Full legal text: https://creativecommons.org/licenses/by-nc/4.0/legalcode
25
+ Plain-language summary: https://creativecommons.org/licenses/by-nc/4.0/
26
+ SPDX-License-Identifier: CC-BY-NC-4.0
27
+
28
+ ==============================================================================
29
+ Part 2 of 2. The Hippocratic License 3.0 (ethical use)
30
+ ==============================================================================
31
+
32
+ Module set enabled: bds, cl, eco, extr, ffd, law, media, mil, my, soc, sup, sv, usta.
33
+ Canonical build: https://firstdonoharm.dev/build/?modules=bds,cl,eco,extr,ffd,law,media,mil,my,soc,sup,sv,usta
34
+
35
+ The verbatim official Hippocratic License 3.0 text for exactly this module set follows,
36
+ between the markers.
37
+
38
+ --------------------- BEGIN OFFICIAL HIPPOCRATIC LICENSE 3.0 TEXT ---------------------
39
+
40
+ HIPPOCRATIC LICENSE
41
+
42
+ Version 3.0, October 2021
43
+
44
+ https://firstdonoharm.dev/version/3/0/bds-cl-eco-extr-ffd-law-media-mil-my-soc-sup-sv-usta.txt
45
+
46
+ TERMS AND CONDITIONS
47
+
48
+ TERMS AND CONDITIONS FOR USE, COPY, MODIFICATION, PREPARATION OF DERIVATIVE
49
+ WORK, REPRODUCTION, AND DISTRIBUTION:
50
+
51
+ 1. DEFINITIONS:
52
+
53
+ This section defines certain terms used throughout this license agreement.
54
+
55
+ 1.1. “License” means the terms and conditions, as stated herein, for use, copy,
56
+ modification, preparation of derivative work, reproduction, and distribution of
57
+ Software (as defined below).
58
+
59
+ 1.2. “Licensor” means the copyright and/or patent owner or entity authorized by
60
+ the copyright and/or patent owner that is granting the License.
61
+
62
+ 1.3. “Licensee” means the individual or entity exercising permissions granted by
63
+ this License, including the use, copy, modification, preparation of derivative
64
+ work, reproduction, and distribution of Software (as defined below).
65
+
66
+ 1.4. “Software” means any copyrighted work, including but not limited to
67
+ software code, authored by Licensor and made available under this License.
68
+
69
+ 1.5. “Supply Chain” means the sequence of processes involved in the production
70
+ and/or distribution of a commodity, good, or service offered by the Licensee.
71
+
72
+ 1.6. “Supply Chain Impacted Party” or “Supply Chain Impacted Parties” means any
73
+ person(s) directly impacted by any of Licensee’s Supply Chain, including the
74
+ practices of all persons or entities within the Supply Chain prior to a good or
75
+ service reaching the Licensee.
76
+
77
+ 1.7. “Duty of Care” is defined by its use in tort law, delict law, and/or
78
+ similar bodies of law closely related to tort and/or delict law, including
79
+ without limitation, a requirement to act with the watchfulness, attention,
80
+ caution, and prudence that a reasonable person in the same or similar
81
+ circumstances would use towards any Supply Chain Impacted Party.
82
+
83
+ 1.8. “Worker” is defined to include any and all permanent, temporary, and agency
84
+ workers, as well as piece-rate, salaried, hourly paid, legal young (minors),
85
+ part-time, night, and migrant workers.
86
+
87
+ 2. INTELLECTUAL PROPERTY GRANTS:
88
+
89
+ This section identifies intellectual property rights granted to a Licensee.
90
+
91
+ 2.1. Grant of Copyright License: Subject to the terms and conditions of this
92
+ License, Licensor hereby grants to Licensee a worldwide, non-exclusive,
93
+ no-charge, royalty-free copyright license to use, copy, modify, prepare
94
+ derivative work, reproduce, or distribute the Software, Licensor authored
95
+ modified software, or other work derived from the Software.
96
+
97
+ 2.2. Grant of Patent License: Subject to the terms and conditions of this
98
+ License, Licensor hereby grants Licensee a worldwide, non-exclusive, no-charge,
99
+ royalty-free patent license to make, have made, use, offer to sell, sell,
100
+ import, and otherwise transfer Software.
101
+
102
+ 3. ETHICAL STANDARDS:
103
+
104
+ This section lists conditions the Licensee must comply with in order to have
105
+ rights under this License.
106
+
107
+ The rights granted to the Licensee by this License are expressly made subject to
108
+ the Licensee’s ongoing compliance with the following conditions:
109
+
110
+ * 3.1. The Licensee SHALL NOT, whether directly or indirectly, through agents
111
+ or assigns:
112
+
113
+ * 3.1.1. Infringe upon any person’s right to life or security of person,
114
+ engage in extrajudicial killings, or commit murder, without lawful cause
115
+ (See Article 3, United Nations Universal Declaration of Human Rights;
116
+ Article 6, International Covenant on Civil and Political Rights)
117
+
118
+ * 3.1.2. Hold any person in slavery, servitude, or forced labor (See Article
119
+ 4, United Nations Universal Declaration of Human Rights; Article 8,
120
+ International Covenant on Civil and Political Rights);
121
+
122
+ * 3.1.3. Contribute to the institution of slavery, slave trading, forced
123
+ labor, or unlawful child labor (See Article 4, United Nations Universal
124
+ Declaration of Human Rights; Article 8, International Covenant on Civil and
125
+ Political Rights);
126
+
127
+ * 3.1.4. Torture or subject any person to cruel, inhumane, or degrading
128
+ treatment or punishment (See Article 5, United Nations Universal
129
+ Declaration of Human Rights; Article 7, International Covenant on Civil and
130
+ Political Rights);
131
+
132
+ * 3.1.5. Discriminate on the basis of sex, gender, sexual orientation, race,
133
+ ethnicity, nationality, religion, caste, age, medical disability or
134
+ impairment, and/or any other like circumstances (See Article 7, United
135
+ Nations Universal Declaration of Human Rights; Article 2, International
136
+ Covenant on Economic, Social and Cultural Rights; Article 26, International
137
+ Covenant on Civil and Political Rights);
138
+
139
+ * 3.1.6. Prevent any person from exercising his/her/their right to seek an
140
+ effective remedy by a competent court or national tribunal (including
141
+ domestic judicial systems, international courts, arbitration bodies, and
142
+ other adjudicating bodies) for actions violating the fundamental rights
143
+ granted to him/her/them by applicable constitutions, applicable laws, or by
144
+ this License (See Article 8, United Nations Universal Declaration of Human
145
+ Rights; Articles 9 and 14, International Covenant on Civil and Political
146
+ Rights);
147
+
148
+ * 3.1.7. Subject any person to arbitrary arrest, detention, or exile (See
149
+ Article 9, United Nations Universal Declaration of Human Rights; Article 9,
150
+ International Covenant on Civil and Political Rights);
151
+
152
+ * 3.1.8. Subject any person to arbitrary interference with a person’s
153
+ privacy, family, home, or correspondence without the express written
154
+ consent of the person (See Article 12, United Nations Universal Declaration
155
+ of Human Rights; Article 17, International Covenant on Civil and Political
156
+ Rights);
157
+
158
+ * 3.1.9. Arbitrarily deprive any person of his/her/their property (See
159
+ Article 17, United Nations Universal Declaration of Human Rights);
160
+
161
+ * 3.1.10. Forcibly remove indigenous peoples from their lands or territories
162
+ or take any action with the aim or effect of dispossessing indigenous
163
+ peoples from their lands, territories, or resources, including without
164
+ limitation the intellectual property or traditional knowledge of indigenous
165
+ peoples, without the free, prior, and informed consent of indigenous
166
+ peoples concerned (See Articles 8 and 10, United Nations Declaration on the
167
+ Rights of Indigenous Peoples);
168
+ * 3.1.11. Fossil Fuel Divestment: Be an individual or entity, or a
169
+ representative, agent, affiliate, successor, attorney, or assign of an
170
+ individual or entity, on the FFI Solutions Carbon Underground 200 list
171
+ [https://www.ffisolutions.com/research-analytics-index-solutions/research-screening/the-carbon-underground-200/?cn-reloaded=1];
172
+
173
+ * 3.1.12. Ecocide: Commit ecocide:
174
+
175
+ * 3.1.12.1. For the purpose of this section, “ecocide” means unlawful or
176
+ wanton acts committed with knowledge that there is a substantial
177
+ likelihood of severe and either widespread or long-term damage to the
178
+ environment being caused by those acts;
179
+
180
+ * 3.1.12.2. For the purpose of further defining ecocide and the terms
181
+ contained in the previous paragraph:
182
+
183
+ * 3.1.12.2.1. “Wanton” means with reckless disregard for damage which
184
+ would be clearly excessive in relation to the social and economic
185
+ benefits anticipated;
186
+
187
+ * 3.1.12.2.2. “Severe” means damage which involves very serious adverse
188
+ changes, disruption, or harm to any element of the environment,
189
+ including grave impacts on human life or natural, cultural, or
190
+ economic resources;
191
+
192
+ * 3.1.12.2.3. “Widespread” means damage which extends beyond a limited
193
+ geographic area, crosses state boundaries, or is suffered by an entire
194
+ ecosystem or species or a large number of human beings;
195
+
196
+ * 3.1.12.2.4. “Long-term” means damage which is irreversible or which
197
+ cannot be redressed through natural recovery within a reasonable
198
+ period of time; and
199
+
200
+ * 3.1.12.2.5. “Environment” means the earth, its biosphere, cryosphere,
201
+ lithosphere, hydrosphere, and atmosphere, as well as outer space
202
+
203
+ (See Section II, Independent Expert Panel for the Legal Definition of
204
+ Ecocide, Stop Ecocide Foundation and the Promise Institute for Human
205
+ Rights at UCLA School of Law, June 2021);
206
+
207
+ * 3.1.13. Extractive Industries: Be an individual or entity, or a
208
+ representative, agent, affiliate, successor, attorney, or assign of an
209
+ individual or entity, that engages in fossil fuel or mineral exploration,
210
+ extraction, development, or sale;
211
+
212
+ * 3.1.14. Boycott / Divestment / Sanctions: Be an individual or entity, or a
213
+ representative, agent, affiliate, successor, attorney, or assign of an
214
+ individual or entity, identified by the Boycott, Divestment, Sanctions
215
+ (“BDS”) movement on its website (https://bdsmovement.net/
216
+ [https://bdsmovement.net/] and
217
+ https://bdsmovement.net/get-involved/what-to-boycott
218
+ [https://bdsmovement.net/get-involved/what-to-boycott]) as a target for
219
+ boycott;
220
+
221
+ * 3.1.15. Myanmar: Be an individual or entity that:
222
+
223
+ * 3.1.15.1. engages in any commercial transactions with the
224
+ Myanmar/Burmese military junta; or
225
+
226
+ * 3.1.15.2. is a representative, agent, affiliate, successor, attorney, or
227
+ assign of the Myanmar/Burmese government;
228
+
229
+ * 3.1.16. US Tariff Act: Be an individual or entity:
230
+
231
+ * 3.1.16.1. which U.S. Customs and Border Protection (CBP) has currently
232
+ issued a Withhold Release Order (WRO) or finding against based on
233
+ reasonable suspicion of forced labor; or
234
+
235
+ * 3.1.16.2. that is a representative, agent, affiliate, successor,
236
+ attorney, or assign of an individual or entity that does business with
237
+ an individual or entity which currently has a WRO or finding from CBP
238
+ issued against it based on reasonable suspicion of forced labor;
239
+
240
+ * 3.1.17. Mass Surveillance: Be a government agency or multinational
241
+ corporation, or a representative, agent, affiliate, successor, attorney,
242
+ or assign of a government or multinational corporation, which participates
243
+ in mass surveillance programs;
244
+
245
+ * 3.1.18. Military Activities: Be an entity or a representative, agent,
246
+ affiliate, successor, attorney, or assign of an entity which conducts
247
+ military activities;
248
+
249
+ * 3.1.19. Law Enforcement: Be an individual or entity, or a representative,
250
+ agent, affiliate, successor, attorney, or assign of an individual or
251
+ entity, that provides good or services to, or otherwise enters into any
252
+ commercial contracts with, any local, state, or federal law enforcement
253
+ agency;
254
+
255
+ * 3.1.20. Media: Be an individual or entity, or a representative, agent,
256
+ affiliate, successor, attorney, or assign of an individual or entity, that
257
+ broadcasts messages promoting killing, torture, or other forms of extreme
258
+ violence;
259
+
260
+ * 3.1.21. Interfere with Workers’ free exercise of the right to organize and
261
+ associate (See Article 20, United Nations Universal Declaration of Human
262
+ Rights; C087 - Freedom of Association and Protection of the Right to
263
+ Organise Convention, 1948 (No. 87), International Labour Organization;
264
+ Article 8, International Covenant on Economic, Social and Cultural Rights);
265
+ and
266
+
267
+ * 3.1.22. Harm the environment in a manner inconsistent with local, state,
268
+ national, or international law.
269
+
270
+ * 3.2. The Licensee SHALL:
271
+
272
+ * 3.2.1. Social Auditing: Only use social auditing mechanisms that adhere to
273
+ Worker-Driven Social Responsibility Network’s Statement of Principles
274
+ (https://wsr-network.org/what-is-wsr/statement-of-principles/
275
+ [https://wsr-network.org/what-is-wsr/statement-of-principles/]) over
276
+ traditional social auditing mechanisms, to the extent the Licensee uses
277
+ any social auditing mechanisms at all;
278
+
279
+ * 3.2.2. Supply Chain: Provide clear, accessible supply chain data to the
280
+ public in accordance with the following conditions:
281
+
282
+ * 3.2.2.1. All data will be on Licensee’s website and/or, to the extent
283
+ Licensee is a representative, agent, affiliate, successor, attorney,
284
+ subsidiary, or assign, on Licensee’s principal’s or parent’s website or
285
+ some other online platform accessible to the public via an internet
286
+ search on a common internet search engine; and
287
+
288
+ * 3.2.2.2. Data published will include, where applicable, manufacturers,
289
+ top tier suppliers, subcontractors, cooperatives, component parts
290
+ producers, and farms;
291
+
292
+ * 3.2.3. Provide equal pay for equal work where the performance of such work
293
+ requires equal skill, effort, and responsibility, and which are performed
294
+ under similar working conditions, except where such payment is made
295
+ pursuant to:
296
+
297
+ * 3.2.3.1. A seniority system;
298
+
299
+ * 3.2.3.2. A merit system;
300
+
301
+ * 3.2.3.3. A system which measures earnings by quantity or quality of
302
+ production; or
303
+
304
+ * 3.2.3.4. A differential based on any other factor other than sex, gender,
305
+ sexual orientation, race, ethnicity, nationality, religion, caste, age,
306
+ medical disability or impairment, and/or any other like circumstances
307
+ (See 29 U.S.C.A. § 206(d)(1); Article 23, United Nations Universal
308
+ Declaration of Human Rights; Article 7, International Covenant on
309
+ Economic, Social and Cultural Rights; Article 26, International Covenant
310
+ on Civil and Political Rights); and
311
+
312
+ * 3.2.4. Allow for reasonable limitation of working hours and periodic
313
+ holidays with pay (See Article 24, United Nations Universal Declaration of
314
+ Human Rights; Article 7, International Covenant on Economic, Social and
315
+ Cultural Rights).
316
+
317
+ 4. SUPPLY CHAIN IMPACTED PARTIES:
318
+
319
+ This section identifies additional individuals or entities that a Licensee could
320
+ harm as a result of violating the Ethical Standards section, the condition that
321
+ the Licensee must voluntarily accept a Duty of Care for those individuals or
322
+ entities, and the right to a private right of action that those individuals or
323
+ entities possess as a result of violations of the Ethical Standards section.
324
+
325
+ 4.1. In addition to the above Ethical Standards, Licensee voluntarily accepts a
326
+ Duty of Care for Supply Chain Impacted Parties of this License, including
327
+ individuals and communities impacted by violations of the Ethical Standards. The
328
+ Duty of Care is breached when a provision within the Ethical Standards section
329
+ is violated by a Licensee, one of its successors or assigns, or by an individual
330
+ or entity that exists within the Supply Chain prior to a good or service
331
+ reaching the Licensee.
332
+
333
+ 4.2. Breaches of the Duty of Care, as stated within this section, shall create a
334
+ private right of action, allowing any Supply Chain Impacted Party harmed by the
335
+ Licensee to take legal action against the Licensee in accordance with applicable
336
+ negligence laws, whether they be in tort law, delict law, and/or similar bodies
337
+ of law closely related to tort and/or delict law, regardless if Licensee is
338
+ directly responsible for the harms suffered by a Supply Chain Impacted Party.
339
+ Nothing in this section shall be interpreted to include acts committed by
340
+ individuals outside of the scope of his/her/their employment.
341
+
342
+ 5. NOTICE: This section explains when a Licensee must notify others of the
343
+ License.
344
+
345
+ 5.1. Distribution of Notice: Licensee must ensure that everyone who receives a
346
+ copy of or uses any part of Software from Licensee, with or without changes,
347
+ also receives the License and the copyright notice included with Software (and
348
+ if included by the Licensor, patent, trademark, and attribution notice).
349
+ Licensee must ensure that License is prominently displayed so that any
350
+ individual or entity seeking to download, copy, use, or otherwise receive any
351
+ part of Software from Licensee is notified of this License and its terms and
352
+ conditions. Licensee must cause any modified versions of the Software to carry
353
+ prominent notices stating that Licensee changed the Software.
354
+
355
+ 5.2. Modified Software: Licensee is free to create modifications of the Software
356
+ and distribute only the modified portion created by Licensee, however, any
357
+ derivative work stemming from the Software or its code must be distributed
358
+ pursuant to this License, including this Notice provision.
359
+
360
+ 5.3. Recipients as Licensees: Any individual or entity that uses, copies,
361
+ modifies, reproduces, distributes, or prepares derivative work based upon the
362
+ Software, all or part of the Software’s code, or a derivative work developed by
363
+ using the Software, including a portion of its code, is a Licensee as defined
364
+ above and is subject to the terms and conditions of this License.
365
+
366
+ 6. REPRESENTATIONS AND WARRANTIES:
367
+
368
+ 6.1. Disclaimer of Warranty: TO THE FULL EXTENT ALLOWED BY LAW, THIS SOFTWARE
369
+ COMES “AS IS,” WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED, AND LICENSOR SHALL NOT
370
+ BE LIABLE TO ANY PERSON OR ENTITY FOR ANY DAMAGES OR OTHER LIABILITY ARISING
371
+ FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THIS LICENSE, UNDER ANY
372
+ LEGAL CLAIM.
373
+
374
+ 6.2. Limitation of Liability: LICENSEE SHALL HOLD LICENSOR HARMLESS AGAINST ANY
375
+ AND ALL CLAIMS, DEBTS, DUES, LIABILITIES, LIENS, CAUSES OF ACTION, DEMANDS,
376
+ OBLIGATIONS, DISPUTES, DAMAGES, LOSSES, EXPENSES, ATTORNEYS’ FEES, COSTS,
377
+ LIABILITIES, AND ALL OTHER CLAIMS OF EVERY KIND AND NATURE WHATSOEVER, WHETHER
378
+ KNOWN OR UNKNOWN, ANTICIPATED OR UNANTICIPATED, FORESEEN OR UNFORESEEN, ACCRUED
379
+ OR UNACCRUED, DISCLOSED OR UNDISCLOSED, ARISING OUT OF OR RELATING TO LICENSEE’S
380
+ USE OF THE SOFTWARE. NOTHING IN THIS SECTION SHOULD BE INTERPRETED TO REQUIRE
381
+ LICENSEE TO INDEMNIFY LICENSOR, NOR REQUIRE LICENSOR TO INDEMNIFY LICENSEE.
382
+
383
+ 7. TERMINATION
384
+
385
+ 7.1. Violations of Ethical Standards or Breaching Duty of Care: If Licensee
386
+ violates the Ethical Standards section or Licensee, or any other person or
387
+ entity within the Supply Chain prior to a good or service reaching the Licensee,
388
+ breaches its Duty of Care to Supply Chain Impacted Parties, Licensee must remedy
389
+ the violation or harm caused by Licensee within 30 days of being notified of the
390
+ violation or harm. If Licensee fails to remedy the violation or harm within 30
391
+ days, all rights in the Software granted to Licensee by License will be null and
392
+ void as between Licensor and Licensee.
393
+
394
+ 7.2. Failure of Notice: If any person or entity notifies Licensee in writing
395
+ that Licensee has not complied with the Notice section of this License, Licensee
396
+ can keep this License by taking all practical steps to comply within 30 days
397
+ after the notice of noncompliance. If Licensee does not do so, Licensee’s
398
+ License (and all rights licensed hereunder) will end immediately.
399
+
400
+ 7.3. Judicial Findings: In the event Licensee is found by a civil, criminal,
401
+ administrative, or other court of competent jurisdiction, or some other
402
+ adjudicating body with legal authority, to have committed actions which are in
403
+ violation of the Ethical Standards or Supply Chain Impacted Party sections of
404
+ this License, all rights granted to Licensee by this License will terminate
405
+ immediately.
406
+
407
+ 7.4. Patent Litigation: If Licensee institutes patent litigation against any
408
+ entity (including a cross-claim or counterclaim in a suit) alleging that the
409
+ Software, all or part of the Software’s code, or a derivative work developed
410
+ using the Software, including a portion of its code, constitutes direct or
411
+ contributory patent infringement, then any patent license, along with all other
412
+ rights, granted to Licensee under this License will terminate as of the date
413
+ such litigation is filed.
414
+
415
+ 7.5. Additional Remedies: Termination of the License by failing to remedy harms
416
+ in no way prevents Licensor or Supply Chain Impacted Party from seeking
417
+ appropriate remedies at law or in equity.
418
+
419
+ 8. MISCELLANEOUS:
420
+
421
+ 8.1. Conditions: Sections 3, 4.1, 5.1, 5.2, 7.1, 7.2, 7.3, and 7.4 are
422
+ conditions of the rights granted to Licensee in the License.
423
+
424
+ 8.2. Equitable Relief: Licensor and any Supply Chain Impacted Party shall be
425
+ entitled to equitable relief, including injunctive relief or specific
426
+ performance of the terms hereof, in addition to any other remedy to which they
427
+ are entitled at law or in equity.
428
+
429
+ 8.3. Copyleft: Modified software, source code, or other derivative work must be
430
+ licensed, in its entirety, under the exact same conditions as this License.
431
+
432
+ 8.4. Severability: If any term or provision of this License is determined to be
433
+ invalid, illegal, or unenforceable by a court of competent jurisdiction, any
434
+ such determination of invalidity, illegality, or unenforceability shall not
435
+ affect any other term or provision of this License or invalidate or render
436
+ unenforceable such term or provision in any other jurisdiction. If the
437
+ determination of invalidity, illegality, or unenforceability by a court of
438
+ competent jurisdiction pertains to the terms or provisions contained in the
439
+ Ethical Standards section of this License, all rights in the Software granted to
440
+ Licensee shall be deemed null and void as between Licensor and Licensee.
441
+
442
+ 8.5. Section Titles: Section titles are solely written for organizational
443
+ purposes and should not be used to interpret the language within each section.
444
+
445
+ 8.6. Citations: Citations are solely written to provide context for the source
446
+ of the provisions in the Ethical Standards.
447
+
448
+ 8.7. Section Summaries: Some sections have a brief italicized description which
449
+ is provided for the sole purpose of briefly describing the section and should
450
+ not be used to interpret the terms of the License.
451
+
452
+ 8.8. Entire License: This is the entire License between the Licensor and
453
+ Licensee with respect to the claims released herein and that the consideration
454
+ stated herein is the only consideration or compensation to be paid or exchanged
455
+ between them for this License. This License cannot be modified or amended except
456
+ in a writing signed by Licensor and Licensee.
457
+
458
+ 8.9. Successors and Assigns: This License shall be binding upon and inure to the
459
+ benefit of the Licensor’s and Licensee’s respective heirs, successors, and
460
+ assigns.
461
+ ---------------------- END OFFICIAL HIPPOCRATIC LICENSE 3.0 TEXT ----------------------
462
+
463
+ ==============================================================================
464
+ Attribution, commercial use, and warranty
465
+ ==============================================================================
466
+
467
+ Attribution: cite this work as described in the model card (README.md), section
468
+ "How to cite". Attribution to Lowdown Labs is required under CC BY-NC 4.0.
469
+
470
+ Commercial use: CC BY-NC 4.0 does not grant commercial rights. Commercial licenses are
471
+ sold by Lowdown Labs; contact Lowdown Labs to purchase one.
472
+
473
+ No warranty: this work is provided as is, without warranty of any kind. See the model card
474
+ for the intended use, the evaluated conditions, and the known limitations.
README.md ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: other
3
+ license_name: lowdown-labs-lovely-license-1.0
4
+ license_link: LICENSE
5
+ tags:
6
+ - fela
7
+ - fourier-neural-operator
8
+ - fno
9
+ - cpu
10
+ - on-device
11
+ - edge
12
+ - time-series
13
+ - forecasting
14
+ - energy
15
+ - electricity
16
+ library_name: transformers
17
+ pipeline_tag: time-series-forecasting
18
+ ---
19
+
20
+ # DISCLAIMER
21
+
22
+ This model is a research preview. It is released by Lowdown Labs in the interest of advancing
23
+ public science and demonstrating that a Fourier Neural Operator can forecast on a plain CPU with
24
+ a constant memory footprint. The dataset behind this
25
+ one (UCI electricity load) is CC BY 4.0 and could permit commercial use with attribution; see the
26
+ license notes below before deploying.
27
+
28
+ # FELA-TS edge: On device electricity load forecaster
29
+
30
+ FELA-TS edge reads a window of recent load history and forecasts the next 96 steps ahead. It is
31
+ tiny, about 1.76M parameters, and runs on a plain CPU with no GPU. Its working memory does not grow with how long the stream has been running, so you can drop
32
+ it into a meter or a building controller and let it forecast a live feed for years without the
33
+ memory climbing due to the model expanding its usage.
34
+
35
+ The shipped checkpoint is trained on the standard 321 channel electricity load benchmark, but the
36
+ architecture underneath is a generic multi channel forecaster for long horizons.
37
+
38
+ # What goes in, what comes out
39
+
40
+ - Input: one history window of shape `(1, 512, 321)`: 512 past time steps across 321 load
41
+ channels, per channel standardized on the training statistics. RevIN handles the instance
42
+ normalization inside the model, so you pass the standardized history and the model manages the
43
+ per window mean and scale itself.
44
+ - Output: a forecast of shape `(1, 96, 321)`: the next 96 steps for all 321 channels, returned in
45
+ the original (denormalized) units.
46
+ - In plain terms: "here are the last 512 hours of load for these meters" goes in, and "here is the
47
+ next 96 hours for each of them" comes out.
48
+
49
+ The edge/on device unit runs a single load stream at a time (one channel), which is the
50
+ sub millisecond, constant memory path described under Performance.
51
+
52
+ # Why we built it this way
53
+
54
+ The sequence mixer is a Fourier Neural Operator, a filter the model learns and then applies in the
55
+ frequency domain. Electricity load runs on strong daily and weekly cycles, and those cycles are
56
+ what a frequency domain filter reads best, so the method fits the signal. The model is pure FNO
57
+ with a patch embedding, and it normalizes each history window internally (a step called RevIN) so
58
+ you do not have to hand tune it. It is pure FNO, with none of the gated memory or attention layers
59
+ that some sibling FELA models add.
60
+
61
+ Because it carries no attention and no KV cache, the working memory stays small and fixed no matter
62
+ how much history has streamed through it. The live single stream path keeps its history in a 512
63
+ sample ring buffer, about 2 KB, and one forward pass runs on roughly 126 KB of activations. That
64
+ flat footprint is the whole point at the edge: a full history attention model would keep growing its
65
+ memory until it ran out, while this one does not move.
66
+
67
+ # Performance
68
+
69
+ Speed and footprint, measured on CPU (single core, single load stream).
70
+
71
+ | Format | Size on disk | Notes |
72
+ |---|---|---|
73
+ | fp32 | 9.96 MB | full model weights |
74
+ | int8 (PyTorch/ONNX) | 7.29 MB | deployable edge unit |
75
+ | TFLite float16 | 4.9 MB | smallest deployable export |
76
+
77
+ - Full 321 channel forecast: median 165.7 ms on one CPU core.
78
+ - Single channel edge unit forecast: median 0.863 ms on one CPU core.
79
+ - int8 ONNX single stream update: about 0.56 ms per update (roughly 1,700 updates per second) on
80
+ one core.
81
+ - Live working RAM (constant, independent of history length): a 2 KB ring buffer holds the entire
82
+ retained history, plus about 126 KB of activations, for a working set under 200 KB excluding
83
+ weights.
84
+
85
+ Constant memory is verified: the O(1) ring buffer streaming path was checked against recomputing
86
+ the forecast on the explicit window and matched exactly (mean absolute difference 0.0 over 1,800
87
+ streamed steps).
88
+
89
+ The model fits comfortably on a Raspberry Pi 4/5 or Pi Zero 2 W (Cortex-A class,
90
+ ONNX path); it probably could not fit a small microcontroller (the 5 to 7 MB model is larger than typical
91
+ MCU flash) without explicitly targeting those constraints, so the realistic edge target is a Cortex-A single board computer, not a Cortex-M part.
92
+
93
+ # Accuracy
94
+
95
+ Protocol: UCI ElectricityLoadDiagrams20112014 ("electricity" / ECL benchmark), the standard
96
+ Informer chronological 70/10/20 train/validation/test split, lookback L = 512, forecast horizon
97
+ H = 96, over all 321 channels. Metric is mean squared error (MSE) and mean absolute error (MAE) on
98
+ the z normalized test windows, the standard long horizon ECL protocol.
99
+
100
+ | Benchmark | Metric | This model | Baseline (named) |
101
+ |---|---|---|---|
102
+ | Electricity, horizon 96 | MSE | 0.1325 | PatchTST ~0.129 |
103
+ | Electricity, horizon 96 | MAE | 0.2233 | iTransformer MSE ~0.148, DLinear MSE ~0.140 |
104
+
105
+ The card MSE/MAE of 0.1325 / 0.2233 reproduced at 0.1344 / 0.2254 on a fresh held out evaluation
106
+ (1.76M parameters). PatchTST leads on accuracy by a small margin at this
107
+ horizon; iTransformer and DLinear are behind. However, sub millisecond single stream forecasts on one CPU core with a flat, sub 200 KB working set are provably attainable, vs a full history attention model whose memory climbs with the length of the stream.
108
+
109
+ # How to run it
110
+
111
+ The short version:
112
+
113
+ ```python
114
+ import torch
115
+ from modeling import load_model, forecast
116
+
117
+ m = load_model("/path/to/weights_dir") # a dir with model.safetensors + config.json
118
+ # x: a (1, 512, 321) history window, per channel standardized on training stats
119
+ y = forecast(m, x) # -> (1, 96, 321) forecast in original units
120
+ ```
121
+
122
+ `load_model` also accepts the `model.safetensors` path directly or a Hugging Face repo id. The fp32
123
+ weights ship as `model.safetensors`; the loader builds the architecture from `config.json` and
124
+ loads the state dict.
125
+
126
+ # Training data and license
127
+
128
+ - Dataset: UCI ElectricityLoadDiagrams20112014 ("electricity" / ECL), the 321 client hourly
129
+ variant used across the Informer / Autoformer / PatchTST time series literature (26,304 hourly
130
+ timesteps x 321 client load streams). Source: UCI Machine Learning Repository, dataset 321
131
+ (DOI 10.24432/C58C86). The training split, windowing, and the audited train window count are
132
+ reproduced in `train.py` (`--smoke` rebuilds the split and asserts 17,805 train windows).
133
+ - License: Creative Commons Attribution 4.0 International (CC BY 4.0), as listed on the UCI dataset
134
+ page. Commercial use is ALLOWED, contingent only on attribution and preserving the license terms.
135
+ This is the one dataset in the FELA industrial family with an unambiguous, commercially usable
136
+ license. Attribution: cite the UCI ElectricityLoadDiagrams20112014 dataset (DOI 10.24432/C58C86).
137
+
138
+ # Intended use, limitations, and safety
139
+
140
+ What it is for: the forecasting core inside an edge or on premises energy product, running on a CPU
141
+ or a single board computer. Fit includes live load forecasting on a meter or gateway, building and
142
+ microgrid controllers, and any long running multi channel forecast where the memory must stay flat
143
+ while history accumulates.
144
+
145
+ What it is not for: this is a forecasting model, not a control system or a guarantee. It was
146
+ trained and evaluated only on the UCI electricity benchmark; generalization to other load profiles,
147
+ sampling rates, sensors, and populations is not established and must be validated before any
148
+ operational use. Accuracy is at parity with, not ahead of, the strongest published transformer
149
+ forecaster (PatchTST leads by a small margin); the model wins on footprint and constant memory, not
150
+ on top line accuracy. Continuous stream benchmarks beyond the verified streaming equals batch check
151
+ (for example multi day real time factor on a specific physical board) are not yet measured.
152
+
153
+ # Model family
154
+
155
+ This is part of the FELA family from Lowdown Labs: one Fourier Neural Operator architecture across
156
+ many modalities, all CPU native and subquadratic. Sibling repos share no weights, so none carries a
157
+ `base_model` link.
158
+
159
+ # License
160
+
161
+ Released under the Lowdown Labs Lovely License 1.0 (CC BY-NC 4.0 plus Hippocratic License 3.0). See LICENSE. For most LL models, a commercial license may be available; contact Lowdown Labs.
config.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_type": "fela-ts",
3
+ "architectures": [
4
+ "FelaTsModel"
5
+ ],
6
+ "auto_map": {
7
+ "AutoConfig": "configuration_ts.FelaTsConfig",
8
+ "AutoModel": "modeling_ts.FelaTsModel"
9
+ },
10
+ "library_name": "pytorch",
11
+ "arch": "FELA_TS",
12
+ "note": "FELA time series forecaster, about 1.76M params. RevIN, patch embedding, FNO spectral mixer blocks, linear head. Trained on electricity, 321 channels, L=512, H=96.",
13
+ "C": 321,
14
+ "L": 512,
15
+ "H": 96,
16
+ "patch": 16,
17
+ "stride": 8,
18
+ "D": 128,
19
+ "modes": 16,
20
+ "nblk": 3,
21
+ "input_shape": [
22
+ 1,
23
+ 512,
24
+ 321
25
+ ],
26
+ "input_desc": "history window shape (1, 512, 321): 512 past steps of 321 channels, standardized per channel on training statistics. RevIN normalizes instances inside the model.",
27
+ "complex_keys": [
28
+ "blocks.0.fno.w",
29
+ "blocks.1.fno.w",
30
+ "blocks.2.fno.w"
31
+ ]
32
+ }
configuration_ts.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import PretrainedConfig
2
+
3
+
4
+ class FelaTsConfig(PretrainedConfig):
5
+ model_type = "fela-ts"
6
+
7
+ def __init__(
8
+ self,
9
+ C=321,
10
+ L=512,
11
+ H=96,
12
+ patch=16,
13
+ stride=8,
14
+ D=128,
15
+ modes=16,
16
+ nblk=3,
17
+ **kwargs,
18
+ ):
19
+ self.C = C
20
+ self.L = L
21
+ self.H = H
22
+ self.patch = patch
23
+ self.stride = stride
24
+ self.D = D
25
+ self.modes = modes
26
+ self.nblk = nblk
27
+ super().__init__(**kwargs)
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4f4fbc05634862cbdf2cc8bc35906426785750d491b71d25cae39ea20389b0be
3
+ size 10199640
modeling.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+ import json
3
+ import os
4
+ from dataclasses import dataclass
5
+ import torch
6
+ import torch.nn as nn
7
+ import torch.nn.functional as F
8
+
9
+
10
+ @dataclass
11
+ class TSConfig:
12
+ C: int = 321
13
+ L: int = 512
14
+ H: int = 96
15
+ patch: int = 16
16
+ stride: int = 8
17
+ D: int = 128
18
+ modes: int = 16
19
+ nblk: int = 3
20
+
21
+
22
+ class RevIN(nn.Module):
23
+ def __init__(self, C):
24
+ super().__init__()
25
+ self.g = nn.Parameter(torch.ones(C))
26
+ self.b = nn.Parameter(torch.zeros(C))
27
+
28
+ def norm(self, x):
29
+ self.m = x.mean(1, keepdim=True)
30
+ self.s = x.std(1, keepdim=True) + 1e-05
31
+ return (x - self.m) / self.s * self.g + self.b
32
+
33
+ def denorm(self, x):
34
+ return (x - self.b) / self.g * self.s + self.m
35
+
36
+
37
+ class FNO1D(nn.Module):
38
+ def __init__(self, D, m):
39
+ super().__init__()
40
+ self.m = m
41
+ self.w = nn.Parameter(1 / (D * D) * torch.rand(m, D, D, dtype=torch.cfloat))
42
+
43
+ def forward(self, x):
44
+ P = x.shape[1]
45
+ xf = torch.fft.rfft(x, dim=1)
46
+ mm = min(self.m, xf.shape[1])
47
+ o = torch.zeros_like(xf)
48
+ o[:, :mm] = torch.einsum("bpd,pde->bpe", xf[:, :mm], self.w[:mm])
49
+ return torch.fft.irfft(o, n=P, dim=1)
50
+
51
+
52
+ class Block(nn.Module):
53
+ def __init__(self, D, m, ff=2, drop=0.2):
54
+ super().__init__()
55
+ self.n1 = nn.LayerNorm(D)
56
+ self.fno = FNO1D(D, m)
57
+ self.d1 = nn.Dropout(drop)
58
+ self.n2 = nn.LayerNorm(D)
59
+ self.ff = nn.Sequential(
60
+ nn.Linear(D, D * ff), nn.GELU(), nn.Dropout(drop), nn.Linear(D * ff, D)
61
+ )
62
+
63
+ def forward(self, x):
64
+ x = x + self.d1(self.fno(self.n1(x)))
65
+ return x + self.ff(self.n2(x))
66
+
67
+
68
+ class FELA_TS(nn.Module):
69
+ def __init__(self, C, L, H, patch=16, stride=8, D=128, modes=16, nblk=3):
70
+ super().__init__()
71
+ self.C, self.L, self.H, self.patch, self.stride = (C, L, H, patch, stride)
72
+ self.revin = RevIN(C)
73
+ self.np_ = (L - patch) // stride + 1
74
+ self.embed = nn.Linear(patch, D)
75
+ self.blocks = nn.ModuleList([Block(D, modes) for _ in range(nblk)])
76
+ self.head = nn.Linear(self.np_ * D, H)
77
+
78
+ def forward(self, x):
79
+ x = self.revin.norm(x)
80
+ x = x.permute(0, 2, 1).reshape(-1, self.L)
81
+ x = x.unfold(1, self.patch, self.stride)
82
+ h = self.embed(x)
83
+ for b in self.blocks:
84
+ h = b(h)
85
+ y = self.head(h.flatten(1)).reshape(-1, self.C, self.H).permute(0, 2, 1)
86
+ return self.revin.denorm(y)
87
+
88
+
89
+ _CONFIG_FIELDS = set(TSConfig.__dataclass_fields__.keys())
90
+
91
+
92
+ def _read_json(path):
93
+ with open(path) as f:
94
+ return json.load(f)
95
+
96
+
97
+ def _cfg_from_dict(d):
98
+ return TSConfig(**{k: v for k, v in d.items() if k in _CONFIG_FIELDS})
99
+
100
+
101
+ def validate_history(x: torch.Tensor, cfg: TSConfig):
102
+ if x.dim() != 3:
103
+ raise ValueError(f"expected a 3D tensor (B, L, C); got {tuple(x.shape)}")
104
+ if x.size(1) != cfg.L or x.size(2) != cfg.C:
105
+ raise ValueError(
106
+ f"expected history of shape (B, {cfg.L}, {cfg.C}); got {tuple(x.shape)}"
107
+ )
108
+
109
+
110
+ def load_model(path_or_repo: str):
111
+ if os.path.isdir(path_or_repo):
112
+ cfg_dict = _read_json(os.path.join(path_or_repo, "config.json"))
113
+ weights = os.path.join(path_or_repo, "model.safetensors")
114
+ elif os.path.isfile(path_or_repo) and path_or_repo.endswith(".safetensors"):
115
+ cfg_dict = _read_json(
116
+ os.path.join(os.path.dirname(path_or_repo), "config.json")
117
+ )
118
+ weights = path_or_repo
119
+ elif os.path.isfile(path_or_repo):
120
+ cfg_dict = _read_json(
121
+ os.path.join(os.path.dirname(path_or_repo) or ".", "config.json")
122
+ )
123
+ weights = path_or_repo
124
+ else:
125
+ from huggingface_hub import hf_hub_download
126
+
127
+ cfg_dict = _read_json(hf_hub_download(path_or_repo, "config.json"))
128
+ weights = hf_hub_download(path_or_repo, "model.safetensors")
129
+ cfg = _cfg_from_dict(cfg_dict)
130
+ model = FELA_TS(
131
+ cfg.C, cfg.L, cfg.H, cfg.patch, cfg.stride, cfg.D, cfg.modes, cfg.nblk
132
+ ).eval()
133
+ if weights.endswith(".safetensors"):
134
+ from safetensors.torch import load_file
135
+
136
+ state = load_file(weights)
137
+ cplx = set(cfg_dict.get("complex_keys", []))
138
+ state = {
139
+ k: (torch.view_as_complex(v.contiguous()) if k in cplx else v)
140
+ for k, v in state.items()
141
+ }
142
+ else:
143
+ state = torch.load(weights, map_location="cpu", weights_only=False)
144
+ if isinstance(state, dict) and "state_dict" in state:
145
+ state = state["state_dict"]
146
+ model.load_state_dict(state)
147
+ model.cfg = cfg
148
+ return model
149
+
150
+
151
+ from_pretrained = load_model
152
+
153
+
154
+ @torch.no_grad()
155
+ def forecast(model, x: torch.Tensor) -> torch.Tensor:
156
+ validate_history(x, model.cfg)
157
+ return model(x)
modeling_ts.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import types
4
+
5
+ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
6
+ import torch
7
+ import torch.nn as nn
8
+ from transformers import PreTrainedModel
9
+ from transformers.modeling_outputs import CausalLMOutput
10
+
11
+ from .configuration_ts import FelaTsConfig
12
+ from .modeling import FELA_TS, FNO1D
13
+
14
+
15
+ def _fno1d_forward(self, x):
16
+ w = torch.view_as_complex(self.w)
17
+ P = x.shape[1]
18
+ xf = torch.fft.rfft(x, dim=1)
19
+ mm = min(self.m, xf.shape[1])
20
+ o = torch.zeros_like(xf)
21
+ o[:, :mm] = torch.einsum("bpd,pde->bpe", xf[:, :mm], w[:mm])
22
+ return torch.fft.irfft(o, n=P, dim=1)
23
+
24
+
25
+ def _realify(model):
26
+ for m in model.modules():
27
+ if isinstance(m, FNO1D):
28
+ m.w = nn.Parameter(torch.view_as_real(m.w.detach()).contiguous())
29
+ m.forward = types.MethodType(_fno1d_forward, m)
30
+
31
+
32
+ class FelaTsModel(PreTrainedModel):
33
+ config_class = FelaTsConfig
34
+ base_model_prefix = "model"
35
+ main_input_name = "x"
36
+
37
+ def __init__(self, config):
38
+ super().__init__(config)
39
+ self.model = FELA_TS(
40
+ config.C,
41
+ config.L,
42
+ config.H,
43
+ config.patch,
44
+ config.stride,
45
+ config.D,
46
+ config.modes,
47
+ config.nblk,
48
+ )
49
+ _realify(self.model)
50
+ self.post_init()
51
+
52
+ def forward(self, x=None, input_values=None, **kwargs):
53
+ if x is None:
54
+ x = input_values
55
+ out = self.model(x)
56
+ return CausalLMOutput(logits=out)
streaming/manifest.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model": "ts-edge",
3
+ "format": "fp16-streaming",
4
+ "note": "load order is smallest-first for progressive/streaming load",
5
+ "files": [
6
+ {
7
+ "file": "model_fp16.safetensors",
8
+ "source": "model.safetensors",
9
+ "dtype": "fp16",
10
+ "bytes": 5101188,
11
+ "approx_mb": 4.865
12
+ }
13
+ ]
14
+ }
streaming/model_fp16.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:11ca25fba43652d89559fc17bd610ded2f920b2cb742046bc3d7482f57e59332
3
+ size 5101188
train.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys, numpy as np, pandas as pd, torch, torch.nn as nn, torch.nn.functional as F
2
+
3
+ dev = "cuda" if torch.cuda.is_available() else "cpu"
4
+ torch.manual_seed(0)
5
+ np.random.seed(0)
6
+ csv, L, H = ("/workspace/data/electricity.csv", 512, 96)
7
+ smoke = "--smoke" in sys.argv
8
+ save = (
9
+ sys.argv[sys.argv.index("--save") + 1]
10
+ if "--save" in sys.argv
11
+ else "/workspace/ts_demo/fela_ts_electricity.pt"
12
+ )
13
+ epochs = int(sys.argv[sys.argv.index("--epochs") + 1]) if "--epochs" in sys.argv else 30
14
+
15
+
16
+ class RevIN(nn.Module):
17
+ def __init__(s, C):
18
+ super().__init__()
19
+ s.g = nn.Parameter(torch.ones(C))
20
+ s.b = nn.Parameter(torch.zeros(C))
21
+
22
+ def norm(s, x):
23
+ s.m = x.mean(1, keepdim=True)
24
+ s.s = x.std(1, keepdim=True) + 1e-05
25
+ return (x - s.m) / s.s * s.g + s.b
26
+
27
+ def denorm(s, x):
28
+ return (x - s.b) / s.g * s.s + s.m
29
+
30
+
31
+ class FNO1D(nn.Module):
32
+ def __init__(s, D, m):
33
+ super().__init__()
34
+ s.m = m
35
+ s.w = nn.Parameter(1 / (D * D) * torch.rand(m, D, D, dtype=torch.cfloat))
36
+
37
+ def forward(s, x):
38
+ P = x.shape[1]
39
+ xf = torch.fft.rfft(x, dim=1)
40
+ mm = min(s.m, xf.shape[1])
41
+ o = torch.zeros_like(xf)
42
+ o[:, :mm] = torch.einsum("bpd,pde->bpe", xf[:, :mm], s.w[:mm])
43
+ return torch.fft.irfft(o, n=P, dim=1)
44
+
45
+
46
+ class Block(nn.Module):
47
+ def __init__(s, D, m, ff=2, drop=0.2):
48
+ super().__init__()
49
+ s.n1 = nn.LayerNorm(D)
50
+ s.fno = FNO1D(D, m)
51
+ s.d1 = nn.Dropout(drop)
52
+ s.n2 = nn.LayerNorm(D)
53
+ s.ff = nn.Sequential(
54
+ nn.Linear(D, D * ff), nn.GELU(), nn.Dropout(drop), nn.Linear(D * ff, D)
55
+ )
56
+
57
+ def forward(s, x):
58
+ x = x + s.d1(s.fno(s.n1(x)))
59
+ return x + s.ff(s.n2(x))
60
+
61
+
62
+ class FELA_TS(nn.Module):
63
+ def __init__(s, C, L, H, patch=16, stride=8, D=128, modes=16, nblk=3):
64
+ super().__init__()
65
+ s.C, s.L, s.H, s.patch, s.stride = (C, L, H, patch, stride)
66
+ s.revin = RevIN(C)
67
+ s.np_ = (L - patch) // stride + 1
68
+ s.embed = nn.Linear(patch, D)
69
+ s.blocks = nn.ModuleList([Block(D, modes) for _ in range(nblk)])
70
+ s.head = nn.Linear(s.np_ * D, H)
71
+
72
+ def forward(s, x):
73
+ x = s.revin.norm(x)
74
+ x = x.permute(0, 2, 1).reshape(-1, s.L)
75
+ x = x.unfold(1, s.patch, s.stride)
76
+ h = s.embed(x)
77
+ for b in s.blocks:
78
+ h = b(h)
79
+ y = s.head(h.flatten(1)).reshape(-1, s.C, s.H).permute(0, 2, 1)
80
+ return s.revin.denorm(y)
81
+
82
+
83
+ df = pd.read_csv(csv)
84
+ cols = [c for c in df.columns if c != "date"]
85
+ data = df[cols].values.astype(np.float32)
86
+ n = len(data)
87
+ ntr, nva = (int(n * 0.7), int(n * 0.1))
88
+ mu = data[:ntr].mean(0)
89
+ sd = data[:ntr].std(0) + 1e-08
90
+ data = (data - mu) / sd
91
+
92
+
93
+ def win(a):
94
+ xs, ys = ([], [])
95
+ for i in range(0, len(a) - L - H + 1, 1):
96
+ xs.append(a[i : i + L])
97
+ ys.append(a[i + L : i + L + H])
98
+ return (torch.tensor(np.array(xs)), torch.tensor(np.array(ys)))
99
+
100
+
101
+ Xtr, Ytr = win(data[:ntr])
102
+ Xte, Yte = win(data[ntr + nva :])
103
+ C = data.shape[1]
104
+ assert len(Xtr) == 17805
105
+ if smoke:
106
+ print(
107
+ f"Electricity C={C} n={n} ntr={ntr} nva={nva} train {len(Xtr)} test {len(Xte)}"
108
+ )
109
+ sys.exit()
110
+ m = FELA_TS(C, L, H).to(dev)
111
+ opt = torch.optim.Adam(m.parameters(), lr=0.001)
112
+ sch = torch.optim.lr_scheduler.CosineAnnealingLR(opt, epochs)
113
+ bs = 64
114
+ print(f"[Ts] electricity C={C} train {len(Xtr)} test {len(Xte)}")
115
+ for ep in range(epochs):
116
+ m.train()
117
+ p = torch.randperm(len(Xtr))
118
+ for i in range(0, len(Xtr) - bs, bs):
119
+ idx = p[i : i + bs]
120
+ loss = F.l1_loss(m(Xtr[idx].to(dev)), Ytr[idx].to(dev))
121
+ opt.zero_grad()
122
+ loss.backward()
123
+ opt.step()
124
+ sch.step()
125
+ m.eval()
126
+ se = ae = cnt = 0
127
+ with torch.no_grad():
128
+ for i in range(0, len(Xte), 256):
129
+ pr = m(Xte[i : i + 256].to(dev))
130
+ y = Yte[i : i + 256].to(dev)
131
+ se += F.mse_loss(pr, y, reduction="sum").item()
132
+ ae += (pr - y).abs().sum().item()
133
+ cnt += y.numel()
134
+ mse, mae = (se / cnt, ae / cnt)
135
+ print(f"[Ts] electricity/96 TEST MSE {mse:.4f} MAE {mae:.4f}")
136
+ torch.save(m.state_dict(), save)
137
+ print(f"SAVED {save}")