QuiLLMan Documentation

repository·main·Indexed 22 days ago

https://github.com/modal-labs/quillman

A voice chat application using Kyutai Lab's Moshi speech-to-speech model, designed for low-latency bidirectional audio streaming. Built with a React frontend and a FastAPI backend deployed serverlessly on Modal, it utilizes WebSockets and the Opus audio codec to enable real-time, human-like speech interaction.

Tokens
2.9K
Snippets
9
Records
17
Agent score
79%

What's inside QuiLLMan

  1. Overview of QuiLLMan

    main

    QuiLLMan is a voice chat application powered by Kyutai Lab's Moshi speech-to-speech language model. It utilizes bidirectional websocket streaming and the Opus audio codec to achieve low-latency, human-like speech interaction.

    Key components include:

    • Moshi Model: Continuously listens, plans, and responds.
    • Mimi: A streaming encoder/decoder for unbroken audio streams.
    • Speech-text foundation model: Determines response timing and content.

    The project architecture consists of a React frontend (served by src/app.py) and a Moshi websocket server (src/moshi.py).

  2. Overview of QuiLLMan: Voice Chat with Moshi

    main
    QuiLLMan is a complete voice chat application built on Modal that enables real-time, speech-to-speech interaction. It uses Kyutai Lab's Moshi model, which bundles speech-to-text, text-to-text, and text-to-speech into a single model to minimize latency. The application uses bidirectional websocket streaming and Opus audio compression to achieve near-instantaneous response times. The entire stack—including the React frontend and the Moshi model backend—is deployed serverlessly on Modal.
  3. How Moshi handles statefulness and streaming on Modal

    main

    Because the Moshi model is stateful (it maintains conversation context), QuiLLMan ensures user isolation by spinning up a unique GPU per concurrent user session. This is achieved using Modal's @app.cls configuration.

    To handle the continuous stream of audio data, the application uses FastAPI's bidirectional websockets. A FastAPI app is attached to a Modal class method using @modal.asgi_app(), allowing a prewarmed Moshi model to be coupled directly to a websocket session. This enables asynchronous loops to simultaneously receive audio bytes from the client and send inference output back to the user.

    @app.cls(
        image=image,
        gpu="A10G",
        scaledown_window=300,
        ...
    )
    class Moshi:
        # ...
    
        @modal.asgi_app()
        def web(self):
            from fastapi import FastAPI, Response, WebSocket, WebSocketDisconnect
    
            web_app = FastAPI()
            @web_app.websocket("/ws")
            async def websocket(ws: WebSocket):
                with torch.no_grad():
                    await ws.accept()
    
                    # handle user session
    
                    # spawn loops for async IO
                    async def recv_loop():
                        while True:
                            data = await ws.receive_bytes()
                            # send data into inference stream...
    
                    async def send_loop():
                        while True:
                            await asyncio.sleep(0.001)
                            msg = self.opus_stream_outbound.read_bytes()
                            # send inference output to user ...
  4. Understand the QuiLLMan frontend architecture

    main

    The QuiLLMan frontend is a React application that facilitates real-time voice interaction with the Moshi model. It manages three primary data flows:

    1. Audio Input: Captures microphone audio using an Opus recorder, encoding it at 24000 Hz to match the model's requirements, and streaming it via WebSocket.
    2. Audio Output: Receives Opus-encoded audio chunks via WebSocket, decodes them to PCM using OggOpusDecoder, and schedules them for seamless, gapless playback using the Web Audio API.
    3. Text Output: Receives text fragments via WebSocket, reconstructs sentences based on punctuation ('.', '!', '?'), and displays them in a scrolling UI.

    The application relies on a WebSocket connection to a backend endpoint (constructed by replacing -web with -moshi-web in the current hostname) to communicate with the Moshi inference server.

  5. Set up Modal for local development

    main

    Before developing locally, ensure you have the Modal client installed and configured in your Python environment:

    1. Install the Modal client:
      pip install modal
    2. Set up your Modal account:
      modal setup
    3. Generate a new Modal token:
      modal token new
    pip install modal
    modal setup
    modal token new
  6. Develop the Moshi inference module

    main

    The Moshi server is implemented as a modal.Cls module that loads models and maintains streaming state, exposing a websocket interface via FastAPI.

    To run a development server for the Moshi module, use modal serve. This enables hot-reloading, where changes to project files are automatically applied. Use Ctrl+C to stop the server. The terminal output will provide the URL required to establish a websocket connection.

    modal serve -m src.moshi
  7. Develop the HTTP server and frontend

    main

    The HTTP server located at src/app.py is a FastAPI application that serves the React frontend as static files.

    Running the development server for src.app will also automatically start the Moshi websocket server because src/app.py imports src/moshi.py.

    To run the development server:

    modal serve src.app

    Note: If you make changes to the frontend, you may need to clear your browser cache to see them reflected.

  8. Run the React Frontend and Moshi Server in development mode

    main

    To run the full application (including the React frontend and the Moshi websocket server), use the modal serve command pointing to src.app. Because src/app.py imports src/moshi.py, this command serves both the frontend assets and the Moshi websocket endpoint.

    modal serve src.app
  9. Test the Moshi websocket connection via CLI

    main

    You can test the websocket connection directly from the command line using the provided tests/moshi_client.py client. This requires specific development dependencies.

    1. Create and activate a virtual environment:
      python -m venv venv
      source venv/bin/activate
    2. Install development requirements:
      pip install -r requirements/requirements-dev.txt
    3. Run the client:
      python tests/moshi_client.py

    Ensure your microphone and speakers are enabled before starting.

    python -m venv venv
    source venv/bin/activate
    pip install -r requirements/requirements-dev.txt
    python tests/moshi_client.py
  10. Deploy QuiLLMan to Modal

    main

    To deploy both the frontend server and the Moshi websocket server to production, use the modal deploy command.

    Because Modal is serverless, the application scales to zero when not in use, meaning there are no costs incurred while the app is idle.

    modal deploy src.app
  11. Run the Moshi Websocket Server in development mode

    main

    To run a development server specifically for the Moshi module, use the modal serve command pointing to the src.moshi module. The terminal output will provide a URL that you can use to establish a websocket connection for testing.

    modal serve src.moshi
  12. Configure Opus recorder settings

    main

    The application uses an Opus recorder to capture audio. To ensure compatibility with the Moshi model, the following configuration is used:

    • encoderSampleRate: 24000 (matches model sample rate)
    • encoderFrameSize: 80 (milliseconds)
    • encoderApplication: 2049
    • streamPages: true
    • maxFramesPerPage: 1
    • numberOfChannels: 1

    Audio data is sent to the WebSocket via the recorder.ondataavailable event handler.