1 คะแนน โดย GN⁺ 2024-09-20 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Moshi เป็นโมเดลพื้นฐานแบบ speech-text สำหรับการสนทนาด้วยเสียงแบบเรียลไทม์ และเป็นเฟรมเวิร์กสนทนาด้วยเสียงแบบ full-duplex โดยมีทั้งไลฟ์เดโมและโมเดลบน Hugging Face
  • ใน repository แยก inference stack ไว้เป็น PyTorch สำหรับงานวิจัยและการทดลอง, MLX สำหรับการอนุมานบนอุปกรณ์ iPhone/Mac และ Rust สำหรับ production
  • โมเดลจัดการ สตรีมเสียงสองสตรีม ได้แก่ เสียงพูดของ Moshi และเสียงพูดของผู้ใช้ พร้อมทั้งคาดการณ์ inner monologue ซึ่งเป็นโทเคนข้อความที่สอดคล้องกับเสียงพูดของ Moshi เอง เพื่อยกระดับคุณภาพการสร้างผลลัพธ์
  • โคเดก Mimi ประมวลผลเสียง 24kHz แบบสตรีมมิงเป็นตัวแทนความถี่ 12.5Hz และแบนด์วิดท์ 1.1kbps มีความหน่วงของเฟรม 80ms โดยความหน่วงเชิงทฤษฎีของ Moshi อยู่ที่ 160ms และความหน่วงรวมที่วัดได้จริงบน L4 GPU ต่ำสุด 200ms
  • โมเดลที่เปิดเผยประกอบด้วยเสียงสังเคราะห์ชาย Moshiko, เสียงสังเคราะห์หญิง Moshika และโคเดกเสียง Mimi โดยน้ำหนักโมเดลเผยแพร่ภายใต้ CC-BY 4.0, โค้ด Python และเว็บไคลเอนต์ภายใต้ MIT, และแบ็กเอนด์ Rust ภายใต้ไลเซนส์ Apache

เป้าหมายและองค์ประกอบของ Moshi

  • Moshi เป็น speech-text foundation model และเฟรมเวิร์ก full-duplex สำหรับการสนทนาด้วยเสียงแบบเรียลไทม์
  • ไลฟ์เดโมมีให้ที่ moshi.chat และคอลเลกชันโมเดลเผยแพร่บน Hugging Face
  • repository มี inference stack 3 แบบ
    • PyTorch: สำหรับงานวิจัยและการทดลอง อยู่ในไดเรกทอรี moshi/
    • MLX: สำหรับการอนุมานบนอุปกรณ์ iPhone และ Mac อยู่ในไดเรกทอรี moshi_mlx/
    • Rust: สำหรับ production อยู่ในไดเรกทอรี rust/
      • รวม implementation ของ Mimi บน Rust และ Python binding rustymimi
  • โค้ดเว็บ UI ไคลเอนต์ที่ใช้ในเดโม Moshi อยู่ในไดเรกทอรี client/
  • การ fine-tuning Moshi จัดการใน repository แยก kyutai-labs/moshi-finetune

โมเดล Kyutai ที่เกี่ยวข้อง

  • โค้ดเบส Moshi ยังใช้รันโมเดลที่เกี่ยวข้องของ Kyutai ซึ่งใช้ multi-stream architecture คล้ายกับ Moshi

สถาปัตยกรรมโมเดล

  • Moshi โมเดล สตรีมเสียงสองสตรีม
    • สตรีมหนึ่งคือสตรีมที่ Moshi พูด
    • อีกสตรีมคือสตรีมที่ผู้ใช้พูด
  • นอกจากสตรีมเสียงทั้งสองแล้ว Moshi ยังทำนาย inner monologue ซึ่งเป็นโทเคนข้อความที่สอดคล้องกับเสียงพูดของตนเอง และวิธีนี้ช่วยปรับปรุงคุณภาพการสร้างผลลัพธ์ได้อย่างมาก
  • Depth Transformer ขนาดเล็กใช้โมเดล dependency ระหว่าง codebook ใน time step เฉพาะ
  • Temporal Transformer ขนาดใหญ่ระดับ 7B พารามิเตอร์ ใช้โมเดล dependency ตามเวลา
  • ความหน่วงเชิงทฤษฎีอยู่ที่ 160ms
    • ขนาดเฟรม Mimi 80ms
    • ความหน่วงด้านอะคูสติก 80ms
  • ความหน่วงรวมในทางปฏิบัติบน L4 GPU ต่ำสุดอยู่ที่ 200ms

โคเดกเสียง Mimi

  • Mimi เป็นโคเดกเสียงแบบ neural network ที่ลดเสียง 24kHz ลงเป็นตัวแทนความถี่ 12.5Hz
  • Mimi ทำงานแบบสตรีมมิงเต็มรูปแบบ มีแบนด์วิดท์ 1.1kbps และความหน่วงเท่ากับขนาดเฟรมคือ 80ms
  • ตาม README ระบุว่า Mimi มีประสิทธิภาพดีกว่าโคเดกเดิมที่ไม่ใช่แบบสตรีมมิง
  • Mimi อ้างอิงจากโคเดกเสียง neural network รุ่นก่อนหน้าอย่าง SoundStream และ EnCodec
    • เพิ่ม Transformer ทั้งฝั่ง encoder และ decoder
    • ปรับ stride เพื่อให้ frame rate รวมอยู่ที่ 12.5Hz
  • frame rate 12.5Hz ใกล้เคียงกับ frame rate เฉลี่ยของโทเคนข้อความประมาณ 3~4Hz มากขึ้น และช่วยลดจำนวนขั้นตอน autoregressive ของ Moshi
  • คล้ายกับ SpeechTokenizer, Mimi ใช้ distillation loss เพื่อให้โทเคน codebook ตัวแรกสอดคล้องกับตัวแทนแบบ self-supervised ของ WavLM
  • เช่นเดียวกับ EBEN, Mimi ใช้ เฉพาะ adversarial training loss ร่วมกับ feature matching และช่วยปรับปรุงคุณภาพเชิงอัตวิสัยได้อย่างชัดเจนแม้ใน bitrate ต่ำ

โมเดลที่เผยแพร่และรูปแบบ

ข้อกำหนดและข้อจำกัดในการติดตั้ง

  • ต้องใช้ Python อย่างน้อย 3.10 และแนะนำ 3.12
  • PyTorch และ MLX client ติดตั้งได้จาก PyPI
pip install -U moshi
pip install -U moshi_mlx
pip install rustymimi
  • หากไม่ใช่ Python 3.12 อาจเกิดข้อผิดพลาดระหว่างติดตั้ง moshi_mlx หรือ dependency อย่าง rustymimi ซึ่งในกรณีนี้ต้องติดตั้ง Rust toolchain หรือเปลี่ยนไปใช้ Python 3.12
  • คาดว่าจะทำงานบน Windows ได้ แต่ไม่มีการสนับสนุนอย่างเป็นทางการ
  • เวอร์ชัน MLX ทดสอบบน MacBook Pro M3
  • เวอร์ชัน PyTorch ปัจจุบันยังไม่รองรับ quantization จึงต้องใช้หน่วยความจำ GPU ค่อนข้างมากระดับ 24GB
  • แบ็กเอนด์ Rust ต้องใช้ Rust toolchain เวอร์ชันล่าสุด
  • หากต้องการคอมไพล์การรองรับ GPU ต้องมี CUDA ที่ตรงกับ GPU และ nvcc

วิธีรัน

  • PyTorch

    • PyTorch API อยู่ในไดเรกทอรี moshi และให้ เวอร์ชันสตรีมมิง ของ Mimi audio tokenizer และ Moshi language model
    • โหมดโต้ตอบต้องรัน model server ก่อน แล้วใช้เว็บ UI หรือ command-line client
    python -m moshi.server [--gradio-tunnel] [--hf-repo kyutai/moshika-pytorch-bf16]
    
    • โดยค่าเริ่มต้น เว็บ UI เข้าถึงได้ที่ localhost:8998
    • หากเข้าถึง GPU บนเครื่องรีโมตผ่าน HTTP การใช้ไมโครโฟนอาจถูกบล็อกโดยนโยบายความปลอดภัยของเบราว์เซอร์
    • สามารถใช้ SSH -L เพื่อ forward พอร์ต 8998 ของเครื่องรีโมตมายัง localhost ได้
    • ใช้ --gradio-tunnel เพื่อสร้าง tunnel ที่เข้าถึงได้จากทุกที่
    • tunnel นี้วิ่งผ่านสหรัฐฯ และเมื่ออ้างอิงจากยุโรปอาจเพิ่มความหน่วงสูงสุดถึง 500ms
    • ใช้ --gradio-tunnel-token เพื่อตั้ง secret token แบบคงที่และ reuse ที่อยู่เดิมได้
    • ใช้ --hf-repo เพื่อเลือกโมเดล pre-trained อื่นบน Hugging Face ได้
    • มี command-line client ให้ใช้ด้วย แต่ต่างจากเว็บเบราว์เซอร์ตรงที่ไม่มี echo cancellation และไม่ข้ามเฟรมเพื่อชดเชย latency ที่สะสม
    python -m moshi.client [--url URL_TO_GRADIO]
    
  • MLX

    • หลังติดตั้ง moshi_mlx แล้ว สามารถรันการอนุมานแบบ local บน macOS ได้
    python -m moshi_mlx.local -q 4
    python -m moshi_mlx.local -q 8
    python -m moshi_mlx.local -q 4 --hf-repo kyutai/moshika-mlx-q4
    python -m moshi_mlx.local -q 8 --hf-repo kyutai/moshika-mlx-q8
    
    • flag -q และ --hf-repo ต้องสอดคล้องกันเสมอ
    • command-line interface ของ MLX ก็เป็นแบบ barebone และไม่มี echo cancellation หรือการชดเชย latency ที่สะสม
    • สามารถรันเว็บ UI ด้วย python -m moshi_mlx.local_web และ HTTP connection ให้บริการที่ localhost:8998
  • Rust

    • inference server ของ Rust รันจากไดเรกทอรี rust
    cargo run --features cuda --bin moshi-backend -r -- --config moshi-backend/config.json standalone
    
    • บน macOS สามารถใช้ --features metal แทน --features cuda ได้
    • หากใช้ config-q8.json แทน config.json จะใช้ โมเดล quantization q8 ได้
    • เลือกโมเดล pre-trained อื่นได้โดยเปลี่ยนคีย์ "hf_repo" ในไฟล์ config
    • เมื่อ server แสดงผล standalone worker listening ก็สามารถใช้เว็บ UI ได้
    • Rust server ใช้ HTTPS เป็นค่าเริ่มต้น จึงเข้าถึงได้ที่ https://localhost:8998
    • ในเบราว์เซอร์อาจมีคำเตือนว่าเป็นไซต์ไม่ปลอดภัย และใน Chrome สามารถกด “Details” หรือ “Advanced” เพื่อเข้าถึง localhost ต่อได้

ไคลเอนต์และการพัฒนา

  • แนะนำให้ใช้เว็บ UI เพราะมี echo cancellation ซึ่งช่วยคุณภาพโดยรวมของโมเดล
  • คำสั่งส่วนใหญ่จะ serve เว็บ UI โดยตรงจาก URL ที่ให้มา
  • มี command-line interface สำหรับ Rust และ Python ด้วย และใช้ protocol เดียวกับเว็บ UI จึงไม่ต้องแก้ไขฝั่ง server
  • การ build เว็บ UI ทำในไดเรกทอรี client
cd client
npm install
npm run build
  • Rust command-line client รันจากไดเรกทอรี rust
cargo run --bin moshi-cli -r -- tui --host localhost
  • Python PyTorch client รันด้วยคำสั่งต่อไปนี้
python -m moshi.client
  • เดโม Gradio รันหลังติดตั้ง gradio-webrtc>=0.0.18
python -m moshi.client_gradio --url <moshi-server-url>
docker compose up

ไลเซนส์และการอ้างอิง

  • โค้ดส่วน Python เผยแพร่ภายใต้ไลเซนส์ MIT
  • แบ็กเอนด์ Rust เผยแพร่ภายใต้ไลเซนส์ Apache
  • โค้ดเว็บไคลเอนต์เผยแพร่ภายใต้ไลเซนส์ MIT
  • โค้ดบางส่วนอ้างอิงจาก AudioCraft ซึ่งใช้ไลเซนส์ MIT
  • น้ำหนักโมเดลเผยแพร่ภายใต้ไลเซนส์ CC-BY 4.0
  • หากใช้ Mimi หรือ Moshi ขอให้อ้างอิงบทความ Moshi: a speech-text foundation model for real-time dialogue

1 ความคิดเห็น

 
GN⁺ 2024-09-20
ความคิดเห็นบน Hacker News
  • ความเห็นที่นี่แทบทั้งหมดเป็นเชิงลบ เลยขอฝากฟีดแบ็กไว้ว่า latency ดีมาก ดีจนรู้สึกเหมือนมันขัดจังหวะพูดอยู่บ่อย ๆ ด้วยซ้ำ
    ในฐานะโมเดลโอเพนซอร์ส ถือว่าเป็นความสำเร็จครั้งใหญ่ แต่ช่วงนี้ผู้คนคุ้นเคยกับโมเดลภาษาขนาดใหญ่ที่เก่งมาก ๆ กันแล้ว และคุณภาพเนื้อหาคำตอบของโมเดลนี้ยังห่างจากโมเดลระดับแนวหน้าในปัจจุบันมาก ให้ความรู้สึกใกล้เคียงกับโมเดลภาษาขนาดใหญ่ที่เคยเห็นราวปี 2019 มากกว่า ดังนั้นฝั่งเสียงน่าจะมาถึงระดับ “ดีพอ” แล้ว และต่อจากนี้ควรไปโฟกัสที่ คุณภาพคำตอบ จะดีกว่า

    • เห็นด้วยเต็มที่ latency ก็ดี เทคโนโลยีก็เจ๋ง Rust และการรันบน edge ของแล็ปท็อปสำหรับผู้บริโภคก็น่าประทับใจ
      คำถามที่เกิดขึ้นตามธรรมชาติคือ มีวิธีนำ “โมเดลภาษาขนาดใหญ่ที่ดีกว่า” มาใช้โดยไม่ทำลายประสบการณ์ของ Moshi ได้หรือไม่
  • Moshi เป็น CC-BY และยังมีโมเดลสนทนาเรียลไทม์แบบเสียง-ข้อความขนาดใกล้เคียง 7B ที่เพิ่งเปิดเผยภายใต้ Apache v2 ด้วย: https://tincans.ai/slm3 / https://huggingface.co/collections/tincans-ai/gazelle-v02-65...

    • ความแตกต่างสำคัญคือ tincans ไม่ใช่โมเดล speech-to-speech แต่ใช้โมเดลตรวจจับการพูด/หยุดพูดแยกต่างหาก และมีขั้นตอนสุดท้ายเป็น text-to-speech
  • ช่วงหลังมีการพัฒนาด้าน โมเดลภาษาที่รองรับเสียง มากขึ้น เช่น https://github.com/ictnlp/LLaMA-Omni, https://github.com/gpt-omni/mini-omni

  • เซิร์ฟเวอร์ inference ของพวกเขาเขียนด้วย Rust โดยใช้ crate Candle ของ huggingface หนึ่งในผู้เขียน Moshi ก็เป็นผู้เขียนหลักของ Candle ด้วย
    เราก็กำลังสร้าง inference stack บน Candle อยู่ และใช้งานได้ค่อนข้างน่าพอใจ

    • สนใจมาก มีอะไรที่เทียบได้กับ vLLM ไหม? อยากรู้ว่าต้องเขียนพวก batch processing หรือ paged attention ใหม่เองหรือเปล่า
  • ระหว่างหาเดโมบน YouTube ไปเจอวิดีโอตลก ๆ จากไม่กี่เดือนก่อน: https://youtu.be/coroLWOS7II?si=TeVghP_Zi0P9exQh
    ตอนนี้น่าจะปรับปรุงขึ้นแล้วแน่นอน :-)

  • น่าสนใจดี ชอบที่ตรงนี้โฟกัสเรื่อง latency และอ้างว่าบน GPU แบบโลคัลทำได้จริงราว 200ms
    เพราะอิงกับโมเดล Transformer 7B ก็คงไม่ได้ฉลาดมากนัก ถ้าจินตนาการว่า latency ของโมเดล 70B อยู่ราว 1 วินาที ก็ดูเป็นไปได้ที่จะมี สถาปัตยกรรมระบบ ที่ให้การตอบสนองคั่นกลางเพื่อบอกเป็นคำพูดว่า “โมเดลกำลังพูดอยู่ตอนนี้” ใช้โมเดลระดับ 7B/Phi-3 ให้คำตอบเริ่มต้นเร็ว ๆ แล้วค่อยส่งต่อไปยังโมเดลใหญ่กว่า โมเดล Phi-3 อาจรับหน้าที่ปรับแต่ง เช่น รับคำตอบที่ถูกต้องจริง ๆ แล้วถ้าจำเป็นก็ขอโทษและแก้ไขให้ถูก
    จากประสบการณ์ส่วนตัว ผมคิดว่าสมองคนเราหลายครั้งก็ทำงานแบบนี้เหมือนกัน คือโต้ตอบเร็ว แล้วอีก 1–2 วินาทีค่อยแก้หรือเสริม แน่นอนว่าก็มีคนที่ไม่แก้เลยเหมือนกัน หรือคนที่หยุดคิดนานแล้วค่อยให้คำตอบที่ไตร่ตรองมาดีครบถ้วน

  • ลองใช้แล้ว ใส่อีเมลอะไรก็ได้ มันตอบทันที แทบจะทันควัน แม้เรายังพูดไม่จบก็ตาม
    แต่นั่นดูเหมือนเป็นแค่ ประโยคเติมช่องว่าง และอาจเป็นคำตอบที่ cache ไว้ คำตอบต่อสิ่งที่ถามจริง ๆ จะออกมาทีหลังมาก และต้องไม่ให้มันหลุดเข้า loop ระหว่างนั้น

    • ผมเคยลองเดโมนี้ตอนเปิดตัวใหม่ ๆ และวันนี้กลับมาลองอีกครั้ง ไม่ได้จะลากไปทางเดียวกับกรณี Reflection 70B แต่ดูเหมือนว่า weights ที่อัปโหลดจะไม่ใช่ชุดเดียวกับที่โชว์ในเดโมเดิมเดือนกรกฎาคม: https://the-decoder.com/french-ai-lab-kyutai-unveils-convers...
  • ผมกำลังทำโซลูชันเสียงเรียลไทม์ → โมเดลภาษาขนาดใหญ่ → เอาต์พุตเสียง และคิดว่าส่วนที่น่าสนใจที่สุดตรงนี้คือ neural audio codec แบบสตรีมมิง เพราะในทางปฏิบัติทำ speech-to-text แบบสตรีมมิงให้ดีด้วย Whisper ได้ยาก
    แต่จากมุมมองผลิตภัณฑ์ ผมไม่แน่ใจว่าอยากป้อนสิ่งนั้นเข้าโมเดลภาษาขนาดใหญ่โดยตรงเพื่อให้ตอบเลย ในหลาย use case ผมคิดว่าต้องมีขั้นตอน tool/function calling ก่อนตอบเสมอ ถ้ามีใครทำงานในทิศทางนี้ ผมยินดีคุยได้ทุกเมื่อ
    tincans ที่มีคนพูดถึงด้านล่างก็ดูยอดเยี่ยม แต่เห็นว่าการพัฒนา tincans จบลงแล้ว ดังนั้นทิศทางนี้ยังมีพื้นที่ให้ทำต่ออีก 10000% ถ้า Chris อ่านอยู่ ผมอยากอธิบาย use case ด้านผลิตภัณฑ์/ธุรกิจที่สิ่งนี้แก้ได้จริง ๆ ไม่ว่าโมเดลภาษาขนาดใหญ่จะเก่งขึ้นแค่ไหนก็ตาม

    • ผมก็กำลังทดลอง flow นี้อยู่ ใช้การตั้งค่า “สตรีมมิง” ที่ตัด sample ด้วย Whisper แล้วเริ่มถอดเสียงแม้ผู้ใช้ยังพูดอยู่ จากนั้นป้อนผลลัพธ์เข้า Mistral 8B ให้เป็นตัวกลางสนทนาที่เดินตาม IVR tree ที่กำหนดไว้ล่วงหน้าและเรียกใช้ tool
      โมเดลภาษาขนาดใหญ่ไม่ได้ตอบเองโดยตรง แค่เลือก node ใน tree ที่มีเอาต์พุต text-to-speech เตรียมไว้แล้ว มีพารามิเตอร์ “ความยาวช่วงหยุด” เพื่อ判断ว่าผู้ใช้พูดจบหรือยัง แล้วจึงส่งผลถอดเสียงให้โมเดล ซึ่งไม่ได้ซับซ้อนเป็นพิเศษ ผมยังคิดต่ออยู่เรื่อย ๆ ว่าจะจัดการอินพุตเสียงให้ถูกต้องได้อย่างไร หรือจะควบคุมโมเดลให้แม่นพอจนตัด IVR tree ออกได้ด้วยการจัด prompt อย่างเดียวหรือไม่ ตอนนี้ก็ทำงานได้ค่อนข้างดีแล้ว แต่ยังมีพื้นที่ให้ปรับปรุงอีกมาก
    • ประเด็นที่ว่าต้องมีขั้นตอน tool/function calling ก่อนตอบนั้น ผมเคยทำไว้เกือบตรงเป๊ะเมื่อ 1 ปีก่อน :) ใช้ได้โอเค แต่ยังไม่เร็วพอ เลยทำให้ต้องสร้าง โมเดลแบบผสาน ขึ้นมา
  • ความเร็วในการตอบสนอง น่าประทับใจ แต่ “คุณภาพ” ของคำตอบไม่ใช่แบบนั้น บันทึกบทสนทนาของการทดสอบครั้งที่สองเป็นแบบนี้
    Moshi: “สวัสดีครับ มีอะไรเหรอ?”
    ผม: “ตอนนี้ปีอะไร?”
    Moshi: “อ้อ ปี 2019 ครับ น่าจะประมาณหนึ่งปีก่อนมั้งครับ”
    ผม: “แน่ใจเหรอว่าเป็นปี 2019?”
    Moshi: “อ้อ ครับ แน่ใจครับ ต้องเป็นปี 2019 แน่นอน ตัวเลขนั้นเอาไว้สำหรับอันสุดท้ายครับ”
    ผม: “COVID-19 คืออะไร?”
    Moshi: “มันเป็นโรคหายากครับ เกิดจากระบบภูมิคุ้มกันที่ทำงานมากเกินไปซึ่งโจมตีผิวหนังครับ”
    ถึงจุดนี้มันก็ไม่ตอบอีกแล้ว

  • Moshi เป็นโมเดลที่สนุกที่สุดเท่าที่เคยมีมา ประสบการณ์ล่าสุดอยู่ที่นี่: https://x.com/tommoor/status/1809051817860354471
    แต่อย่าคาดหวังเรื่อง ความถูกต้อง จะดีกว่า