@oneciel-ai/ciel-runtime 0.2.5 → 0.2.6
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.
- package/ciel_runtime_support/config_repository.py +9 -0
- package/ciel_runtime_support/runtime_constants.py +1 -1
- package/ciel_runtime_support/speech_http_controller.py +41 -0
- package/ciel_runtime_support/web_ui.py +30 -0
- package/docs/COLAB_SPEECH.md +3 -1
- package/package.json +1 -1
- package/scripts/colab/__pycache__/bootstrap_moss_tts.cpython-311.pyc +0 -0
- package/scripts/colab/__pycache__/bootstrap_qwen_asr.cpython-311.pyc +0 -0
- package/scripts/configure_speech_workers.py +69 -5
- package/scripts/deploy_colab_speech.ps1 +41 -14
|
@@ -27,6 +27,15 @@ def build_default_config(provider_defaults: dict[str, Any]) -> dict[str, Any]:
|
|
|
27
27
|
"tailscale_https": False,
|
|
28
28
|
},
|
|
29
29
|
"speech": {
|
|
30
|
+
"colab": {
|
|
31
|
+
"enabled": True,
|
|
32
|
+
"distribution": "Ubuntu-26.04",
|
|
33
|
+
"auth": "adc",
|
|
34
|
+
"asr_session": "ciel-asr",
|
|
35
|
+
"tts_session": "ciel-tts",
|
|
36
|
+
"asr_accelerator": "T4",
|
|
37
|
+
"tts_accelerator": "T4",
|
|
38
|
+
},
|
|
30
39
|
"asr": {
|
|
31
40
|
"enabled": False,
|
|
32
41
|
"base_url": "http://ciel-asr:8000",
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import base64
|
|
6
6
|
import json
|
|
7
|
+
import re
|
|
7
8
|
import secrets
|
|
8
9
|
import urllib.error
|
|
9
10
|
import urllib.parse
|
|
@@ -72,6 +73,8 @@ class SpeechHttpController:
|
|
|
72
73
|
public[name] = item
|
|
73
74
|
tailscale = speech.get("tailscale")
|
|
74
75
|
public["tailscale"] = dict(tailscale) if isinstance(tailscale, dict) else {}
|
|
76
|
+
colab = speech.get("colab")
|
|
77
|
+
public["colab"] = dict(colab) if isinstance(colab, dict) else {}
|
|
75
78
|
public["endpoints"] = self.discovery_payload()["endpoints"]
|
|
76
79
|
return public
|
|
77
80
|
|
|
@@ -147,6 +150,14 @@ class SpeechHttpController:
|
|
|
147
150
|
for key in ("enabled", "asr_hostname", "tts_hostname"):
|
|
148
151
|
if key in tailscale:
|
|
149
152
|
current_tailscale[key] = tailscale[key]
|
|
153
|
+
colab = update.get("colab")
|
|
154
|
+
if isinstance(colab, dict):
|
|
155
|
+
current_colab = speech.setdefault("colab", {})
|
|
156
|
+
if not isinstance(current_colab, dict):
|
|
157
|
+
current_colab = {}
|
|
158
|
+
speech["colab"] = current_colab
|
|
159
|
+
for key, value in colab.items():
|
|
160
|
+
current_colab[key] = self._validated_colab_value(key, value)
|
|
150
161
|
self.ports.save_config(config)
|
|
151
162
|
self.ports.write_json(handler, self.public_config())
|
|
152
163
|
except (UnicodeError, ValueError, TypeError) as exc:
|
|
@@ -192,6 +203,36 @@ class SpeechHttpController:
|
|
|
192
203
|
raise ValueError(f"{service} {key} must begin with /")
|
|
193
204
|
return text
|
|
194
205
|
|
|
206
|
+
@staticmethod
|
|
207
|
+
def _validated_colab_value(key: str, value: Any) -> Any:
|
|
208
|
+
allowed = {
|
|
209
|
+
"enabled",
|
|
210
|
+
"distribution",
|
|
211
|
+
"auth",
|
|
212
|
+
"asr_session",
|
|
213
|
+
"tts_session",
|
|
214
|
+
"asr_accelerator",
|
|
215
|
+
"tts_accelerator",
|
|
216
|
+
}
|
|
217
|
+
if key not in allowed:
|
|
218
|
+
raise ValueError(f"unsupported colab setting: {key}")
|
|
219
|
+
if key == "enabled":
|
|
220
|
+
return bool(value)
|
|
221
|
+
text = str(value or "").strip()
|
|
222
|
+
if key == "auth":
|
|
223
|
+
auth = text.lower()
|
|
224
|
+
if auth not in {"adc", "oauth2"}:
|
|
225
|
+
raise ValueError("Colab auth must be adc or oauth2")
|
|
226
|
+
return auth
|
|
227
|
+
if key.endswith("_accelerator"):
|
|
228
|
+
accelerator = text.upper()
|
|
229
|
+
if accelerator not in {"T4", "L4", "G4", "A100", "H100"}:
|
|
230
|
+
raise ValueError("unsupported Colab accelerator")
|
|
231
|
+
return accelerator
|
|
232
|
+
if not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._-]{0,127}", text):
|
|
233
|
+
raise ValueError(f"invalid Colab {key}")
|
|
234
|
+
return text
|
|
235
|
+
|
|
195
236
|
def _probe(self, name: str) -> dict[str, Any]:
|
|
196
237
|
config = self._service_config(name)
|
|
197
238
|
enabled = bool(config.get("enabled"))
|
|
@@ -230,6 +230,19 @@ def render_web_chat_page(
|
|
|
230
230
|
<label class="wide">Remote bearer token<input id="ttsApiKey" type="password" autocomplete="new-password" placeholder="Leave blank to keep current token"></label>
|
|
231
231
|
</div>
|
|
232
232
|
</section>
|
|
233
|
+
<section class="settings-section">
|
|
234
|
+
<h3>Colab CLI connection</h3>
|
|
235
|
+
<div class="settings-grid">
|
|
236
|
+
<label class="check"><input id="colabEnabled" type="checkbox"> Manage workers with Colab CLI</label>
|
|
237
|
+
<label>WSL distribution<input id="colabDistribution" placeholder="Ubuntu-26.04"></label>
|
|
238
|
+
<label>Authentication<select id="colabAuth"><option value="adc">ADC</option><option value="oauth2">OAuth2</option></select></label>
|
|
239
|
+
<label>ASR session<input id="colabAsrSession" placeholder="ciel-asr"></label>
|
|
240
|
+
<label>TTS session<input id="colabTtsSession" placeholder="ciel-tts"></label>
|
|
241
|
+
<label>ASR GPU<select id="colabAsrAccelerator"><option>T4</option><option>L4</option><option>G4</option><option>A100</option><option>H100</option></select></label>
|
|
242
|
+
<label>TTS GPU<select id="colabTtsAccelerator"><option>T4</option><option>L4</option><option>G4</option><option>A100</option><option>H100</option></select></label>
|
|
243
|
+
</div>
|
|
244
|
+
<div class="hint">Saved here for scripts/deploy_colab_speech.ps1. Credentials remain in the Colab CLI profile and are never stored by Ciel.</div>
|
|
245
|
+
</section>
|
|
233
246
|
<section class="settings-section">
|
|
234
247
|
<h3>Tailscale tunnel</h3>
|
|
235
248
|
<div class="settings-grid">
|
|
@@ -568,6 +581,7 @@ def render_web_chat_page(
|
|
|
568
581
|
function setSpeechForm(config) {{
|
|
569
582
|
const asr = config.asr || {{}};
|
|
570
583
|
const tts = config.tts || {{}};
|
|
584
|
+
const colab = config.colab || {{}};
|
|
571
585
|
const tailscale = config.tailscale || {{}};
|
|
572
586
|
document.getElementById('asrEnabled').checked = Boolean(asr.enabled);
|
|
573
587
|
document.getElementById('asrBaseUrl').value = asr.base_url || '';
|
|
@@ -588,6 +602,13 @@ def render_web_chat_page(
|
|
|
588
602
|
pendingTtsReferenceAudio = '';
|
|
589
603
|
document.getElementById('ttsApiKey').value = '';
|
|
590
604
|
document.getElementById('ttsApiKey').placeholder = tts.api_key_set ? 'Token is set; leave blank to keep it' : 'Optional remote bearer token';
|
|
605
|
+
document.getElementById('colabEnabled').checked = colab.enabled !== false;
|
|
606
|
+
document.getElementById('colabDistribution').value = colab.distribution || 'Ubuntu-26.04';
|
|
607
|
+
document.getElementById('colabAuth').value = colab.auth || 'adc';
|
|
608
|
+
document.getElementById('colabAsrSession').value = colab.asr_session || 'ciel-asr';
|
|
609
|
+
document.getElementById('colabTtsSession').value = colab.tts_session || 'ciel-tts';
|
|
610
|
+
document.getElementById('colabAsrAccelerator').value = colab.asr_accelerator || 'T4';
|
|
611
|
+
document.getElementById('colabTtsAccelerator').value = colab.tts_accelerator || 'T4';
|
|
591
612
|
document.getElementById('tailscaleEnabled').checked = tailscale.enabled !== false;
|
|
592
613
|
document.getElementById('tailscaleAsrHostname').value = tailscale.asr_hostname || 'ciel-asr';
|
|
593
614
|
document.getElementById('tailscaleTtsHostname').value = tailscale.tts_hostname || 'ciel-tts';
|
|
@@ -623,6 +644,15 @@ def render_web_chat_page(
|
|
|
623
644
|
clear_ref_audio: document.getElementById('ttsClearReferenceAudio').checked,
|
|
624
645
|
api_key: document.getElementById('ttsApiKey').value,
|
|
625
646
|
}},
|
|
647
|
+
colab: {{
|
|
648
|
+
enabled: document.getElementById('colabEnabled').checked,
|
|
649
|
+
distribution: document.getElementById('colabDistribution').value,
|
|
650
|
+
auth: document.getElementById('colabAuth').value,
|
|
651
|
+
asr_session: document.getElementById('colabAsrSession').value,
|
|
652
|
+
tts_session: document.getElementById('colabTtsSession').value,
|
|
653
|
+
asr_accelerator: document.getElementById('colabAsrAccelerator').value,
|
|
654
|
+
tts_accelerator: document.getElementById('colabTtsAccelerator').value,
|
|
655
|
+
}},
|
|
626
656
|
tailscale: {{
|
|
627
657
|
enabled: document.getElementById('tailscaleEnabled').checked,
|
|
628
658
|
asr_hostname: document.getElementById('tailscaleAsrHostname').value,
|
package/docs/COLAB_SPEECH.md
CHANGED
|
@@ -16,7 +16,9 @@ From PowerShell at the repository root:
|
|
|
16
16
|
.\scripts\deploy_colab_speech.ps1
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Set the WSL distribution, authentication mode, ASR/TTS session names, and accelerators in **Web Chat > Speech Settings > Colab CLI connection**. These values are available through `GET|POST /ca/speech/config`; Ciel does not store Colab credentials. The deployment script reads the saved values automatically. Command-line parameters such as `-Distribution`, `-ColabAuth`, `-AsrSession`, and `-AsrAccelerator` override them for one run.
|
|
20
|
+
|
|
21
|
+
The script reuses matching active sessions when possible, otherwise creates them, installs Qwen3-ASR-0.6B and MOSS-TTS-Nano, starts Tailscale in userspace networking mode, publishes each localhost model server with Tailscale Serve, and saves both returned `base_url` values into Web Chat > Speech Settings automatically.
|
|
20
22
|
|
|
21
23
|
MOSS-TTS-Nano is a voice-cloning model without built-in speakers. Deployment configures the project's official `zh_1.wav` sample so the first request works immediately. In Web Chat > Speech Settings, upload a reference voice clip (10 MB maximum) to replace it. Ciel stores uploaded audio only in the local protected runtime configuration, omits it from configuration responses, and adds it to TTS requests automatically. API clients can instead pass `ref_audio` as an HTTP(S) URL or base64 audio data URL to `POST /v1/audio/speech`.
|
|
22
24
|
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import argparse
|
|
6
|
+
import json
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
import sys
|
|
8
9
|
from typing import Any
|
|
@@ -11,30 +12,93 @@ sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
DEFAULT_TTS_REFERENCE_AUDIO = "https://raw.githubusercontent.com/OpenMOSS/MOSS-TTS-Nano/main/assets/audio/zh_1.wav"
|
|
15
|
+
DEFAULT_COLAB_SETTINGS: dict[str, Any] = {
|
|
16
|
+
"enabled": True,
|
|
17
|
+
"distribution": "Ubuntu-26.04",
|
|
18
|
+
"auth": "adc",
|
|
19
|
+
"asr_session": "ciel-asr",
|
|
20
|
+
"tts_session": "ciel-tts",
|
|
21
|
+
"asr_accelerator": "T4",
|
|
22
|
+
"tts_accelerator": "T4",
|
|
23
|
+
}
|
|
14
24
|
|
|
15
25
|
|
|
16
|
-
def
|
|
26
|
+
def colab_settings(config: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
27
|
+
import ciel_runtime
|
|
28
|
+
|
|
29
|
+
active = config if config is not None else ciel_runtime.load_config()
|
|
30
|
+
speech = active.get("speech") if isinstance(active.get("speech"), dict) else {}
|
|
31
|
+
saved = speech.get("colab") if isinstance(speech.get("colab"), dict) else {}
|
|
32
|
+
return {**DEFAULT_COLAB_SETTINGS, **saved}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def configure(
|
|
36
|
+
asr_base_url: str,
|
|
37
|
+
tts_base_url: str,
|
|
38
|
+
tts_reference_audio: str = DEFAULT_TTS_REFERENCE_AUDIO,
|
|
39
|
+
*,
|
|
40
|
+
distribution: str | None = None,
|
|
41
|
+
auth: str | None = None,
|
|
42
|
+
asr_session: str | None = None,
|
|
43
|
+
tts_session: str | None = None,
|
|
44
|
+
asr_accelerator: str | None = None,
|
|
45
|
+
tts_accelerator: str | None = None,
|
|
46
|
+
) -> dict[str, Any]:
|
|
17
47
|
import ciel_runtime
|
|
18
48
|
|
|
19
49
|
config = ciel_runtime.load_config()
|
|
20
50
|
speech = config.setdefault("speech", {})
|
|
21
51
|
asr = speech.setdefault("asr", {})
|
|
22
52
|
tts = speech.setdefault("tts", {})
|
|
53
|
+
colab = colab_settings(config)
|
|
54
|
+
overrides = {
|
|
55
|
+
"distribution": distribution,
|
|
56
|
+
"auth": auth,
|
|
57
|
+
"asr_session": asr_session,
|
|
58
|
+
"tts_session": tts_session,
|
|
59
|
+
"asr_accelerator": asr_accelerator,
|
|
60
|
+
"tts_accelerator": tts_accelerator,
|
|
61
|
+
}
|
|
62
|
+
colab.update({key: value for key, value in overrides.items() if value is not None})
|
|
63
|
+
colab["enabled"] = True
|
|
64
|
+
speech["colab"] = colab
|
|
23
65
|
asr.update({"enabled": True, "base_url": asr_base_url.rstrip("/"), "model": "Qwen/Qwen3-ASR-0.6B"})
|
|
24
66
|
tts.update({"enabled": True, "base_url": tts_base_url.rstrip("/"), "model": "OpenMOSS-Team/MOSS-TTS-Nano"})
|
|
25
67
|
if tts_reference_audio and not str(tts.get("ref_audio") or "").strip():
|
|
26
68
|
tts["ref_audio"] = tts_reference_audio
|
|
27
69
|
ciel_runtime.save_config(config)
|
|
28
|
-
return {"asr": asr["base_url"], "tts": tts["base_url"]}
|
|
70
|
+
return {"asr": asr["base_url"], "tts": tts["base_url"], "colab": colab}
|
|
29
71
|
|
|
30
72
|
|
|
31
73
|
def main() -> int:
|
|
32
74
|
parser = argparse.ArgumentParser()
|
|
33
|
-
parser.add_argument("--asr-base-url"
|
|
34
|
-
parser.add_argument("--tts-base-url"
|
|
75
|
+
parser.add_argument("--asr-base-url")
|
|
76
|
+
parser.add_argument("--tts-base-url")
|
|
35
77
|
parser.add_argument("--tts-reference-audio", default=DEFAULT_TTS_REFERENCE_AUDIO)
|
|
78
|
+
parser.add_argument("--distribution")
|
|
79
|
+
parser.add_argument("--auth", choices=("adc", "oauth2"))
|
|
80
|
+
parser.add_argument("--asr-session")
|
|
81
|
+
parser.add_argument("--tts-session")
|
|
82
|
+
parser.add_argument("--asr-accelerator")
|
|
83
|
+
parser.add_argument("--tts-accelerator")
|
|
84
|
+
parser.add_argument("--print-colab-settings", action="store_true")
|
|
36
85
|
args = parser.parse_args()
|
|
37
|
-
|
|
86
|
+
if args.print_colab_settings:
|
|
87
|
+
print(json.dumps(colab_settings(), separators=(",", ":")))
|
|
88
|
+
return 0
|
|
89
|
+
if not args.asr_base_url or not args.tts_base_url:
|
|
90
|
+
parser.error("--asr-base-url and --tts-base-url are required unless --print-colab-settings is used")
|
|
91
|
+
result = configure(
|
|
92
|
+
args.asr_base_url,
|
|
93
|
+
args.tts_base_url,
|
|
94
|
+
args.tts_reference_audio,
|
|
95
|
+
distribution=args.distribution,
|
|
96
|
+
auth=args.auth,
|
|
97
|
+
asr_session=args.asr_session,
|
|
98
|
+
tts_session=args.tts_session,
|
|
99
|
+
asr_accelerator=args.asr_accelerator,
|
|
100
|
+
tts_accelerator=args.tts_accelerator,
|
|
101
|
+
)
|
|
38
102
|
print(f"Configured Ciel speech workers: ASR={result['asr']} TTS={result['tts']}")
|
|
39
103
|
return 0
|
|
40
104
|
|
|
@@ -1,11 +1,32 @@
|
|
|
1
1
|
param(
|
|
2
|
-
[string]$Distribution
|
|
3
|
-
[string]$
|
|
4
|
-
[string]$
|
|
2
|
+
[string]$Distribution,
|
|
3
|
+
[string]$ColabAuth,
|
|
4
|
+
[string]$AsrSession,
|
|
5
|
+
[string]$TtsSession,
|
|
6
|
+
[string]$AsrAccelerator,
|
|
7
|
+
[string]$TtsAccelerator
|
|
5
8
|
)
|
|
6
9
|
|
|
7
10
|
$ErrorActionPreference = "Stop"
|
|
8
11
|
$repo = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
|
|
12
|
+
$settingsJson = (& python (Join-Path $PSScriptRoot "configure_speech_workers.py") --print-colab-settings) -join "`n"
|
|
13
|
+
if ($LASTEXITCODE -ne 0) { throw "Could not read Ciel Colab settings." }
|
|
14
|
+
$settings = $settingsJson | ConvertFrom-Json
|
|
15
|
+
if ($settings.enabled -eq $false) { throw "Colab worker management is disabled in Web Chat > Speech Settings." }
|
|
16
|
+
if ([string]::IsNullOrWhiteSpace($Distribution)) { $Distribution = [string]$settings.distribution }
|
|
17
|
+
if ([string]::IsNullOrWhiteSpace($ColabAuth)) { $ColabAuth = [string]$settings.auth }
|
|
18
|
+
if ([string]::IsNullOrWhiteSpace($AsrSession)) { $AsrSession = [string]$settings.asr_session }
|
|
19
|
+
if ([string]::IsNullOrWhiteSpace($TtsSession)) { $TtsSession = [string]$settings.tts_session }
|
|
20
|
+
if ([string]::IsNullOrWhiteSpace($AsrAccelerator)) { $AsrAccelerator = [string]$settings.asr_accelerator }
|
|
21
|
+
if ([string]::IsNullOrWhiteSpace($TtsAccelerator)) { $TtsAccelerator = [string]$settings.tts_accelerator }
|
|
22
|
+
if ($Distribution -notmatch '^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$') { throw "Invalid WSL distribution name." }
|
|
23
|
+
if ($ColabAuth -notin @('adc', 'oauth2')) { throw "ColabAuth must be adc or oauth2." }
|
|
24
|
+
foreach ($session in @($AsrSession, $TtsSession)) {
|
|
25
|
+
if ($session -notmatch '^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$') { throw "Invalid Colab session name: $session" }
|
|
26
|
+
}
|
|
27
|
+
foreach ($accelerator in @($AsrAccelerator, $TtsAccelerator)) {
|
|
28
|
+
if ($accelerator -notin @('T4', 'L4', 'G4', 'A100', 'H100')) { throw "Unsupported Colab accelerator: $accelerator" }
|
|
29
|
+
}
|
|
9
30
|
$wslRepo = (& wsl -d $Distribution -- wslpath -a ($repo -replace '\\', '/')).Trim()
|
|
10
31
|
if (-not $wslRepo) { throw "Could not resolve the repository path in WSL." }
|
|
11
32
|
$bootstrapEnv = ""
|
|
@@ -19,25 +40,31 @@ if ($env:CIEL_SPEECH_API_KEY) {
|
|
|
19
40
|
}
|
|
20
41
|
|
|
21
42
|
Write-Host "Checking Colab CLI authentication..."
|
|
22
|
-
& wsl -d $Distribution -- bash -lc "colab --auth
|
|
43
|
+
& wsl -d $Distribution -- bash -lc "colab --auth $ColabAuth status >/dev/null"
|
|
23
44
|
if ($LASTEXITCODE -ne 0) {
|
|
24
|
-
throw "Colab CLI is not authenticated
|
|
45
|
+
throw "Colab CLI is not authenticated with '$ColabAuth' in WSL '$Distribution'."
|
|
25
46
|
}
|
|
26
47
|
|
|
27
|
-
|
|
28
|
-
& wsl -d $Distribution -- bash -lc "colab --auth
|
|
29
|
-
if ($LASTEXITCODE -
|
|
48
|
+
function Ensure-ColabSession([string]$Session, [string]$Accelerator, [string]$Role) {
|
|
49
|
+
& wsl -d $Distribution -- bash -lc "colab --auth $ColabAuth status --session '$Session' >/dev/null 2>&1"
|
|
50
|
+
if ($LASTEXITCODE -eq 0) {
|
|
51
|
+
Write-Host "Reusing $Role $Accelerator session: $Session"
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
Write-Host "Creating $Role $Accelerator session: $Session"
|
|
55
|
+
& wsl -d $Distribution -- bash -lc "colab --auth $ColabAuth new --gpu $Accelerator --session '$Session'"
|
|
56
|
+
if ($LASTEXITCODE -ne 0) { throw "Could not create $Role Colab session." }
|
|
57
|
+
}
|
|
30
58
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if ($LASTEXITCODE -ne 0) { throw "Could not create TTS Colab session." }
|
|
59
|
+
Ensure-ColabSession $AsrSession $AsrAccelerator "ASR"
|
|
60
|
+
Ensure-ColabSession $TtsSession $TtsAccelerator "TTS"
|
|
34
61
|
|
|
35
62
|
Write-Host "Installing Qwen3-ASR and its Tailscale service..."
|
|
36
|
-
$asrOutput = (& wsl -d $Distribution -- bash -lc "colab --auth
|
|
63
|
+
$asrOutput = (& wsl -d $Distribution -- bash -lc "colab --auth $ColabAuth exec --session '$AsrSession'$bootstrapEnv --file '$wslRepo/scripts/colab/bootstrap_qwen_asr.py'" 2>&1 | Tee-Object -Variable asrDisplay) -join "`n"
|
|
37
64
|
if ($LASTEXITCODE -ne 0) { throw "ASR bootstrap failed." }
|
|
38
65
|
|
|
39
66
|
Write-Host "Installing MOSS-TTS-Nano and its Tailscale service..."
|
|
40
|
-
$ttsOutput = (& wsl -d $Distribution -- bash -lc "colab --auth
|
|
67
|
+
$ttsOutput = (& wsl -d $Distribution -- bash -lc "colab --auth $ColabAuth exec --session '$TtsSession'$bootstrapEnv --file '$wslRepo/scripts/colab/bootstrap_moss_tts.py'" 2>&1 | Tee-Object -Variable ttsDisplay) -join "`n"
|
|
41
68
|
if ($LASTEXITCODE -ne 0) { throw "TTS bootstrap failed." }
|
|
42
69
|
|
|
43
70
|
function Read-BootstrapResult([string]$Text, [string]$Role) {
|
|
@@ -50,7 +77,7 @@ function Read-BootstrapResult([string]$Text, [string]$Role) {
|
|
|
50
77
|
|
|
51
78
|
$asr = Read-BootstrapResult $asrOutput "asr"
|
|
52
79
|
$tts = Read-BootstrapResult $ttsOutput "tts"
|
|
53
|
-
& python (Join-Path $PSScriptRoot "configure_speech_workers.py") --asr-base-url $asr.base_url --tts-base-url $tts.base_url
|
|
80
|
+
& python (Join-Path $PSScriptRoot "configure_speech_workers.py") --asr-base-url $asr.base_url --tts-base-url $tts.base_url --distribution $Distribution --auth $ColabAuth --asr-session $AsrSession --tts-session $TtsSession --asr-accelerator $AsrAccelerator --tts-accelerator $TtsAccelerator
|
|
54
81
|
if ($LASTEXITCODE -ne 0) { throw "Workers started, but Ciel speech configuration failed." }
|
|
55
82
|
|
|
56
83
|
Write-Host "Both services are running and connected to Web Chat > Speech Settings."
|