zarx 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. zarx-0.2.0/.gitignore +33 -0
  2. zarx-0.2.0/LICENSE +202 -0
  3. zarx-0.2.0/NOTICE +4 -0
  4. zarx-0.2.0/PKG-INFO +246 -0
  5. zarx-0.2.0/README.md +221 -0
  6. zarx-0.2.0/pyproject.toml +42 -0
  7. zarx-0.2.0/src/zarx/__init__.py +64 -0
  8. zarx-0.2.0/src/zarx/__main__.py +3 -0
  9. zarx-0.2.0/src/zarx/_client.py +66 -0
  10. zarx-0.2.0/src/zarx/_config.py +67 -0
  11. zarx-0.2.0/src/zarx/_forecast_result.py +100 -0
  12. zarx-0.2.0/src/zarx/_realtime.py +149 -0
  13. zarx-0.2.0/src/zarx/_responses.py +36 -0
  14. zarx-0.2.0/src/zarx/_series.py +121 -0
  15. zarx-0.2.0/src/zarx/_speech_stream.py +53 -0
  16. zarx-0.2.0/src/zarx/_version.py +1 -0
  17. zarx-0.2.0/src/zarx/audio.py +246 -0
  18. zarx-0.2.0/src/zarx/cli/__init__.py +1 -0
  19. zarx-0.2.0/src/zarx/cli/audio_cmd.py +53 -0
  20. zarx-0.2.0/src/zarx/cli/chat_cmd.py +60 -0
  21. zarx-0.2.0/src/zarx/cli/console.py +18 -0
  22. zarx-0.2.0/src/zarx/cli/forecast_cmd.py +64 -0
  23. zarx-0.2.0/src/zarx/cli/main.py +71 -0
  24. zarx-0.2.0/src/zarx/cli/models_cmd.py +24 -0
  25. zarx-0.2.0/src/zarx/errors.py +36 -0
  26. zarx-0.2.0/src/zarx/forecasting.py +135 -0
  27. zarx-0.2.0/src/zarx/models.py +52 -0
  28. zarx-0.2.0/src/zarx/py.typed +0 -0
  29. zarx-0.2.0/src/zarx/reasoning.py +14 -0
  30. zarx-0.2.0/src/zarx/voices.py +58 -0
  31. zarx-0.2.0/tests/__init__.py +0 -0
  32. zarx-0.2.0/tests/conftest.py +100 -0
  33. zarx-0.2.0/tests/test_audio.py +183 -0
  34. zarx-0.2.0/tests/test_cli.py +161 -0
  35. zarx-0.2.0/tests/test_config.py +124 -0
  36. zarx-0.2.0/tests/test_forecast.py +184 -0
  37. zarx-0.2.0/tests/test_live.py +251 -0
  38. zarx-0.2.0/tests/test_models.py +29 -0
  39. zarx-0.2.0/tests/test_realtime.py +104 -0
  40. zarx-0.2.0/tests/test_requests.py +68 -0
  41. zarx-0.2.0/tests/test_voices.py +54 -0
zarx-0.2.0/.gitignore ADDED
@@ -0,0 +1,33 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ .venv/
5
+ *.egg-info/
6
+ build/
7
+ dist/
8
+ .pytest_cache/
9
+ .ruff_cache/
10
+ .mypy_cache/
11
+
12
+ # Node
13
+ node_modules/
14
+ *.tgz
15
+ typescript/dist/
16
+ .npm/
17
+
18
+ # Local secrets and env files: never committed
19
+ .env
20
+ .env.*
21
+ *.env
22
+ stage.env
23
+
24
+ # Editors and OS
25
+ .DS_Store
26
+ .idea/
27
+ .vscode/
28
+
29
+ # Audio produced by examples
30
+ *.mp3
31
+ *.wav
32
+ *.pcm
33
+ !examples/assets/*.wav
zarx-0.2.0/LICENSE ADDED
@@ -0,0 +1,202 @@
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 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 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 those 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
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
zarx-0.2.0/NOTICE ADDED
@@ -0,0 +1,4 @@
1
+ Zarx SDK
2
+ Copyright 2026 NPAW (Nice People At Work S.L.)
3
+
4
+ This product is licensed under the Apache License, Version 2.0 (see LICENSE).
zarx-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,246 @@
1
+ Metadata-Version: 2.5
2
+ Name: zarx
3
+ Version: 0.2.0
4
+ Summary: Python SDK for Zarx, the OpenAI-compatible inference API run by NPAW in Europe.
5
+ Project-URL: Homepage, https://zarx.ai
6
+ Author-email: NPAW <contact@zarx.ai>
7
+ License: Apache-2.0
8
+ License-File: LICENSE
9
+ License-File: NOTICE
10
+ Keywords: europe,inference,llm,openai,zarx
11
+ Classifier: License :: OSI Approved :: Apache Software License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Typing :: Typed
16
+ Requires-Python: >=3.9
17
+ Requires-Dist: openai<4,>=1.99
18
+ Provides-Extra: dev
19
+ Requires-Dist: build>=1.2; extra == 'dev'
20
+ Requires-Dist: pytest>=8; extra == 'dev'
21
+ Requires-Dist: websockets>=12; extra == 'dev'
22
+ Provides-Extra: realtime
23
+ Requires-Dist: websockets>=12; extra == 'realtime'
24
+ Description-Content-Type: text/markdown
25
+
26
+ # zarx (Python)
27
+
28
+ Python SDK and command line for [Zarx](https://zarx.ai), the OpenAI-compatible inference API that NPAW runs on its own GPUs in Spain (EU).
29
+
30
+ `zarx` is a thin layer over the official `openai` package: `zarx.Zarx` *is* an `openai.OpenAI` client, so everything you know from the OpenAI SDK works as is. What the layer adds:
31
+
32
+ - the right endpoint and key: production by default, beta with `environment="beta"` or `ZARX_ENVIRONMENT=beta`, and `ZARX_API_KEY` only (an `OPENAI_API_KEY` is never sent to Zarx, an `OPENAI_BASE_URL` never redirects it);
33
+ - Responses API calls default to `store=False`, so responses are not stored for later retrieval unless you ask for it (what else is retained depends on your key's retention policy, see `docs/data.md`);
34
+ - generous read timeouts for the reasoning tiers (300 s read, 10 s connect) and 2 retries;
35
+ - model name helpers (tiers and dated ids), a helper to read the reasoning text, and a `zarx` command;
36
+ - one call per capability beyond chat: `zarx.audio.transcribe`, `transcribe_realtime`, `speak`, `translate`, and `zarx.forecast` / `forecast_csv` for time series.
37
+
38
+ Requires Python 3.9 or newer (0.1.0 verified on 3.9 to 3.13 on 2026-10-31; 0.2.0 run on 3.13 on 2026-11-01).
39
+
40
+ ## Install
41
+
42
+ ```bash
43
+ pip install zarx
44
+ pip install "zarx[realtime]" # adds websockets, for transcribe_realtime
45
+ ```
46
+
47
+ or from a checkout of this repository: `pip install ./python` (`pip install './python[realtime]'` for realtime transcription).
48
+
49
+ ## Quickstart
50
+
51
+ ```bash
52
+ export ZARX_API_KEY=... # your Zarx key
53
+ # export ZARX_ENVIRONMENT=beta # only for beta, with a beta key
54
+ ```
55
+
56
+ ```python
57
+ from zarx import Zarx, Z_FAST
58
+
59
+ client = Zarx()
60
+ completion = client.chat.completions.create(
61
+ model=Z_FAST,
62
+ messages=[{"role": "user", "content": "Say hello in one sentence."}],
63
+ max_tokens=64,
64
+ )
65
+ print(completion.choices[0].message.content)
66
+ print(completion.model) # the dated id that answered, e.g. z-fast-2026-10
67
+ ```
68
+
69
+ Async: `from zarx import AsyncZarx`, same arguments.
70
+
71
+ ### Plain OpenAI SDK
72
+
73
+ You do not need this package to use Zarx. The official SDK works with two settings:
74
+
75
+ ```python
76
+ import os
77
+ from openai import OpenAI
78
+
79
+ client = OpenAI(api_key=os.environ["ZARX_API_KEY"], base_url="https://api.zarx.ai/v1")
80
+ ```
81
+
82
+ If you go this way, pass `store=False` yourself on every Responses API call.
83
+
84
+ ## Models
85
+
86
+ | Tier | Use it for | Context |
87
+ |---|---|---|
88
+ | `z-ultra` | hardest reasoning, long documents | 600,000 tokens |
89
+ | `z-pro` | strong general model with reasoning, very long documents | 1,048,576 tokens (1M) |
90
+ | `z-fast` | low latency, high volume | 16,384 tokens |
91
+
92
+ `client.models.list()` is the authority on these values; production and beta both list 1,048,576 tokens for `z-pro` (checked 2026-11-01). `z-ultra` and `z-pro` also read images; `z-fast` is text only. See `docs/models.md`.
93
+
94
+ A tier always points at its current release. To pin one release, use its dated id:
95
+
96
+ ```python
97
+ from zarx import pin, tier_of, Z_FAST
98
+
99
+ pin(Z_FAST, "2026-10") # "z-fast-2026-10"
100
+ tier_of("z-fast-2026-10") # "z-fast"
101
+ ```
102
+
103
+ Reasoning tokens count toward `max_tokens`: give `z-pro` at least 128 (`zarx.models.Z_PRO_MIN_MAX_TOKENS`), or the answer can come back empty with `finish_reason` `length`. The reasoning tiers accept `reasoning_effort` (`none`, `low`, `medium`, `high`) and return their reasoning next to the answer. `z-ultra` still reasons with `none` (stage, 2026-10-31), so leave it room in `max_tokens`:
104
+
105
+ ```python
106
+ from zarx import reasoning_text
107
+
108
+ message = completion.choices[0].message
109
+ print(reasoning_text(message)) # None when the tier returned no reasoning
110
+ ```
111
+
112
+ ## Responses API and data
113
+
114
+ ```python
115
+ response = client.responses.create(model="z-pro", input="Two lines on GDPR.", max_output_tokens=256)
116
+ print(response.output_text)
117
+ ```
118
+
119
+ This client sends `store=False` unless you pass `store=True`. The server default is `store=True`, and how long stored content is kept depends on your key's retention policy. See `docs/data.md` in the repository.
120
+
121
+ ## Errors
122
+
123
+ Zarx answers in the OpenAI error format, so the OpenAI exception classes apply and are re-exported:
124
+
125
+ ```python
126
+ import zarx
127
+
128
+ try:
129
+ client.chat.completions.create(model="z-unknown", messages=[{"role": "user", "content": "hi"}])
130
+ except zarx.NotFoundError as exc:
131
+ print(exc.code) # model_not_found
132
+ ```
133
+
134
+ A missing key raises `zarx.ZarxConfigError` before any request is made.
135
+
136
+ ### Retries and rate limits
137
+
138
+ Like the OpenAI client, `Zarx` retries twice on connection errors, 408, 409, 429 and 5xx. On a 429 it waits what the `retry-after` header says (up to 59 seconds), so one call can block silently for up to about 2 minutes. Zarx keeps nothing after the response, so a retry runs the request again (there is no server-side deduplication; `Idempotency-Key` is ignored). When latency or a duplicate matters, turn retries off and handle the error yourself:
139
+
140
+ ```python
141
+ client = Zarx(max_retries=0)
142
+ try:
143
+ client.chat.completions.create(model="z-fast", messages=[{"role": "user", "content": "hi"}])
144
+ except zarx.RateLimitError as exc:
145
+ print(exc.response.headers.get("retry-after")) # seconds until the next minute window
146
+ ```
147
+
148
+ Chat Completions responses carry `x-ratelimit-*` headers (requests and tokens: limit, remaining, reset) when your account has rate limits set, and every response carries an `x-request-id`. The per-minute window is the clock minute. See `docs/errors.md`.
149
+
150
+ ## Production or beta
151
+
152
+ | Environment | Base URL | What it is |
153
+ |---|---|---|
154
+ | `production` (default) | `https://api.zarx.ai/v1` | the stable API |
155
+ | `beta` | `https://api-stage.zarx.ai/v1` | the stage environment: new models and features land here first and may change |
156
+
157
+ ```python
158
+ from zarx import Zarx
159
+
160
+ client = Zarx() # production
161
+ beta = Zarx(environment="beta") # beta; "prod" and "stage" also work
162
+ ```
163
+
164
+ The first that is set wins: `base_url=`, `environment=`, `ZARX_BASE_URL`, `ZARX_ENVIRONMENT`, then production. What the code says beats what the shell says. Keys are per environment: a production key gets 401 on beta and the other way round, so set the key that matches. `zarx.ENVIRONMENTS`, `zarx.PRODUCTION_BASE_URL` and `zarx.BETA_BASE_URL` are exported; `STAGE_BASE_URL` stays as an alias of `BETA_BASE_URL`. Realtime transcription follows the client's environment.
165
+
166
+ ## Command line
167
+
168
+ ```bash
169
+ zarx models # models your key can use
170
+ zarx chat "Hello" # streams the answer from z-fast
171
+ zarx chat -m z-pro --show-reasoning "Why is the sky blue?"
172
+ zarx speak "Good morning" -o hello.wav # text to speech (WAV; -f mp3 for MP3, -v for the voice)
173
+ zarx transcribe hello.wav # speech to text
174
+ zarx translate "Good morning" --to es # text translation (a code or a name: es, Spanish)
175
+ zarx forecast 3 4 6 5 7 9 -p 3 # next 3 periods of a series (hourly steps ending now)
176
+ zarx forecast --csv visits.csv -p 24 --band # from a CSV, with a low/high band; --json for the raw answer
177
+ zarx --beta models # same against beta (or ZARX_ENVIRONMENT=beta)
178
+ ```
179
+
180
+ Exit codes: 0 success, 1 API or network error, 2 configuration or input error (for example, no key, or fewer than 3 values to forecast).
181
+
182
+ If the console cannot print a character of the answer (for example a Windows console in cp1252 and an answer with Japanese text), `zarx` prints `?` in its place instead of failing. Set `PYTHONIOENCODING=utf-8` to see every character.
183
+
184
+ ## Audio
185
+
186
+ One call each, with the client built from the environment unless you pass `client=`:
187
+
188
+ ```python
189
+ from zarx import audio
190
+
191
+ text = audio.transcribe("meeting.wav") # speech to text
192
+ wav = audio.speak("Good morning", voice="marin") # text to speech, WAV bytes
193
+ spanish = audio.translate("Good morning", "Spanish") # text translation
194
+ text = audio.transcribe_realtime("meeting-16k.wav", on_delta=print) # text as it is recognised
195
+ spanish_wav = audio.speech_to_speech("meeting.wav", "es") # voice to voice, WAV bytes
196
+ for piece in audio.speak_stream("Good morning"): # speech in pieces (beta), PCM 24 kHz
197
+ player.write(piece)
198
+ ```
199
+
200
+ Voices: `zarx.voices.voices()` lists them and `zarx.voices.voice_catalog()` adds the design attributes (beta and production since 2026-11-02; a deployment without the route raises `zarx.voices.VoicesNotAvailableError`).
201
+
202
+ `zarx.audio` (`transcribe`, `speak`, `translate`) and the `zarx speak`, `zarx transcribe` and `zarx translate` commands were run against stage on 2026-10-30, 2026-10-31 and 2026-11-01 with a zero-retention key: all three audio models are cleared for zero retention and answer 200. The audio model names may still change before general availability. Production lists the audio models since 2026-11-02; the measurements below are from stage (beta):
203
+
204
+ - `transcribe` (`z-transcribe`, `/v1/audio/transcriptions`): WAV (8, 16, 24 or 44.1 kHz, mono or stereo), MP3 or FLAC. 13 languages detected from the audio, plus Catalan, Galician and Basque on files when you name them: `transcribe(path, language="ca")` (`gl`, `eu`; the plain ISO 639-1 code) is served by a second engine of Zarx behind the same model, same name and price (beta since 2026-11-02; production when its next release is promoted). Without `language`, Catalan comes out as Spanish with no warning, so name the language when you know it. For the other languages `language` is a hint that does not change the result; `prompt` never does. `response_format="text"` answers plain text (`text/plain`) on production and beta; the helper returns the text. `verbose_json`, `srt` and `vtt` get 400 (on beta `verbose_json` is answered when `language` is `ca`, `gl` or `eu`). `/v1/audio/translations` does not translate.
205
+ - `transcribe_realtime` (`z-transcribe`, WebSocket at `/v1/audio/transcriptions/realtime`, Zarx's own events, not the OpenAI Realtime API): takes a WAV file or bytes in PCM16 mono 16 kHz (other WAV formats are refused before connecting), raw PCM bytes, or an iterable of PCM chunks (a microphone). `on_delta(text)` gets every piece of recognised text, `on_segment(text)` every finished sentence; the return value is the final transcript. Needs the `realtime` extra (`websockets`). A 3 s sample answered in 1.4 s on stage on 2026-11-01. Catalan, Galician and Basque are served on files only: the live route refuses `source_language` `ca`, `gl` or `eu` with `unsupported_language` (the helper never sends it), and Catalan audio sent live comes out as Spanish.
206
+ - `speak` (`z-speech`, `/v1/audio/speech`): `response_format` `wav` (default, 24 kHz mono 16-bit), `mp3`, `opus`, `flac`, `aac` or `pcm`; `ogg` gets 422. `voice` defaults to `"alloy"`, one of 13 presets (`alloy`, `ash`, `ballad`, `cedar`, `coral`, `echo`, `fable`, `marin`, `nova`, `onyx`, `sage`, `shimmer`, `verse`); `auto` also works, and `design:<attributes>` builds a voice from comma-separated attributes, at most one per group (gender, age, pitch, style, accent), for example `design:female,british accent` or `design:male,elderly,low pitch`; the lists are in `zarx.audio.VOICE_DESIGN_ATTRIBUTES`; free text or an unknown name gets 400 `invalid_voice` with a partner key and 422 with an account-wide key, and two attributes of one group (two accents) get 500. The same preset is not guaranteed to sound identical across calls. `speed` works; free-text `instructions` gets 422.
207
+ - `speak_stream` (`z-speech` with `stream_format="sse"`): yields the audio in pieces as it is generated (PCM by default, about ten pieces for a sentence) and sets `.usage` (`{"input_characters": N}`) at the end. Streams on beta and production (2026-11-02); a deployment that does not stream sends the whole audio as one piece.
208
+ - `translate` (`z-translate`, through chat completions): the target is a language name in English (`"Spanish"`) or a code (`"es"`, `"pt-BR"`); good for English, Spanish, French and German, and `GET /v1/models` lists the 36 languages it serves in `capabilities.languages.supported` on beta. Catalan, Galician and Basque are not served by `z-translate`: on beta since 2026-11-02 the request answers 400 `unsupported_language` (`openai.BadRequestError`; before that it answered Spanish in 8 of 10 sentences; production when its next release is promoted). The helper does not switch models by itself: for those three languages pass `model="z-ultra"`, `zarx.audio.translate(text, "ca", model="z-ultra")` (45 of 46 correct in our test).
209
+ - `speech_to_speech` (`z-voice`, `/v1/audio/speech-to-speech`): an audio file in, the same speech in `target_language` (an ISO 639-1 code, default `"en"`) out, as WAV bytes whatever format is asked. About 3 s for a short sentence on beta and production (2026-11-02). `target_language` `"ca"`, `"gl"` or `"eu"` works with nothing to do on your side: the translation step runs on `z-ultra` behind the same call (beta since 2026-11-02, a Spanish clip into Catalan in 4.2 s; production when its next release is promoted).
210
+ - Use the model name you sent, not the `model` field of audio responses, to identify the model.
211
+
212
+ See `docs/models.md` for the routes and events.
213
+
214
+ ## Forecasting
215
+
216
+ ```python
217
+ import zarx
218
+
219
+ result = zarx.forecast([3, 4, 6, 5, 7, 9], 3) # next 3 periods, hourly steps ending now
220
+ result = zarx.forecast(pairs, 12, include_band=True) # [(timestamp, value), ...] with a low/high band
221
+ result = zarx.forecast_csv("visits.csv", 24, data_points=256) # header row, timestamp first, value last
222
+
223
+ print(result.values) # the point forecasts
224
+ for point in result: # .timestamp, .value, .low, .high, .percentiles
225
+ print(point.timestamp, point.value)
226
+ print(result.billable_points) # what the call is billed for (usage.datapoints, or context plus forecast points)
227
+ ```
228
+
229
+ `series` is a list of numbers (one timestamp every `step`, default `"1h"`, ending now or starting at `start`), of `(timestamp, value)` pairs, of dicts `{"timestamp", "value", ...covariates}`, or a mapping of timestamp to value; at least 3 points. Pass real timestamps when you have them, the model uses the calendar. `periods` must be at least 1. Anything else you pass as a keyword goes into the request body as is (for example `forecast_extra_params={"quantile_low": 0.2, "quantile_high": 0.8}`). `result.raw` is the response exactly as the API returned it.
230
+
231
+ Verified on beta on 2026-11-01 and 2026-11-02 with `z-forecast` (64 hourly points, a 512-row CSV, a 12-point daily series); production lists the model since 2026-11-02. The horizon is at most 1,000 periods per call. See `docs/models.md`.
232
+
233
+ ## Development
234
+
235
+ ```bash
236
+ uv venv .venv && uv pip install -e '.[dev]'
237
+ .venv/bin/pytest # offline tests
238
+ ZARX_API_KEY=... ZARX_ENVIRONMENT=beta .venv/bin/pytest -m live # with a beta key
239
+ uv build # wheel and sdist in dist/
240
+ ```
241
+
242
+ The `dev` extra includes `websockets`, which the `realtime` extra adds for users of `transcribe_realtime`.
243
+
244
+ ## License
245
+
246
+ Apache License 2.0. See LICENSE and NOTICE.