EVI Python Quickstart | Hume API

Using Hume's Python SDK to Integrate with EVI

In this guide, you’ll learn how to use Hume’s Python SDK to integrate with EVI, for applications like command-line or desktop applications.

Use the Python SDK for Client-Side Applications

Use the Python SDK for client-side applications like CLIs and desktop apps that run directly on the user’s machine.

For Hosted Environments

For hosted environments (e.g., Streamlit, Gradio, or backend servers), Python won’t be able to access the user’s audio devices. In these cases, use our TypeScript quickstart to build a client-side component that connects to EVI from the browser.

Steps

  1. Environment setup: Download package and system dependencies to run EVI.
  2. Import statements and helpers: Import needed symbols and define helper functions.
  3. Authentication: Use your API credentials to authenticate your EVI application.
  4. Connection: Set up a secure WebSocket connection to interact with EVI.
  5. Handling incoming messages: Process incoming chat events.
  6. Audio input: Capture audio data from an input device and send to EVI.

Environment Setup

This guide uses the Hume SDK Python package hume with the [microphone] package extra. You can install this with uv (recommended), poetry, or pip. It also uses the python-dotenv package for loading environment variables from an .env file.

System Dependencies

The Hume Python SDK uses the sounddevice library for audio recording and playback, which relies on the PortAudio C Library to be installed on your system. On macOS and Windows, PortAudio is typically included with the sounddevice package. However, on Linux, you will need to manually install PortAudio correctly for your distribution.

Installation on Debian-based Linux Systems

sudo apt-get --yes update
sudo apt-get --yes install libasound2-dev libportaudio2

Import Statements and Helpers

First, we import needed symbols from the Python standard library and define some helpers.

quickstart.py

import asyncio
import datetime
import os
from dotenv import load_dotenv
from hume import MicrophoneInterface, Stream
from hume.client import AsyncHumeClient
from hume.empathic_voice.types import SubscribeEvent

def extract_top_n_emotions(emotion_scores: dict, n: int) -> dict:
    sorted_emotions = sorted(emotion_scores.items(), key=lambda item: item[1], reverse=True)
    top_n_emotions = {emotion: score for emotion, score in sorted_emotions[:n]}
    return top_n_emotions

def print_emotions(emotion_scores: dict) -> None:
    print(' | '.join([f"{emotion} ({score:.2f})" for emotion, score in emotion_scores.items()]))

def log(text: str) -> None:
    now = datetime.datetime.now(tz=datetime.timezone.utc).strftime("%H:%M:%S")
    print(f"[{now}] {text}")

Authentication

Log into your Hume AI Account and obtain an API key. Store it as HUME_API_KEY inside your project’s .env file.

quickstart.py

async def main() -> None:
    load_dotenv()
    HUME_API_KEY = os.getenv("HUME_API_KEY")
    HUME_CONFIG_ID = os.getenv("HUME_CONFIG_ID")
    client = AsyncHumeClient(api_key=HUME_API_KEY)
    ...

Connection

To connect to an EVI chat, use client.empathic_voice.chat.connect(...) with connection arguments passed directly.

quickstart.py

async def main() -> None:
    ...
    async def on_message(message: SubscribeEvent):
        ...
    async with client.empathic_voice.chat.connect(
        config_id=HUME_CONFIG_ID
    ) as socket:
        print("WebSocket connection opened.")
        async for message in socket:
            await on_message(message)

Handling Incoming Messages

Iterate over messages from the socket and pass each one to your on_message handler.

quickstart.py

async def main() -> None:
    ...
    async def on_message(message: SubscribeEvent):
        if message.type == "chat_metadata":
            log(
                f"<{message.type}> Chat ID: {message.chat_id}, Chat Group ID: {message.chat_group_id}"
            )
        elif message.type == "user_message":
            if getattr(message, "interim", False):
                return
            log(f"{message.message.role}: {message.message.content}")
            print_emotions(
                extract_top_n_emotions(dict(message.models.prosody and message.models.prosody.scores or {}), 3)
            )
        elif message.type == "error":
            raise RuntimeError(
                f"Received error message from Hume websocket ({message.code}): {message.message}"
            )
        else:
            return
    ...

Audio Input

The Hume SDK provides MicrophoneInterface.start(...), which handles microphone capture and streaming recorded audio through the WebSocket to EVI.

Pass the chat socket provided by connect(...) to use MicrophoneInterface.start:

quickstart.py

async def main() -> None:
    ...
    stream = Stream.new()
    ...
    async with client.empathic_voice.chat.connect(
        config_id=HUME_CONFIG_ID
    ) as socket:
        await MicrophoneInterface.start(
            socket,
            allow_user_interrupt=False,
            byte_stream=stream
        )

Specify a Microphone Device

To specify a specific audio input device, you can pass it via the optional device parameter in MicrophoneInterface.start.

Python

# Specify device 4 in MicrophoneInterface
await MicrophoneInterface.start(
  socket,
  device=4,
  allow_user_interrupt=False,
  byte_stream=stream
)

Interruption

The allow_user_interrupt parameter controls whether the user can send a message while the assistant is speaking:

Allowing an Interrupt

await MicrophoneInterface.start(
  socket,
  allow_user_interrupt=True,
  byte_stream=stream
)

Put It All Together

Finally, add the following code at the end of your script to run the main function:

quickstart.py

if __name__ == "__main__":
    asyncio.run(main())

Next Steps

Congratulations! You’ve successfully implemented a real-time conversational application using Hume’s Empathic Voice Interface (EVI).

Next, consider exploring these areas to enhance your EVI application:

  1. Configure EVI
  2. Chat History
  3. API Reference
  4. Hume API Examples on GitHub.