# 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](https://dev.hume.ai/docs/speech-to-speech-evi/quickstart/typescript) to build a client-side component that connects to EVI from the browser.

## Steps
1. [**Environment setup**](https://dev.hume.ai/docs/speech-to-speech-evi/quickstart/python#env-setup): Download package and system dependencies to run EVI.
2. [**Import statements and helpers**](https://dev.hume.ai/docs/speech-to-speech-evi/quickstart/python#import-statements-and-helpers): Import needed symbols and define helper functions.
3. [**Authentication**](https://dev.hume.ai/docs/speech-to-speech-evi/quickstart/python#authentication): Use your API credentials to authenticate your EVI application.
4. [**Connection**](https://dev.hume.ai/docs/speech-to-speech-evi/quickstart/python#connection): Set up a secure WebSocket connection to interact with EVI.
5. [**Handling incoming messages**](https://dev.hume.ai/docs/speech-to-speech-evi/quickstart/python#incoming-messages): Process incoming chat events.
6. [**Audio input**](https://dev.hume.ai/docs/speech-to-speech-evi/quickstart/python#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](https://python-sounddevice.readthedocs.io/en/0.5.1/installation.html) library for audio recording and playback, which relies on the [PortAudio C Library](https://www.portaudio.com/) 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

```bash
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**

```python
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](https://app.hume.ai/keys) and [obtain an API key](https://dev.hume.ai/docs/introduction/api-key). Store it as `HUME_API_KEY` inside your project’s `.env` file.

**quickstart.py**

```python
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**

```python
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**

```python
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**

```python
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**

```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**

```python
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**

```python
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](https://dev.hume.ai/docs/speech-to-speech-evi/configuration/build-a-configuration)  
2. [Chat History](https://dev.hume.ai/docs/speech-to-speech-evi/features/chat-history)  
3. [API Reference](https://dev.hume.ai/reference/speech-to-speech-evi/chat)  
4. [Hume API Examples](https://github.com/HumeAI/hume-api-examples/tree/main/evi) on GitHub.
