ONNX एक प्रशिक्षित न्यूरल नेटवर्क के लिए एक फ़ाइल फ़ॉर्मैट है: वेट्स और कंप्यूटेशन ग्राफ़, स्थिर, जिसे प्रशिक्षित करने वाले फ़्रेमवर्क पर कोई निर्भरता नहीं। ONNX में निर्यातित एक मॉडल ONNX Runtime के ज़रिए चल सकता है, एक छोटा इन्फ़रेंस इंजन जो केवल उस ग्राफ़ को निष्पादित करता है और कुछ नहीं। यह नहीं जानता कि मॉडल कैसे प्रशिक्षित किया गया था, प्रशिक्षण का समर्थन नहीं करता, और इसे PyTorch या TensorFlow इंस्टॉल करने की ज़रूरत नहीं होती।
हमारी कई लाइब्रेरियाँ एक नियम पर टिकी हैं: रनटाइम पर, एकमात्र निर्भरताएँ onnxruntime और numpy हैं। “ज़्यादातर” नहीं — पैकेज का इंपोर्ट कभी भी किसी प्रशिक्षण फ़्रेमवर्क को नहीं खींचता। audiosronnx (बैंडविड्थ विस्तार और डिनॉइज़िंग), voiceclonnx (वॉयस क्लोनिंग), speakeronnx (स्पीकर एम्बेडिंग), speechonnxmetrics (मूल्यांकन), stressonnx (शब्द बल), vadonnx (वॉयस एक्टिविटी डिटेक्शन), और phoonnx (फ़ोनेमाइज़ेशन और टेक्स्ट-टू-स्पीच) सभी इसका पालन करते हैं, हर एक अपने ही PyPI पैकेज में। दो और, phoonnx.js और precise-onnx-js, वही विचार onnxruntime-web के साथ ब्राउज़र में लागू करते हैं।
परवाह क्यों करें
किसी स्पीच मॉडल को भेजने का स्पष्ट तरीक़ा इन्फ़रेंस के लिए भी प्रशिक्षण फ़्रेमवर्क को साथ रखना है। यह विकास के दौरान सुविधाजनक है। यह प्रोडक्शन में एक देनदारी है।
- इंस्टॉल आकार। एक PyTorch + CUDA इंस्टॉल एक भी मॉडल लोड करने से पहले गीगाबाइट्स में चला जाता है।
onnxruntimeऔरnumpyमिलकर कुछ दसियों मेगाबाइट्स के हैं। - कोई CUDA प्रबंधित नहीं करना। एक GPU ड्राइवर, CUDA टूलकिट संस्करण, और एक फ़्रेमवर्क बिल्ड को मिलाना टूटने का बार-बार आने वाला स्रोत है। केवल-CPU ONNX Runtime इसे पूरी तरह छोड़ देता है, और फिर भी वही ग्राफ़ किसी GPU पर चलाता है जहाँ एक उपलब्ध हो।
- मामूली हार्डवेयर पर चलता है। एक Raspberry Pi या दस साल पुराना लैपटॉप आराम से
onnxruntimeचला सकता है। यह आमतौर पर पूरा PyTorch स्टैक किसी काम की गति पर नहीं चला सकता, या 32-बिट या मेमोरी-सीमित बोर्ड पर इसे इंस्टॉल भी नहीं कर सकता। - एक कलाकृति, हर प्लेटफ़ॉर्म। वही
.onnxफ़ाइल Linux, macOS, Windows पर बिना बदलाव चलती है — और,onnxruntime-webके ज़रिए, किसी ब्राउज़र टैब के भीतर। प्रति लक्ष्य कोई अलग निर्यात क़दम नहीं है। - कोई प्रशिक्षण/सर्विंग संस्करण टकराव नहीं। एक प्रशिक्षण स्टैक विशिष्ट फ़्रेमवर्क और CUDA संस्करण पिन करता है। एक सर्विंग स्टैक निर्भरताओं का सबसे छोटा, सबसे स्थिर सेट चाहता है। इन्हें अलग करने का मतलब है एक को अपग्रेड करना बिना दूसरे को तोड़े।
इसकी क़ीमत क्या है
यह बाधा वास्तविक है, और यह मुफ़्त नहीं है।
आप इन-प्रोसेस फ़ाइन-ट्यून नहीं कर सकते। एक ONNX ग्राफ़ में कोई ऑप्टिमाइज़र नहीं, कोई backward pass नहीं। इनमें से हर एक लाइब्रेरी मॉडलों को स्थिर कलाकृतियों की तरह देखती है: आप उन्हें लोड करते हैं और चलाते हैं। प्रशिक्षण या फ़ाइन-ट्यूनिंग अलग से होती है, मूल फ़्रेमवर्क के साथ, और परिणाम बाद में ONNX में निर्यातित होता है। stressonnx और speechonnxmetrics दोनों एक वैकल्पिक export एक्स्ट्रा रखते हैं जो शुद्ध रूप से उस ऑफ़लाइन रूपांतरण क़दम के लिए torch खींचता है — इन्फ़रेंस के लिए कभी नहीं।
हर आर्किटेक्चर साफ़-सुथरे ढंग से निर्यात नहीं होता। डायनामिक कंट्रोल फ़्लो, कस्टम CUDA कर्नेल, या ऐसे ऑप्स जिनका कोई ONNX समकक्ष नहीं है, एक सीधा-सादा निर्यात रोक सकते हैं। audiosronnx का README इसे सीधे दस्तावेज़ करता है: यह उन मॉडलों की एक शिप-न-की-गई सूची रखता है जिनका इसने मूल्यांकन किया और अस्वीकार किया, कारणों सहित, बजाय यह दिखावा करने के कि हर रिसर्च मॉडल पोर्ट हो जाता है।
प्रीप्रोसेसिंग को हाथ से फिर से लागू करना पड़ता है। PyTorch या Kaldi जैसा फ़्रेमवर्क STFT (एक वेवफ़ॉर्म को एक स्पेक्ट्रोग्राम में बदलना), mel-filterbank फ़ीचर्स, और रीसैंपलिंग के तेज़, परीक्षित कार्यान्वयन भेजता है। एक बार जब मॉडल ख़ुद उस फ़्रेमवर्क पर निर्भर नहीं रहता, तो इसकी प्रीप्रोसेसिंग भी नहीं रह सकती — speakeronnx ठीक इसी कारण से एक 80-बैंड log-mel filterbank को शुद्ध NumPy में फिर से लागू करता है, और audiosronnx STFT और रीसैंपलिंग के लिए वही करता है। यह सही करने के लिए ज़्यादा कोड है, और इसे मूल के विरुद्ध अपने ख़ुद के समानता परीक्षणों की ज़रूरत होती है।
एक काम, कई इंजन, एक API
प्रशिक्षित स्पीच मॉडल भाषा, रिकॉर्डिंग स्थिति, और लक्ष्य डोमेन के अनुसार बेहद भिन्न होते हैं। साफ़ पढ़ी गई वाणी पर प्रशिक्षित एक स्पीकर-सत्यापन मॉडल फ़ोन ऑडियो पर विफल हो सकता है। अंग्रेज़ी timbre ट्रांसफ़र के लिए ट्यून किया गया एक वॉयस-क्लोनिंग मॉडल टोनल भाषाओं पर सुबोधता खो सकता है। कोई एक मॉडल हर जगह जीतता नहीं है, इसलिए पहले से एक के प्रति प्रतिबद्ध होना एक अनुमान है।
इस परिवार में हर लाइब्रेरी एक अकेला काम चुनती है और कई स्वतंत्र प्रकाशित मॉडलों को एक इंटरफ़ेस के पीछे लपेटती है, ताकि इंजन बदलना एक पुनर्लेखन के बजाय एक-पंक्ति का बदलाव हो।
audiosronnx अपने दो कामों — डिनॉइज़िंग और बैंडविड्थ विस्तार (एक नैरोबैंड रिकॉर्डिंग, जैसे 8 kHz टेलीफ़ोन ऑडियो, को एक ज़्यादा भरे-पूरे, उच्चतर सैंपल रेट सिग्नल में बदलना) — को दो लोडरों के पीछे अलग करता है, हर एक कई इंजनों से समर्थित:
from audiosronnx import load_denoise, load_sr
clean, rate = load_denoise("dpdfnet").denoise("noisy_call.wav") # remove noise
wide, _ = load_sr("lavasr").upscale(clean, rate) # extend to 48 kHz
load_denoise वर्तमान में दस डिनॉइज़र पंजीकृत करता है (dpdfnet, mossformer2, frcrn, mpsenet, gtcrn, cmgan, metadenoiser, mossformergan, voicefixer, deepfilternet), 0.54 MB के एक मॉडल से 415 MB के एक मॉडल तक, अलग-अलग लाइसेंसों के अंतर्गत। load_sr सात बैंडविड्थ एक्सटेंडर पंजीकृत करता है (lavasr, novasr, flowhigh, hifiganbwe, apbwe, sidon, callenhancer)। हावी हो चुके मॉडल — जिन्हें कोई और इंजन हर मापे गए पहलू पर हरा देता है — फिर भी रजिस्ट्री में रहते हैं, ताकि एक प्रकाशित बेंचमार्क परिणाम माँगे जाने पर पुनरुत्पादनीय रहे।
voiceclonnx वॉयस क्लोनिंग के लिए वही तरीक़ा अपनाता है — किसी मौजूदा रिकॉर्डिंग की आवाज़ को एक अलग संदर्भ स्पीकर जैसा सुनाने में बदलना, टेक्स्ट से गुज़रे बिना:
from voiceclonnx import VoiceCloner
cloner = VoiceCloner(engine="facodec")
out = cloner.clone_voice("source.wav", "reference.wav", "out.wav")
दस इंजन पंजीकृत हैं (facodec, openvoice, chatterbox, triaan, cosyvoice, bicodec, knnvc, focalcodec, lscodec, rvc), जो छह अलग-अलग मॉडल परिवारों में फैले हैं — kNN फ़ीचर-स्वैप, फ़ैक्टराइज़्ड कोडेक, फ़्लो-मैचिंग, टोन-कलर ट्रांसफ़र, AR कोडेक-LM, और स्पीकर-डीकपल्ड कोडेक। पर्दे के पीछे हर एक प्रकाशित सुबोधता और स्पीकर-समानता आँकड़ों के साथ आता है, इसलिए इंजन चुनना एक तुलना है, सिक्का उछालना नहीं।
vadonnx उसी पैटर्न को वॉयस एक्टिविटी डिटेक्शन पर लागू करता है — यह तय करना कि किसी ऑडियो स्ट्रीम के किन हिस्सों में बिलकुल भी वाणी है:
from vadonnx import load_vad
vad = load_vad("silero")
segments = vad.get_speech_segments(audio, sample_rate=16000)
# -> [SpeechSegment(start=0.32, end=2.27), SpeechSegment(start=3.27, end=4.45), ...]
छह मॉडल परिवार पंजीकृत हैं (silero, marblenet, pyannote, fsmn, speechbrain, ten), और एक घोषणात्मक IOSignature एक अकेले सामान्य इंजन को इनमें से अधिकांश चलाने देता है, या किसी भी कस्टम .onnx VAD फ़ाइल की ओर इंगित करने देता है।
speakeronnx एक स्पीकर एम्बेडिंग निकालता है — एक स्थिर-लंबाई वेक्टर जो सारांशित करता है कि कौन बोल रहा है, इससे स्वतंत्र कि उन्होंने क्या कहा — और यह जाँचने के लिए कि क्या दो क्लिप एक ही स्पीकर के हैं, दो एम्बेडिंग की तुलना कोसाइन समानता से करता है:
from speakeronnx import SpeakerEmbedder, cosine
embedder = SpeakerEmbedder(model="wespeaker-resnet34")
alice1 = embedder.embed("alice_clip1.wav")
alice2 = embedder.embed("alice_clip2.wav")
print(cosine(alice1, alice2)) # e.g. 0.82 - same speaker
यह चार आर्किटेक्चर परिवारों (WeSpeaker, CAM++, ERes2Net, ReDimNet) में नौ मॉडल पंजीकृत करता है, प्रकाशित एम्बेडिंग आयामों और लाइसेंसों के साथ।
stressonnx टेक्स्ट-टू-स्पीच फ़्रंट-एंड के लिए शब्द बल चुनता है — किसी शब्द का कौन-सा अक्षर ज़ोर वहन करता है, ऐसी जानकारी जिसे कई भाषाएँ लिखकर नहीं बतातीं (रूसी за́мок, महल, बनाम замо́к, ताला, हर अक्षर साझा करते हैं)। यह रूसी के लिए एक न्यूरल पाइपलाइन, यूक्रेनी और बेलारूसी के लिए एक दूसरी, और बिना किसी न्यूरल इन्फ़रेंस के 26 भाषाओं को कवर करने वाला एक नियम-और-शब्दावली बैकएंड पंजीकृत करता है:
from stressonnx import stress
stress("старинный замок стоит на горе", "ru")
# 'стари́нный за́мок сто́ит на горе́'
phoonnx टेक्स्ट को फ़ोनेमाइज़ करता है (लिखे गए शब्दों को उन ध्वनि इकाइयों में बदलता है जिन्हें एक TTS मॉडल उपभोग करता है) और कई पारिस्थितिकी तंत्रों (मूल phoonnx, Piper, Mimic3, Coqui, MMS, Transformers) से निर्यातित 17 पंजीकृत संश्लेषण इंजनों और आवाज़ों में टेक्स्ट-टू-स्पीच चलाता है:
import wave
from phoonnx.voice import TTSVoice
voice = TTSVoice.load("model.onnx", "model.json")
with wave.open("hello.wav", "wb") as wav_file:
voice.synthesize_wav("Hello world!", wav_file)
phoonnx.js वही टोकनाइज़र पथ onnxruntime-web के साथ ब्राउज़र में ले जाता है, और precise-onnx-js वेक-वर्ड डिटेक्शन (MFCC फ़ीचर एक्सट्रैक्शन प्लस एक ONNX वर्गीकारक, Mycroft Precise मॉडलों के साथ संगत) को JavaScript में पोर्ट करता है, दोनों बिना किसी सर्वर के:
import { loadVoice, synthesizeWav } from "phoonnx";
import { getVoice } from "phoonnx/voices";
const voice = await loadVoice(getVoice("phoonnx_eu-ES_dii_unicode")!);
const blob = await synthesizeWav(voice, "Kaixo mundua!");
audiosronnx (18 प्रकाशित मॉडल) और voiceclonnx (10 प्रकाशित मॉडल) के लिए वेट्स TigreGótico Hugging Face संगठन पर अलग डाउनलोड के रूप में रहते हैं, पहले उपयोग पर लाए जाते हैं और लोकली कैश किए जाते हैं, इसलिए एक अलग इंजन चुनना एक कॉन्फ़िग बदलाव है, फिर से परिनियोजन नहीं।
लूप बंद करना: इंजनों को आँकना, अनुमान लगाना नहीं
एक API के पीछे कई इंजन पंजीकृत करना तभी फ़ायदेमंद होता है जब आप बता सकें कि आपके इनपुट के लिए कौन-सा असल में बेहतर है। यही speechonnxmetrics के लिए है: वही numpy + onnxruntime बाधा पर बनी एक मेट्रिक्स लाइब्रेरी, ताकि किसी मॉडल को स्कोर करने में इंस्टॉल करने के लिए कुछ भी अतिरिक्त न लगे।
यह मेट्रिक्स को तीन तरह में समूहित करती है। संदर्भ-रहित MOS अनुमानक — UTMOS, DNSMOS, NISQA, SIGMOS — एक Mean Opinion Score का पूर्वानुमान लगाते हैं, वह 1-से-5 स्वाभाविकता रेटिंग जो एक मानव श्रोता पैनल किसी क्लिप को देता, बिना तुलना करने के लिए किसी साफ़ संदर्भ की ज़रूरत के। Intrusive मेट्रिक्स — STOI (short-time objective intelligibility), SI-SDR (scale-invariant signal-to-distortion ratio), MCD (mel-cepstral distortion) — एक मेल खाते साफ़ संदर्भ की ज़रूरत रखती हैं और मापती हैं कि आउटपुट उससे कितना क़रीब है। ASR-आधारित टेक्स्ट मेट्रिक्स — WER (word error rate) और CER (character error rate) — आउटपुट पर एक स्पीच रिकग्नाइज़र चलाते हैं और ट्रांसक्रिप्ट की तुलना अपेक्षित टेक्स्ट से करते हैं, ऐसे मामलों को पकड़ते हुए जहाँ कोई मॉडल ऐसा ऑडियो बनाता है जो सुनने में ठीक लगता है पर ग़लत शब्द कहता है।
import speechonnxmetrics as s
print(s.score("degraded.wav", ["utmos"]))
# -> {'utmos': 4.41...}
print(s.score("clone_output.wav", ["stoi", "mcd", "si_sdr"], ref="source.wav"))
# -> {'stoi': 0.662..., 'mcd': 10.459..., 'si_sdr': -26.937...}
यह इंजन चुनाव को एक सुनने के परीक्षण से एक तालिका में बदल देता है। voiceclonnx अपने दस क्लोनिंग इंजनों के लिए ठीक वही तुलना प्रकाशित करता है — स्रोत ट्रांसक्रिप्ट के विरुद्ध WER प्लस हर एक के लिए एक अलग स्पीकर-समानता स्कोर, ताकि “facodec 0% WER देता है” या “lscodec मज़बूत timbre ट्रांसफ़र के लिए WER से समझौता करता है” जैसे दावे मापे गए हों, प्रभाव न हों। इसे भाषाओं और रिकॉर्डिंग स्थितियों में गुणा करें और मैनुअल तुलना यथार्थवादी नहीं रह जाती; एक निष्पक्ष मेट्रिक ही वह चीज़ है जो दस-इंजन रजिस्ट्री को अभिभूत करने वाला नहीं बल्कि उपयोगी बनाती है।
यह कहाँ उपयोगी है
अगर आपको ऑफ़लाइन स्पीच प्रोसेसिंग चाहिए — किसी रिकॉर्डिंग को साफ़ करना, किसी आवाज़ को क्लोन करना, यह पता लगाना कि कौन बोल रहा है, या किसी को संश्लेषित करना — ऐसे हार्डवेयर पर जो कभी कोई GPU नहीं देखेगा, यही वह आकार है जिसे देखना चाहिए: एक छोटी रनटाइम निर्भरता, एक तय डिफ़ॉल्ट के बजाय प्रकाशित मॉडलों का एक चुनाव, और यह मापने का एक तरीक़ा कि आपके मामले के लिए असल में कौन-सा काम करता है। ऊपर की हर लाइब्रेरी एक pip install दूर है, कोड स्तर पर MIT- या Apache-लाइसेंस प्राप्त (व्यक्तिगत मॉडल वेट्स अपने-अपने अपस्ट्रीम लाइसेंस रखते हैं, प्रति इंजन दस्तावेज़ीकृत), और लैपटॉप, सर्वर, या Raspberry Pi पर एक जैसी चलती है।
/hi/contact के ज़रिए संपर्क करें या देखें हम और क्या बनाते हैं /hi/services पर।