@elizaos/plugin-local-inference 2.0.0-beta.1 → 2.0.3-beta.2
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/LICENSE +21 -0
- package/README.md +83 -0
- package/package.json +82 -15
- package/src/actions/generate-media.d.ts +59 -0
- package/src/actions/generate-media.d.ts.map +1 -0
- package/src/actions/generate-media.ts +647 -0
- package/src/actions/identify-speaker.d.ts +23 -0
- package/src/actions/identify-speaker.d.ts.map +1 -0
- package/src/actions/identify-speaker.ts +171 -0
- package/src/actions/transcription-control.d.ts +29 -0
- package/src/actions/transcription-control.d.ts.map +1 -0
- package/src/actions/transcription-control.test.ts +100 -0
- package/src/actions/transcription-control.ts +127 -0
- package/src/adapters/capacitor-llama/__tests__/compat-behavior.test.ts +218 -0
- package/src/adapters/capacitor-llama/__tests__/index.test.ts +68 -0
- package/src/adapters/capacitor-llama/__tests__/structured-output.test.ts +215 -0
- package/src/adapters/capacitor-llama/__tests__/text-streaming.test.ts +174 -0
- package/src/adapters/capacitor-llama/environment.ts +71 -0
- package/src/adapters/capacitor-llama/index.browser.ts +83 -0
- package/src/adapters/capacitor-llama/index.ts +807 -0
- package/src/adapters/capacitor-llama/loader.ts +109 -0
- package/src/adapters/capacitor-llama/structured-output.ts +165 -0
- package/src/adapters/capacitor-llama/text-streaming.ts +227 -0
- package/src/adapters/capacitor-llama/types.ts +374 -0
- package/src/backends/apple-foundation.ts +127 -0
- package/src/index.d.ts +8 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.ts +62 -0
- package/src/local-inference-routes.d.ts +38 -0
- package/src/local-inference-routes.d.ts.map +1 -0
- package/src/local-inference-routes.test.ts +344 -0
- package/src/local-inference-routes.ts +1543 -0
- package/src/provider.d.ts +21 -0
- package/src/provider.d.ts.map +1 -0
- package/src/provider.ts +1082 -0
- package/src/routes/compat-helpers.d.ts +18 -0
- package/src/routes/compat-helpers.d.ts.map +1 -0
- package/src/routes/compat-helpers.ts +274 -0
- package/src/routes/family-member-route.d.ts +62 -0
- package/src/routes/family-member-route.d.ts.map +1 -0
- package/src/routes/family-member-route.ts +353 -0
- package/src/routes/index.d.ts +19 -0
- package/src/routes/index.d.ts.map +1 -0
- package/src/routes/index.ts +60 -0
- package/src/routes/live-diarization-route.d.ts +26 -0
- package/src/routes/live-diarization-route.d.ts.map +1 -0
- package/src/routes/live-diarization-route.test.ts +213 -0
- package/src/routes/live-diarization-route.ts +122 -0
- package/src/routes/local-inference-asr-route.d.ts +4 -0
- package/src/routes/local-inference-asr-route.d.ts.map +1 -0
- package/src/routes/local-inference-asr-route.test.ts +205 -0
- package/src/routes/local-inference-asr-route.ts +163 -0
- package/src/routes/local-inference-asr-transcribe.d.ts +20 -0
- package/src/routes/local-inference-asr-transcribe.d.ts.map +1 -0
- package/src/routes/local-inference-asr-transcribe.test.ts +118 -0
- package/src/routes/local-inference-asr-transcribe.ts +97 -0
- package/src/routes/local-inference-compat-routes.d.ts +16 -0
- package/src/routes/local-inference-compat-routes.d.ts.map +1 -0
- package/src/routes/local-inference-compat-routes.test.ts +485 -0
- package/src/routes/local-inference-compat-routes.ts +808 -0
- package/src/routes/local-inference-tts-route.d.ts +7 -0
- package/src/routes/local-inference-tts-route.d.ts.map +1 -0
- package/src/routes/local-inference-tts-route.test.ts +179 -0
- package/src/routes/local-inference-tts-route.ts +230 -0
- package/src/routes/transcript-audio-store.d.ts +15 -0
- package/src/routes/transcript-audio-store.d.ts.map +1 -0
- package/src/routes/transcript-audio-store.ts +27 -0
- package/src/routes/transcripts-routes.d.ts +36 -0
- package/src/routes/transcripts-routes.d.ts.map +1 -0
- package/src/routes/transcripts-routes.test.ts +144 -0
- package/src/routes/transcripts-routes.ts +159 -0
- package/src/routes/voice-first-run-routes.d.ts +62 -0
- package/src/routes/voice-first-run-routes.d.ts.map +1 -0
- package/src/routes/voice-first-run-routes.ts +524 -0
- package/src/routes/voice-models-routes.d.ts +62 -0
- package/src/routes/voice-models-routes.d.ts.map +1 -0
- package/src/routes/voice-models-routes.ts +554 -0
- package/src/routes/voice-profile-plugin-routes.d.ts +19 -0
- package/src/routes/voice-profile-plugin-routes.d.ts.map +1 -0
- package/src/routes/voice-profile-plugin-routes.ts +138 -0
- package/src/routes/voice-profiles-management-routes.d.ts +52 -0
- package/src/routes/voice-profiles-management-routes.d.ts.map +1 -0
- package/src/routes/voice-profiles-management-routes.ts +476 -0
- package/src/routes/voice-speaker-profile-routes.d.ts +57 -0
- package/src/routes/voice-speaker-profile-routes.d.ts.map +1 -0
- package/src/routes/voice-speaker-profile-routes.ts +199 -0
- package/src/runtime/aosp-llama-loader-selection.test.ts +80 -0
- package/src/runtime/capacitor-llama.d.ts +25 -0
- package/src/runtime/embedding-manager-support.d.ts +77 -0
- package/src/runtime/embedding-manager-support.d.ts.map +1 -0
- package/src/runtime/embedding-manager-support.ts +497 -0
- package/src/runtime/embedding-presets.d.ts +16 -0
- package/src/runtime/embedding-presets.d.ts.map +1 -0
- package/src/runtime/embedding-presets.ts +81 -0
- package/src/runtime/embedding-warmup-policy.d.ts +14 -0
- package/src/runtime/embedding-warmup-policy.d.ts.map +1 -0
- package/src/runtime/embedding-warmup-policy.test.ts +53 -0
- package/src/runtime/embedding-warmup-policy.ts +48 -0
- package/src/runtime/ensure-local-inference-handler.d.ts +62 -0
- package/src/runtime/ensure-local-inference-handler.d.ts.map +1 -0
- package/src/runtime/ensure-local-inference-handler.test.ts +528 -0
- package/src/runtime/ensure-local-inference-handler.ts +1448 -0
- package/src/runtime/index.d.ts +15 -0
- package/src/runtime/index.d.ts.map +1 -0
- package/src/runtime/index.ts +33 -0
- package/src/runtime/mobile-local-inference-gate.d.ts +31 -0
- package/src/runtime/mobile-local-inference-gate.d.ts.map +1 -0
- package/src/runtime/mobile-local-inference-gate.test.ts +69 -0
- package/src/runtime/mobile-local-inference-gate.ts +44 -0
- package/src/runtime/voice-entity-binding.d.ts +103 -0
- package/src/runtime/voice-entity-binding.d.ts.map +1 -0
- package/src/runtime/voice-entity-binding.transcript.test.ts +69 -0
- package/src/runtime/voice-entity-binding.ts +328 -0
- package/src/services/README.md +71 -0
- package/src/services/__tests__/backend-selector.test.ts +101 -0
- package/src/services/__tests__/checkpoint-manager.test.ts +376 -0
- package/src/services/__tests__/gpu-autotune.test.ts +400 -0
- package/src/services/__tests__/llm-streaming-binding.test.ts +85 -0
- package/src/services/__tests__/planner-grammar.test.ts +372 -0
- package/src/services/__tests__/runtime-target.test.ts +176 -0
- package/src/services/active-model-switch-rollback.test.ts +183 -0
- package/src/services/active-model.d.ts +282 -0
- package/src/services/active-model.d.ts.map +1 -0
- package/src/services/active-model.ts +1213 -0
- package/src/services/assignments.d.ts +71 -0
- package/src/services/assignments.d.ts.map +1 -0
- package/src/services/assignments.test.ts +80 -0
- package/src/services/assignments.ts +230 -0
- package/src/services/backend-selector.ts +95 -0
- package/src/services/backend.d.ts +346 -0
- package/src/services/backend.d.ts.map +1 -0
- package/src/services/backend.ts +612 -0
- package/src/services/bionic-host-loader.d.ts +46 -0
- package/src/services/bionic-host-loader.d.ts.map +1 -0
- package/src/services/bionic-host-loader.test.ts +133 -0
- package/src/services/bionic-host-loader.ts +180 -0
- package/src/services/bundled-models.d.ts +34 -0
- package/src/services/bundled-models.d.ts.map +1 -0
- package/src/services/bundled-models.ts +129 -0
- package/src/services/cache-bridge.d.ts +206 -0
- package/src/services/cache-bridge.d.ts.map +1 -0
- package/src/services/cache-bridge.test.ts +516 -0
- package/src/services/cache-bridge.ts +423 -0
- package/src/services/catalog.d.ts +10 -0
- package/src/services/catalog.d.ts.map +1 -0
- package/src/services/catalog.test.ts +238 -0
- package/src/services/catalog.ts +27 -0
- package/src/services/checkpoint-client.d.ts +109 -0
- package/src/services/checkpoint-client.d.ts.map +1 -0
- package/src/services/checkpoint-client.ts +258 -0
- package/src/services/checkpoint-manager.ts +474 -0
- package/src/services/cloud-fallback.d.ts +102 -0
- package/src/services/cloud-fallback.d.ts.map +1 -0
- package/src/services/cloud-fallback.ts +230 -0
- package/src/services/conversation-registry.d.ts +142 -0
- package/src/services/conversation-registry.d.ts.map +1 -0
- package/src/services/conversation-registry.test.ts +235 -0
- package/src/services/conversation-registry.ts +264 -0
- package/src/services/desktop-fused-ffi-backend-runtime.d.ts +95 -0
- package/src/services/desktop-fused-ffi-backend-runtime.d.ts.map +1 -0
- package/src/services/desktop-fused-ffi-backend-runtime.ts +339 -0
- package/src/services/device-bridge.d.ts +188 -0
- package/src/services/device-bridge.d.ts.map +1 -0
- package/src/services/device-bridge.ts +1237 -0
- package/src/services/device-resource-metrics.d.ts +149 -0
- package/src/services/device-resource-metrics.d.ts.map +1 -0
- package/src/services/device-resource-metrics.test.ts +98 -0
- package/src/services/device-resource-metrics.ts +346 -0
- package/src/services/device-tier.d.ts +115 -0
- package/src/services/device-tier.d.ts.map +1 -0
- package/src/services/device-tier.test.ts +371 -0
- package/src/services/device-tier.ts +410 -0
- package/src/services/downloader.d.ts +82 -0
- package/src/services/downloader.d.ts.map +1 -0
- package/src/services/downloader.test.ts +747 -0
- package/src/services/downloader.ts +925 -0
- package/src/services/engine-direct-bundle.test.ts +58 -0
- package/src/services/engine-streaming.test.ts +80 -0
- package/src/services/engine.d.ts +540 -0
- package/src/services/engine.d.ts.map +1 -0
- package/src/services/engine.ts +1909 -0
- package/src/services/ensure-local-artifacts.integration.test.ts +273 -0
- package/src/services/ensure-local-artifacts.test.ts +368 -0
- package/src/services/ensure-local-artifacts.ts +351 -0
- package/src/services/external-scanner.d.ts +17 -0
- package/src/services/external-scanner.d.ts.map +1 -0
- package/src/services/external-scanner.ts +312 -0
- package/src/services/ffi-llm-mock.ts +354 -0
- package/src/services/ffi-llm-streaming-abi.ts +442 -0
- package/src/services/ffi-streaming-backend.d.ts +180 -0
- package/src/services/ffi-streaming-backend.d.ts.map +1 -0
- package/src/services/ffi-streaming-backend.ts +382 -0
- package/src/services/ffi-streaming-runner.d.ts +122 -0
- package/src/services/ffi-streaming-runner.d.ts.map +1 -0
- package/src/services/ffi-streaming-runner.test.ts +60 -0
- package/src/services/ffi-streaming-runner.ts +354 -0
- package/src/services/ffi-unload-ordering.test.ts +162 -0
- package/src/services/gpu-autotune.ts +534 -0
- package/src/services/gpu-detect.d.ts +56 -0
- package/src/services/gpu-detect.d.ts.map +1 -0
- package/src/services/gpu-detect.ts +139 -0
- package/src/services/handler-registry.d.ts +72 -0
- package/src/services/handler-registry.d.ts.map +1 -0
- package/src/services/handler-registry.ts +240 -0
- package/src/services/hardware.d.ts +63 -0
- package/src/services/hardware.d.ts.map +1 -0
- package/src/services/hardware.test.ts +231 -0
- package/src/services/hardware.ts +410 -0
- package/src/services/hf-search.d.ts +26 -0
- package/src/services/hf-search.d.ts.map +1 -0
- package/src/services/hf-search.test.ts +69 -0
- package/src/services/hf-search.ts +420 -0
- package/src/services/image-description-runtime.d.ts +14 -0
- package/src/services/image-description-runtime.d.ts.map +1 -0
- package/src/services/image-description-runtime.test.ts +61 -0
- package/src/services/image-description-runtime.ts +118 -0
- package/src/services/imagegen/aosp-unavailable.d.ts +134 -0
- package/src/services/imagegen/aosp-unavailable.d.ts.map +1 -0
- package/src/services/imagegen/aosp-unavailable.ts +229 -0
- package/src/services/imagegen/backend-selector.d.ts +118 -0
- package/src/services/imagegen/backend-selector.d.ts.map +1 -0
- package/src/services/imagegen/backend-selector.ts +277 -0
- package/src/services/imagegen/coreml-unavailable.d.ts +105 -0
- package/src/services/imagegen/coreml-unavailable.d.ts.map +1 -0
- package/src/services/imagegen/coreml-unavailable.ts +237 -0
- package/src/services/imagegen/errors.d.ts +16 -0
- package/src/services/imagegen/errors.d.ts.map +1 -0
- package/src/services/imagegen/errors.ts +40 -0
- package/src/services/imagegen/index.d.ts +58 -0
- package/src/services/imagegen/index.d.ts.map +1 -0
- package/src/services/imagegen/index.ts +144 -0
- package/src/services/imagegen/mflux.d.ts +74 -0
- package/src/services/imagegen/mflux.d.ts.map +1 -0
- package/src/services/imagegen/mflux.ts +313 -0
- package/src/services/imagegen/sd-cpp.d.ts +180 -0
- package/src/services/imagegen/sd-cpp.d.ts.map +1 -0
- package/src/services/imagegen/sd-cpp.ts +718 -0
- package/src/services/imagegen/tensorrt-unavailable.d.ts +83 -0
- package/src/services/imagegen/tensorrt-unavailable.d.ts.map +1 -0
- package/src/services/imagegen/tensorrt-unavailable.ts +295 -0
- package/src/services/imagegen/types.d.ts +181 -0
- package/src/services/imagegen/types.d.ts.map +1 -0
- package/src/services/imagegen/types.ts +193 -0
- package/src/services/index.d.ts +29 -0
- package/src/services/index.d.ts.map +1 -0
- package/src/services/index.ts +211 -0
- package/src/services/inference-capabilities.d.ts +132 -0
- package/src/services/inference-capabilities.d.ts.map +1 -0
- package/src/services/inference-capabilities.test.ts +75 -0
- package/src/services/inference-capabilities.ts +204 -0
- package/src/services/inference-telemetry.d.ts +59 -0
- package/src/services/inference-telemetry.d.ts.map +1 -0
- package/src/services/inference-telemetry.ts +143 -0
- package/src/services/ios-llama-streaming.ts +248 -0
- package/src/services/kv-spill.d.ts +189 -0
- package/src/services/kv-spill.d.ts.map +1 -0
- package/src/services/kv-spill.test.ts +222 -0
- package/src/services/kv-spill.ts +356 -0
- package/src/services/latency-trace.d.ts +346 -0
- package/src/services/latency-trace.d.ts.map +1 -0
- package/src/services/latency-trace.test.ts +266 -0
- package/src/services/latency-trace.ts +844 -0
- package/src/services/llama-server-metrics.ts +304 -0
- package/src/services/llm-streaming-binding.d.ts +96 -0
- package/src/services/llm-streaming-binding.d.ts.map +1 -0
- package/src/services/llm-streaming-binding.ts +136 -0
- package/src/services/load-args.d.ts +82 -0
- package/src/services/load-args.d.ts.map +1 -0
- package/src/services/load-args.ts +81 -0
- package/src/services/manifest/eliza-1.manifest.v1.json +708 -0
- package/src/services/manifest/index.d.ts +4 -0
- package/src/services/manifest/index.d.ts.map +1 -0
- package/src/services/manifest/index.ts +66 -0
- package/src/services/manifest/manifest.test.ts +689 -0
- package/src/services/manifest/schema.d.ts +713 -0
- package/src/services/manifest/schema.d.ts.map +1 -0
- package/src/services/manifest/schema.ts +653 -0
- package/src/services/manifest/types.d.ts +30 -0
- package/src/services/manifest/types.d.ts.map +1 -0
- package/src/services/manifest/types.ts +55 -0
- package/src/services/manifest/validator.d.ts +66 -0
- package/src/services/manifest/validator.d.ts.map +1 -0
- package/src/services/manifest/validator.ts +567 -0
- package/src/services/memory-arbiter.d.ts +318 -0
- package/src/services/memory-arbiter.d.ts.map +1 -0
- package/src/services/memory-arbiter.test.ts +419 -0
- package/src/services/memory-arbiter.ts +925 -0
- package/src/services/memory-monitor.d.ts +122 -0
- package/src/services/memory-monitor.d.ts.map +1 -0
- package/src/services/memory-monitor.test.ts +208 -0
- package/src/services/memory-monitor.ts +297 -0
- package/src/services/memory-pressure.d.ts +130 -0
- package/src/services/memory-pressure.d.ts.map +1 -0
- package/src/services/memory-pressure.ts +414 -0
- package/src/services/mtp-doctor.d.ts +13 -0
- package/src/services/mtp-doctor.d.ts.map +1 -0
- package/src/services/mtp-doctor.ts +78 -0
- package/src/services/network-policy.d.ts +127 -0
- package/src/services/network-policy.d.ts.map +1 -0
- package/src/services/network-policy.ts +346 -0
- package/src/services/paths.d.ts +6 -0
- package/src/services/paths.d.ts.map +1 -0
- package/src/services/paths.ts +25 -0
- package/src/services/planner-skeleton.d.ts +124 -0
- package/src/services/planner-skeleton.d.ts.map +1 -0
- package/src/services/planner-skeleton.ts +175 -0
- package/src/services/providers.d.ts +38 -0
- package/src/services/providers.d.ts.map +1 -0
- package/src/services/providers.ts +507 -0
- package/src/services/ram-budget-cache.test.ts +163 -0
- package/src/services/ram-budget.d.ts +110 -0
- package/src/services/ram-budget.d.ts.map +1 -0
- package/src/services/ram-budget.ts +0 -0
- package/src/services/readiness.d.ts +9 -0
- package/src/services/readiness.d.ts.map +1 -0
- package/src/services/readiness.test.ts +87 -0
- package/src/services/readiness.ts +238 -0
- package/src/services/recommendation.d.ts +111 -0
- package/src/services/recommendation.d.ts.map +1 -0
- package/src/services/recommendation.ts +671 -0
- package/src/services/registry.d.ts +35 -0
- package/src/services/registry.d.ts.map +1 -0
- package/src/services/registry.ts +151 -0
- package/src/services/router-handler.d.ts +92 -0
- package/src/services/router-handler.d.ts.map +1 -0
- package/src/services/router-handler.test.ts +45 -0
- package/src/services/router-handler.ts +407 -0
- package/src/services/routing-policy.d.ts +69 -0
- package/src/services/routing-policy.d.ts.map +1 -0
- package/src/services/routing-policy.test.ts +164 -0
- package/src/services/routing-policy.ts +297 -0
- package/src/services/routing-preferences.d.ts +8 -0
- package/src/services/routing-preferences.d.ts.map +1 -0
- package/src/services/routing-preferences.ts +17 -0
- package/src/services/runtime-target.d.ts +98 -0
- package/src/services/runtime-target.d.ts.map +1 -0
- package/src/services/runtime-target.ts +154 -0
- package/src/services/service.d.ts +128 -0
- package/src/services/service.d.ts.map +1 -0
- package/src/services/service.test.ts +223 -0
- package/src/services/service.ts +735 -0
- package/src/services/session-pool.d.ts +72 -0
- package/src/services/session-pool.d.ts.map +1 -0
- package/src/services/session-pool.ts +153 -0
- package/src/services/structured-output/deterministic-repair.d.ts +23 -0
- package/src/services/structured-output/deterministic-repair.d.ts.map +1 -0
- package/src/services/structured-output/deterministic-repair.test.ts +169 -0
- package/src/services/structured-output/deterministic-repair.ts +443 -0
- package/src/services/structured-output/index.ts +4 -0
- package/src/services/structured-output.d.ts +311 -0
- package/src/services/structured-output.d.ts.map +1 -0
- package/src/services/structured-output.test.ts +483 -0
- package/src/services/structured-output.ts +712 -0
- package/src/services/system-memory.d.ts +33 -0
- package/src/services/system-memory.d.ts.map +1 -0
- package/src/services/system-memory.test.ts +47 -0
- package/src/services/system-memory.ts +67 -0
- package/src/services/transcription-priority.test.ts +211 -0
- package/src/services/types.d.ts +19 -0
- package/src/services/types.d.ts.map +1 -0
- package/src/services/types.ts +55 -0
- package/src/services/verify-on-device.d.ts +34 -0
- package/src/services/verify-on-device.d.ts.map +1 -0
- package/src/services/verify-on-device.test.ts +87 -0
- package/src/services/verify-on-device.ts +127 -0
- package/src/services/verify.d.ts +8 -0
- package/src/services/verify.d.ts.map +1 -0
- package/src/services/verify.ts +13 -0
- package/src/services/vision/aosp-unavailable.d.ts +115 -0
- package/src/services/vision/aosp-unavailable.d.ts.map +1 -0
- package/src/services/vision/aosp-unavailable.ts +163 -0
- package/src/services/vision/capacitor-llama.d.ts +99 -0
- package/src/services/vision/capacitor-llama.d.ts.map +1 -0
- package/src/services/vision/capacitor-llama.ts +255 -0
- package/src/services/vision/cloud-fallback.d.ts +47 -0
- package/src/services/vision/cloud-fallback.d.ts.map +1 -0
- package/src/services/vision/cloud-fallback.test.ts +243 -0
- package/src/services/vision/cloud-fallback.ts +268 -0
- package/src/services/vision/fallback-chain.test.ts +86 -0
- package/src/services/vision/hash.d.ts +71 -0
- package/src/services/vision/hash.d.ts.map +1 -0
- package/src/services/vision/hash.ts +157 -0
- package/src/services/vision/index.d.ts +95 -0
- package/src/services/vision/index.d.ts.map +1 -0
- package/src/services/vision/index.ts +251 -0
- package/src/services/vision/llama-server.d.ts +73 -0
- package/src/services/vision/llama-server.d.ts.map +1 -0
- package/src/services/vision/llama-server.ts +177 -0
- package/src/services/vision/types.d.ts +153 -0
- package/src/services/vision/types.d.ts.map +1 -0
- package/src/services/vision/types.ts +154 -0
- package/src/services/vision/vast-fallback.d.ts +18 -0
- package/src/services/vision/vast-fallback.d.ts.map +1 -0
- package/src/services/vision/vast-fallback.ts +127 -0
- package/src/services/vision-embedding-cache.d.ts +98 -0
- package/src/services/vision-embedding-cache.d.ts.map +1 -0
- package/src/services/vision-embedding-cache.ts +189 -0
- package/src/services/voice/VOICE_WORKBENCH.md +88 -0
- package/src/services/voice/__test-helpers__/fake-ffi.ts +94 -0
- package/src/services/voice/__test-helpers__/synthetic-speech.ts +124 -0
- package/src/services/voice/__tests__/checkpoint-manager.test.ts +241 -0
- package/src/services/voice/__tests__/checkpoint-policy.test.ts +270 -0
- package/src/services/voice/__tests__/eager-context-builder.test.ts +257 -0
- package/src/services/voice/__tests__/eliza1-eot-scorer.test.ts +288 -0
- package/src/services/voice/__tests__/eot-classifier.test.ts +431 -0
- package/src/services/voice/__tests__/optimistic-rollback.test.ts +312 -0
- package/src/services/voice/__tests__/prefill-client.test.ts +266 -0
- package/src/services/voice/__tests__/prefix-preserving-queue.test.ts +208 -0
- package/src/services/voice/__tests__/streaming-asr.test.ts +450 -0
- package/src/services/voice/__tests__/streaming-transcriber.test.ts +339 -0
- package/src/services/voice/__tests__/turn-detector-resolver.test.ts +195 -0
- package/src/services/voice/__tests__/voice-state-machine-prefill.test.ts +275 -0
- package/src/services/voice/__tests__/voice-state-machine.test.ts +354 -0
- package/src/services/voice/asr-timed.real.test.ts +141 -0
- package/src/services/voice/audio-frame-consumer.d.ts +212 -0
- package/src/services/voice/audio-frame-consumer.d.ts.map +1 -0
- package/src/services/voice/audio-frame-consumer.test.ts +343 -0
- package/src/services/voice/audio-frame-consumer.ts +491 -0
- package/src/services/voice/barge-in.d.ts +112 -0
- package/src/services/voice/barge-in.d.ts.map +1 -0
- package/src/services/voice/barge-in.test.ts +244 -0
- package/src/services/voice/barge-in.ts +336 -0
- package/src/services/voice/cancellation-coordinator.d.ts +127 -0
- package/src/services/voice/cancellation-coordinator.d.ts.map +1 -0
- package/src/services/voice/cancellation-coordinator.test.ts +196 -0
- package/src/services/voice/cancellation-coordinator.ts +269 -0
- package/src/services/voice/checkpoint-manager.d.ts +199 -0
- package/src/services/voice/checkpoint-manager.d.ts.map +1 -0
- package/src/services/voice/checkpoint-manager.ts +401 -0
- package/src/services/voice/checkpoint-policy.ts +336 -0
- package/src/services/voice/composite-eot-classifier.test.ts +59 -0
- package/src/services/voice/e2e-harness.test.ts +182 -0
- package/src/services/voice/e2e-harness.ts +743 -0
- package/src/services/voice/eager-context-builder.d.ts +170 -0
- package/src/services/voice/eager-context-builder.d.ts.map +1 -0
- package/src/services/voice/eager-context-builder.ts +262 -0
- package/src/services/voice/eliza1-eot-scorer.d.ts +124 -0
- package/src/services/voice/eliza1-eot-scorer.d.ts.map +1 -0
- package/src/services/voice/eliza1-eot-scorer.ts +242 -0
- package/src/services/voice/embedding-server.ts +200 -0
- package/src/services/voice/embedding.d.ts +133 -0
- package/src/services/voice/embedding.d.ts.map +1 -0
- package/src/services/voice/embedding.test.ts +131 -0
- package/src/services/voice/embedding.ts +243 -0
- package/src/services/voice/emotion-attribution.d.ts +68 -0
- package/src/services/voice/emotion-attribution.d.ts.map +1 -0
- package/src/services/voice/emotion-attribution.test.ts +129 -0
- package/src/services/voice/emotion-attribution.ts +361 -0
- package/src/services/voice/engine-bridge-cancellation.test.ts +422 -0
- package/src/services/voice/engine-bridge.d.ts +759 -0
- package/src/services/voice/engine-bridge.d.ts.map +1 -0
- package/src/services/voice/engine-bridge.test.ts +384 -0
- package/src/services/voice/engine-bridge.ts +2302 -0
- package/src/services/voice/eot-classifier-ggml.d.ts +179 -0
- package/src/services/voice/eot-classifier-ggml.d.ts.map +1 -0
- package/src/services/voice/eot-classifier-ggml.ts +566 -0
- package/src/services/voice/eot-classifier.d.ts +214 -0
- package/src/services/voice/eot-classifier.d.ts.map +1 -0
- package/src/services/voice/eot-classifier.ts +533 -0
- package/src/services/voice/errors.d.ts +20 -0
- package/src/services/voice/errors.d.ts.map +1 -0
- package/src/services/voice/errors.ts +32 -0
- package/src/services/voice/expressive-tags.d.ts +158 -0
- package/src/services/voice/expressive-tags.d.ts.map +1 -0
- package/src/services/voice/expressive-tags.ts +405 -0
- package/src/services/voice/ffi-bindings.d.ts +674 -0
- package/src/services/voice/ffi-bindings.d.ts.map +1 -0
- package/src/services/voice/ffi-bindings.test.ts +728 -0
- package/src/services/voice/ffi-bindings.ts +3225 -0
- package/src/services/voice/first-line-cache.d.ts +181 -0
- package/src/services/voice/first-line-cache.d.ts.map +1 -0
- package/src/services/voice/first-line-cache.ts +725 -0
- package/src/services/voice/fused-eot-scorer.d.ts +51 -0
- package/src/services/voice/fused-eot-scorer.d.ts.map +1 -0
- package/src/services/voice/fused-eot-scorer.ts +135 -0
- package/src/services/voice/index.d.ts +91 -0
- package/src/services/voice/index.d.ts.map +1 -0
- package/src/services/voice/index.ts +481 -0
- package/src/services/voice/kokoro/__tests__/kokoro-backend.test.ts +151 -0
- package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.real.test.ts +151 -0
- package/src/services/voice/kokoro/__tests__/kokoro-engine-bridge.test.ts +60 -0
- package/src/services/voice/kokoro/__tests__/kokoro-engine-discovery.test.ts +277 -0
- package/src/services/voice/kokoro/__tests__/kokoro-ffi-runtime.test.ts +235 -0
- package/src/services/voice/kokoro/__tests__/kokoro-runtime.test.ts +95 -0
- package/src/services/voice/kokoro/__tests__/phonemizer.test.ts +53 -0
- package/src/services/voice/kokoro/__tests__/runtime-selection.test.ts +231 -0
- package/src/services/voice/kokoro/__tests__/voices.test.ts +57 -0
- package/src/services/voice/kokoro/index.ts +79 -0
- package/src/services/voice/kokoro/kokoro-backend.d.ts +72 -0
- package/src/services/voice/kokoro/kokoro-backend.d.ts.map +1 -0
- package/src/services/voice/kokoro/kokoro-backend.ts +207 -0
- package/src/services/voice/kokoro/kokoro-engine-discovery.d.ts +58 -0
- package/src/services/voice/kokoro/kokoro-engine-discovery.d.ts.map +1 -0
- package/src/services/voice/kokoro/kokoro-engine-discovery.ts +177 -0
- package/src/services/voice/kokoro/kokoro-ffi-runtime.d.ts +75 -0
- package/src/services/voice/kokoro/kokoro-ffi-runtime.d.ts.map +1 -0
- package/src/services/voice/kokoro/kokoro-ffi-runtime.ts +233 -0
- package/src/services/voice/kokoro/kokoro-runtime.d.ts +100 -0
- package/src/services/voice/kokoro/kokoro-runtime.d.ts.map +1 -0
- package/src/services/voice/kokoro/kokoro-runtime.ts +170 -0
- package/src/services/voice/kokoro/phoneme-stream.ts +123 -0
- package/src/services/voice/kokoro/phonemizer.d.ts +50 -0
- package/src/services/voice/kokoro/phonemizer.d.ts.map +1 -0
- package/src/services/voice/kokoro/phonemizer.ts +344 -0
- package/src/services/voice/kokoro/pick-runtime.d.ts +61 -0
- package/src/services/voice/kokoro/pick-runtime.d.ts.map +1 -0
- package/src/services/voice/kokoro/pick-runtime.test.ts +91 -0
- package/src/services/voice/kokoro/pick-runtime.ts +130 -0
- package/src/services/voice/kokoro/runtime-selection.d.ts +92 -0
- package/src/services/voice/kokoro/runtime-selection.d.ts.map +1 -0
- package/src/services/voice/kokoro/runtime-selection.ts +237 -0
- package/src/services/voice/kokoro/types.d.ts +82 -0
- package/src/services/voice/kokoro/types.d.ts.map +1 -0
- package/src/services/voice/kokoro/types.ts +95 -0
- package/src/services/voice/kokoro/voice-presets.d.ts +23 -0
- package/src/services/voice/kokoro/voice-presets.d.ts.map +1 -0
- package/src/services/voice/kokoro/voice-presets.ts +129 -0
- package/src/services/voice/kokoro/voices.d.ts +30 -0
- package/src/services/voice/kokoro/voices.d.ts.map +1 -0
- package/src/services/voice/kokoro/voices.ts +64 -0
- package/src/services/voice/lifecycle.d.ts +135 -0
- package/src/services/voice/lifecycle.d.ts.map +1 -0
- package/src/services/voice/lifecycle.test.ts +315 -0
- package/src/services/voice/lifecycle.ts +301 -0
- package/src/services/voice/live-diarization-session.d.ts +96 -0
- package/src/services/voice/live-diarization-session.d.ts.map +1 -0
- package/src/services/voice/live-diarization-session.ts +289 -0
- package/src/services/voice/mic-source.d.ts +136 -0
- package/src/services/voice/mic-source.d.ts.map +1 -0
- package/src/services/voice/mic-source.test.ts +210 -0
- package/src/services/voice/mic-source.ts +503 -0
- package/src/services/voice/optimistic-policy.d.ts +109 -0
- package/src/services/voice/optimistic-policy.d.ts.map +1 -0
- package/src/services/voice/optimistic-policy.test.ts +101 -0
- package/src/services/voice/optimistic-policy.ts +192 -0
- package/src/services/voice/optimistic-rollback.ts +343 -0
- package/src/services/voice/partial-stabilizer.d.ts +73 -0
- package/src/services/voice/partial-stabilizer.d.ts.map +1 -0
- package/src/services/voice/partial-stabilizer.test.ts +68 -0
- package/src/services/voice/partial-stabilizer.ts +140 -0
- package/src/services/voice/phoneme-tokenizer.d.ts +49 -0
- package/src/services/voice/phoneme-tokenizer.d.ts.map +1 -0
- package/src/services/voice/phoneme-tokenizer.ts +158 -0
- package/src/services/voice/phrase-cache.d.ts +76 -0
- package/src/services/voice/phrase-cache.d.ts.map +1 -0
- package/src/services/voice/phrase-cache.test.ts +242 -0
- package/src/services/voice/phrase-cache.ts +186 -0
- package/src/services/voice/phrase-chunker.d.ts +62 -0
- package/src/services/voice/phrase-chunker.d.ts.map +1 -0
- package/src/services/voice/phrase-chunker.test.ts +239 -0
- package/src/services/voice/phrase-chunker.ts +281 -0
- package/src/services/voice/pipeline-impls.d.ts +151 -0
- package/src/services/voice/pipeline-impls.d.ts.map +1 -0
- package/src/services/voice/pipeline-impls.l6.test.ts +110 -0
- package/src/services/voice/pipeline-impls.test.ts +292 -0
- package/src/services/voice/pipeline-impls.ts +315 -0
- package/src/services/voice/pipeline.d.ts +216 -0
- package/src/services/voice/pipeline.d.ts.map +1 -0
- package/src/services/voice/pipeline.ts +505 -0
- package/src/services/voice/prefill-client.d.ts +123 -0
- package/src/services/voice/prefill-client.d.ts.map +1 -0
- package/src/services/voice/prefill-client.ts +316 -0
- package/src/services/voice/prefix-preserving-queue.d.ts +113 -0
- package/src/services/voice/prefix-preserving-queue.d.ts.map +1 -0
- package/src/services/voice/prefix-preserving-queue.ts +162 -0
- package/src/services/voice/profile-store.d.ts +248 -0
- package/src/services/voice/profile-store.d.ts.map +1 -0
- package/src/services/voice/profile-store.ts +887 -0
- package/src/services/voice/real-audio-decode.test.ts +148 -0
- package/src/services/voice/ring-buffer.d.ts +40 -0
- package/src/services/voice/ring-buffer.d.ts.map +1 -0
- package/src/services/voice/ring-buffer.test.ts +129 -0
- package/src/services/voice/ring-buffer.ts +123 -0
- package/src/services/voice/rollback-queue.d.ts +24 -0
- package/src/services/voice/rollback-queue.d.ts.map +1 -0
- package/src/services/voice/rollback-queue.ts +74 -0
- package/src/services/voice/samantha-preset-placeholder.d.ts +67 -0
- package/src/services/voice/samantha-preset-placeholder.d.ts.map +1 -0
- package/src/services/voice/samantha-preset-placeholder.test.ts +97 -0
- package/src/services/voice/samantha-preset-placeholder.ts +148 -0
- package/src/services/voice/samantha-preset-regenerator.d.ts +87 -0
- package/src/services/voice/samantha-preset-regenerator.d.ts.map +1 -0
- package/src/services/voice/samantha-preset-regenerator.ts +393 -0
- package/src/services/voice/scheduler.d.ts +146 -0
- package/src/services/voice/scheduler.d.ts.map +1 -0
- package/src/services/voice/scheduler.t2.test.ts +141 -0
- package/src/services/voice/scheduler.ts +927 -0
- package/src/services/voice/shared-resources.d.ts +190 -0
- package/src/services/voice/shared-resources.d.ts.map +1 -0
- package/src/services/voice/shared-resources.ts +320 -0
- package/src/services/voice/speaker/attribution-pipeline.d.ts +74 -0
- package/src/services/voice/speaker/attribution-pipeline.d.ts.map +1 -0
- package/src/services/voice/speaker/attribution-pipeline.ts +386 -0
- package/src/services/voice/speaker/diarizer-fused.d.ts +59 -0
- package/src/services/voice/speaker/diarizer-fused.d.ts.map +1 -0
- package/src/services/voice/speaker/diarizer-fused.real.test.ts +100 -0
- package/src/services/voice/speaker/diarizer-fused.ts +154 -0
- package/src/services/voice/speaker/diarizer.d.ts +75 -0
- package/src/services/voice/speaker/diarizer.d.ts.map +1 -0
- package/src/services/voice/speaker/diarizer.ts +218 -0
- package/src/services/voice/speaker/encoder-fused.d.ts +60 -0
- package/src/services/voice/speaker/encoder-fused.d.ts.map +1 -0
- package/src/services/voice/speaker/encoder-fused.real.test.ts +113 -0
- package/src/services/voice/speaker/encoder-fused.ts +138 -0
- package/src/services/voice/speaker/encoder-ggml.d.ts +33 -0
- package/src/services/voice/speaker/encoder-ggml.d.ts.map +1 -0
- package/src/services/voice/speaker/encoder-ggml.ts +79 -0
- package/src/services/voice/speaker/encoder.d.ts +37 -0
- package/src/services/voice/speaker/encoder.d.ts.map +1 -0
- package/src/services/voice/speaker/encoder.ts +105 -0
- package/src/services/voice/speaker-imprint.d.ts +83 -0
- package/src/services/voice/speaker-imprint.d.ts.map +1 -0
- package/src/services/voice/speaker-imprint.test.ts +185 -0
- package/src/services/voice/speaker-imprint.ts +312 -0
- package/src/services/voice/speaker-preset-cache.d.ts +77 -0
- package/src/services/voice/speaker-preset-cache.d.ts.map +1 -0
- package/src/services/voice/speaker-preset-cache.test.ts +154 -0
- package/src/services/voice/speaker-preset-cache.ts +195 -0
- package/src/services/voice/streaming-asr/streaming-pipeline-adapter.ts +292 -0
- package/src/services/voice/system-audio-sink.d.ts +73 -0
- package/src/services/voice/system-audio-sink.d.ts.map +1 -0
- package/src/services/voice/system-audio-sink.test.ts +29 -0
- package/src/services/voice/system-audio-sink.ts +366 -0
- package/src/services/voice/transcriber.d.ts +244 -0
- package/src/services/voice/transcriber.d.ts.map +1 -0
- package/src/services/voice/transcriber.test.ts +392 -0
- package/src/services/voice/transcriber.ts +704 -0
- package/src/services/voice/transcript-knowledge.d.ts +37 -0
- package/src/services/voice/transcript-knowledge.d.ts.map +1 -0
- package/src/services/voice/transcript-knowledge.test.ts +68 -0
- package/src/services/voice/transcript-knowledge.ts +75 -0
- package/src/services/voice/transcript-service.d.ts +41 -0
- package/src/services/voice/transcript-service.d.ts.map +1 -0
- package/src/services/voice/transcript-service.test.ts +137 -0
- package/src/services/voice/transcript-service.ts +141 -0
- package/src/services/voice/transcript-store.d.ts +53 -0
- package/src/services/voice/transcript-store.d.ts.map +1 -0
- package/src/services/voice/transcript-store.test.ts +153 -0
- package/src/services/voice/transcript-store.ts +132 -0
- package/src/services/voice/turn-controller.d.ts +183 -0
- package/src/services/voice/turn-controller.d.ts.map +1 -0
- package/src/services/voice/turn-controller.test.ts +575 -0
- package/src/services/voice/turn-controller.ts +596 -0
- package/src/services/voice/types.d.ts +643 -0
- package/src/services/voice/types.d.ts.map +1 -0
- package/src/services/voice/types.ts +699 -0
- package/src/services/voice/vad.d.ts +282 -0
- package/src/services/voice/vad.d.ts.map +1 -0
- package/src/services/voice/vad.test.ts +480 -0
- package/src/services/voice/vad.ts +827 -0
- package/src/services/voice/vad.v1-v4.test.ts +222 -0
- package/src/services/voice/voice-budget.d.ts +241 -0
- package/src/services/voice/voice-budget.d.ts.map +1 -0
- package/src/services/voice/voice-budget.test.ts +418 -0
- package/src/services/voice/voice-budget.ts +635 -0
- package/src/services/voice/voice-duet.test.ts +375 -0
- package/src/services/voice/voice-emotion-classifier.d.ts +95 -0
- package/src/services/voice/voice-emotion-classifier.d.ts.map +1 -0
- package/src/services/voice/voice-emotion-classifier.test.ts +210 -0
- package/src/services/voice/voice-emotion-classifier.ts +273 -0
- package/src/services/voice/voice-preset-format.d.ts +158 -0
- package/src/services/voice/voice-preset-format.d.ts.map +1 -0
- package/src/services/voice/voice-preset-format.ts +700 -0
- package/src/services/voice/voice-preset-generator.test.ts +89 -0
- package/src/services/voice/voice-profile-artifact.d.ts +116 -0
- package/src/services/voice/voice-profile-artifact.d.ts.map +1 -0
- package/src/services/voice/voice-profile-artifact.test.ts +138 -0
- package/src/services/voice/voice-profile-artifact.ts +518 -0
- package/src/services/voice/voice-profile-routes.d.ts +83 -0
- package/src/services/voice/voice-profile-routes.d.ts.map +1 -0
- package/src/services/voice/voice-profile-routes.test.ts +429 -0
- package/src/services/voice/voice-profile-routes.ts +425 -0
- package/src/services/voice/voice-scenario.ts +154 -0
- package/src/services/voice/voice-settings.d.ts +82 -0
- package/src/services/voice/voice-settings.d.ts.map +1 -0
- package/src/services/voice/voice-settings.ts +172 -0
- package/src/services/voice/voice-state-machine.d.ts +364 -0
- package/src/services/voice/voice-state-machine.d.ts.map +1 -0
- package/src/services/voice/voice-state-machine.ts +727 -0
- package/src/services/voice/voice-workbench-report.test.ts +168 -0
- package/src/services/voice/voice-workbench-report.ts +326 -0
- package/src/services/voice/voice-workbench.test.ts +158 -0
- package/src/services/voice/voice.test.ts +1070 -0
- package/src/services/voice/wake-word-ggml.d.ts +101 -0
- package/src/services/voice/wake-word-ggml.d.ts.map +1 -0
- package/src/services/voice/wake-word-ggml.ts +320 -0
- package/src/services/voice/wake-word.d.ts +255 -0
- package/src/services/voice/wake-word.d.ts.map +1 -0
- package/src/services/voice/wake-word.test.ts +298 -0
- package/src/services/voice/wake-word.ts +554 -0
- package/src/services/voice/wrap-with-first-line-cache.d.ts +70 -0
- package/src/services/voice/wrap-with-first-line-cache.d.ts.map +1 -0
- package/src/services/voice/wrap-with-first-line-cache.ts +267 -0
- package/src/services/voice-model-updater.d.ts +240 -0
- package/src/services/voice-model-updater.d.ts.map +1 -0
- package/src/services/voice-model-updater.ts +724 -0
- package/src/services/voice-prewarm.d.ts +3 -0
- package/src/services/voice-prewarm.d.ts.map +1 -0
- package/src/services/voice-prewarm.ts +51 -0
- package/dist/index.d.ts +0 -37
- package/dist/index.js +0 -1098
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LiveKit turn-detector — GGUF-backed binding (J1.d).
|
|
3
|
+
*
|
|
4
|
+
* The text-side turn-completion classifier formats the latest partial
|
|
5
|
+
* user transcript with the Qwen chat template, strips the trailing
|
|
6
|
+
* `<|im_end|>`, and reads `P(<|im_end|>)` from the next-token
|
|
7
|
+
* distribution. The upstream `livekit/turn-detector` ships an ONNX
|
|
8
|
+
* graph; this binding consumes the **GGUF** export published at
|
|
9
|
+
* `elizaos/eliza-1` under `voice/turn-detector/onnx/turn-detector-en-q8.gguf`
|
|
10
|
+
* (and the multilingual variant at
|
|
11
|
+
* `voice/turn/intl/turn-detector-intl-q8.gguf`), running through the
|
|
12
|
+
* canonical fork wrapper `capacitor-llama` (per
|
|
13
|
+
* `plugins/plugin-local-inference/native/AGENTS.md` §1 — the npm
|
|
14
|
+
* `capacitor-llama` dep is the elizaOS fork's republish, binding to the
|
|
15
|
+
* fork's `libllama`).
|
|
16
|
+
*
|
|
17
|
+
* Why this exists: per I1's single-runtime audit
|
|
18
|
+
* (`.swarm/impl/I1-single-runtime.md` §B), the turn-detector was the
|
|
19
|
+
* cheapest of the four remaining ONNX surfaces to retire — the GGUF
|
|
20
|
+
* artifact was already published by H4 (see commit history), and the
|
|
21
|
+
* detector's architecture (Qwen2-style small decoder + classification
|
|
22
|
+
* head on the `<|im_end|>` logit) is exactly what `LLM_ARCH_QWEN2`
|
|
23
|
+
* already implements in the fork. The work is wiring, not porting.
|
|
24
|
+
*
|
|
25
|
+
* No silent fallback (AGENTS.md §3): when `capacitor-llama` is
|
|
26
|
+
* unavailable, the GGUF is missing, or the model load fails, this
|
|
27
|
+
* class throws `EotGgmlUnavailableError` with a structured code. The
|
|
28
|
+
* resolver above this binding picks `HeuristicEotClassifier` or the
|
|
29
|
+
* legacy ONNX path; the binding itself never fabricates a probability.
|
|
30
|
+
*
|
|
31
|
+
* Tokenizer ownership: the GGUF carries its own tokenizer (BPE +
|
|
32
|
+
* special tokens, including `<|im_end|>`); this binding does NOT
|
|
33
|
+
* import `@huggingface/transformers`. The `apply_chat_template`
|
|
34
|
+
* formatting is re-implemented here using the same template upstream
|
|
35
|
+
* uses (single-turn user message wrapped in `<|im_start|>user\n... \n`)
|
|
36
|
+
* — see `applyQwenUserTemplate` below.
|
|
37
|
+
*
|
|
38
|
+
* --- Planned LoRA hot-swap path ---
|
|
39
|
+
*
|
|
40
|
+
* The LiveKit GGUF is a separate 66 MB (EN) or 396 MB (intl) resident
|
|
41
|
+
* model. The chat target model (eliza-1-{2b,4b}) is already
|
|
42
|
+
* loaded for conversation — its next-token distribution after the
|
|
43
|
+
* chat-template-formatted partial transcript provides exactly the
|
|
44
|
+
* same `P(<|im_end|>)` signal. A LoRA adapter (rank 8, ~5-10 MB)
|
|
45
|
+
* trained on `(transcript, eot_label)` pairs can shape that signal
|
|
46
|
+
* to match or beat the LiveKit baseline.
|
|
47
|
+
*
|
|
48
|
+
* The training pipeline lives at
|
|
49
|
+
* `packages/training/scripts/voice/eot/RUNBOOK.md`. The publish gates
|
|
50
|
+
* (AUROC ≥ 0.85, ECE ≤ 0.05, p95 ≤ 50 ms) are in
|
|
51
|
+
* `packages/training/benchmarks/eot_gates.md`.
|
|
52
|
+
*
|
|
53
|
+
* Integration sketch (deferred — implement when an adapter ships):
|
|
54
|
+
*
|
|
55
|
+
* 1. Bundle ships `voice/eot-lora/eliza-1-<tier>-eot-lora.bin`
|
|
56
|
+
* alongside the chat target GGUF, with a manifest sidecar binding
|
|
57
|
+
* the adapter to the target's SHA256 (refuse to load if mismatched).
|
|
58
|
+
* 2. Runtime detects the adapter via the bundle catalog. When present
|
|
59
|
+
* AND the chat target is already loaded, the EOT resolver prefers
|
|
60
|
+
* LoRA hot-swap over standing up the LiveKit GGUF process.
|
|
61
|
+
* 3. The hot-swap path uses llama.cpp's `--lora` flag on the chat
|
|
62
|
+
* target. A single forward pass against the chat-template-formatted
|
|
63
|
+
* transcript yields the next-token logits; read `<|im_end|>`'s
|
|
64
|
+
* probability and return it.
|
|
65
|
+
* 4. Fail-closed: if adapter load fails or the SHA binding mismatches,
|
|
66
|
+
* throw `EotGgmlUnavailableError("model-load-failed", ...)`. No
|
|
67
|
+
* silent fallback to the un-adapted target (the un-adapted logits
|
|
68
|
+
* would be the chat-model's own prior, not a calibrated EOT
|
|
69
|
+
* classifier).
|
|
70
|
+
*
|
|
71
|
+
* Until that lands, this binding remains the canonical EOT path.
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
import { access } from "node:fs/promises";
|
|
75
|
+
import path from "node:path";
|
|
76
|
+
import { resolveStateDir } from "@elizaos/core";
|
|
77
|
+
import type { EotClassifier, VoiceTurnSignal } from "./eot-classifier";
|
|
78
|
+
import { turnSignalFromProbability } from "./eot-classifier";
|
|
79
|
+
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Errors
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
/** Raised when the GGUF binding cannot be loaded or scored. */
|
|
85
|
+
export class EotGgmlUnavailableError extends Error {
|
|
86
|
+
readonly code:
|
|
87
|
+
| "native-missing"
|
|
88
|
+
| "model-missing"
|
|
89
|
+
| "model-load-failed"
|
|
90
|
+
| "tokenizer-missing-im-end"
|
|
91
|
+
| "evaluate-failed"
|
|
92
|
+
| "invalid-input";
|
|
93
|
+
constructor(code: EotGgmlUnavailableError["code"], message: string) {
|
|
94
|
+
super(message);
|
|
95
|
+
this.name = "EotGgmlUnavailableError";
|
|
96
|
+
this.code = code;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// HF asset constants
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
|
|
104
|
+
/** HF mono-repo holding every voice sub-model. */
|
|
105
|
+
export const LIVEKIT_TURN_DETECTOR_HF_REPO = "elizaos/eliza-1";
|
|
106
|
+
|
|
107
|
+
/** Canonical English GGUF asset path inside the bundle. */
|
|
108
|
+
export const DEFAULT_LIVEKIT_TURN_DETECTOR_GGUF_EN =
|
|
109
|
+
"voice/turn-detector/onnx/turn-detector-en-q8.gguf";
|
|
110
|
+
|
|
111
|
+
/** Canonical multilingual GGUF asset path inside the bundle. */
|
|
112
|
+
export const DEFAULT_LIVEKIT_TURN_DETECTOR_GGUF_INTL =
|
|
113
|
+
"voice/turn/intl/turn-detector-intl-q8.gguf";
|
|
114
|
+
|
|
115
|
+
/** Special-token literal the detector reads the probability of. */
|
|
116
|
+
export const LIVEKIT_IM_END_TOKEN = "<|im_end|>";
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Default on-disk location for the staged GGUF. The bundle downloader
|
|
120
|
+
* materializes assets under `<stateDir>/local-inference/models/...`; this
|
|
121
|
+
* matches the bundle downloader's staged-asset path layout.
|
|
122
|
+
*/
|
|
123
|
+
export const DEFAULT_LIVEKIT_TURN_DETECTOR_GGML_DIR = path.join(
|
|
124
|
+
resolveStateDir(),
|
|
125
|
+
"local-inference",
|
|
126
|
+
"models",
|
|
127
|
+
"turn-detector",
|
|
128
|
+
"livekit-turn-detector",
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Resolve which GGUF variant a given Eliza-1 tier should bundle.
|
|
133
|
+
* Mirrors `turnDetectorRevisionForTier` in `eot-classifier.ts` —
|
|
134
|
+
* mobile tiers get the English-only ~40 MB Q8 GGUF, desktop tiers
|
|
135
|
+
* get the multilingual ~280 MB Q8 GGUF.
|
|
136
|
+
*
|
|
137
|
+
* Accepts both bare tier ids (`"4b"`) and prefixed catalog ids
|
|
138
|
+
* (`"eliza-1-4b"`).
|
|
139
|
+
*/
|
|
140
|
+
export function turnDetectorGgufForTier(tierId: string): {
|
|
141
|
+
hfPath: string;
|
|
142
|
+
variant: "en" | "intl";
|
|
143
|
+
} {
|
|
144
|
+
const bare = tierId.startsWith("eliza-1-")
|
|
145
|
+
? tierId.slice("eliza-1-".length)
|
|
146
|
+
: tierId;
|
|
147
|
+
if (bare === "2b") {
|
|
148
|
+
return {
|
|
149
|
+
hfPath: DEFAULT_LIVEKIT_TURN_DETECTOR_GGUF_EN,
|
|
150
|
+
variant: "en",
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
hfPath: DEFAULT_LIVEKIT_TURN_DETECTOR_GGUF_INTL,
|
|
155
|
+
variant: "intl",
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
// Legacy llama.cpp controlled-evaluate surface (held over from the removed
|
|
161
|
+
// node-llama-cpp binding). The shapes below describe the API the GGUF-backed
|
|
162
|
+
// LiveKit detector needs (controlledEvaluate → next-token probability map).
|
|
163
|
+
// Until capacitor-llama / the bun:ffi shim expose an equivalent entry point,
|
|
164
|
+
// `loadNlc()` throws and the resolver above falls back to HeuristicEotClassifier.
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
|
|
167
|
+
interface NlcModule {
|
|
168
|
+
getLlama(opts?: {
|
|
169
|
+
gpu?: false | "auto" | "metal" | "cuda" | "vulkan";
|
|
170
|
+
logLevel?: string;
|
|
171
|
+
}): Promise<NlcLlama>;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
interface NlcLlama {
|
|
175
|
+
loadModel(opts: {
|
|
176
|
+
modelPath: string;
|
|
177
|
+
gpuLayers?: number | "max" | "auto";
|
|
178
|
+
}): Promise<NlcLlamaModel>;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
interface NlcLlamaModel {
|
|
182
|
+
tokenize(text: string, specialTokens?: boolean): number[];
|
|
183
|
+
detokenize(tokens: readonly number[], specialTokens?: boolean): string;
|
|
184
|
+
createContext(opts?: {
|
|
185
|
+
contextSize?: number | "auto";
|
|
186
|
+
batchSize?: number;
|
|
187
|
+
threads?: number;
|
|
188
|
+
}): Promise<NlcLlamaContext>;
|
|
189
|
+
dispose(): Promise<void>;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
interface NlcLlamaContext {
|
|
193
|
+
getSequence(): NlcLlamaSequence;
|
|
194
|
+
dispose(): Promise<void>;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
interface NlcControlledIndexOutput {
|
|
198
|
+
next: {
|
|
199
|
+
token?: number | null;
|
|
200
|
+
confidence?: number;
|
|
201
|
+
probabilities?: Map<number, number>;
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
interface NlcLlamaSequence {
|
|
206
|
+
controlledEvaluate(
|
|
207
|
+
input: ReadonlyArray<
|
|
208
|
+
| number
|
|
209
|
+
| [
|
|
210
|
+
number,
|
|
211
|
+
{
|
|
212
|
+
generateNext?: {
|
|
213
|
+
probabilities?: boolean;
|
|
214
|
+
confidence?: boolean;
|
|
215
|
+
token?: boolean;
|
|
216
|
+
};
|
|
217
|
+
},
|
|
218
|
+
]
|
|
219
|
+
>,
|
|
220
|
+
opts?: unknown,
|
|
221
|
+
): Promise<ReadonlyArray<NlcControlledIndexOutput | undefined>>;
|
|
222
|
+
clearHistory(): Promise<void>;
|
|
223
|
+
dispose?(): Promise<void>;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async function loadNlc(): Promise<NlcModule> {
|
|
227
|
+
// The legacy `node-llama-cpp` binding (now removed) exposed
|
|
228
|
+
// `LlamaContextSequence.controlledEvaluate({ generateNext: { probabilities:
|
|
229
|
+
// true } })` to read the next-token probability distribution after a
|
|
230
|
+
// truncated prompt. The current `capacitor-llama` adapter and the desktop
|
|
231
|
+
// bun:ffi shim do not expose an equivalent (both surface `completion()`,
|
|
232
|
+
// which consumes tokens rather than returning a logit map without sampling).
|
|
233
|
+
//
|
|
234
|
+
// The resolver above this binding (`tryBuildEliza1EotClassifier`) is gated
|
|
235
|
+
// on the dispatcher's active backend and model pointer, so this path is
|
|
236
|
+
// only reached if a caller bypasses the resolver. Throwing here
|
|
237
|
+
// keeps fail-closed semantics: the binding never fabricates a probability.
|
|
238
|
+
throw new EotGgmlUnavailableError(
|
|
239
|
+
"native-missing",
|
|
240
|
+
"[eot-ggml] the active llama.cpp adapter (capacitor-llama / bun:ffi shim) does not expose a controlled-evaluate API for next-token probabilities. Use HeuristicEotClassifier until the shim exposes `llama_get_logits_ith`.",
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async function getLlama(): Promise<NlcLlama> {
|
|
245
|
+
// Unreachable while loadNlc() throws — kept so the signature still
|
|
246
|
+
// satisfies the call sites below.
|
|
247
|
+
await loadNlc();
|
|
248
|
+
throw new EotGgmlUnavailableError(
|
|
249
|
+
"native-missing",
|
|
250
|
+
"[eot-ggml] llama runtime unavailable",
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// ---------------------------------------------------------------------------
|
|
255
|
+
// Construction options
|
|
256
|
+
// ---------------------------------------------------------------------------
|
|
257
|
+
|
|
258
|
+
export interface LiveKitGgmlTurnDetectorOptions {
|
|
259
|
+
/** Absolute path to the GGUF file. Required. */
|
|
260
|
+
ggufPath: string;
|
|
261
|
+
/**
|
|
262
|
+
* Upstream revision tag for telemetry only (`"v1.2.2-en"` /
|
|
263
|
+
* `"v0.4.1-intl"`). Does not affect inference.
|
|
264
|
+
*/
|
|
265
|
+
revision?: string;
|
|
266
|
+
/** Max history tokens after Qwen-template wrapping. Default: 128. */
|
|
267
|
+
maxHistoryTokens?: number;
|
|
268
|
+
/** Optional model label for telemetry. */
|
|
269
|
+
model?: string;
|
|
270
|
+
/** Optional thread count for the context. Default: 2. */
|
|
271
|
+
threads?: number;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// ---------------------------------------------------------------------------
|
|
275
|
+
// Detector
|
|
276
|
+
// ---------------------------------------------------------------------------
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Local GGUF-backed LiveKit turn-detector. Uses a `capacitor-llama`
|
|
280
|
+
* evaluation of the Qwen2-style decoder, reading `P(<|im_end|>)` from the
|
|
281
|
+
* next-token distribution after the truncated user-template prefix.
|
|
282
|
+
*
|
|
283
|
+
* One detector instance owns one `LlamaModel` + one `LlamaContext` +
|
|
284
|
+
* one `LlamaSequence`. `score()` resets the sequence between calls —
|
|
285
|
+
* the detector is intentionally stateless (no carried context across
|
|
286
|
+
* different user transcripts).
|
|
287
|
+
*/
|
|
288
|
+
export class LiveKitGgmlTurnDetector implements EotClassifier {
|
|
289
|
+
readonly ggufPath: string;
|
|
290
|
+
private readonly maxHistoryTokens: number;
|
|
291
|
+
private readonly model: string;
|
|
292
|
+
private readonly revision: string | undefined;
|
|
293
|
+
private readonly threads: number;
|
|
294
|
+
private ready: Promise<{
|
|
295
|
+
llamaModel: NlcLlamaModel;
|
|
296
|
+
context: NlcLlamaContext;
|
|
297
|
+
sequence: NlcLlamaSequence;
|
|
298
|
+
imEndTokenId: number;
|
|
299
|
+
}> | null = null;
|
|
300
|
+
|
|
301
|
+
constructor(opts: LiveKitGgmlTurnDetectorOptions) {
|
|
302
|
+
if (typeof opts.ggufPath !== "string" || opts.ggufPath.length === 0) {
|
|
303
|
+
throw new EotGgmlUnavailableError(
|
|
304
|
+
"invalid-input",
|
|
305
|
+
"[eot-ggml] ggufPath is required",
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
this.ggufPath = opts.ggufPath;
|
|
309
|
+
this.maxHistoryTokens = opts.maxHistoryTokens ?? 128;
|
|
310
|
+
this.revision = opts.revision;
|
|
311
|
+
this.threads = opts.threads ?? 2;
|
|
312
|
+
this.model =
|
|
313
|
+
opts.model ??
|
|
314
|
+
(opts.revision
|
|
315
|
+
? `${LIVEKIT_TURN_DETECTOR_HF_REPO}@${opts.revision}`
|
|
316
|
+
: LIVEKIT_TURN_DETECTOR_HF_REPO);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
async score(partialTranscript: string): Promise<number> {
|
|
320
|
+
return (await this.signal(partialTranscript)).endOfTurnProbability;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
async signal(partialTranscript: string): Promise<VoiceTurnSignal> {
|
|
324
|
+
const started = performance.now();
|
|
325
|
+
const loaded = await this.load();
|
|
326
|
+
const transcript = normalizeTurnDetectorText(partialTranscript);
|
|
327
|
+
// Tokenize the user-templated transcript WITHOUT the trailing
|
|
328
|
+
// `<|im_end|>` (the head must score that token as the next one).
|
|
329
|
+
// We do not pass `specialTokens=true` for the user text itself —
|
|
330
|
+
// only the template wrappers themselves are special tokens.
|
|
331
|
+
const promptText = applyQwenUserTemplate(transcript);
|
|
332
|
+
|
|
333
|
+
// Tokenize: the template wrappers are special tokens; the GGUF's
|
|
334
|
+
// BPE handles the inner text. Passing `true` tells the tokenizer
|
|
335
|
+
// to recognize the `<|im_start|>` / `\n` literals as the real
|
|
336
|
+
// special-token ids. Truncate from the LEFT so the recent text
|
|
337
|
+
// is preserved.
|
|
338
|
+
let tokens = loaded.llamaModel.tokenize(promptText, true);
|
|
339
|
+
if (tokens.length > this.maxHistoryTokens) {
|
|
340
|
+
tokens = tokens.slice(tokens.length - this.maxHistoryTokens);
|
|
341
|
+
}
|
|
342
|
+
if (tokens.length === 0) {
|
|
343
|
+
throw new EotGgmlUnavailableError(
|
|
344
|
+
"evaluate-failed",
|
|
345
|
+
"[eot-ggml] tokenizer produced empty token list for transcript",
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Clear the sequence before each evaluation — turn detection is
|
|
350
|
+
// stateless per transcript.
|
|
351
|
+
await loaded.sequence.clearHistory();
|
|
352
|
+
|
|
353
|
+
// Feed every token, asking for the probability distribution only
|
|
354
|
+
// on the LAST one. That gives us P(token=<|im_end|>) after the
|
|
355
|
+
// truncated template prefix.
|
|
356
|
+
const lastIdx = tokens.length - 1;
|
|
357
|
+
const input = tokens.map((tok, i) =>
|
|
358
|
+
i === lastIdx
|
|
359
|
+
? ([tok, { generateNext: { probabilities: true } }] as [
|
|
360
|
+
number,
|
|
361
|
+
{ generateNext: { probabilities: boolean } },
|
|
362
|
+
])
|
|
363
|
+
: tok,
|
|
364
|
+
);
|
|
365
|
+
const results = await loaded.sequence.controlledEvaluate(input);
|
|
366
|
+
const last = results[lastIdx];
|
|
367
|
+
const probs = last?.next.probabilities;
|
|
368
|
+
if (!probs) {
|
|
369
|
+
throw new EotGgmlUnavailableError(
|
|
370
|
+
"evaluate-failed",
|
|
371
|
+
"[eot-ggml] controlledEvaluate did not return probabilities for the last token",
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
const imEndProb = probs.get(loaded.imEndTokenId) ?? 0;
|
|
375
|
+
|
|
376
|
+
return turnSignalFromProbability({
|
|
377
|
+
probability: imEndProb,
|
|
378
|
+
transcript,
|
|
379
|
+
source: "livekit-turn-detector",
|
|
380
|
+
model: this.model,
|
|
381
|
+
latencyMs: performance.now() - started,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/** Release the underlying GGUF + context. Idempotent. */
|
|
386
|
+
async dispose(): Promise<void> {
|
|
387
|
+
const r = this.ready;
|
|
388
|
+
this.ready = null;
|
|
389
|
+
if (!r) return;
|
|
390
|
+
const loaded = await r.catch(() => null);
|
|
391
|
+
if (!loaded) return;
|
|
392
|
+
await loaded.sequence.dispose?.().catch(() => undefined);
|
|
393
|
+
await loaded.context.dispose().catch(() => undefined);
|
|
394
|
+
await loaded.llamaModel.dispose().catch(() => undefined);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
private load(): Promise<{
|
|
398
|
+
llamaModel: NlcLlamaModel;
|
|
399
|
+
context: NlcLlamaContext;
|
|
400
|
+
sequence: NlcLlamaSequence;
|
|
401
|
+
imEndTokenId: number;
|
|
402
|
+
}> {
|
|
403
|
+
this.ready ??= this.loadInner();
|
|
404
|
+
return this.ready;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
private async loadInner(): Promise<{
|
|
408
|
+
llamaModel: NlcLlamaModel;
|
|
409
|
+
context: NlcLlamaContext;
|
|
410
|
+
sequence: NlcLlamaSequence;
|
|
411
|
+
imEndTokenId: number;
|
|
412
|
+
}> {
|
|
413
|
+
try {
|
|
414
|
+
await access(this.ggufPath);
|
|
415
|
+
} catch {
|
|
416
|
+
throw new EotGgmlUnavailableError(
|
|
417
|
+
"model-missing",
|
|
418
|
+
`[eot-ggml] GGUF not found at ${this.ggufPath}. Stage it via the bundle downloader from ${LIVEKIT_TURN_DETECTOR_HF_REPO}.`,
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
const llama = await getLlama();
|
|
423
|
+
let llamaModel: NlcLlamaModel;
|
|
424
|
+
try {
|
|
425
|
+
llamaModel = await llama.loadModel({
|
|
426
|
+
modelPath: this.ggufPath,
|
|
427
|
+
gpuLayers: 0,
|
|
428
|
+
});
|
|
429
|
+
} catch (err) {
|
|
430
|
+
throw new EotGgmlUnavailableError(
|
|
431
|
+
"model-load-failed",
|
|
432
|
+
`[eot-ggml] loadModel failed for ${this.ggufPath}: ${err instanceof Error ? err.message : String(err)}`,
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Resolve the <|im_end|> token id from the GGUF's BPE tokenizer.
|
|
437
|
+
// Passing `specialTokens=true` tells the tokenizer to recognize
|
|
438
|
+
// the literal as the corresponding special token.
|
|
439
|
+
const imEndTokens = llamaModel.tokenize(LIVEKIT_IM_END_TOKEN, true);
|
|
440
|
+
if (imEndTokens.length !== 1) {
|
|
441
|
+
await llamaModel.dispose().catch(() => undefined);
|
|
442
|
+
throw new EotGgmlUnavailableError(
|
|
443
|
+
"tokenizer-missing-im-end",
|
|
444
|
+
`[eot-ggml] tokenizer produced ${imEndTokens.length} tokens for <|im_end|>; expected exactly 1. The GGUF's special-token table is missing the expected entry.`,
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
const imEndTokenId = imEndTokens[0];
|
|
448
|
+
|
|
449
|
+
let context: NlcLlamaContext;
|
|
450
|
+
try {
|
|
451
|
+
context = await llamaModel.createContext({
|
|
452
|
+
contextSize: Math.max(this.maxHistoryTokens, 256),
|
|
453
|
+
threads: this.threads,
|
|
454
|
+
});
|
|
455
|
+
} catch (err) {
|
|
456
|
+
await llamaModel.dispose().catch(() => undefined);
|
|
457
|
+
throw new EotGgmlUnavailableError(
|
|
458
|
+
"model-load-failed",
|
|
459
|
+
`[eot-ggml] createContext failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const sequence = context.getSequence();
|
|
464
|
+
return { llamaModel, context, sequence, imEndTokenId };
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// ---------------------------------------------------------------------------
|
|
469
|
+
// Resolver
|
|
470
|
+
// ---------------------------------------------------------------------------
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Resolve a `LiveKitGgmlTurnDetector` against the bundle's on-disk
|
|
474
|
+
* staging directory. Search order:
|
|
475
|
+
*
|
|
476
|
+
* 1. Explicit `opts.ggufPath`.
|
|
477
|
+
* 2. `ELIZA_TURN_DETECTOR_GGUF` env var.
|
|
478
|
+
* 3. `<modelDir>/<en GGUF name>` (the canonical layout for the
|
|
479
|
+
* bundle's English variant).
|
|
480
|
+
* 4. `<modelDir>/<intl GGUF name>` (multilingual).
|
|
481
|
+
*
|
|
482
|
+
* Returns `null` if no GGUF is found alongside the directory — the
|
|
483
|
+
* caller falls back to `HeuristicEotClassifier`.
|
|
484
|
+
*/
|
|
485
|
+
export async function createBundledLiveKitGgmlTurnDetector(
|
|
486
|
+
opts: {
|
|
487
|
+
ggufPath?: string;
|
|
488
|
+
modelDir?: string;
|
|
489
|
+
revision?: string;
|
|
490
|
+
maxHistoryTokens?: number;
|
|
491
|
+
threads?: number;
|
|
492
|
+
} = {},
|
|
493
|
+
): Promise<LiveKitGgmlTurnDetector | null> {
|
|
494
|
+
const candidates: string[] = [];
|
|
495
|
+
|
|
496
|
+
const envOverride = process.env.ELIZA_TURN_DETECTOR_GGUF;
|
|
497
|
+
if (opts.ggufPath) candidates.push(opts.ggufPath);
|
|
498
|
+
if (envOverride) candidates.push(envOverride);
|
|
499
|
+
|
|
500
|
+
const modelDir =
|
|
501
|
+
opts.modelDir ??
|
|
502
|
+
process.env.ELIZA_TURN_DETECTOR_MODEL_DIR ??
|
|
503
|
+
DEFAULT_LIVEKIT_TURN_DETECTOR_GGML_DIR;
|
|
504
|
+
|
|
505
|
+
// The on-disk staging layout mirrors the HF asset path, so the bundle
|
|
506
|
+
// downloader will materialize the GGUF at one of these locations.
|
|
507
|
+
candidates.push(
|
|
508
|
+
path.join(modelDir, "turn-detector-en-q8.gguf"),
|
|
509
|
+
path.join(modelDir, "turn-detector-intl-q8.gguf"),
|
|
510
|
+
path.join(modelDir, "onnx", "turn-detector-en-q8.gguf"),
|
|
511
|
+
path.join(modelDir, DEFAULT_LIVEKIT_TURN_DETECTOR_GGUF_EN),
|
|
512
|
+
path.join(modelDir, DEFAULT_LIVEKIT_TURN_DETECTOR_GGUF_INTL),
|
|
513
|
+
);
|
|
514
|
+
|
|
515
|
+
for (const candidate of candidates) {
|
|
516
|
+
try {
|
|
517
|
+
await access(candidate);
|
|
518
|
+
return new LiveKitGgmlTurnDetector({
|
|
519
|
+
ggufPath: candidate,
|
|
520
|
+
...(opts.revision ? { revision: opts.revision } : {}),
|
|
521
|
+
...(opts.maxHistoryTokens !== undefined
|
|
522
|
+
? { maxHistoryTokens: opts.maxHistoryTokens }
|
|
523
|
+
: {}),
|
|
524
|
+
...(opts.threads !== undefined ? { threads: opts.threads } : {}),
|
|
525
|
+
});
|
|
526
|
+
} catch {
|
|
527
|
+
// try next
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// ---------------------------------------------------------------------------
|
|
534
|
+
// Helpers
|
|
535
|
+
// ---------------------------------------------------------------------------
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Mirror of `normalizeTurnDetectorText` in `eot-classifier.ts`. The
|
|
539
|
+
* upstream LiveKit detector lowercases + strips most punctuation
|
|
540
|
+
* before tokenizing; we do the same so the two paths produce
|
|
541
|
+
* comparable readings.
|
|
542
|
+
*/
|
|
543
|
+
function normalizeTurnDetectorText(text: string): string {
|
|
544
|
+
return text
|
|
545
|
+
.normalize("NFKC")
|
|
546
|
+
.toLowerCase()
|
|
547
|
+
.replace(/[^\p{L}\p{N}'\-\s]/gu, " ")
|
|
548
|
+
.replace(/\s+/g, " ")
|
|
549
|
+
.trim();
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Apply the single-turn user Qwen chat template, omitting the trailing
|
|
554
|
+
* `<|im_end|>` so the detector head scores it as the next token.
|
|
555
|
+
*
|
|
556
|
+
* Upstream `livekit/turn-detector` formats:
|
|
557
|
+
*
|
|
558
|
+
* <|im_start|>user\n{transcript}<|im_end|>\n
|
|
559
|
+
*
|
|
560
|
+
* The detector strips the trailing `<|im_end|>\n` and reads
|
|
561
|
+
* `P(<|im_end|>)` after the user content. We emit the prefix exactly,
|
|
562
|
+
* stopping where the `<|im_end|>` would go.
|
|
563
|
+
*/
|
|
564
|
+
export function applyQwenUserTemplate(transcript: string): string {
|
|
565
|
+
return `<|im_start|>user\n${transcript}`;
|
|
566
|
+
}
|