bolo-speech 0.2.0__py3-none-any.whl
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.
- bolo/__init__.py +5 -0
- bolo/__main__.py +3 -0
- bolo/_probe.py +46 -0
- bolo/_ui/apple-touch-icon.png +0 -0
- bolo/_ui/assets/__vite-browser-external-BSasRvcZ.js +1 -0
- bolo/_ui/assets/alert-y-6lUFzu.js +1 -0
- bolo/_ui/assets/bench-CXahGonE.js +4 -0
- bolo/_ui/assets/benchmark-RcT7OOFg.js +1 -0
- bolo/_ui/assets/capabilities-DpMMPQxp.js +1 -0
- bolo/_ui/assets/chart-DRTUqEVi.js +39 -0
- bolo/_ui/assets/chart-kit-mr_qOori.js +1 -0
- bolo/_ui/assets/checkbox-Bi4Sxs1u.js +1 -0
- bolo/_ui/assets/circle-dashed-C69JWix9.js +1 -0
- bolo/_ui/assets/command-palette-B2KssZUw.js +1 -0
- bolo/_ui/assets/component-install-BwyIMwZl.js +1 -0
- bolo/_ui/assets/components-BEXD5Elv.js +1 -0
- bolo/_ui/assets/connect-Clm8-W3X.js +62 -0
- bolo/_ui/assets/conversation-BNxIedQ8.js +1 -0
- bolo/_ui/assets/diagnostics-panel-DtQM9wcJ.js +5 -0
- bolo/_ui/assets/engine-BBt21Gim.js +1 -0
- bolo/_ui/assets/index-CT0tCA22.css +2 -0
- bolo/_ui/assets/index-D3MZkqFc.js +53 -0
- bolo/_ui/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- bolo/_ui/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- bolo/_ui/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- bolo/_ui/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- bolo/_ui/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- bolo/_ui/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- bolo/_ui/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- bolo/_ui/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- bolo/_ui/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- bolo/_ui/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- bolo/_ui/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- bolo/_ui/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- bolo/_ui/assets/latency-6nIM0TzI.js +1 -0
- bolo/_ui/assets/mic-help-BCNXE1u9.js +1 -0
- bolo/_ui/assets/mic-help-DWI9T5LW.js +1 -0
- bolo/_ui/assets/model-bits-BQ6IN8hE.js +1 -0
- bolo/_ui/assets/model-picker-CvHhnt-R.js +1 -0
- bolo/_ui/assets/models-BZlzXSJo.js +1 -0
- bolo/_ui/assets/noto-naskh-arabic-arabic-wght-normal-DIN-4rtF.woff2 +0 -0
- bolo/_ui/assets/noto-sans-bengali-bengali-wght-normal-DeF8kf4m.woff2 +0 -0
- bolo/_ui/assets/noto-sans-devanagari-devanagari-wght-normal-DWI_L5Cu.woff2 +0 -0
- bolo/_ui/assets/noto-sans-gujarati-gujarati-wght-normal-Clz9kKLg.woff2 +0 -0
- bolo/_ui/assets/noto-sans-gurmukhi-gurmukhi-wght-normal-HnZqhN5g.woff2 +0 -0
- bolo/_ui/assets/noto-sans-kannada-kannada-wght-normal-DuwB-P8d.woff2 +0 -0
- bolo/_ui/assets/noto-sans-malayalam-malayalam-wght-normal-C3telsSh.woff2 +0 -0
- bolo/_ui/assets/noto-sans-oriya-oriya-wght-normal-JNDXqas0.woff2 +0 -0
- bolo/_ui/assets/noto-sans-tamil-tamil-wght-normal-iihgzMBi.woff2 +0 -0
- bolo/_ui/assets/noto-sans-telugu-telugu-wght-normal-DoLU0sI2.woff2 +0 -0
- bolo/_ui/assets/override-text-Bc61tRXI.js +2 -0
- bolo/_ui/assets/panel-BOw-dJi0.js +1 -0
- bolo/_ui/assets/pcm-CalXEOke.js +1 -0
- bolo/_ui/assets/phases-CzeIuT4q.js +1 -0
- bolo/_ui/assets/play-Dqd68TKN.js +1 -0
- bolo/_ui/assets/player-CfRYFkCd.js +1 -0
- bolo/_ui/assets/popover-COkCDp7k.js +1 -0
- bolo/_ui/assets/progress-BComADHS.js +6 -0
- bolo/_ui/assets/save-6C0ZNYFi.js +1 -0
- bolo/_ui/assets/select-Ck7UCXuF.js +1 -0
- bolo/_ui/assets/square-DZNyf3XQ.js +1 -0
- bolo/_ui/assets/stats-DrD9fvoe.js +1 -0
- bolo/_ui/assets/stt-irLffRRk.js +1 -0
- bolo/_ui/assets/support-Bs5mvCB-.js +1 -0
- bolo/_ui/assets/table-nZl6qBmo.js +1 -0
- bolo/_ui/assets/textarea-suSe5u83.js +1 -0
- bolo/_ui/assets/toggle-group-D2I8RWGl.js +1 -0
- bolo/_ui/assets/trash-PPSB5uoo.js +1 -0
- bolo/_ui/assets/tts-BnZ715Yz.js +1 -0
- bolo/_ui/assets/uccharan-t0Qlhkc9.js +1 -0
- bolo/_ui/assets/uccharan_wasm_bg-N3GqjhT8.wasm +0 -0
- bolo/_ui/assets/use-api-FEiHCTKE.js +2 -0
- bolo/_ui/assets/use-support-C39-orRL.js +1 -0
- bolo/_ui/assets/wav-D2r1V-VA.js +1 -0
- bolo/_ui/assets/wordlist-select-d1jwiaFv.js +1 -0
- bolo/_ui/assets/wordlists-C7isQm94.js +3 -0
- bolo/_ui/assets/worker-C83FPhzz.js +12 -0
- bolo/_ui/assets/worker-DccfG_ez.js +49 -0
- bolo/_ui/favicon.svg +4 -0
- bolo/_ui/icon-192.png +0 -0
- bolo/_ui/icon-512.png +0 -0
- bolo/_ui/index.html +44 -0
- bolo/_ui/og.png +0 -0
- bolo/_ui/site.webmanifest +13 -0
- bolo/agents.py +100 -0
- bolo/api/__init__.py +5 -0
- bolo/api/app.py +122 -0
- bolo/api/chat.py +315 -0
- bolo/api/common.py +78 -0
- bolo/api/native.py +389 -0
- bolo/api/openai.py +686 -0
- bolo/api/realtime.py +185 -0
- bolo/api/speaches.py +165 -0
- bolo/api/static.py +115 -0
- bolo/api/wordlists.py +140 -0
- bolo/api/ws.py +347 -0
- bolo/audio/__init__.py +29 -0
- bolo/audio/codecs.py +209 -0
- bolo/audio/decode.py +175 -0
- bolo/audio/encode.py +391 -0
- bolo/audio/features.py +160 -0
- bolo/audio/resample.py +81 -0
- bolo/bench.py +237 -0
- bolo/catalog/__init__.py +383 -0
- bolo/catalog/diarization.yaml +188 -0
- bolo/catalog/plugin-torch.yaml +698 -0
- bolo/catalog/separation.yaml +42 -0
- bolo/catalog/stt-faster-whisper.yaml +1291 -0
- bolo/catalog/stt-onnxruntime.yaml +34 -0
- bolo/catalog/stt-sherpa.yaml +3841 -0
- bolo/catalog/tts-mms.yaml +749 -0
- bolo/catalog/tts-orpheus.yaml +413 -0
- bolo/catalog/tts-piper.yaml +3970 -0
- bolo/catalog/tts-server.yaml +1958 -0
- bolo/catalog/tts.yaml +1900 -0
- bolo/catalog/turn.yaml +23 -0
- bolo/catalog/vad.yaml +88 -0
- bolo/cli.py +717 -0
- bolo/components.py +566 -0
- bolo/config.py +321 -0
- bolo/core.py +1296 -0
- bolo/custom.py +265 -0
- bolo/diarize.py +520 -0
- bolo/engines/__init__.py +120 -0
- bolo/engines/base.py +403 -0
- bolo/engines/dicow_onnx.py +610 -0
- bolo/engines/fake.py +478 -0
- bolo/engines/faster_whisper.py +182 -0
- bolo/engines/kokoro_onnx.py +83 -0
- bolo/engines/moonshine.py +64 -0
- bolo/engines/nemotron.py +387 -0
- bolo/engines/onnx_turn.py +83 -0
- bolo/engines/orpheus_llamacpp.py +530 -0
- bolo/engines/sherpa.py +882 -0
- bolo/engines/tts_server.py +678 -0
- bolo/engines/whispercpp.py +65 -0
- bolo/errors.py +120 -0
- bolo/jobs.py +67 -0
- bolo/lifecycle.py +372 -0
- bolo/llm.py +177 -0
- bolo/obs/__init__.py +1 -0
- bolo/obs/events.py +70 -0
- bolo/obs/metrics.py +127 -0
- bolo/obs/sketch.py +89 -0
- bolo/obs/trace.py +291 -0
- bolo/piper.py +157 -0
- bolo/plugin/__init__.py +6 -0
- bolo/plugin/host.py +569 -0
- bolo/plugin/protocol.py +126 -0
- bolo/plugin/reference.py +60 -0
- bolo/plugin/sdk.py +241 -0
- bolo/py.typed +0 -0
- bolo/realtime.py +1327 -0
- bolo/s2s.py +495 -0
- bolo/samples/__init__.py +94 -0
- bolo/samples/en-long.wav +0 -0
- bolo/samples/en-short.wav +0 -0
- bolo/samples/hi-short.wav +0 -0
- bolo/samples/index.json +83 -0
- bolo/scheduler.py +281 -0
- bolo/separate.py +584 -0
- bolo/store.py +623 -0
- bolo/streaming/__init__.py +1 -0
- bolo/streaming/agreement.py +82 -0
- bolo/streaming/session.py +637 -0
- bolo/streaming/vad.py +235 -0
- bolo/text/__init__.py +1 -0
- bolo/text/formats.py +47 -0
- bolo/text/normalize.py +433 -0
- bolo/text/phonemize.py +508 -0
- bolo/text/prepare.py +300 -0
- bolo/text/segment.py +168 -0
- bolo/text/ssml.py +133 -0
- bolo/text/wordlists.py +207 -0
- bolo/tts_runtimes.py +328 -0
- bolo/webrtc.py +295 -0
- bolo/wyoming_server.py +287 -0
- bolo_speech-0.2.0.dist-info/METADATA +505 -0
- bolo_speech-0.2.0.dist-info/RECORD +183 -0
- bolo_speech-0.2.0.dist-info/WHEEL +4 -0
- bolo_speech-0.2.0.dist-info/entry_points.txt +2 -0
- bolo_speech-0.2.0.dist-info/licenses/LICENSE +202 -0
- bolo_speech-0.2.0.dist-info/licenses/NOTICE +150 -0
bolo/__init__.py
ADDED
bolo/__main__.py
ADDED
bolo/_probe.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Load a model in a throw-away process: ``python -m bolo._probe <data_dir> <model_id>``.
|
|
2
|
+
|
|
3
|
+
Native inference libraries sometimes abort the whole process when a model
|
|
4
|
+
file is not what they expect (a wrong export, a truncated download, missing
|
|
5
|
+
metadata). The server therefore loads every newly installed model once in a
|
|
6
|
+
child process first. If the child dies, the server reports an error for
|
|
7
|
+
that model instead of going down with it.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import sys
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main(argv: list[str]) -> int:
|
|
17
|
+
if len(argv) != 3:
|
|
18
|
+
sys.stderr.write("usage: python -m bolo._probe <data_dir> <model_id> <threads>\n")
|
|
19
|
+
return 2
|
|
20
|
+
from bolo.catalog import Catalog
|
|
21
|
+
from bolo.engines import EngineRegistry
|
|
22
|
+
from bolo.engines.base import LoadOptions
|
|
23
|
+
from bolo.store import ModelStore
|
|
24
|
+
|
|
25
|
+
data_dir, model_id, threads = Path(argv[0]), argv[1], int(argv[2])
|
|
26
|
+
spec = Catalog.load(data_dir).resolve(model_id)
|
|
27
|
+
if spec is None:
|
|
28
|
+
sys.stderr.write(f"unknown model {model_id}\n")
|
|
29
|
+
return 3
|
|
30
|
+
engine = EngineRegistry().get(spec.engine)
|
|
31
|
+
if engine is None:
|
|
32
|
+
sys.stderr.write(f"unknown engine {spec.engine}\n")
|
|
33
|
+
return 3
|
|
34
|
+
options = dict(spec.options)
|
|
35
|
+
if spec.voices:
|
|
36
|
+
options.setdefault("voices", spec.voices)
|
|
37
|
+
model = engine.load(
|
|
38
|
+
spec.kind, spec.task, ModelStore(data_dir).model_dir(spec.id), options, LoadOptions(threads=threads)
|
|
39
|
+
)
|
|
40
|
+
model.close()
|
|
41
|
+
sys.stdout.write("ok\n")
|
|
42
|
+
return 0
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
if __name__ == "__main__":
|
|
46
|
+
raise SystemExit(main(sys.argv[1:]))
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"./worker-C83FPhzz.js";var t=/* @__PURE__ */ e(((e,t)=>{t.exports={}}));export default t();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{U as e,V as t,ft as n,pt as r}from"./use-api-FEiHCTKE.js";r();var i=n(),a=t(`group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4`,{variants:{variant:{default:`bg-card text-card-foreground`,destructive:`bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current`}},defaultVariants:{variant:`default`}});function o({className:t,variant:n,...r}){return(0,i.jsx)(`div`,{"data-slot":`alert`,role:`alert`,className:e(a({variant:n}),t),...r})}function s({className:t,...n}){return(0,i.jsx)(`div`,{"data-slot":`alert-title`,className:e(`font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground`,t),...n})}function c({className:t,...n}){return(0,i.jsx)(`div`,{"data-slot":`alert-description`,className:e(`text-sm text-balance text-muted-foreground md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4`,t),...n})}export{c as n,s as r,o as t};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{r as e}from"./stats-DrD9fvoe.js";var t={first_partial_ms:`First partial`,final_ms:`Final`,ttfa_ms:`Time to first audio`};function n(e){return e===`tts`?`ttfa_ms`:`final_ms`}function r(e,t=256){let n=new Set;for(let r of e.split(/[\s,;]+/).filter(Boolean)){let e=/^(\d+)\s*[-–]\s*(\d+)$/.exec(r);if(e){let r=Number(e[1]),i=Number(e[2]);for(let e=Math.min(r,i);e<=Math.max(r,i)&&n.size<64;e++)e>=1&&e<=t&&n.add(e)}else if(/^\d+$/.test(r)){let e=Number(r);e>=1&&e<=t&&n.add(e)}}return[...n].sort((e,t)=>e-t)}function i(t,n,r){return e(t.map(e=>({concurrency:e.concurrency,latencyMs:e[n]?.p95})),r)}var a=e=>{if(e==null)return``;let t=String(e);return/[",\n]/.test(t)?`"${t.replace(/"/g,`""`)}"`:t};function o(e){return[[`model`,`kind`,`sample`,`duration_s`,`concurrency`,`ok`,`errors`,`first_partial_p50_ms`,`first_partial_p95_ms`,`final_p50_ms`,`final_p95_ms`,`ttfa_p50_ms`,`ttfa_p95_ms`,`rtf_p50`,`rtf_p95`,`throughput_x_realtime`],...e.points.map(t=>[e.request.model,e.request.kind,e.request.sample,e.request.duration_s,t.concurrency,t.ok,t.errors,t.first_partial_ms?.p50,t.first_partial_ms?.p95,t.final_ms?.p50,t.final_ms?.p95,t.ttfa_ms?.p50,t.ttfa_ms?.p95,t.rtf?.p50,t.rtf?.p95,t.throughput_x_realtime])].map(e=>e.map(a).join(`,`)).join(`
|
|
2
|
+
`)+`
|
|
3
|
+
`}function s(e){return JSON.stringify({started_at:new Date(e.startedAt).toISOString(),request:e.request,points:e.points},null,2)+`
|
|
4
|
+
`}var c=`bolo.benchRuns`;function l(){try{let e=JSON.parse(localStorage.getItem(c)??`[]`);return Array.isArray(e)?e.filter(e=>e&&Array.isArray(e.points)):[]}catch{return[]}}function u(e){try{localStorage.setItem(c,JSON.stringify(e.slice(0,12)))}catch{}}function d(e,t,n){let r=new Blob([t],{type:n}),i=URL.createObjectURL(r),a=document.createElement(`a`);a.href=i,a.download=e,document.body.appendChild(a),a.click(),a.remove(),setTimeout(()=>URL.revokeObjectURL(i),1e3)}export{l as a,o as c,d as i,s as l,i as n,r as o,n as r,u as s,t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e,t}from"./trash-PPSB5uoo.js";import{B as n,G as r,H as i,Lt as a,V as ee,a as o,g as s,o as c,r as te,v as l,x as ne}from"./index-D3MZkqFc.js";import{t as re}from"./play-Dqd68TKN.js";import{t as ie}from"./square-DZNyf3XQ.js";import{F as u,P as d,b as ae,ft as f,gt as oe,h as se,l as ce,m as le,p as ue,pt as p,r as de,t as fe,u as pe}from"./use-api-FEiHCTKE.js";import{a as me,d as he,f as m,n as ge,o as _e,r as ve,s as h,t as ye}from"./chart-DRTUqEVi.js";import{a as g,i as be,n as xe,o as Se,r as _,t as Ce}from"./chart-kit-mr_qOori.js";import{t as we}from"./model-picker-CvHhnt-R.js";import{r as v,t as Te}from"./panel-BOw-dJi0.js";import{t as Ee}from"./progress-BComADHS.js";import{i as y,n as b,o as x,s as S,t as C}from"./select-Ck7UCXuF.js";import{n as De,t as Oe}from"./toggle-group-D2I8RWGl.js";import{a as ke,c as Ae,i as je,l as Me,n as Ne,o as Pe,r as Fe,s as Ie,t as w}from"./bench-CXahGonE.js";import{o as Le}from"./stats-DrD9fvoe.js";var T=oe(p(),1),E=f(),Re=class extends Error{},ze=[`1, 2, 4, 8`,`1, 2, 4, 8, 16`,`1, 2, 3, 4, 6, 8, 12, 16`],Be=[`up to 8`,`up to 16`,`fine`],D=`__none`,Ve={p50:{label:`p50`,color:`var(--chart-1)`},p95:{label:`p95`,color:`var(--chart-2)`}},O=e=>({r:4,fill:e,stroke:`var(--card)`,strokeWidth:2});function He(e,t,n){return[...new Set([...e.map(e=>e.concurrency),...(t??[]).map(e=>e.concurrency)])].sort((e,t)=>e-t).map(r=>{let i=e.find(e=>e.concurrency===r),a=t?.find(e=>e.concurrency===r);return{c:r,p50:i?.[n]?.p50??null,p95:i?.[n]?.p95??null,thr:i?.throughput_x_realtime??null,bp95:a?.[n]?.p95??null,bthr:a?.throughput_x_realtime??null}})}function Ue(e,t=4){let n=Le(Math.max(e,1),t),r=Math.ceil(e/n)*n;return{max:r,ticks:Array.from({length:Math.round(r/n)+1},(e,t)=>t*n)}}function k(e){return`${e.request.model} · ${s(e.startedAt)}`}function A(){let[f,oe]=(0,T.useState)(`stt`),{models:p,isLoading:Le}=ce(f),A=pe(),j=ue(le),[We,Ge]=(0,T.useState)(null),[Ke,qe]=(0,T.useState)(null),[M,Je]=(0,T.useState)(ze[0]),[N,Ye]=(0,T.useState)(10),[Xe,Ze]=(0,T.useState)(0),[P,F]=(0,T.useState)(null),[I,Qe]=(0,T.useState)(ke),[$e,L]=(0,T.useState)(()=>ke()[0]?.id??null),[R,et]=(0,T.useState)(D),[z,tt]=(0,T.useState)(null),B=(0,T.useMemo)(()=>de(p,We??(f===`stt`?j.sttModel:j.ttsModel)),[p,We,f,j.sttModel,j.ttsModel]),V=(A.data?.samples??[]).filter(e=>e.kind===(f===`stt`?`audio`:`text`)),H=V.find(e=>e.id===Ke)?.id??V[0]?.id??null,U=Pe(M),W=(0,T.useRef)(!0);(0,T.useEffect)(()=>()=>{W.current=!1},[]);let nt=async()=>{if(!B||!H||U.length===0)return;let e={kind:f,model:B.id,concurrency:U,duration_s:N,sample:`builtin:${H}`},t,n;try{n=(await ae.bench(e)).job_id,t={id:`${n}:${Date.now()}`,startedAt:Date.now(),request:e,points:[]},F(t),Ze(0),tt(null)}catch(e){d.error(`Could not start the benchmark`,{description:fe(e)});return}let r=0;for(;W.current;){await new Promise(e=>setTimeout(e,400));try{let e=await ae.benchJob(n);if(r=0,!W.current)return;if(t={...t,points:e.result?.points??t.points},F(t),Ze(e.progress??0),e.state===`done`){let e=t;Qe(t=>{let n=[e,...t.filter(t=>t.id!==e.id)].slice(0,12);return Ie(n),n}),L(e.id),F(null),d.success(`Benchmark finished`,{description:`${e.points.length} concurrency levels measured`});return}if(e.state===`error`)throw new Re(e.error??`The benchmark job failed`)}catch(e){if(e instanceof Re||++r>=5){W.current&&(F(null),d.error(`Benchmark failed`,{description:fe(e)}));return}}}},G=P!=null,K=G?P:I.find(e=>e.id===$e)??null,q=!G&&R!==D?I.find(e=>e.id===R)??null:null,J=K?.request.kind??f,Y=z&&J===`tts`==(z===`ttfa_ms`)?z:Fe(J),X=K?He(K.points,q?.points??null,Y):[],Z=K&&K.points.length?Ne(K.points,Y,j.targetMs):null,rt=q?Ne(q.points,Y,j.targetMs):null,it=Ue(Math.max(j.targetMs*1.2,...X.flatMap(e=>[e.p95??0,e.bp95??0]))),at=Ue(Math.max(1,...X.flatMap(e=>[e.thr??0,e.bthr??0]))),ot=K?.points.length&&Z==null,Q=Z!=null&&Z===Math.max(...K?.points.map(e=>e.concurrency)??[0]),st=e=>{if(!K)return;let t=`bolo-bench-${K.request.model}-${new Date(K.startedAt).toISOString().slice(0,19).replace(/[:T]/g,``)}`;e===`json`?je(`${t}.json`,Me(K),`application/json`):je(`${t}.csv`,Ae(K),`text/csv`)},ct=e=>{let t=I.filter(t=>t.id!==e);Qe(t),Ie(t),$e===e&&L(t[0]?.id??null),R===e&&et(D)},$=q!=null,lt=$?K?k(K):`A`:`p95`,ut=(0,E.jsx)(_e,{dataKey:`c`,type:`category`,...g});return(0,E.jsxs)(te,{title:`Benchmark`,children:[!1,(0,E.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-[20rem_minmax(0,1fr)]`,children:[(0,E.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-4`,children:[(0,E.jsx)(v,{title:`Sweep`,description:`Runs on the server against a built-in sample`,children:(0,E.jsxs)(`form`,{className:`grid gap-4`,onSubmit:e=>{e.preventDefault(),nt()},children:[(0,E.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,E.jsx)(o,{className:`text-xs`,id:`bench-kind`,children:`Task`}),(0,E.jsxs)(Oe,{type:`single`,variant:`outline`,size:`sm`,value:f,onValueChange:e=>e&&(oe(e),Ge(null),qe(null)),"aria-labelledby":`bench-kind`,disabled:G,className:`w-full`,children:[(0,E.jsx)(De,{value:`stt`,className:`flex-1 text-xs`,children:`Speech to text`}),(0,E.jsx)(De,{value:`tts`,className:`flex-1 text-xs`,disabled:!1,title:void 0,children:`Text to speech`})]})]}),(0,E.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,E.jsx)(o,{htmlFor:`bench-model`,className:`text-xs`,children:`Model`}),(0,E.jsx)(we,{id:`bench-model`,models:p,value:B?.id??null,onChange:Ge,loading:Le,disabled:G,className:`w-full`})]}),(0,E.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,E.jsx)(o,{htmlFor:`bench-sample`,className:`text-xs`,children:`Sample`}),(0,E.jsxs)(C,{value:H??void 0,onValueChange:qe,disabled:G||V.length===0,children:[(0,E.jsx)(x,{id:`bench-sample`,className:`h-8 w-full`,children:(0,E.jsx)(S,{placeholder:A.isLoading?`Loading…`:`No samples`})}),(0,E.jsx)(b,{position:`popper`,align:`start`,children:V.map(e=>(0,E.jsxs)(y,{value:e.id,children:[(0,E.jsx)(`span`,{className:`num text-[13px]`,children:e.id}),e.seconds!=null&&(0,E.jsxs)(`span`,{className:`ml-2 num text-xs text-muted-foreground`,children:[e.seconds.toFixed(1),` s`]})]},e.id))})]})]}),(0,E.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,E.jsx)(o,{htmlFor:`bench-levels`,className:`text-xs`,children:`Concurrency levels`}),(0,E.jsx)(c,{id:`bench-levels`,value:M,onChange:e=>Je(e.target.value),className:`h-8 num`,disabled:G,"aria-describedby":`bench-levels-hint`,"aria-invalid":U.length===0,spellCheck:!1}),(0,E.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:ze.map((e,t)=>(0,E.jsx)(u,{type:`button`,size:`xs`,variant:M===e?`secondary`:`ghost`,className:`num`,onClick:()=>Je(e),disabled:G,children:Be[t]},e))}),(0,E.jsx)(`p`,{id:`bench-levels-hint`,className:`text-[11px] leading-4 text-muted-foreground`,children:U.length===0?`Enter numbers or ranges, e.g. 1, 2, 4-8.`:`${U.length} level${U.length===1?``:`s`} · about ${U.length*N} s in total`})]}),(0,E.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,E.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,E.jsx)(o,{htmlFor:`bench-duration`,className:`text-xs`,children:`Seconds per level`}),(0,E.jsx)(c,{id:`bench-duration`,type:`number`,min:2,max:120,value:N,onChange:e=>Ye(Math.max(2,Math.min(120,Number(e.target.value)||10))),className:`h-8 num`,disabled:G})]}),(0,E.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,E.jsx)(o,{htmlFor:`bench-target`,className:`text-xs`,children:`Target p95 (ms)`}),(0,E.jsx)(c,{id:`bench-target`,type:`number`,min:50,max:5e3,step:50,value:j.targetMs,onChange:e=>{let t=Number(e.target.value);t>=50&&t<=5e3&&se(`targetMs`,Math.round(t))},className:`h-8 num`})]})]}),G?(0,E.jsxs)(u,{type:`button`,variant:`outline`,disabled:!0,children:[(0,E.jsx)(ie,{className:`fill-current`}),` Running…`]}):(0,E.jsxs)(u,{type:`submit`,disabled:!B?.installed||!H||U.length===0,"data-testid":`bench-run`,children:[(0,E.jsx)(re,{className:`fill-current`}),` Run benchmark`]}),B&&!B.installed&&(0,E.jsx)(`p`,{className:`text-xs text-warning-text`,children:`This model is not installed. Pull it first.`})]})}),(0,E.jsx)(v,{title:`Runs`,description:`Kept in this browser`,bodyClassName:`p-0`,children:I.length===0?(0,E.jsx)(`p`,{className:`px-4 py-5 text-[13px] leading-5 text-muted-foreground`,children:`Finished runs are listed here so you can reopen and compare them.`}):(0,E.jsx)(`ul`,{children:I.map(e=>(0,E.jsxs)(`li`,{className:`flex items-center gap-1 border-b border-border px-2 last:border-b-0`,children:[(0,E.jsxs)(`button`,{type:`button`,onClick:()=>L(e.id),"aria-current":K?.id===e.id,className:`min-w-0 flex-1 rounded-md px-2 py-2 text-left hover:bg-muted/50 aria-[current=true]:bg-muted/60`,children:[(0,E.jsx)(`div`,{className:`truncate num text-[13px]`,children:e.request.model}),(0,E.jsxs)(`div`,{className:`num text-[11px] text-muted-foreground`,children:[s(e.startedAt),` · `,e.points.length,` levels · up to`,` `,Math.max(0,...e.points.map(e=>e.concurrency))]})]}),(0,E.jsx)(u,{size:`icon-sm`,variant:`ghost`,"aria-label":`Delete run ${k(e)}`,onClick:()=>ct(e.id),children:(0,E.jsx)(t,{})})]},e.id))})})]}),(0,E.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-4`,children:[G&&(0,E.jsxs)(`div`,{className:`rounded-xl border border-border bg-card px-4 py-3`,role:`status`,children:[(0,E.jsxs)(`div`,{className:`mb-2 flex items-baseline justify-between gap-3 text-sm`,children:[(0,E.jsxs)(`span`,{children:[`Benchmarking `,(0,E.jsx)(`span`,{className:`num font-medium`,children:P.request.model})]}),(0,E.jsxs)(`span`,{className:`num text-xs text-muted-foreground`,children:[`level `,Math.min(P.request.concurrency.length,P.points.length+1),` of`,` `,P.request.concurrency.length,` · `,Math.round(Xe*100),`%`]})]}),(0,E.jsx)(Ee,{value:Xe*100,className:`h-1.5`,"aria-label":`Benchmark progress`})]}),K?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,E.jsxs)(`div`,{className:`mr-auto min-w-0`,children:[(0,E.jsx)(`div`,{className:`truncate num text-sm font-medium`,children:K.request.model}),(0,E.jsxs)(`div`,{className:`num text-xs text-muted-foreground`,children:[K.request.sample,` · `,K.request.duration_s,` s per level · `,s(K.startedAt)]})]}),J===`stt`&&(0,E.jsxs)(C,{value:Y,onValueChange:e=>tt(e),children:[(0,E.jsx)(x,{className:`h-8 w-40`,"aria-label":`Latency metric`,children:(0,E.jsx)(S,{})}),(0,E.jsxs)(b,{position:`popper`,align:`end`,children:[(0,E.jsx)(y,{value:`final_ms`,children:`Final`}),(0,E.jsx)(y,{value:`first_partial_ms`,children:`First partial`})]})]}),(0,E.jsxs)(C,{value:q?R:D,onValueChange:et,disabled:G||I.length<2,children:[(0,E.jsx)(x,{className:`h-8 w-56`,"aria-label":`Compare with another run`,children:(0,E.jsx)(S,{})}),(0,E.jsxs)(b,{position:`popper`,align:`end`,children:[(0,E.jsx)(y,{value:D,children:I.length<2?`Compare: needs two runs`:`Compare with…`}),I.filter(e=>e.id!==K.id).map(e=>(0,E.jsx)(y,{value:e.id,children:(0,E.jsx)(`span`,{className:`num text-[13px]`,children:k(e)})},e.id))]})]}),(0,E.jsxs)(n,{children:[(0,E.jsx)(r,{asChild:!0,children:(0,E.jsxs)(u,{size:`sm`,variant:`outline`,className:`h-8`,disabled:K.points.length===0,children:[(0,E.jsx)(e,{}),` Export`]})}),(0,E.jsxs)(ee,{align:`end`,children:[(0,E.jsx)(i,{onSelect:()=>st(`json`),children:`JSON`}),(0,E.jsx)(i,{onSelect:()=>st(`csv`),children:`CSV`})]})]})]}),(0,E.jsxs)(`div`,{className:`rounded-xl border border-border bg-card px-5 py-4`,"data-testid":`ceiling`,children:[(0,E.jsxs)(`div`,{className:`text-xs text-muted-foreground`,children:[`Concurrency ceiling · `,w[Y].toLowerCase(),` p95 within`,` `,(0,E.jsxs)(`span`,{className:`num`,children:[j.targetMs,` ms`]})]}),(0,E.jsxs)(`div`,{className:`mt-1 flex flex-wrap items-baseline gap-x-3 gap-y-1`,children:[(0,E.jsx)(`span`,{className:`text-5xl leading-none font-semibold tracking-tight`,children:K.points.length===0?`–`:Z??0}),(0,E.jsx)(`span`,{className:`text-sm text-muted-foreground`,children:K.points.length===0?`measuring…`:ot?`Even the lowest level misses the target.`:Q?`streams, and every level tested met the target. Try higher levels to find the limit.`:`concurrent stream${Z===1?``:`s`} before p95 crosses the target`}),q&&(0,E.jsxs)(`span`,{className:`ml-auto num text-sm text-muted-foreground`,children:[`vs `,rt??0,` for `,q.request.model]})]})]}),(0,E.jsxs)(`div`,{className:`grid gap-4 lg:grid-cols-2`,children:[(0,E.jsx)(Ce,{title:`${w[Y]} vs concurrency`,description:`ms, by concurrent streams · lower is better`,legend:$?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(_,{color:`var(--chart-1)`,label:(0,E.jsxs)(`span`,{className:`num`,children:[lt,` p95`]})}),(0,E.jsx)(_,{color:`var(--chart-2)`,label:(0,E.jsxs)(`span`,{className:`num`,children:[k(q),` p95`]})}),(0,E.jsx)(_,{color:`var(--foreground)`,label:`target`,dashed:!0})]}):(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(_,{color:`var(--chart-1)`,label:`p50`}),(0,E.jsx)(_,{color:`var(--chart-2)`,label:`p95`}),(0,E.jsx)(_,{color:`var(--foreground)`,label:`target ${j.targetMs} ms`,dashed:!0})]}),chart:(0,E.jsx)(ye,{config:Ve,className:`aspect-auto h-64 w-full`,"data-testid":`bench-latency`,children:(0,E.jsxs)(ve,{data:X,margin:{top:16,right:16,bottom:0,left:0},accessibilityLayer:!0,children:[(0,E.jsx)(he,{...Se}),ut,(0,E.jsx)(me,{...g,axisLine:!1,width:48,domain:[0,it.max],ticks:it.ticks}),(0,E.jsx)(ge,{cursor:{stroke:`var(--chart-axis)`,strokeWidth:1},isAnimationActive:!1,content:({active:e,payload:t})=>{let n=t?.[0]?.payload;return!e||!n?null:(0,E.jsx)(be,{title:`${n.c} concurrent`,rows:$?[{color:`var(--chart-1)`,label:`this run p95`,value:l(n.p95)},{color:`var(--chart-2)`,label:`other run p95`,value:l(n.bp95)}]:[{color:`var(--chart-2)`,label:`p95`,value:l(n.p95)},{color:`var(--chart-1)`,label:`p50`,value:l(n.p50)}],footer:n.p95==null?void 0:n.p95<=j.targetMs?`within target`:`over target by ${l(n.p95-j.targetMs)}`})}}),(0,E.jsx)(m,{y:j.targetMs,stroke:`var(--foreground)`,strokeOpacity:.45,strokeWidth:1}),Z!=null&&!Q&&(0,E.jsx)(m,{x:Z,stroke:`var(--foreground)`,strokeOpacity:.45,strokeWidth:1,label:{value:`ceiling ${Z}`,position:`insideTopLeft`,fill:`var(--foreground)`,fontSize:11}}),$?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(h,{dataKey:`bp95`,stroke:`var(--chart-2)`,strokeWidth:2,dot:O(`var(--chart-2)`),isAnimationActive:!1,connectNulls:!0}),(0,E.jsx)(h,{dataKey:`p95`,stroke:`var(--chart-1)`,strokeWidth:2,dot:O(`var(--chart-1)`),isAnimationActive:!1,connectNulls:!0})]}):(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(h,{dataKey:`p95`,stroke:`var(--chart-2)`,strokeWidth:2,dot:O(`var(--chart-2)`),isAnimationActive:!1,connectNulls:!0}),(0,E.jsx)(h,{dataKey:`p50`,stroke:`var(--chart-1)`,strokeWidth:2,dot:O(`var(--chart-1)`),isAnimationActive:!1,connectNulls:!0})]})]})}),table:(0,E.jsx)(xe,{caption:`Latency by concurrency`,head:$?[`Concurrency`,`This run p95 ms`,`Other run p95 ms`]:[`Concurrency`,`p50 ms`,`p95 ms`],rows:X.map(e=>$?[e.c,l(e.p95,!1),l(e.bp95,!1)]:[e.c,l(e.p50,!1),l(e.p95,!1)])})}),(0,E.jsx)(Ce,{title:`Throughput vs concurrency`,description:`× real time, by concurrent streams · higher is better`,legend:$?(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(_,{color:`var(--chart-1)`,label:(0,E.jsx)(`span`,{className:`num`,children:lt})}),(0,E.jsx)(_,{color:`var(--chart-2)`,label:(0,E.jsx)(`span`,{className:`num`,children:k(q)})})]}):void 0,chart:(0,E.jsx)(ye,{config:Ve,className:`aspect-auto h-64 w-full`,"data-testid":`bench-throughput`,children:(0,E.jsxs)(ve,{data:X,margin:{top:16,right:16,bottom:0,left:0},accessibilityLayer:!0,children:[(0,E.jsx)(he,{...Se}),ut,(0,E.jsx)(me,{...g,axisLine:!1,width:48,domain:[0,at.max],ticks:at.ticks,tickFormatter:e=>`${e}×`}),(0,E.jsx)(ge,{cursor:{stroke:`var(--chart-axis)`,strokeWidth:1},isAnimationActive:!1,content:({active:e,payload:t})=>{let n=t?.[0]?.payload;if(!e||!n)return null;let r=[{color:`var(--chart-1)`,label:$?`this run`:`throughput`,value:n.thr==null?`–`:`${n.thr}×`}];return $&&r.push({color:`var(--chart-2)`,label:`other run`,value:n.bthr==null?`–`:`${n.bthr}×`}),(0,E.jsx)(be,{title:`${n.c} concurrent`,rows:r})}}),Z!=null&&!Q&&(0,E.jsx)(m,{x:Z,stroke:`var(--foreground)`,strokeOpacity:.45,strokeWidth:1,label:{value:`ceiling ${Z}`,position:`insideTopLeft`,fill:`var(--foreground)`,fontSize:11}}),$&&(0,E.jsx)(h,{dataKey:`bthr`,stroke:`var(--chart-2)`,strokeWidth:2,dot:O(`var(--chart-2)`),isAnimationActive:!1,connectNulls:!0}),(0,E.jsx)(h,{dataKey:`thr`,stroke:`var(--chart-1)`,strokeWidth:2,dot:O(`var(--chart-1)`),isAnimationActive:!1,connectNulls:!0})]})}),table:(0,E.jsx)(xe,{caption:`Throughput by concurrency`,head:$?[`Concurrency`,`This run ×`,`Other run ×`]:[`Concurrency`,`× real time`],rows:X.map(e=>$?[e.c,e.thr??`–`,e.bthr??`–`]:[e.c,e.thr??`–`])})})]}),(0,E.jsx)(v,{title:`Results`,description:`One row per concurrency level`,bodyClassName:`p-0 overflow-x-auto`,children:(0,E.jsxs)(`table`,{className:`w-full min-w-[640px] text-xs`,"data-testid":`bench-table`,children:[(0,E.jsx)(`thead`,{children:(0,E.jsx)(`tr`,{className:`border-b border-border text-left text-muted-foreground`,children:[`Concurrency`,`OK`,`Errors`,`${w[Y]} p50`,`${w[Y]} p95`,`RTF p50`,`RTF p95`,`Throughput`,`Target`].map((e,t)=>(0,E.jsx)(`th`,{scope:`col`,className:`px-4 py-2 font-medium whitespace-nowrap ${t>0&&t<8?`text-right`:``}`,children:e},e))})}),(0,E.jsxs)(`tbody`,{children:[K.points.map(e=>{let t=e[Y],n=t?.p95!=null&&t.p95<=j.targetMs;return(0,E.jsxs)(`tr`,{className:`border-b border-border last:border-b-0`,children:[(0,E.jsx)(`td`,{className:`px-4 py-2 num font-medium`,children:e.concurrency}),(0,E.jsx)(`td`,{className:`px-4 py-2 text-right num`,children:e.ok}),(0,E.jsx)(`td`,{className:`px-4 py-2 text-right num`,children:e.errors}),(0,E.jsx)(`td`,{className:`px-4 py-2 text-right num`,children:l(t?.p50)}),(0,E.jsx)(`td`,{className:`px-4 py-2 text-right num`,children:l(t?.p95)}),(0,E.jsx)(`td`,{className:`px-4 py-2 text-right num`,children:ne(e.rtf?.p50)}),(0,E.jsx)(`td`,{className:`px-4 py-2 text-right num`,children:ne(e.rtf?.p95)}),(0,E.jsxs)(`td`,{className:`px-4 py-2 text-right num`,children:[e.throughput_x_realtime,`×`]}),(0,E.jsx)(`td`,{className:`px-4 py-2`,children:(0,E.jsxs)(`span`,{className:`inline-flex items-center gap-1.5`,children:[(0,E.jsx)(`span`,{className:`size-1.5 rounded-full ${t?.p95==null?`bg-chart-mute`:n?`bg-good`:`bg-critical`}`,"aria-hidden":!0}),t?.p95==null?`n/a`:n?`met`:`missed`]})})]},e.concurrency)}),K.points.length===0&&(0,E.jsx)(`tr`,{children:(0,E.jsx)(`td`,{colSpan:9,className:`px-4 py-6 text-center text-muted-foreground`,children:`Waiting for the first level to finish…`})})]})]})})]}):(0,E.jsx)(`div`,{className:`rounded-xl border border-dashed border-border bg-card`,children:(0,E.jsx)(Te,{icon:a,title:`No benchmark yet`,className:`py-20`,children:`Pick a model and run a sweep. You will get latency and throughput at each concurrency level, and the highest level that still meets your target.`})})]})]})]})}export{A as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{K as e}from"./use-api-FEiHCTKE.js";var t={name:`lock`,size:24,node:[[`rect`,{width:`18`,height:`11`,x:`3`,y:`11`,rx:`2`,ry:`2`,key:`1w4ew1`}],[`path`,{d:`M7 11V7a5 5 0 0 1 10 0v4`,key:`fwvmzm`}]]};t.node;var n=e(t),r=[`cascade`,`audio-llm`,`speech-to-speech`],i={cascade:{label:`Cascade`,summary:`bolo transcribes you, your language model answers in text, and bolo's voice speaks the answer.`},"audio-llm":{label:`Audio LLM`,summary:`An audio-understanding model hears your turn directly; bolo's voice speaks its answer.`},"speech-to-speech":{label:`Speech to speech`,summary:`A speech-to-speech model hears you and answers with its own voice. bolo keeps turn taking and transcripts.`}},a=`LFM Open License: commercial use only below USD 10M revenue`;function o(e){return!!e?.capabilities?.realtime?.pipelines}function s(e,t=[]){let n=e?.capabilities?.realtime?.pipelines??{},o=e?.capabilities?.llm;return r.map(e=>{let r=i[e],s=n[e],c=!1,l=null,u;if(e===`cascade`)c=!!(s?.available??o?.configured),u=o?.model?`language model ${o.model}`:null,c||(l=`No language model is configured (setting llm_base_url).`);else if(e===`audio-llm`)c=!!(s?.configured??s?.available),u=s?.model?`audio model ${s.model}`:null,c||(l=`No audio-understanding model is configured (settings audio_llm_base_url, audio_llm_model).`);else if(u=s?.model?`model ${s.model}`:null,s?.url)c=!0,u=`${u?`${u} at `:``}${s.url}`;else if(s?.model){let e=t.find(e=>e.id===`llama-server`);c=!e||e.installed,c||(l=`Needs llama-server (install it on the Components screen) or the setting s2s_server_url.`)}else l=s?`No speech-to-speech model is configured (settings s2s_model or s2s_server_url).`:`This server has no speech-to-speech pipeline.`;return!s&&e!==`cascade`&&(c=!1,l??=`This server does not offer this pipeline.`),{id:e,...r,available:c,reason:c?null:l,detail:u,note:e===`speech-to-speech`?a:null}})}function c(e,t){let n=e?.capabilities?.realtime?.pipeline,r=t.filter(e=>e.available);return n&&r.some(e=>e.id===n)?n:r[0]?.id??n??`cascade`}var l={"nemotron-3-diarization":`Better with overlapping or phone audio, misses more quiet speech`,"pyannote-3.0-eres2net":`Default: segmentation and clustering, small and fast`};function u(e,t){let n=e?.capabilities?.diarization?.default_model??`pyannote-3.0-eres2net`;return t.filter(e=>e.task===`diarization`&&e.status!==`pending`&&!h(e)).map(e=>({id:e.id,label:e.id===n?`${e.id} (default)`:e.id,note:l[e.id]??null,isDefault:e.id===n,installed:e.installed,usable:e.available!==!1})).sort((e,t)=>Number(t.isDefault)-Number(e.isDefault)||d(e.id)-d(t.id))}function d(e){return e.startsWith(`pyannote`)?0:e.startsWith(`nemotron`)?1:e.startsWith(`fake`)?3:2}function f(e,t){let n=new Set(e?.capabilities?.diarization?.speaker_conditioned_models??[]);return t.filter(e=>e.task===`stt`&&(n.has(e.id)||e.features.includes(`speaker-conditioned`))&&e.status!==`pending`)}function p(e){return e.filter(e=>e.task===`separation`&&e.status!==`pending`&&!h(e))}function m(e){return e.status===`pending`}function h(e){return e.status===`not_implemented`||e.status===`not-implemented`||/not runnable yet/i.test(e.description)}function g(e){return!e.hardware||e.hardware.gpu===`optional`}function _(e){if(!e)return null;let t=e.gpu===`required`?`GPU required`:e.gpu===`recommended`?`GPU recommended`:e.gpu===`optional`?`GPU optional`:`GPU ${e.gpu}`;return e.vram_gb==null?t:`${t}, ~${v(e.vram_gb)}`}function v(e){return`${e>=10?Math.round(e):Math.round(e*10)/10} GB`}function y(e){return e.engine.startsWith(`plugin:`)?`plugin ${e.engine.slice(7)}`:e.engine===`tts-server`?e.requires?.includes(`audio.cpp`)||e.id.endsWith(`-audiocpp`)?`audio.cpp`:`llama.cpp`:null}var b=/^(veena|svara|orpheus|snortts)/i;function x(e){return e.engine===`tts-server`&&b.test(e.id)?`Orpheus family (llama.cpp)`:e.engine===`tts-server`?e.id.endsWith(`-audiocpp`)?`audio.cpp voices`:`llama.cpp voices`:e.engine.startsWith(`plugin:`)?`Engine plugin voices`:`Built-in voices`}function S(e){return!!e?.features.includes(`voice-cloning`)}var C={auto:`Automatic`,uccharan:`uccharan`,"uccharan:compatible":`uccharan`,"uccharan:improved":`uccharan, improved`,"espeak-ng":`eSpeak NG`};function w(e,t){return t?.phonemizers??e?.phonemizers??[]}export{_ as a,h as c,s as d,y as f,n as g,x as h,u as i,m as l,f as m,S as n,o,p,c as r,g as s,C as t,w as u};
|