# `vllm_mlx.models.mllm`

MLX Multimodal Language Model (MLLM) wrapper.

[View the complete module source at #L1-L2944](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1-L2944).

## API details

Each callable below includes its exact signature, type annotations, inputs, defaults, return contract, documented exceptions, implementation source, and parsed docstring sections when the source provides them.

::: vllm_mlx.models.mllm
    options:
      members:
        - logger
        - TempFileManager
        - _temp_manager
        - cleanup_temp_file
        - cleanup_all_temp_files
        - FRAME_FACTOR
        - DEFAULT_FPS
        - MIN_FRAMES
        - MAX_FRAMES
        - IMAGE_FACTOR
        - MAX_IMAGE_SIZE
        - MAX_VIDEO_SIZE
        - MAX_AUDIO_SIZE
        - MAX_BASE64_IMAGE_LENGTH
        - MAX_BASE64_VIDEO_LENGTH
        - MAX_BASE64_AUDIO_LENGTH
        - FileSizeExceededError
        - UnsafeRemoteURLError
        - _normalize_content_part
        - _extract_media_url
        - _text_content_part
        - _append_text_content_part
        - _build_string_mllm_message_content
        - _append_ordered_mllm_content_part
        - _build_ordered_mllm_message_content
        - _normalize_mllm_tool_calls
        - _build_mllm_chat_messages
        - MultimodalInput
        - MLLMOutput
        - load_gemma4_assistant_drafter
        - _DRAFT_KWARG_NAMES
        - _count_draft_tokens
        - _install_draft_metrics_hooks
        - is_base64_image
        - is_url
        - is_base64_video
        - is_base64_audio
        - decode_base64_image
        - _validate_url_safety
        - _request_with_safe_redirects
        - download_image
        - _VIDEO_EXT_MAP
        - _AUDIO_EXT_MAP
        - _download_media
        - download_video
        - download_audio
        - decode_base64_video
        - decode_base64_audio
        - process_video_input
        - process_audio_input
        - _video_has_audio_track
        - _model_has_sound_encoder
        - extract_audio_from_video
        - _base64_image_cache
        - save_base64_image
        - process_image_input
        - round_by_factor
        - ceil_by_factor
        - floor_by_factor
        - smart_nframes
        - extract_video_frames_smart
        - save_frames_to_temp
        - MLXMultimodalLM
        - MLXVisionLanguageModel
        - VLMOutput
        - is_vlm_model
      filters: []
      show_if_no_docstring: true

## Complete contract reference

Expand any definition for its exact inputs, annotations, defaults, return contract, directly raised exceptions, source-grounded behavior, and immutable line link. This section includes private and nested definitions that ordinary API generators omit.

<details class="api-contract" id="contract-vllm_mlx.models.mllm.TempFileManager" markdown="1">
<summary><code>vllm_mlx.models.mllm.TempFileManager</code> · class</summary>

```python
vllm_mlx.models.mllm.TempFileManager()
```

Thread-safe manager for tracking and cleaning up temporary files.

**Parameters**

This callable has no explicit inputs.

**Returns**

- Constructs: `vllm_mlx.models.mllm.TempFileManager`

**Exceptions and behavior**

Class `TempFileManager` declares 4 direct member(s).
No direct `raise` statement appears in this definition.

[View source #L41-L86](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L41-L86).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.TempFileManager.__init__" markdown="1">
<summary><code>vllm_mlx.models.mllm.TempFileManager.__init__</code> · method</summary>

```python
vllm_mlx.models.mllm.TempFileManager.__init__() -> not annotated
```

Method `TempFileManager.__init__` updates `self._files`, `self._lock`; calls `set`, `threading.Lock`, `atexit.register`.

**Parameters**

This callable has no explicit inputs.

**Returns**

- Type: `not annotated`

**Exceptions and behavior**

Method `TempFileManager.__init__` updates `self._files`, `self._lock`; calls `set`, `threading.Lock`, `atexit.register`.
No direct `raise` statement appears in this definition.

[View source #L44-L47](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L44-L47).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.TempFileManager.register" markdown="1">
<summary><code>vllm_mlx.models.mllm.TempFileManager.register</code> · method</summary>

```python
vllm_mlx.models.mllm.TempFileManager.register(path: str) -> str
```

Register a temp file for tracking.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `path` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `str`
- Direct return expressions: `path`

**Exceptions and behavior**

Method `TempFileManager.register` calls `self._files.add`; returns `path`.
No direct `raise` statement appears in this definition.

[View source #L49-L53](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L49-L53).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.TempFileManager.cleanup" markdown="1">
<summary><code>vllm_mlx.models.mllm.TempFileManager.cleanup</code> · method</summary>

```python
vllm_mlx.models.mllm.TempFileManager.cleanup(path: str) -> bool
```

Clean up a specific temp file.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `path` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `bool`
- Direct return expressions: `True`; `False`

**Exceptions and behavior**

Method `TempFileManager.cleanup` calls `self._files.discard`, `os.path.exists`, `os.unlink`, `logger.debug`; has 2 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L55-L67](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L55-L67).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.TempFileManager.cleanup_all" markdown="1">
<summary><code>vllm_mlx.models.mllm.TempFileManager.cleanup_all</code> · method</summary>

```python
vllm_mlx.models.mllm.TempFileManager.cleanup_all() -> int
```

Clean up all tracked temp files.

**Parameters**

This callable has no explicit inputs.

**Returns**

- Type: `int`
- Direct return expressions: `cleaned`

**Exceptions and behavior**

Method `TempFileManager.cleanup_all` calls `list`, `self._files.clear`, `os.path.exists`, `os.unlink`; returns `cleaned`.
No direct `raise` statement appears in this definition.

[View source #L69-L86](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L69-L86).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.cleanup_temp_file" markdown="1">
<summary><code>vllm_mlx.models.mllm.cleanup_temp_file</code> · function</summary>

```python
vllm_mlx.models.mllm.cleanup_temp_file(path: str) -> bool
```

Clean up a specific temporary file.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `path` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `bool`
- Direct return expressions: `_temp_manager.cleanup(path)`

**Exceptions and behavior**

Function `cleanup_temp_file` calls `_temp_manager.cleanup`; returns `_temp_manager.cleanup(path)`.
No direct `raise` statement appears in this definition.

[View source #L93-L95](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L93-L95).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.cleanup_all_temp_files" markdown="1">
<summary><code>vllm_mlx.models.mllm.cleanup_all_temp_files</code> · function</summary>

```python
vllm_mlx.models.mllm.cleanup_all_temp_files() -> int
```

Clean up all tracked temporary files.

**Parameters**

This callable has no explicit inputs.

**Returns**

- Type: `int`
- Direct return expressions: `_temp_manager.cleanup_all()`

**Exceptions and behavior**

Function `cleanup_all_temp_files` calls `_temp_manager.cleanup_all`; returns `_temp_manager.cleanup_all()`.
No direct `raise` statement appears in this definition.

[View source #L98-L100](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L98-L100).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.FileSizeExceededError" markdown="1">
<summary><code>vllm_mlx.models.mllm.FileSizeExceededError</code> · class</summary>

```python
vllm_mlx.models.mllm.FileSizeExceededError()
```

Raised when a downloaded file exceeds the size limit.

**Parameters**

This callable has no explicit inputs.

**Returns**

- Constructs: `vllm_mlx.models.mllm.FileSizeExceededError`

**Exceptions and behavior**

Class `FileSizeExceededError` derives from `Exception` and declares 0 direct member(s).
No direct `raise` statement appears in this definition.

[View source #L119-L122](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L119-L122).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.UnsafeRemoteURLError" markdown="1">
<summary><code>vllm_mlx.models.mllm.UnsafeRemoteURLError</code> · class</summary>

```python
vllm_mlx.models.mllm.UnsafeRemoteURLError(message: str, *, public_message: str = 'Remote media URL is not allowed')
```

Raised when a remote media URL targets an unsafe destination.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `message` | `str` | `yes` | `none` | Required positional or keyword input. |
| `public_message` | `str` | `no` | `'Remote media URL is not allowed'` | Optional keyword-only input; defaults to `'Remote media URL is not allowed'`. |

**Returns**

- Constructs: `vllm_mlx.models.mllm.UnsafeRemoteURLError`

**Exceptions and behavior**

Class `UnsafeRemoteURLError` derives from `ValueError` and declares 1 direct member(s).
No direct `raise` statement appears in this definition.

[View source #L125-L135](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L125-L135).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.UnsafeRemoteURLError.__init__" markdown="1">
<summary><code>vllm_mlx.models.mllm.UnsafeRemoteURLError.__init__</code> · method</summary>

```python
vllm_mlx.models.mllm.UnsafeRemoteURLError.__init__(message: str, *, public_message: str = 'Remote media URL is not allowed') -> None
```

Method `UnsafeRemoteURLError.__init__` updates `self.public_message`; calls `super().__init__`, `super`.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `message` | `str` | `yes` | `none` | Required positional or keyword input. |
| `public_message` | `str` | `no` | `'Remote media URL is not allowed'` | Optional keyword-only input; defaults to `'Remote media URL is not allowed'`. |

**Returns**

- Type: `None`

**Exceptions and behavior**

Method `UnsafeRemoteURLError.__init__` updates `self.public_message`; calls `super().__init__`, `super`.
No direct `raise` statement appears in this definition.

[View source #L128-L135](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L128-L135).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._normalize_content_part" markdown="1">
<summary><code>vllm_mlx.models.mllm._normalize_content_part</code> · function</summary>

```python
vllm_mlx.models.mllm._normalize_content_part(item: object) -> object
```

Convert Pydantic content parts into plain Python objects.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `item` | `object` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `object`
- Direct return expressions: `item.model_dump(exclude_none=True)`; `{k: v for k, v in item.dict().items() if v is not None}`; `item`

**Exceptions and behavior**

Function `_normalize_content_part` calls `hasattr`, `item.model_dump`, `item.dict().items`, `item.dict`; has 3 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L138-L144](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L138-L144).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._extract_media_url" markdown="1">
<summary><code>vllm_mlx.models.mllm._extract_media_url</code> · function</summary>

```python
vllm_mlx.models.mllm._extract_media_url(item: dict, item_type: str) -> str
```

Function `_extract_media_url` calls `item.get`, `isinstance`, `media_value.get`; has 2 explicit return paths.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `item` | `dict` | `yes` | `none` | Required positional or keyword input. |
| `item_type` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `str`
- Direct return expressions: `''`; `media_value if isinstance(media_value, str) else ''`

**Exceptions and behavior**

Function `_extract_media_url` calls `item.get`, `isinstance`, `media_value.get`; has 2 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L147-L161](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L147-L161).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._text_content_part" markdown="1">
<summary><code>vllm_mlx.models.mllm._text_content_part</code> · function</summary>

```python
vllm_mlx.models.mllm._text_content_part(text: str) -> dict[str, str]
```

Function `_text_content_part` returns `{'type': 'text', 'text': text, 'content': text}`.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `text` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `dict[str, str]`
- Direct return expressions: `{'type': 'text', 'text': text, 'content': text}`

**Exceptions and behavior**

Function `_text_content_part` returns `{'type': 'text', 'text': text, 'content': text}`.
No direct `raise` statement appears in this definition.

[View source #L164-L165](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L164-L165).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._append_text_content_part" markdown="1">
<summary><code>vllm_mlx.models.mllm._append_text_content_part</code> · function</summary>

```python
vllm_mlx.models.mllm._append_text_content_part(built_parts: list[dict[str, str]], text_parts: list[str], text: str) -> None
```

Function `_append_text_content_part` calls `built_parts.append`, `_text_content_part`, `text_parts.append`; returns `None`.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `built_parts` | `list[dict[str, str]]` | `yes` | `none` | Required positional or keyword input. |
| `text_parts` | `list[str]` | `yes` | `none` | Required positional or keyword input. |
| `text` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `None`
- Direct return expressions: `None`

**Exceptions and behavior**

Function `_append_text_content_part` calls `built_parts.append`, `_text_content_part`, `text_parts.append`; returns `None`.
No direct `raise` statement appears in this definition.

[View source #L168-L174](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L168-L174).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._build_string_mllm_message_content" markdown="1">
<summary><code>vllm_mlx.models.mllm._build_string_mllm_message_content</code> · function</summary>

```python
vllm_mlx.models.mllm._build_string_mllm_message_content(content: str, role: str) -> tuple[object, bool]
```

Function `_build_string_mllm_message_content` calls `_text_content_part`; has 3 explicit return paths.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `content` | `str` | `yes` | `none` | Required positional or keyword input. |
| `role` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `tuple[object, bool]`
- Direct return expressions: `('', False)`; `(content, True)`; `([_text_content_part(content)], True)`

**Exceptions and behavior**

Function `_build_string_mllm_message_content` calls `_text_content_part`; has 3 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L177-L182](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L177-L182).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._append_ordered_mllm_content_part" markdown="1">
<summary><code>vllm_mlx.models.mllm._append_ordered_mllm_content_part</code> · function</summary>

```python
vllm_mlx.models.mllm._append_ordered_mllm_content_part(raw_item: object, *, built_parts: list[dict[str, str]], text_parts: list[str], all_image_urls: list[str], video_frame_count: int) -> int
```

Function `_append_ordered_mllm_content_part` calls `_normalize_content_part`, `isinstance`, `_append_text_content_part`, `item.get`; has 2 explicit return paths.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `raw_item` | `object` | `yes` | `none` | Required positional or keyword input. |
| `built_parts` | `list[dict[str, str]]` | `yes` | `none` | Required keyword-only input. |
| `text_parts` | `list[str]` | `yes` | `none` | Required keyword-only input. |
| `all_image_urls` | `list[str]` | `yes` | `none` | Required keyword-only input. |
| `video_frame_count` | `int` | `yes` | `none` | Required keyword-only input. |

**Returns**

- Type: `int`
- Direct return expressions: `video_frame_count`; `0`

**Exceptions and behavior**

Function `_append_ordered_mllm_content_part` calls `_normalize_content_part`, `isinstance`, `_append_text_content_part`, `item.get`; has 2 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L185-L220](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L185-L220).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._build_ordered_mllm_message_content" markdown="1">
<summary><code>vllm_mlx.models.mllm._build_ordered_mllm_message_content</code> · function</summary>

```python
vllm_mlx.models.mllm._build_ordered_mllm_message_content(content: object, *, role: str, all_image_urls: list[str], video_frame_count: int = 0) -> tuple[object, bool]
```

Build template content while preserving OpenAI media/text part order.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `content` | `object` | `yes` | `none` | Required positional or keyword input. |
| `role` | `str` | `yes` | `none` | Required keyword-only input. |
| `all_image_urls` | `list[str]` | `yes` | `none` | Required keyword-only input. |
| `video_frame_count` | `int` | `no` | `0` | Optional keyword-only input; defaults to `0`. |

**Returns**

- Type: `tuple[object, bool]`
- Direct return expressions: `_build_string_mllm_message_content(content, role)`; `('', False)`; `(text, bool(text))`; `(built_parts, bool(built_parts))`

**Exceptions and behavior**

Function `_build_ordered_mllm_message_content` calls `isinstance`, `_build_string_mllm_message_content`, `_append_ordered_mllm_content_part`, `''.join`; has 4 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L223-L254](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L223-L254).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._normalize_mllm_tool_calls" markdown="1">
<summary><code>vllm_mlx.models.mllm._normalize_mllm_tool_calls</code> · function</summary>

```python
vllm_mlx.models.mllm._normalize_mllm_tool_calls(tool_calls: list) -> list
```

Normalize replayed assistant tool calls for chat templates.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `tool_calls` | `list` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `list`
- Direct return expressions: `normalized[0].get('tool_calls', plain_calls)`

**Exceptions and behavior**

Function `_normalize_mllm_tool_calls` calls `_normalize_content_part`, `normalize_messages_for_chat_template`, `normalized[0].get`; returns `normalized[0].get('tool_calls', plain_calls)`.
No direct `raise` statement appears in this definition.

[View source #L257-L268](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L257-L268).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._build_mllm_chat_messages" markdown="1">
<summary><code>vllm_mlx.models.mllm._build_mllm_chat_messages</code> · function</summary>

```python
vllm_mlx.models.mllm._build_mllm_chat_messages(messages: list[dict], *, all_image_urls: list[str], video_frame_counts: dict[int, int]) -> list[dict]
```

Build chat-template messages without reordering multimodal content parts.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `messages` | `list[dict]` | `yes` | `none` | Required positional or keyword input. |
| `all_image_urls` | `list[str]` | `yes` | `none` | Required keyword-only input. |
| `video_frame_counts` | `dict[int, int]` | `yes` | `none` | Required keyword-only input. |

**Returns**

- Type: `list[dict]`
- Direct return expressions: `chat_messages`

**Exceptions and behavior**

Function `_build_mllm_chat_messages` calls `enumerate`, `msg.get`, `isinstance`, `str`; returns `chat_messages`.
No direct `raise` statement appears in this definition.

[View source #L271-L315](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L271-L315).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MultimodalInput" markdown="1">
<summary><code>vllm_mlx.models.mllm.MultimodalInput</code> · class</summary>

```python
vllm_mlx.models.mllm.MultimodalInput(prompt: str, images: list[str] = field(default_factory=list), videos: list[str] = field(default_factory=list), audio: list[str] = field(default_factory=list))
```

Input for multimodal generation.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `prompt` | `str` | `yes` | `none` | Required constructor field. |
| `images` | `list[str]` | `no` | `field(default_factory=list)` | Optional constructor field; defaults to `field(default_factory=list)`. |
| `videos` | `list[str]` | `no` | `field(default_factory=list)` | Optional constructor field; defaults to `field(default_factory=list)`. |
| `audio` | `list[str]` | `no` | `field(default_factory=list)` | Optional constructor field; defaults to `field(default_factory=list)`. |

**Returns**

- Constructs: `vllm_mlx.models.mllm.MultimodalInput`

**Exceptions and behavior**

Class `MultimodalInput` declares 0 direct member(s).
No direct `raise` statement appears in this definition.

[View source #L319-L325](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L319-L325).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLLMOutput" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLLMOutput</code> · class</summary>

```python
vllm_mlx.models.mllm.MLLMOutput(text: str, finish_reason: str | None = None, prompt_tokens: int = 0, completion_tokens: int = 0, mtp_drafts: int = 0, mtp_accepted: int = 0)
```

Output from multimodal language model.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `text` | `str` | `yes` | `none` | Required constructor field. |
| `finish_reason` | `str \| None` | `no` | `None` | Optional constructor field; defaults to `None`. |
| `prompt_tokens` | `int` | `no` | `0` | Optional constructor field; defaults to `0`. |
| `completion_tokens` | `int` | `no` | `0` | Optional constructor field; defaults to `0`. |
| `mtp_drafts` | `int` | `no` | `0` | Optional constructor field; defaults to `0`. |
| `mtp_accepted` | `int` | `no` | `0` | Optional constructor field; defaults to `0`. |

**Returns**

- Constructs: `vllm_mlx.models.mllm.MLLMOutput`

**Exceptions and behavior**

Class `MLLMOutput` declares 0 direct member(s).
No direct `raise` statement appears in this definition.

[View source #L329-L337](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L329-L337).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.load_gemma4_assistant_drafter" markdown="1">
<summary><code>vllm_mlx.models.mllm.load_gemma4_assistant_drafter</code> · function</summary>

```python
vllm_mlx.models.mllm.load_gemma4_assistant_drafter(model_path: str) -> not annotated
```

Load a Gemma 4 assistant drafter for mlx-vlm speculative decoding.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `model_path` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `not annotated`
- Direct return expressions: `model`

**Exceptions and behavior**

Function `load_gemma4_assistant_drafter` calls `ImportError`, `version`, `logger.info`, `Path`; can raise `ImportError`, `FileNotFoundError`; returns `model`.
Directly raised exceptions: `ImportError`, `FileNotFoundError`.

[View source #L340-L381](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L340-L381).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._count_draft_tokens" markdown="1">
<summary><code>vllm_mlx.models.mllm._count_draft_tokens</code> · function</summary>

```python
vllm_mlx.models.mllm._count_draft_tokens(draft_tokens) -> int
```

Best-effort drafted-token count for an mlx-vlm drafter output.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `draft_tokens` | `not annotated` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `int`
- Direct return expressions: `max(int(shape[-1]), 0)`; `max(len(draft_tokens), 0)`; `0`

**Exceptions and behavior**

Function `_count_draft_tokens` calls `getattr`, `max`, `int`, `len`; has 3 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L387-L398](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L387-L398).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._install_draft_metrics_hooks" markdown="1">
<summary><code>vllm_mlx.models.mllm._install_draft_metrics_hooks</code> · function</summary>

```python
vllm_mlx.models.mllm._install_draft_metrics_hooks(draft_model) -> None
```

Record actual drafted token counts from mlx-vlm assistant drafters.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `draft_model` | `not annotated` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `None`
- Direct return expressions: `None`

**Exceptions and behavior**

Function `_install_draft_metrics_hooks` calls `getattr`, `hasattr`, `callable`; returns `None`.
No direct `raise` statement appears in this definition.

[View source #L401-L428](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L401-L428).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._install_draft_metrics_hooks.draft_block_with_metrics" markdown="1">
<summary><code>vllm_mlx.models.mllm._install_draft_metrics_hooks.draft_block_with_metrics</code> · nested function</summary>

```python
vllm_mlx.models.mllm._install_draft_metrics_hooks.draft_block_with_metrics(*args, **kwargs) -> not annotated
```

Nested Function `_install_draft_metrics_hooks.draft_block_with_metrics` calls `draft_block`, `draft_model._vllm_mlx_draft_counts.append`, `_count_draft_tokens`; returns `draft_tokens`.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `*args` | `not annotated` | `no` | `none` | Additional variadic positional inputs accepted by this callable. |
| `**kwargs` | `not annotated` | `no` | `none` | Additional variadic keyword inputs accepted by this callable. |

**Returns**

- Type: `not annotated`
- Direct return expressions: `draft_tokens`

**Exceptions and behavior**

Nested Function `_install_draft_metrics_hooks.draft_block_with_metrics` calls `draft_block`, `draft_model._vllm_mlx_draft_counts.append`, `_count_draft_tokens`; returns `draft_tokens`.
No direct `raise` statement appears in this definition.

[View source #L412-L415](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L412-L415).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._install_draft_metrics_hooks.reset_with_metrics" markdown="1">
<summary><code>vllm_mlx.models.mllm._install_draft_metrics_hooks.reset_with_metrics</code> · nested function</summary>

```python
vllm_mlx.models.mllm._install_draft_metrics_hooks.reset_with_metrics(*args, **kwargs) -> not annotated
```

Nested Function `_install_draft_metrics_hooks.reset_with_metrics` calls `reset`; returns `reset(*args, **kwargs)`.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `*args` | `not annotated` | `no` | `none` | Additional variadic positional inputs accepted by this callable. |
| `**kwargs` | `not annotated` | `no` | `none` | Additional variadic keyword inputs accepted by this callable. |

**Returns**

- Type: `not annotated`
- Direct return expressions: `reset(*args, **kwargs)`

**Exceptions and behavior**

Nested Function `_install_draft_metrics_hooks.reset_with_metrics` calls `reset`; returns `reset(*args, **kwargs)`.
No direct `raise` statement appears in this definition.

[View source #L422-L424](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L422-L424).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.is_base64_image" markdown="1">
<summary><code>vllm_mlx.models.mllm.is_base64_image</code> · function</summary>

```python
vllm_mlx.models.mllm.is_base64_image(s: str) -> bool
```

Check if string is base64-encoded image data.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `s` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `bool`
- Direct return expressions: `s.startswith('data:image/') or (len(s) > 100 and (not s.startswith(('http://', 'https://', '/'))))`

**Exceptions and behavior**

Function `is_base64_image` calls `s.startswith`, `len`; returns `s.startswith('data:image/') or (len(s) > 100 and (not s.startswith(('http://', 'https://', '/'))))`.
No direct `raise` statement appears in this definition.

[View source #L431-L435](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L431-L435).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.is_url" markdown="1">
<summary><code>vllm_mlx.models.mllm.is_url</code> · function</summary>

```python
vllm_mlx.models.mllm.is_url(s: str) -> bool
```

Check if string is a URL.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `s` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `bool`
- Direct return expressions: `s.startswith(('http://', 'https://'))`

**Exceptions and behavior**

Function `is_url` calls `s.startswith`; returns `s.startswith(('http://', 'https://'))`.
No direct `raise` statement appears in this definition.

[View source #L438-L440](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L438-L440).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.is_base64_video" markdown="1">
<summary><code>vllm_mlx.models.mllm.is_base64_video</code> · function</summary>

```python
vllm_mlx.models.mllm.is_base64_video(s: str) -> bool
```

Check if string is base64-encoded video data.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `s` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `bool`
- Direct return expressions: `s.startswith('data:video/')`

**Exceptions and behavior**

Function `is_base64_video` calls `s.startswith`; returns `s.startswith('data:video/')`.
No direct `raise` statement appears in this definition.

[View source #L443-L445](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L443-L445).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.is_base64_audio" markdown="1">
<summary><code>vllm_mlx.models.mllm.is_base64_audio</code> · function</summary>

```python
vllm_mlx.models.mllm.is_base64_audio(s: str) -> bool
```

Check if string is base64-encoded audio data.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `s` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `bool`
- Direct return expressions: `s.startswith('data:audio/')`

**Exceptions and behavior**

Function `is_base64_audio` calls `s.startswith`; returns `s.startswith('data:audio/')`.
No direct `raise` statement appears in this definition.

[View source #L448-L450](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L448-L450).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.decode_base64_image" markdown="1">
<summary><code>vllm_mlx.models.mllm.decode_base64_image</code> · function</summary>

```python
vllm_mlx.models.mllm.decode_base64_image(base64_string: str, max_length: int = MAX_BASE64_IMAGE_LENGTH) -> bytes
```

Decode base64 image to bytes.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `base64_string` | `str` | `yes` | `none` | Base64 encoded image (optionally with data URL prefix) |
| `max_length` | `int` | `no` | `MAX_BASE64_IMAGE_LENGTH` | Maximum allowed length of base64 string |

**Returns**

- Type: `bytes`
- Direct return expressions: `base64.b64decode(data)`; `base64.b64decode(base64_string)`

**Exceptions and behavior**

Function `decode_base64_image` calls `len`, `FileSizeExceededError`, `base64_string.startswith`, `base64_string.split`; can raise `FileSizeExceededError`; has 2 explicit return paths.
Directly raised exceptions: `FileSizeExceededError`.

[View source #L453-L480](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L453-L480).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._validate_url_safety" markdown="1">
<summary><code>vllm_mlx.models.mllm._validate_url_safety</code> · function</summary>

```python
vllm_mlx.models.mllm._validate_url_safety(url: str) -> None
```

Reject remote URLs that target local or private network resources.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `url` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `None`

**Exceptions and behavior**

Function `_validate_url_safety` calls `urlparse`, `UnsafeRemoteURLError`, `hostname.endswith`, `ipaddress.ip_address`; can raise `UnsafeRemoteURLError`.
Directly raised exceptions: `UnsafeRemoteURLError`.

[View source #L483-L519](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L483-L519).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._request_with_safe_redirects" markdown="1">
<summary><code>vllm_mlx.models.mllm._request_with_safe_redirects</code> · function</summary>

```python
vllm_mlx.models.mllm._request_with_safe_redirects(method: str, url: str, *, timeout: int, headers: dict[str, str], stream: bool = False, max_redirects: int = 5) -> not annotated
```

Issue a requests call while validating every redirect target.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `method` | `str` | `yes` | `none` | Required positional or keyword input. |
| `url` | `str` | `yes` | `none` | Required positional or keyword input. |
| `timeout` | `int` | `yes` | `none` | Required keyword-only input. |
| `headers` | `dict[str, str]` | `yes` | `none` | Required keyword-only input. |
| `stream` | `bool` | `no` | `False` | Optional keyword-only input; defaults to `False`. |
| `max_redirects` | `int` | `no` | `5` | Optional keyword-only input; defaults to `5`. |

**Returns**

- Type: `not annotated`
- Direct return expressions: `response`

**Exceptions and behavior**

Function `_request_with_safe_redirects` calls `range`, `_validate_url_safety`, `requests.request`, `response.headers.get`; can raise `UnsafeRemoteURLError`; returns `response`.
Directly raised exceptions: `UnsafeRemoteURLError`.

[View source #L522-L557](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L522-L557).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.download_image" markdown="1">
<summary><code>vllm_mlx.models.mllm.download_image</code> · function</summary>

```python
vllm_mlx.models.mllm.download_image(url: str, timeout: int = 30, max_size: int = MAX_IMAGE_SIZE) -> str
```

Download image from URL and return local path.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `url` | `str` | `yes` | `none` | Image URL |
| `timeout` | `int` | `no` | `30` | Download timeout in seconds |
| `max_size` | `int` | `no` | `MAX_IMAGE_SIZE` | Maximum allowed file size in bytes |

**Returns**

- Type: `str`
- Direct return expressions: `_temp_manager.register(temp_file.name)`

**Exceptions and behavior**

Function `download_image` calls `_request_with_safe_redirects`, `head_response.headers.get`, `int`, `FileSizeExceededError`; can raise `FileSizeExceededError`; returns `_temp_manager.register(temp_file.name)`.
Directly raised exceptions: `FileSizeExceededError`.

[View source #L560-L645](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L560-L645).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._download_media" markdown="1">
<summary><code>vllm_mlx.models.mllm._download_media</code> · function</summary>

```python
vllm_mlx.models.mllm._download_media(url: str, media_type: str, ext_map: dict[str, str], default_ext: str, timeout: int, max_size: int) -> str
```

Download media from URL, enforce size limits, and return a local temp path.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `url` | `str` | `yes` | `none` | Required positional or keyword input. |
| `media_type` | `str` | `yes` | `none` | Required positional or keyword input. |
| `ext_map` | `dict[str, str]` | `yes` | `none` | Required positional or keyword input. |
| `default_ext` | `str` | `yes` | `none` | Required positional or keyword input. |
| `timeout` | `int` | `yes` | `none` | Required positional or keyword input. |
| `max_size` | `int` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `str`
- Direct return expressions: `_temp_manager.register(temp_file.name)`

**Exceptions and behavior**

Function `_download_media` calls `logger.info`, `_request_with_safe_redirects`, `head_response.headers.get`, `int`; can raise `FileSizeExceededError`; returns `_temp_manager.register(temp_file.name)`.
Directly raised exceptions: `FileSizeExceededError`.

[View source #L670-L748](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L670-L748).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.download_video" markdown="1">
<summary><code>vllm_mlx.models.mllm.download_video</code> · function</summary>

```python
vllm_mlx.models.mllm.download_video(url: str, timeout: int = 120, max_size: int = MAX_VIDEO_SIZE) -> str
```

Download video from URL and return local path.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `url` | `str` | `yes` | `none` | Required positional or keyword input. |
| `timeout` | `int` | `no` | `120` | Optional positional or keyword input; defaults to `120`. |
| `max_size` | `int` | `no` | `MAX_VIDEO_SIZE` | Optional positional or keyword input; defaults to `MAX_VIDEO_SIZE`. |

**Returns**

- Type: `str`
- Direct return expressions: `_download_media(url, 'video', _VIDEO_EXT_MAP, '.mp4', timeout, max_size)`

**Exceptions and behavior**

Function `download_video` calls `_download_media`; returns `_download_media(url, 'video', _VIDEO_EXT_MAP, '.mp4', timeout, max_size)`.
No direct `raise` statement appears in this definition.

[View source #L751-L753](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L751-L753).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.download_audio" markdown="1">
<summary><code>vllm_mlx.models.mllm.download_audio</code> · function</summary>

```python
vllm_mlx.models.mllm.download_audio(url: str, timeout: int = 120, max_size: int = MAX_AUDIO_SIZE) -> str
```

Download audio from URL and return local path.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `url` | `str` | `yes` | `none` | Required positional or keyword input. |
| `timeout` | `int` | `no` | `120` | Optional positional or keyword input; defaults to `120`. |
| `max_size` | `int` | `no` | `MAX_AUDIO_SIZE` | Optional positional or keyword input; defaults to `MAX_AUDIO_SIZE`. |

**Returns**

- Type: `str`
- Direct return expressions: `_download_media(url, 'audio', _AUDIO_EXT_MAP, '.wav', timeout, max_size)`

**Exceptions and behavior**

Function `download_audio` calls `_download_media`; returns `_download_media(url, 'audio', _AUDIO_EXT_MAP, '.wav', timeout, max_size)`.
No direct `raise` statement appears in this definition.

[View source #L756-L758](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L756-L758).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.decode_base64_video" markdown="1">
<summary><code>vllm_mlx.models.mllm.decode_base64_video</code> · function</summary>

```python
vllm_mlx.models.mllm.decode_base64_video(base64_string: str, max_length: int = MAX_BASE64_VIDEO_LENGTH) -> str
```

Decode base64 video to temp file and return path.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `base64_string` | `str` | `yes` | `none` | Base64-encoded video with data URL prefix |
| `max_length` | `int` | `no` | `MAX_BASE64_VIDEO_LENGTH` | Maximum allowed length of base64 string |

**Returns**

- Type: `str`
- Direct return expressions: `_temp_manager.register(temp_file.name)`

**Exceptions and behavior**

Function `decode_base64_video` calls `len`, `FileSizeExceededError`, `base64_string.startswith`, `base64_string.split`; can raise `FileSizeExceededError`; returns `_temp_manager.register(temp_file.name)`.
Directly raised exceptions: `FileSizeExceededError`.

[View source #L761-L807](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L761-L807).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.decode_base64_audio" markdown="1">
<summary><code>vllm_mlx.models.mllm.decode_base64_audio</code> · function</summary>

```python
vllm_mlx.models.mllm.decode_base64_audio(base64_string: str, max_length: int = MAX_BASE64_AUDIO_LENGTH) -> str
```

Decode base64 audio to temp file and return path.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `base64_string` | `str` | `yes` | `none` | Required positional or keyword input. |
| `max_length` | `int` | `no` | `MAX_BASE64_AUDIO_LENGTH` | Optional positional or keyword input; defaults to `MAX_BASE64_AUDIO_LENGTH`. |

**Returns**

- Type: `str`
- Direct return expressions: `_temp_manager.register(temp_file.name)`

**Exceptions and behavior**

Function `decode_base64_audio` calls `len`, `FileSizeExceededError`, `base64_string.startswith`, `base64_string.split`; can raise `FileSizeExceededError`; returns `_temp_manager.register(temp_file.name)`.
Directly raised exceptions: `FileSizeExceededError`.

[View source #L810-L836](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L810-L836).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.process_video_input" markdown="1">
<summary><code>vllm_mlx.models.mllm.process_video_input</code> · function</summary>

```python
vllm_mlx.models.mllm.process_video_input(video: str | dict) -> str
```

Process video input in various formats and return local path.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `video` | `str \| dict` | `yes` | `none` | Video input in any supported format |

**Returns**

- Type: `str`
- Direct return expressions: `download_video(video)`; `decode_base64_video(video)`

**Exceptions and behavior**

Function `process_video_input` calls `isinstance`, `video.get`, `url.get`, `ValueError`; can raise `ValueError`; has 2 explicit return paths.
Directly raised exceptions: `ValueError`.

[View source #L839-L874](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L839-L874).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.process_audio_input" markdown="1">
<summary><code>vllm_mlx.models.mllm.process_audio_input</code> · function</summary>

```python
vllm_mlx.models.mllm.process_audio_input(audio: str | dict) -> str
```

Process audio input in various formats and return local path.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `audio` | `str \| dict` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `str`
- Direct return expressions: `decode_base64_audio(audio)`; `download_audio(audio)`; `audio`

**Exceptions and behavior**

Function `process_audio_input` calls `isinstance`, `audio.get`, `url.get`, `ValueError`; can raise `ValueError`; has 3 explicit return paths.
Directly raised exceptions: `ValueError`.

[View source #L877-L905](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L877-L905).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._video_has_audio_track" markdown="1">
<summary><code>vllm_mlx.models.mllm._video_has_audio_track</code> · function</summary>

```python
vllm_mlx.models.mllm._video_has_audio_track(video_path: str) -> bool
```

Return True if ffprobe finds an audio stream in the video.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `video_path` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `bool`
- Direct return expressions: `True`; `bool(r.stdout.strip())`

**Exceptions and behavior**

Function `_video_has_audio_track` calls `shutil.which`, `subprocess.run`, `bool`, `r.stdout.strip`; has 2 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L908-L935](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L908-L935).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm._model_has_sound_encoder" markdown="1">
<summary><code>vllm_mlx.models.mllm._model_has_sound_encoder</code> · function</summary>

```python
vllm_mlx.models.mllm._model_has_sound_encoder(model) -> bool
```

Whether a loaded model exposes a usable sound encoder.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `model` | `not annotated` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `bool`
- Direct return expressions: `getattr(model, 'sound_encoder', None) is not None`

**Exceptions and behavior**

Function `_model_has_sound_encoder` calls `getattr`; returns `getattr(model, 'sound_encoder', None) is not None`.
No direct `raise` statement appears in this definition.

[View source #L938-L947](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L938-L947).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.extract_audio_from_video" markdown="1">
<summary><code>vllm_mlx.models.mllm.extract_audio_from_video</code> · function</summary>

```python
vllm_mlx.models.mllm.extract_audio_from_video(video_path: str) -> str | None
```

Extract the audio track from a video file as 16 kHz mono WAV.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `video_path` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `str | None`
- Direct return expressions: `None`; `_temp_manager.register(out_path)`

**Exceptions and behavior**

Function `extract_audio_from_video` calls `shutil.which`, `logger.warning`, `_video_has_audio_track`, `tempfile.mkstemp`; has 2 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L950-L1005](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L950-L1005).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.save_base64_image" markdown="1">
<summary><code>vllm_mlx.models.mllm.save_base64_image</code> · function</summary>

```python
vllm_mlx.models.mllm.save_base64_image(base64_string: str) -> str
```

Save base64 image to temp file and return path.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `base64_string` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `str`
- Direct return expressions: `cached_path`; `path`

**Exceptions and behavior**

Function `save_base64_image` calls `hashlib.sha256(base64_string.encode()).hexdigest`, `hashlib.sha256`, `base64_string.encode`, `Path(cached_path).exists`; has 2 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L1012-L1048](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1012-L1048).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.process_image_input" markdown="1">
<summary><code>vllm_mlx.models.mllm.process_image_input</code> · function</summary>

```python
vllm_mlx.models.mllm.process_image_input(image: str | dict) -> str
```

Process image input in various formats and return local path.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `image` | `str \| dict` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `str`
- Direct return expressions: `save_base64_image(image)`; `download_image(image)`

**Exceptions and behavior**

Function `process_image_input` calls `isinstance`, `image.get`, `url.get`, `ValueError`; can raise `ValueError`; has 2 explicit return paths.
Directly raised exceptions: `ValueError`.

[View source #L1051-L1080](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1051-L1080).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.round_by_factor" markdown="1">
<summary><code>vllm_mlx.models.mllm.round_by_factor</code> · function</summary>

```python
vllm_mlx.models.mllm.round_by_factor(x: int, factor: int) -> int
```

Round to nearest multiple of factor.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `x` | `int` | `yes` | `none` | Required positional or keyword input. |
| `factor` | `int` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `int`
- Direct return expressions: `round(x / factor) * factor`

**Exceptions and behavior**

Function `round_by_factor` calls `round`; returns `round(x / factor) * factor`.
No direct `raise` statement appears in this definition.

[View source #L1083-L1085](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1083-L1085).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.ceil_by_factor" markdown="1">
<summary><code>vllm_mlx.models.mllm.ceil_by_factor</code> · function</summary>

```python
vllm_mlx.models.mllm.ceil_by_factor(x: float, factor: int) -> int
```

Ceiling to next multiple of factor.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `x` | `float` | `yes` | `none` | Required positional or keyword input. |
| `factor` | `int` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `int`
- Direct return expressions: `math.ceil(x / factor) * factor`

**Exceptions and behavior**

Function `ceil_by_factor` calls `math.ceil`; returns `math.ceil(x / factor) * factor`.
No direct `raise` statement appears in this definition.

[View source #L1088-L1090](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1088-L1090).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.floor_by_factor" markdown="1">
<summary><code>vllm_mlx.models.mllm.floor_by_factor</code> · function</summary>

```python
vllm_mlx.models.mllm.floor_by_factor(x: float, factor: int) -> int
```

Floor to previous multiple of factor.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `x` | `float` | `yes` | `none` | Required positional or keyword input. |
| `factor` | `int` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `int`
- Direct return expressions: `math.floor(x / factor) * factor`

**Exceptions and behavior**

Function `floor_by_factor` calls `math.floor`; returns `math.floor(x / factor) * factor`.
No direct `raise` statement appears in this definition.

[View source #L1093-L1095](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1093-L1095).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.smart_nframes" markdown="1">
<summary><code>vllm_mlx.models.mllm.smart_nframes</code> · function</summary>

```python
vllm_mlx.models.mllm.smart_nframes(total_frames: int, video_fps: float, target_fps: float = DEFAULT_FPS, min_frames: int = MIN_FRAMES, max_frames: int = MAX_FRAMES) -> int
```

Calculate optimal number of frames to extract from video.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `total_frames` | `int` | `yes` | `none` | Required positional or keyword input. |
| `video_fps` | `float` | `yes` | `none` | Required positional or keyword input. |
| `target_fps` | `float` | `no` | `DEFAULT_FPS` | Optional positional or keyword input; defaults to `DEFAULT_FPS`. |
| `min_frames` | `int` | `no` | `MIN_FRAMES` | Optional positional or keyword input; defaults to `MIN_FRAMES`. |
| `max_frames` | `int` | `no` | `MAX_FRAMES` | Optional positional or keyword input; defaults to `MAX_FRAMES`. |

**Returns**

- Type: `int`
- Direct return expressions: `int(nframes)`

**Exceptions and behavior**

Function `smart_nframes` calls `max`, `min`, `floor_by_factor`, `int`; returns `int(nframes)`.
No direct `raise` statement appears in this definition.

[View source #L1098-L1120](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1098-L1120).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.extract_video_frames_smart" markdown="1">
<summary><code>vllm_mlx.models.mllm.extract_video_frames_smart</code> · function</summary>

```python
vllm_mlx.models.mllm.extract_video_frames_smart(video_path: str, fps: float = DEFAULT_FPS, max_frames: int = MAX_FRAMES, resize: tuple[int, int] | None = None) -> list[np.ndarray]
```

Extract frames from video with smart sampling.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `video_path` | `str` | `yes` | `none` | Path to video file |
| `fps` | `float` | `no` | `DEFAULT_FPS` | Target frames per second (default: 2.0) |
| `max_frames` | `int` | `no` | `MAX_FRAMES` | Maximum frames to extract |
| `resize` | `tuple[int, int] \| None` | `no` | `None` | Optional (width, height) to resize frames |

**Returns**

- Type: `list[np.ndarray]`
- Direct return expressions: `frames`

**Exceptions and behavior**

Function `extract_video_frames_smart` calls `ImportError`, `cv2.VideoCapture`, `cap.isOpened`, `ValueError`; can raise `ImportError`, `ValueError`; returns `frames`.
Directly raised exceptions: `ImportError`, `ValueError`.

[View source #L1123-L1187](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1123-L1187).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.save_frames_to_temp" markdown="1">
<summary><code>vllm_mlx.models.mllm.save_frames_to_temp</code> · function</summary>

```python
vllm_mlx.models.mllm.save_frames_to_temp(frames: list[np.ndarray]) -> list[str]
```

Save frame arrays to temporary files and return paths.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `frames` | `list[np.ndarray]` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `list[str]`
- Direct return expressions: `paths`

**Exceptions and behavior**

Function `save_frames_to_temp` calls `ImportError`, `enumerate`, `Image.fromarray`, `tempfile.NamedTemporaryFile`; can raise `ImportError`; returns `paths`.
Directly raised exceptions: `ImportError`.

[View source #L1190-L1204](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1190-L1204).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM</code> · class</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM(model_name: str, trust_remote_code: bool = False, enable_cache: bool = True, cache_size: int = 50, max_kv_size: int = 0, draft_model: str | None = None, draft_kind: str | None = None, draft_block_size: int | None = None)
```

Wrapper around mlx-vlm for multimodal inference.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `model_name` | `str` | `yes` | `none` | HuggingFace model name or local path |
| `trust_remote_code` | `bool` | `no` | `False` | Whether to trust remote code |
| `enable_cache` | `bool` | `no` | `True` | Enable KV cache for repeated image/video+prompt (default: True) |
| `cache_size` | `int` | `no` | `50` | Maximum cache entries (default: 50) |
| `max_kv_size` | `int` | `no` | `0` | Maximum KV cache size per sequence (0 = unbounded) |
| `draft_model` | `str \| None` | `no` | `None` | Optional MLLM speculative draft/assistant model path. |
| `draft_kind` | `str \| None` | `no` | `None` | Optional mlx-vlm draft kind, for example "mtp". |
| `draft_block_size` | `int \| None` | `no` | `None` | Optional speculative block size passed to mlx-vlm. |

**Returns**

- Constructs: `vllm_mlx.models.mllm.MLXMultimodalLM`

**Exceptions and behavior**

Class `MLXMultimodalLM` declares 29 direct member(s).
No direct `raise` statement appears in this definition.

[View source #L1207-L2938](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1207-L2938).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.__init__" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.__init__</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.__init__(model_name: str, trust_remote_code: bool = False, enable_cache: bool = True, cache_size: int = 50, max_kv_size: int = 0, draft_model: str | None = None, draft_kind: str | None = None, draft_block_size: int | None = None) -> not annotated
```

Initialize the MLX multimodal language model.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `model_name` | `str` | `yes` | `none` | HuggingFace model name or local path |
| `trust_remote_code` | `bool` | `no` | `False` | Whether to trust remote code |
| `enable_cache` | `bool` | `no` | `True` | Enable KV cache for repeated image/video+prompt (default: True) |
| `cache_size` | `int` | `no` | `50` | Maximum cache entries (default: 50) |
| `max_kv_size` | `int` | `no` | `0` | Maximum KV cache size per sequence (0 = unbounded) |
| `draft_model` | `str \| None` | `no` | `None` | Optional MLLM speculative draft/assistant model path. |
| `draft_kind` | `str \| None` | `no` | `None` | Optional mlx-vlm draft kind, for example "mtp". |
| `draft_block_size` | `int \| None` | `no` | `None` | Optional speculative block size passed to mlx-vlm. |

**Returns**

- Type: `not annotated`

**Exceptions and behavior**

Method `MLXMultimodalLM.__init__` updates `self.model_name`, `self.trust_remote_code`, `self.enable_cache`, `self.max_kv_size`; calls `MLLMPrefixCacheManager`.
No direct `raise` statement appears in this definition.

[View source #L1235-L1278](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1235-L1278).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.load" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.load</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.load() -> None
```

Load the model and processor.

**Parameters**

This callable has no explicit inputs.

**Returns**

- Type: `None`
- Direct return expressions: `None`

**Exceptions and behavior**

Method `MLXMultimodalLM.load` updates `self.model`, `self.processor`, `self.config`, `self._draft_model`; calls `logger.info`, `load`, `load_config`, `self._load_draft_model`; can raise `ImportError`; returns `None`.
Directly raised exceptions: `ImportError`.

[View source #L1280-L1323](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1280-L1323).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM._load_draft_model" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM._load_draft_model</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM._load_draft_model() -> not annotated
```

Method `MLXMultimodalLM._load_draft_model` calls `load_gemma4_assistant_drafter`, `load`; has 2 explicit return paths.

**Parameters**

This callable has no explicit inputs.

**Returns**

- Type: `not annotated`
- Direct return expressions: `load_gemma4_assistant_drafter(self.draft_model_path)`; `draft_model`

**Exceptions and behavior**

Method `MLXMultimodalLM._load_draft_model` calls `load_gemma4_assistant_drafter`, `load`; has 2 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L1325-L1332](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1325-L1332).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM._draft_generation_kwargs" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM._draft_generation_kwargs</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM._draft_generation_kwargs(call_kwargs: dict | None = None) -> dict
```

Return mlx-vlm drafter kwargs when the request explicitly opts in.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `call_kwargs` | `dict \| None` | `no` | `None` | Optional positional or keyword input; defaults to `None`. |

**Returns**

- Type: `dict`
- Direct return expressions: `{}`; `kwargs`

**Exceptions and behavior**

Method `MLXMultimodalLM._draft_generation_kwargs` calls `bool`, `call_kwargs.pop`, `_install_draft_metrics_hooks`; has 2 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L1334-L1355](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1334-L1355).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM._reset_draft_metrics" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM._reset_draft_metrics</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM._reset_draft_metrics() -> int
```

Method `MLXMultimodalLM._reset_draft_metrics` updates `self._draft_model.accept_lens`, `self._draft_model._vllm_mlx_draft_counts`; calls `hasattr`; returns `0`.

**Parameters**

This callable has no explicit inputs.

**Returns**

- Type: `int`
- Direct return expressions: `0`

**Exceptions and behavior**

Method `MLXMultimodalLM._reset_draft_metrics` updates `self._draft_model.accept_lens`, `self._draft_model._vllm_mlx_draft_counts`; calls `hasattr`; returns `0`.
No direct `raise` statement appears in this definition.

[View source #L1357-L1364](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1357-L1364).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM._draft_metrics_since" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM._draft_metrics_since</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM._draft_metrics_since(start_accept_lens: int) -> dict[str, int]
```

Method `MLXMultimodalLM._draft_metrics_since` calls `list`, `getattr`, `len`, `int`; has 2 explicit return paths.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `start_accept_lens` | `int` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `dict[str, int]`
- Direct return expressions: `{'mtp_drafts': 0, 'mtp_accepted': 0}`; `{'mtp_drafts': mtp_drafts, 'mtp_accepted': sum((int(value) for value in new_accept_lens))}`

**Exceptions and behavior**

Method `MLXMultimodalLM._draft_metrics_since` calls `list`, `getattr`, `len`, `int`; has 2 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L1366-L1395](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1366-L1395).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.get_language_model" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.get_language_model</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.get_language_model() -> not annotated
```

Extract the underlying language model for mlx_lm TextModel construction.

**Parameters**

This callable has no explicit inputs.

**Returns**

- Type: `not annotated`
- Direct return expressions: `self.model.language_model`

**Exceptions and behavior**

Method `MLXMultimodalLM.get_language_model` returns `self.model.language_model`.
No direct `raise` statement appears in this definition.

[View source #L1397-L1399](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1397-L1399).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.get_tokenizer" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.get_tokenizer</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.get_tokenizer() -> not annotated
```

Get the text tokenizer (not the multimodal processor).

**Parameters**

This callable has no explicit inputs.

**Returns**

- Type: `not annotated`
- Direct return expressions: `self.processor.tokenizer`

**Exceptions and behavior**

Method `MLXMultimodalLM.get_tokenizer` returns `self.processor.tokenizer`.
No direct `raise` statement appears in this definition.

[View source #L1401-L1403](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1401-L1403).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM._prepare_images" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM._prepare_images</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM._prepare_images(images: list) -> list[str]
```

Process remote/base64 image inputs into local temp file paths.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `images` | `list` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `list[str]`
- Direct return expressions: `processed`

**Exceptions and behavior**

Method `MLXMultimodalLM._prepare_images` calls `process_image_input`, `processed.append`, `logger.warning`; returns `processed`.
No direct `raise` statement appears in this definition.

[View source #L1405-L1414](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1405-L1414).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM._prepare_audio" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM._prepare_audio</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM._prepare_audio(audio_inputs: list) -> list[str]
```

Process audio inputs and return local file paths.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `audio_inputs` | `list` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `list[str]`
- Direct return expressions: `processed`

**Exceptions and behavior**

Method `MLXMultimodalLM._prepare_audio` calls `process_audio_input`, `processed.append`, `logger.warning`; returns `processed`.
No direct `raise` statement appears in this definition.

[View source #L1416-L1425](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1416-L1425).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM._prepare_video" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM._prepare_video</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM._prepare_video(video_input: str | dict, fps: float = DEFAULT_FPS, max_frames: int = MAX_FRAMES, resolved_path: str | None = None) -> list[str]
```

Process video input and extract frames.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `video_input` | `str \| dict` | `yes` | `none` | Video in any supported format |
| `fps` | `float` | `no` | `DEFAULT_FPS` | Frames per second to extract |
| `max_frames` | `int` | `no` | `MAX_FRAMES` | Maximum frames to extract |
| `resolved_path` | `str \| None` | `no` | `None` | Optional pre-resolved local path. Callers that already ran process_video_input (e.g. for parallel audio extraction) pass it here to avoid re-downloading / re-decoding. |

**Returns**

- Type: `list[str]`
- Direct return expressions: `save_frames_to_temp(frames)`

**Exceptions and behavior**

Method `MLXMultimodalLM._prepare_video` calls `process_video_input`, `extract_video_frames_smart`, `save_frames_to_temp`; returns `save_frames_to_temp(frames)`.
No direct `raise` statement appears in this definition.

[View source #L1427-L1463](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1427-L1463).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM._collect_video_inputs" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM._collect_video_inputs</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM._collect_video_inputs(messages: list[dict]) -> dict[int, list]
```

Collect video inputs from messages, keyed by message index.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `messages` | `list[dict]` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `dict[int, list]`
- Direct return expressions: `video_inputs`

**Exceptions and behavior**

Method `MLXMultimodalLM._collect_video_inputs` calls `enumerate`, `msg.get`, `isinstance`, `hasattr`; returns `video_inputs`.
No direct `raise` statement appears in this definition.

[View source #L1465-L1497](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1465-L1497).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM._collect_audio_inputs" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM._collect_audio_inputs</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM._collect_audio_inputs(messages: list[dict]) -> dict[int, list]
```

Collect audio inputs from messages, keyed by message index.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `messages` | `list[dict]` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `dict[int, list]`
- Direct return expressions: `audio_inputs`

**Exceptions and behavior**

Method `MLXMultimodalLM._collect_audio_inputs` calls `enumerate`, `msg.get`, `isinstance`, `hasattr`; returns `audio_inputs`.
No direct `raise` statement appears in this definition.

[View source #L1499-L1528](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1499-L1528).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM._prepare_native_video_inputs" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM._prepare_native_video_inputs</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM._prepare_native_video_inputs(messages: list[dict], video_fps: float = DEFAULT_FPS, video_max_frames: int = MAX_FRAMES, tools: list | None = None) -> tuple[str, dict]
```

Preprocess messages into prompt + generation kwargs for native video.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `messages` | `list[dict]` | `yes` | `none` | Required positional or keyword input. |
| `video_fps` | `float` | `no` | `DEFAULT_FPS` | Optional positional or keyword input; defaults to `DEFAULT_FPS`. |
| `video_max_frames` | `int` | `no` | `MAX_FRAMES` | Optional positional or keyword input; defaults to `MAX_FRAMES`. |
| `tools` | `list \| None` | `no` | `None` | Optional positional or keyword input; defaults to `None`. |

**Returns**

- Type: `tuple[str, dict]`
- Direct return expressions: `(text, gen_kwargs)`

**Exceptions and behavior**

Method `MLXMultimodalLM._prepare_native_video_inputs` calls `ImportError`, `self._translate_messages_for_native_video`, `self.processor.apply_chat_template`, `process_vision_info`; can raise `ImportError`; returns `(text, gen_kwargs)`.
Directly raised exceptions: `ImportError`.

[View source #L1530-L1648](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1530-L1648).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM._generate_native_video" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM._generate_native_video</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM._generate_native_video(messages: list[dict], max_tokens: int = 256, temperature: float = 0.7, video_fps: float = DEFAULT_FPS, video_max_frames: int = MAX_FRAMES, tools: list | None = None, **kwargs) -> MLLMOutput
```

Generate using native video pipeline (Qwen-family models).

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `messages` | `list[dict]` | `yes` | `none` | Required positional or keyword input. |
| `max_tokens` | `int` | `no` | `256` | Optional positional or keyword input; defaults to `256`. |
| `temperature` | `float` | `no` | `0.7` | Optional positional or keyword input; defaults to `0.7`. |
| `video_fps` | `float` | `no` | `DEFAULT_FPS` | Optional positional or keyword input; defaults to `DEFAULT_FPS`. |
| `video_max_frames` | `int` | `no` | `MAX_FRAMES` | Optional positional or keyword input; defaults to `MAX_FRAMES`. |
| `tools` | `list \| None` | `no` | `None` | Optional positional or keyword input; defaults to `None`. |
| `**kwargs` | `not annotated` | `no` | `none` | Additional variadic keyword inputs accepted by this callable. |

**Returns**

- Type: `MLLMOutput`
- Direct return expressions: `MLLMOutput(text=result.text, finish_reason='stop', prompt_tokens=getattr(result, 'prompt_tokens', 0), completion_tokens…`; `MLLMOutput(text=str(result), finish_reason='stop')`

**Exceptions and behavior**

Method `MLXMultimodalLM._generate_native_video` calls `ImportError`, `self._prepare_native_video_inputs`, `generate`, `hasattr`; can raise `ImportError`; has 2 explicit return paths.
Directly raised exceptions: `ImportError`.

[View source #L1650-L1695](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1650-L1695).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM._translate_messages_for_native_video" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM._translate_messages_for_native_video</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM._translate_messages_for_native_video(messages: list[dict], video_fps: float, video_max_frames: int) -> list[dict]
```

Translate OpenAI API format messages to process_vision_info format.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `messages` | `list[dict]` | `yes` | `none` | Required positional or keyword input. |
| `video_fps` | `float` | `yes` | `none` | Required positional or keyword input. |
| `video_max_frames` | `int` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `list[dict]`
- Direct return expressions: `translated`

**Exceptions and behavior**

Method `MLXMultimodalLM._translate_messages_for_native_video` calls `msg.get`, `isinstance`, `translated.append`, `str`; returns `translated`.
No direct `raise` statement appears in this definition.

[View source #L1697-L1832](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1697-L1832).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.generate" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.generate</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.generate(prompt: str, images: list | None = None, videos: list | None = None, audio: list[str] | None = None, max_tokens: int = 256, temperature: float = 0.7, top_p: float = 0.9, video_fps: float = DEFAULT_FPS, video_max_frames: int = MAX_FRAMES, use_cache: bool = True, **kwargs) -> MLLMOutput
```

Generate text from multimodal input.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `prompt` | `str` | `yes` | `none` | Text prompt/question |
| `images` | `list \| None` | `no` | `None` | List of image URLs or base64 strings |
| `videos` | `list \| None` | `no` | `None` | List of video inputs (URLs, base64, or OpenAI format dicts) |
| `audio` | `list[str] \| None` | `no` | `None` | List of audio file paths |
| `max_tokens` | `int` | `no` | `256` | Maximum tokens to generate |
| `temperature` | `float` | `no` | `0.7` | Sampling temperature |
| `top_p` | `float` | `no` | `0.9` | Top-p sampling parameter |
| `video_fps` | `float` | `no` | `DEFAULT_FPS` | FPS for video frame extraction (default: 2.0) |
| `video_max_frames` | `int` | `no` | `MAX_FRAMES` | Max frames to extract from video |
| `use_cache` | `bool` | `no` | `True` | Whether to use KV cache (default: True) |
| `**kwargs` | `not annotated` | `no` | `none` | Additional generation parameters |

**Returns**

- Type: `MLLMOutput`
- Direct return expressions: `MLLMOutput(text=output_text, finish_reason='stop', prompt_tokens=prompt_tokens, completion_tokens=generation_tokens, **…`

**Exceptions and behavior**

Method `MLXMultimodalLM.generate` calls `self.load`, `all_images.extend`, `self._prepare_images`, `all_sources.extend`; returns `MLLMOutput(text=output_text, finish_reason='stop', prompt_tokens=prompt_tokens, completion_tokens=generation_tokens, **…`.
No direct `raise` statement appears in this definition.

[View source #L1834-L2002](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1834-L2002).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.stream_generate" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.stream_generate</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.stream_generate(prompt: str, images: list | None = None, videos: list[str] | None = None, audio: list[str] | None = None, max_tokens: int = 256, temperature: float = 0.7, video_fps: float = DEFAULT_FPS, **kwargs) -> Iterator[str]
```

Stream text generation for multimodal input.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `prompt` | `str` | `yes` | `none` | Text prompt |
| `images` | `list \| None` | `no` | `None` | List of image inputs |
| `videos` | `list[str] \| None` | `no` | `None` | List of video paths |
| `audio` | `list[str] \| None` | `no` | `None` | List of audio inputs |
| `max_tokens` | `int` | `no` | `256` | Maximum tokens to generate |
| `temperature` | `float` | `no` | `0.7` | Sampling temperature |
| `video_fps` | `float` | `no` | `DEFAULT_FPS` | FPS for video frame extraction |
| `**kwargs` | `not annotated` | `no` | `none` | Additional parameters |

**Returns**

- Type: `Iterator[str]`
- Direct return expressions: `None`
- Yields values incrementally.

**Exceptions and behavior**

Method `MLXMultimodalLM.stream_generate` calls `self.load`, `self.generate`, `all_images.extend`, `self._prepare_images`; yields values incrementally; returns `None`.
No direct `raise` statement appears in this definition.

[View source #L2004-L2093](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2004-L2093).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.chat" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.chat</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.chat(messages: list[dict], max_tokens: int = 256, temperature: float = 0.7, **kwargs) -> MLLMOutput
```

Chat with OpenAI-compatible message format.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `messages` | `list[dict]` | `yes` | `none` | List of chat messages (OpenAI format) |
| `max_tokens` | `int` | `no` | `256` | Maximum tokens to generate |
| `temperature` | `float` | `no` | `0.7` | Sampling temperature |
| `**kwargs` | `not annotated` | `no` | `none` | Additional parameters |

**Returns**

- Type: `MLLMOutput`
- Direct return expressions: `self._generate_native_video(messages=messages, max_tokens=max_tokens, temperature=temperature, video_fps=video_fps, vid…`; `MLLMOutput(text=output_text, finish_reason='stop', prompt_tokens=prompt_tokens, completion_tokens=generation_tokens, **…`

**Exceptions and behavior**

Method `MLXMultimodalLM.chat` calls `self.load`, `logger.info`, `len`, `kwargs.pop`; has 2 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L2095-L2487](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2095-L2487).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.stream_chat" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.stream_chat</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.stream_chat(messages: list[dict], max_tokens: int = 256, temperature: float = 0.7, **kwargs) -> Iterator[MLLMOutput]
```

Stream chat with OpenAI-compatible message format.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `messages` | `list[dict]` | `yes` | `none` | List of chat messages (OpenAI format) |
| `max_tokens` | `int` | `no` | `256` | Maximum tokens to generate |
| `temperature` | `float` | `no` | `0.7` | Sampling temperature |
| `**kwargs` | `not annotated` | `no` | `none` | Additional parameters |

**Returns**

- Type: `Iterator[MLLMOutput]`
- Direct return expressions: `None`
- Yields values incrementally.

**Exceptions and behavior**

Method `MLXMultimodalLM.stream_chat` calls `self.load`, `self.chat`, `kwargs.pop`, `chat_template_kwargs.pop`; yields values incrementally; returns `None`.
No direct `raise` statement appears in this definition.

[View source #L2489-L2737](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2489-L2737).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.describe_image" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.describe_image</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.describe_image(image: str, prompt: str = 'Describe this image in detail.', max_tokens: int = 512, **kwargs) -> str
```

Convenience method to describe an image.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `image` | `str` | `yes` | `none` | Image path, URL, or base64 string |
| `prompt` | `str` | `no` | `'Describe this image in detail.'` | Description prompt |
| `max_tokens` | `int` | `no` | `512` | Maximum tokens |
| `**kwargs` | `not annotated` | `no` | `none` | Additional parameters |

**Returns**

- Type: `str`
- Direct return expressions: `output.text`

**Exceptions and behavior**

Method `MLXMultimodalLM.describe_image` calls `self.generate`; returns `output.text`.
No direct `raise` statement appears in this definition.

[View source #L2739-L2764](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2739-L2764).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.answer_about_image" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.answer_about_image</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.answer_about_image(image: str, question: str, max_tokens: int = 256, **kwargs) -> str
```

Answer a question about an image.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `image` | `str` | `yes` | `none` | Image path, URL, or base64 string |
| `question` | `str` | `yes` | `none` | Question about the image |
| `max_tokens` | `int` | `no` | `256` | Maximum tokens |
| `**kwargs` | `not annotated` | `no` | `none` | Additional parameters |

**Returns**

- Type: `str`
- Direct return expressions: `output.text`

**Exceptions and behavior**

Method `MLXMultimodalLM.answer_about_image` calls `self.generate`; returns `output.text`.
No direct `raise` statement appears in this definition.

[View source #L2766-L2791](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2766-L2791).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.describe_video" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.describe_video</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.describe_video(video: str | dict, prompt: str = 'Describe what happens in this video.', fps: float = 2.0, max_frames: int = 32, max_tokens: int = 512, **kwargs) -> str
```

Describe a video using frame extraction.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `video` | `str \| dict` | `yes` | `none` | Video file path, URL, base64, or OpenAI format dict |
| `prompt` | `str` | `no` | `'Describe what happens in this video.'` | Description prompt |
| `fps` | `float` | `no` | `2.0` | Frames per second to extract |
| `max_frames` | `int` | `no` | `32` | Maximum frames to extract |
| `max_tokens` | `int` | `no` | `512` | Maximum tokens to generate |
| `**kwargs` | `not annotated` | `no` | `none` | Additional variadic keyword inputs accepted by this callable. |

**Returns**

- Type: `str`
- Direct return expressions: `output.text`

**Exceptions and behavior**

Method `MLXMultimodalLM.describe_video` calls `self.generate`; returns `output.text`.
No direct `raise` statement appears in this definition.

[View source #L2793-L2830](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2793-L2830).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.get_cache_stats" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.get_cache_stats</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.get_cache_stats() -> dict
```

Get MLLM cache statistics.

**Parameters**

This callable has no explicit inputs.

**Returns**

- Type: `dict`
- Direct return expressions: `{'enabled': False}`; `stats`

**Exceptions and behavior**

Method `MLXMultimodalLM.get_cache_stats` calls `self._cache_manager.get_stats`, `len`; has 2 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L2832-L2846](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2832-L2846).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.clear_cache" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.clear_cache</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.clear_cache() -> None
```

Clear the MLLM KV cache.

**Parameters**

This callable has no explicit inputs.

**Returns**

- Type: `None`

**Exceptions and behavior**

Method `MLXMultimodalLM.clear_cache` calls `self._cache_manager.clear`, `logger.info`.
No direct `raise` statement appears in this definition.

[View source #L2848-L2852](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2848-L2852).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.get_model_info" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.get_model_info</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.get_model_info() -> dict
```

Get information about the loaded model.

**Parameters**

This callable has no explicit inputs.

**Returns**

- Type: `dict`
- Direct return expressions: `{'loaded': False, 'model_name': self.model_name}`; `info`

**Exceptions and behavior**

Method `MLXMultimodalLM.get_model_info` calls `getattr`, `self._cache_manager.get_stats`; has 2 explicit return paths.
No direct `raise` statement appears in this definition.

[View source #L2854-L2874](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2854-L2874).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.list_supported_model_families" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.list_supported_model_families</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.list_supported_model_families() -> dict[str, str]
```

List supported model families and their patterns.

**Parameters**

This callable has no explicit inputs.

**Returns**

- Type: `dict[str, str]`
- Direct return expressions: `{'Qwen-VL': 'Qwen VL models (Qwen2-VL, Qwen2.5-VL, Qwen3-VL, etc.)', 'LLaVA': 'LLaVA vision-language models', 'Idefics'…`

**Exceptions and behavior**

Method `MLXMultimodalLM.list_supported_model_families` returns `{'Qwen-VL': 'Qwen VL models (Qwen2-VL, Qwen2.5-VL, Qwen3-VL, etc.)', 'LLaVA': 'LLaVA vision-language models', 'Idefics'…`.
No direct `raise` statement appears in this definition.

[View source #L2877-L2897](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2877-L2897).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.is_mllm_model" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.is_mllm_model</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.is_mllm_model(model_name: str) -> bool
```

Check if a model name indicates an MLLM model.

**Parameters**

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `model_name` | `str` | `yes` | `none` | Required positional or keyword input. |

**Returns**

- Type: `bool`
- Direct return expressions: `any((pattern.lower() in model_lower for pattern in mllm_patterns))`

**Exceptions and behavior**

Method `MLXMultimodalLM.is_mllm_model` calls `model_name.lower`, `any`, `pattern.lower`; returns `any((pattern.lower() in model_lower for pattern in mllm_patterns))`.
No direct `raise` statement appears in this definition.

[View source #L2900-L2934](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2900-L2934).

</details>

<details class="api-contract" id="contract-vllm_mlx.models.mllm.MLXMultimodalLM.__repr__" markdown="1">
<summary><code>vllm_mlx.models.mllm.MLXMultimodalLM.__repr__</code> · method</summary>

```python
vllm_mlx.models.mllm.MLXMultimodalLM.__repr__() -> str
```

Method `MLXMultimodalLM.__repr__` returns `f'<MLXMultimodalLM model={self.model_name} status={status}>'`.

**Parameters**

This callable has no explicit inputs.

**Returns**

- Type: `str`
- Direct return expressions: `f'<MLXMultimodalLM model={self.model_name} status={status}>'`

**Exceptions and behavior**

Method `MLXMultimodalLM.__repr__` returns `f'<MLXMultimodalLM model={self.model_name} status={status}>'`.
No direct `raise` statement appears in this definition.

[View source #L2936-L2938](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2936-L2938).

</details>

## Complete symbol map

This map also includes private definitions and nested helpers. The signature column exposes every explicit input even when an internal helper has no dedicated parameter prose.

| Symbol | Kind | Signature and inputs | What it does | Source |
| --- | --- | --- | --- | --- |
| [`TempFileManager`](#contract-vllm_mlx.models.mllm.TempFileManager) | class | `TempFileManager()` | Thread-safe manager for tracking and cleaning up temporary files. | [#L41-L86](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L41-L86) |
| [`TempFileManager.__init__`](#contract-vllm_mlx.models.mllm.TempFileManager.__init__) | method | `TempFileManager.__init__() -> not annotated` | Method `TempFileManager.__init__` updates `self._files`, `self._lock`; calls `set`, `threading.Lock`, `atexit.register`. | [#L44-L47](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L44-L47) |
| [`TempFileManager.register`](#contract-vllm_mlx.models.mllm.TempFileManager.register) | method | `TempFileManager.register(path: str) -> str` | Register a temp file for tracking. | [#L49-L53](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L49-L53) |
| [`TempFileManager.cleanup`](#contract-vllm_mlx.models.mllm.TempFileManager.cleanup) | method | `TempFileManager.cleanup(path: str) -> bool` | Clean up a specific temp file. | [#L55-L67](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L55-L67) |
| [`TempFileManager.cleanup_all`](#contract-vllm_mlx.models.mllm.TempFileManager.cleanup_all) | method | `TempFileManager.cleanup_all() -> int` | Clean up all tracked temp files. | [#L69-L86](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L69-L86) |
| [`cleanup_temp_file`](#contract-vllm_mlx.models.mllm.cleanup_temp_file) | function | `cleanup_temp_file(path: str) -> bool` | Clean up a specific temporary file. | [#L93-L95](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L93-L95) |
| [`cleanup_all_temp_files`](#contract-vllm_mlx.models.mllm.cleanup_all_temp_files) | function | `cleanup_all_temp_files() -> int` | Clean up all tracked temporary files. | [#L98-L100](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L98-L100) |
| [`FileSizeExceededError`](#contract-vllm_mlx.models.mllm.FileSizeExceededError) | class | `FileSizeExceededError()` | Raised when a downloaded file exceeds the size limit. | [#L119-L122](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L119-L122) |
| [`UnsafeRemoteURLError`](#contract-vllm_mlx.models.mllm.UnsafeRemoteURLError) | class | `UnsafeRemoteURLError(message: str, *, public_message: str = 'Remote media URL is not allowed')` | Raised when a remote media URL targets an unsafe destination. | [#L125-L135](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L125-L135) |
| [`UnsafeRemoteURLError.__init__`](#contract-vllm_mlx.models.mllm.UnsafeRemoteURLError.__init__) | method | `UnsafeRemoteURLError.__init__(message: str, *, public_message: str = 'Remote media URL is not allowed') -> None` | Method `UnsafeRemoteURLError.__init__` updates `self.public_message`; calls `super().__init__`, `super`. | [#L128-L135](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L128-L135) |
| [`_normalize_content_part`](#contract-vllm_mlx.models.mllm._normalize_content_part) | function | `_normalize_content_part(item: object) -> object` | Convert Pydantic content parts into plain Python objects. | [#L138-L144](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L138-L144) |
| [`_extract_media_url`](#contract-vllm_mlx.models.mllm._extract_media_url) | function | `_extract_media_url(item: dict, item_type: str) -> str` | Function `_extract_media_url` calls `item.get`, `isinstance`, `media_value.get`; has 2 explicit return paths. | [#L147-L161](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L147-L161) |
| [`_text_content_part`](#contract-vllm_mlx.models.mllm._text_content_part) | function | `_text_content_part(text: str) -> dict[str, str]` | Function `_text_content_part` returns `{'type': 'text', 'text': text, 'content': text}`. | [#L164-L165](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L164-L165) |
| [`_append_text_content_part`](#contract-vllm_mlx.models.mllm._append_text_content_part) | function | `_append_text_content_part(built_parts: list[dict[str, str]], text_parts: list[str], text: str) -> None` | Function `_append_text_content_part` calls `built_parts.append`, `_text_content_part`, `text_parts.append`; returns `None`. | [#L168-L174](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L168-L174) |
| [`_build_string_mllm_message_content`](#contract-vllm_mlx.models.mllm._build_string_mllm_message_content) | function | `_build_string_mllm_message_content(content: str, role: str) -> tuple[object, bool]` | Function `_build_string_mllm_message_content` calls `_text_content_part`; has 3 explicit return paths. | [#L177-L182](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L177-L182) |
| [`_append_ordered_mllm_content_part`](#contract-vllm_mlx.models.mllm._append_ordered_mllm_content_part) | function | `_append_ordered_mllm_content_part(raw_item: object, *, built_parts: list[dict[str, str]], text_parts: list[str], all_image_urls: list[str], video_frame_count: int) -> int` | Function `_append_ordered_mllm_content_part` calls `_normalize_content_part`, `isinstance`, `_append_text_content_part`, `item.get`; has 2 explicit return paths. | [#L185-L220](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L185-L220) |
| [`_build_ordered_mllm_message_content`](#contract-vllm_mlx.models.mllm._build_ordered_mllm_message_content) | function | `_build_ordered_mllm_message_content(content: object, *, role: str, all_image_urls: list[str], video_frame_count: int = 0) -> tuple[object, bool]` | Build template content while preserving OpenAI media/text part order. | [#L223-L254](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L223-L254) |
| [`_normalize_mllm_tool_calls`](#contract-vllm_mlx.models.mllm._normalize_mllm_tool_calls) | function | `_normalize_mllm_tool_calls(tool_calls: list) -> list` | Normalize replayed assistant tool calls for chat templates. | [#L257-L268](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L257-L268) |
| [`_build_mllm_chat_messages`](#contract-vllm_mlx.models.mllm._build_mllm_chat_messages) | function | `_build_mllm_chat_messages(messages: list[dict], *, all_image_urls: list[str], video_frame_counts: dict[int, int]) -> list[dict]` | Build chat-template messages without reordering multimodal content parts. | [#L271-L315](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L271-L315) |
| [`MultimodalInput`](#contract-vllm_mlx.models.mllm.MultimodalInput) | class | `MultimodalInput(prompt: str, images: list[str] = field(default_factory=list), videos: list[str] = field(default_factory=list), audio: list[str] = field(default_factory=list))` | Input for multimodal generation. | [#L319-L325](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L319-L325) |
| [`MLLMOutput`](#contract-vllm_mlx.models.mllm.MLLMOutput) | class | `MLLMOutput(text: str, finish_reason: str \| None = None, prompt_tokens: int = 0, completion_tokens: int = 0, mtp_drafts: int = 0, mtp_accepted: int = 0)` | Output from multimodal language model. | [#L329-L337](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L329-L337) |
| [`load_gemma4_assistant_drafter`](#contract-vllm_mlx.models.mllm.load_gemma4_assistant_drafter) | function | `load_gemma4_assistant_drafter(model_path: str) -> not annotated` | Load a Gemma 4 assistant drafter for mlx-vlm speculative decoding. | [#L340-L381](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L340-L381) |
| [`_count_draft_tokens`](#contract-vllm_mlx.models.mllm._count_draft_tokens) | function | `_count_draft_tokens(draft_tokens) -> int` | Best-effort drafted-token count for an mlx-vlm drafter output. | [#L387-L398](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L387-L398) |
| [`_install_draft_metrics_hooks`](#contract-vllm_mlx.models.mllm._install_draft_metrics_hooks) | function | `_install_draft_metrics_hooks(draft_model) -> None` | Record actual drafted token counts from mlx-vlm assistant drafters. | [#L401-L428](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L401-L428) |
| [`_install_draft_metrics_hooks.draft_block_with_metrics`](#contract-vllm_mlx.models.mllm._install_draft_metrics_hooks.draft_block_with_metrics) | nested function | `_install_draft_metrics_hooks.draft_block_with_metrics(*args, **kwargs) -> not annotated` | Nested Function `_install_draft_metrics_hooks.draft_block_with_metrics` calls `draft_block`, `draft_model._vllm_mlx_draft_counts.append`, `_count_draft_tokens`; returns `draft_tokens`. | [#L412-L415](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L412-L415) |
| [`_install_draft_metrics_hooks.reset_with_metrics`](#contract-vllm_mlx.models.mllm._install_draft_metrics_hooks.reset_with_metrics) | nested function | `_install_draft_metrics_hooks.reset_with_metrics(*args, **kwargs) -> not annotated` | Nested Function `_install_draft_metrics_hooks.reset_with_metrics` calls `reset`; returns `reset(*args, **kwargs)`. | [#L422-L424](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L422-L424) |
| [`is_base64_image`](#contract-vllm_mlx.models.mllm.is_base64_image) | function | `is_base64_image(s: str) -> bool` | Check if string is base64-encoded image data. | [#L431-L435](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L431-L435) |
| [`is_url`](#contract-vllm_mlx.models.mllm.is_url) | function | `is_url(s: str) -> bool` | Check if string is a URL. | [#L438-L440](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L438-L440) |
| [`is_base64_video`](#contract-vllm_mlx.models.mllm.is_base64_video) | function | `is_base64_video(s: str) -> bool` | Check if string is base64-encoded video data. | [#L443-L445](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L443-L445) |
| [`is_base64_audio`](#contract-vllm_mlx.models.mllm.is_base64_audio) | function | `is_base64_audio(s: str) -> bool` | Check if string is base64-encoded audio data. | [#L448-L450](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L448-L450) |
| [`decode_base64_image`](#contract-vllm_mlx.models.mllm.decode_base64_image) | function | `decode_base64_image(base64_string: str, max_length: int = MAX_BASE64_IMAGE_LENGTH) -> bytes` | Decode base64 image to bytes. | [#L453-L480](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L453-L480) |
| [`_validate_url_safety`](#contract-vllm_mlx.models.mllm._validate_url_safety) | function | `_validate_url_safety(url: str) -> None` | Reject remote URLs that target local or private network resources. | [#L483-L519](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L483-L519) |
| [`_request_with_safe_redirects`](#contract-vllm_mlx.models.mllm._request_with_safe_redirects) | function | `_request_with_safe_redirects(method: str, url: str, *, timeout: int, headers: dict[str, str], stream: bool = False, max_redirects: int = 5) -> not annotated` | Issue a requests call while validating every redirect target. | [#L522-L557](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L522-L557) |
| [`download_image`](#contract-vllm_mlx.models.mllm.download_image) | function | `download_image(url: str, timeout: int = 30, max_size: int = MAX_IMAGE_SIZE) -> str` | Download image from URL and return local path. | [#L560-L645](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L560-L645) |
| [`_download_media`](#contract-vllm_mlx.models.mllm._download_media) | function | `_download_media(url: str, media_type: str, ext_map: dict[str, str], default_ext: str, timeout: int, max_size: int) -> str` | Download media from URL, enforce size limits, and return a local temp path. | [#L670-L748](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L670-L748) |
| [`download_video`](#contract-vllm_mlx.models.mllm.download_video) | function | `download_video(url: str, timeout: int = 120, max_size: int = MAX_VIDEO_SIZE) -> str` | Download video from URL and return local path. | [#L751-L753](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L751-L753) |
| [`download_audio`](#contract-vllm_mlx.models.mllm.download_audio) | function | `download_audio(url: str, timeout: int = 120, max_size: int = MAX_AUDIO_SIZE) -> str` | Download audio from URL and return local path. | [#L756-L758](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L756-L758) |
| [`decode_base64_video`](#contract-vllm_mlx.models.mllm.decode_base64_video) | function | `decode_base64_video(base64_string: str, max_length: int = MAX_BASE64_VIDEO_LENGTH) -> str` | Decode base64 video to temp file and return path. | [#L761-L807](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L761-L807) |
| [`decode_base64_audio`](#contract-vllm_mlx.models.mllm.decode_base64_audio) | function | `decode_base64_audio(base64_string: str, max_length: int = MAX_BASE64_AUDIO_LENGTH) -> str` | Decode base64 audio to temp file and return path. | [#L810-L836](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L810-L836) |
| [`process_video_input`](#contract-vllm_mlx.models.mllm.process_video_input) | function | `process_video_input(video: str \| dict) -> str` | Process video input in various formats and return local path. | [#L839-L874](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L839-L874) |
| [`process_audio_input`](#contract-vllm_mlx.models.mllm.process_audio_input) | function | `process_audio_input(audio: str \| dict) -> str` | Process audio input in various formats and return local path. | [#L877-L905](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L877-L905) |
| [`_video_has_audio_track`](#contract-vllm_mlx.models.mllm._video_has_audio_track) | function | `_video_has_audio_track(video_path: str) -> bool` | Return True if ffprobe finds an audio stream in the video. | [#L908-L935](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L908-L935) |
| [`_model_has_sound_encoder`](#contract-vllm_mlx.models.mllm._model_has_sound_encoder) | function | `_model_has_sound_encoder(model) -> bool` | Whether a loaded model exposes a usable sound encoder. | [#L938-L947](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L938-L947) |
| [`extract_audio_from_video`](#contract-vllm_mlx.models.mllm.extract_audio_from_video) | function | `extract_audio_from_video(video_path: str) -> str \| None` | Extract the audio track from a video file as 16 kHz mono WAV. | [#L950-L1005](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L950-L1005) |
| [`save_base64_image`](#contract-vllm_mlx.models.mllm.save_base64_image) | function | `save_base64_image(base64_string: str) -> str` | Save base64 image to temp file and return path. | [#L1012-L1048](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1012-L1048) |
| [`process_image_input`](#contract-vllm_mlx.models.mllm.process_image_input) | function | `process_image_input(image: str \| dict) -> str` | Process image input in various formats and return local path. | [#L1051-L1080](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1051-L1080) |
| [`round_by_factor`](#contract-vllm_mlx.models.mllm.round_by_factor) | function | `round_by_factor(x: int, factor: int) -> int` | Round to nearest multiple of factor. | [#L1083-L1085](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1083-L1085) |
| [`ceil_by_factor`](#contract-vllm_mlx.models.mllm.ceil_by_factor) | function | `ceil_by_factor(x: float, factor: int) -> int` | Ceiling to next multiple of factor. | [#L1088-L1090](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1088-L1090) |
| [`floor_by_factor`](#contract-vllm_mlx.models.mllm.floor_by_factor) | function | `floor_by_factor(x: float, factor: int) -> int` | Floor to previous multiple of factor. | [#L1093-L1095](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1093-L1095) |
| [`smart_nframes`](#contract-vllm_mlx.models.mllm.smart_nframes) | function | `smart_nframes(total_frames: int, video_fps: float, target_fps: float = DEFAULT_FPS, min_frames: int = MIN_FRAMES, max_frames: int = MAX_FRAMES) -> int` | Calculate optimal number of frames to extract from video. | [#L1098-L1120](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1098-L1120) |
| [`extract_video_frames_smart`](#contract-vllm_mlx.models.mllm.extract_video_frames_smart) | function | `extract_video_frames_smart(video_path: str, fps: float = DEFAULT_FPS, max_frames: int = MAX_FRAMES, resize: tuple[int, int] \| None = None) -> list[np.ndarray]` | Extract frames from video with smart sampling. | [#L1123-L1187](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1123-L1187) |
| [`save_frames_to_temp`](#contract-vllm_mlx.models.mllm.save_frames_to_temp) | function | `save_frames_to_temp(frames: list[np.ndarray]) -> list[str]` | Save frame arrays to temporary files and return paths. | [#L1190-L1204](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1190-L1204) |
| [`MLXMultimodalLM`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM) | class | `MLXMultimodalLM(model_name: str, trust_remote_code: bool = False, enable_cache: bool = True, cache_size: int = 50, max_kv_size: int = 0, draft_model: str \| None = None, draft_kind: str \| None = None, draft_block_size: int \| None = None)` | Wrapper around mlx-vlm for multimodal inference. | [#L1207-L2938](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1207-L2938) |
| [`MLXMultimodalLM.__init__`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.__init__) | method | `MLXMultimodalLM.__init__(model_name: str, trust_remote_code: bool = False, enable_cache: bool = True, cache_size: int = 50, max_kv_size: int = 0, draft_model: str \| None = None, draft_kind: str \| None = None, draft_block_size: int \| None = None) -> not annotated` | Initialize the MLX multimodal language model. | [#L1235-L1278](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1235-L1278) |
| [`MLXMultimodalLM.load`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.load) | method | `MLXMultimodalLM.load() -> None` | Load the model and processor. | [#L1280-L1323](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1280-L1323) |
| [`MLXMultimodalLM._load_draft_model`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM._load_draft_model) | method | `MLXMultimodalLM._load_draft_model() -> not annotated` | Method `MLXMultimodalLM._load_draft_model` calls `load_gemma4_assistant_drafter`, `load`; has 2 explicit return paths. | [#L1325-L1332](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1325-L1332) |
| [`MLXMultimodalLM._draft_generation_kwargs`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM._draft_generation_kwargs) | method | `MLXMultimodalLM._draft_generation_kwargs(call_kwargs: dict \| None = None) -> dict` | Return mlx-vlm drafter kwargs when the request explicitly opts in. | [#L1334-L1355](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1334-L1355) |
| [`MLXMultimodalLM._reset_draft_metrics`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM._reset_draft_metrics) | method | `MLXMultimodalLM._reset_draft_metrics() -> int` | Method `MLXMultimodalLM._reset_draft_metrics` updates `self._draft_model.accept_lens`, `self._draft_model._vllm_mlx_draft_counts`; calls `hasattr`; returns `0`. | [#L1357-L1364](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1357-L1364) |
| [`MLXMultimodalLM._draft_metrics_since`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM._draft_metrics_since) | method | `MLXMultimodalLM._draft_metrics_since(start_accept_lens: int) -> dict[str, int]` | Method `MLXMultimodalLM._draft_metrics_since` calls `list`, `getattr`, `len`, `int`; has 2 explicit return paths. | [#L1366-L1395](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1366-L1395) |
| [`MLXMultimodalLM.get_language_model`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.get_language_model) | method | `MLXMultimodalLM.get_language_model() -> not annotated` | Extract the underlying language model for mlx_lm TextModel construction. | [#L1397-L1399](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1397-L1399) |
| [`MLXMultimodalLM.get_tokenizer`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.get_tokenizer) | method | `MLXMultimodalLM.get_tokenizer() -> not annotated` | Get the text tokenizer (not the multimodal processor). | [#L1401-L1403](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1401-L1403) |
| [`MLXMultimodalLM._prepare_images`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM._prepare_images) | method | `MLXMultimodalLM._prepare_images(images: list) -> list[str]` | Process remote/base64 image inputs into local temp file paths. | [#L1405-L1414](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1405-L1414) |
| [`MLXMultimodalLM._prepare_audio`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM._prepare_audio) | method | `MLXMultimodalLM._prepare_audio(audio_inputs: list) -> list[str]` | Process audio inputs and return local file paths. | [#L1416-L1425](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1416-L1425) |
| [`MLXMultimodalLM._prepare_video`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM._prepare_video) | method | `MLXMultimodalLM._prepare_video(video_input: str \| dict, fps: float = DEFAULT_FPS, max_frames: int = MAX_FRAMES, resolved_path: str \| None = None) -> list[str]` | Process video input and extract frames. | [#L1427-L1463](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1427-L1463) |
| [`MLXMultimodalLM._collect_video_inputs`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM._collect_video_inputs) | method | `MLXMultimodalLM._collect_video_inputs(messages: list[dict]) -> dict[int, list]` | Collect video inputs from messages, keyed by message index. | [#L1465-L1497](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1465-L1497) |
| [`MLXMultimodalLM._collect_audio_inputs`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM._collect_audio_inputs) | method | `MLXMultimodalLM._collect_audio_inputs(messages: list[dict]) -> dict[int, list]` | Collect audio inputs from messages, keyed by message index. | [#L1499-L1528](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1499-L1528) |
| [`MLXMultimodalLM._prepare_native_video_inputs`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM._prepare_native_video_inputs) | method | `MLXMultimodalLM._prepare_native_video_inputs(messages: list[dict], video_fps: float = DEFAULT_FPS, video_max_frames: int = MAX_FRAMES, tools: list \| None = None) -> tuple[str, dict]` | Preprocess messages into prompt + generation kwargs for native video. | [#L1530-L1648](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1530-L1648) |
| [`MLXMultimodalLM._generate_native_video`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM._generate_native_video) | method | `MLXMultimodalLM._generate_native_video(messages: list[dict], max_tokens: int = 256, temperature: float = 0.7, video_fps: float = DEFAULT_FPS, video_max_frames: int = MAX_FRAMES, tools: list \| None = None, **kwargs) -> MLLMOutput` | Generate using native video pipeline (Qwen-family models). | [#L1650-L1695](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1650-L1695) |
| [`MLXMultimodalLM._translate_messages_for_native_video`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM._translate_messages_for_native_video) | method | `MLXMultimodalLM._translate_messages_for_native_video(messages: list[dict], video_fps: float, video_max_frames: int) -> list[dict]` | Translate OpenAI API format messages to process_vision_info format. | [#L1697-L1832](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1697-L1832) |
| [`MLXMultimodalLM.generate`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.generate) | method | `MLXMultimodalLM.generate(prompt: str, images: list \| None = None, videos: list \| None = None, audio: list[str] \| None = None, max_tokens: int = 256, temperature: float = 0.7, top_p: float = 0.9, video_fps: float = DEFAULT_FPS, video_max_frames: int = MAX_FRAMES, use_cache: bool = True, **kwargs) -> MLLMOutput` | Generate text from multimodal input. | [#L1834-L2002](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L1834-L2002) |
| [`MLXMultimodalLM.stream_generate`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.stream_generate) | method | `MLXMultimodalLM.stream_generate(prompt: str, images: list \| None = None, videos: list[str] \| None = None, audio: list[str] \| None = None, max_tokens: int = 256, temperature: float = 0.7, video_fps: float = DEFAULT_FPS, **kwargs) -> Iterator[str]` | Stream text generation for multimodal input. | [#L2004-L2093](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2004-L2093) |
| [`MLXMultimodalLM.chat`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.chat) | method | `MLXMultimodalLM.chat(messages: list[dict], max_tokens: int = 256, temperature: float = 0.7, **kwargs) -> MLLMOutput` | Chat with OpenAI-compatible message format. | [#L2095-L2487](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2095-L2487) |
| [`MLXMultimodalLM.stream_chat`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.stream_chat) | method | `MLXMultimodalLM.stream_chat(messages: list[dict], max_tokens: int = 256, temperature: float = 0.7, **kwargs) -> Iterator[MLLMOutput]` | Stream chat with OpenAI-compatible message format. | [#L2489-L2737](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2489-L2737) |
| [`MLXMultimodalLM.describe_image`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.describe_image) | method | `MLXMultimodalLM.describe_image(image: str, prompt: str = 'Describe this image in detail.', max_tokens: int = 512, **kwargs) -> str` | Convenience method to describe an image. | [#L2739-L2764](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2739-L2764) |
| [`MLXMultimodalLM.answer_about_image`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.answer_about_image) | method | `MLXMultimodalLM.answer_about_image(image: str, question: str, max_tokens: int = 256, **kwargs) -> str` | Answer a question about an image. | [#L2766-L2791](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2766-L2791) |
| [`MLXMultimodalLM.describe_video`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.describe_video) | method | `MLXMultimodalLM.describe_video(video: str \| dict, prompt: str = 'Describe what happens in this video.', fps: float = 2.0, max_frames: int = 32, max_tokens: int = 512, **kwargs) -> str` | Describe a video using frame extraction. | [#L2793-L2830](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2793-L2830) |
| [`MLXMultimodalLM.get_cache_stats`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.get_cache_stats) | method | `MLXMultimodalLM.get_cache_stats() -> dict` | Get MLLM cache statistics. | [#L2832-L2846](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2832-L2846) |
| [`MLXMultimodalLM.clear_cache`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.clear_cache) | method | `MLXMultimodalLM.clear_cache() -> None` | Clear the MLLM KV cache. | [#L2848-L2852](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2848-L2852) |
| [`MLXMultimodalLM.get_model_info`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.get_model_info) | method | `MLXMultimodalLM.get_model_info() -> dict` | Get information about the loaded model. | [#L2854-L2874](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2854-L2874) |
| [`MLXMultimodalLM.list_supported_model_families`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.list_supported_model_families) | method | `MLXMultimodalLM.list_supported_model_families() -> dict[str, str]` | List supported model families and their patterns. | [#L2877-L2897](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2877-L2897) |
| [`MLXMultimodalLM.is_mllm_model`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.is_mllm_model) | method | `MLXMultimodalLM.is_mllm_model(model_name: str) -> bool` | Check if a model name indicates an MLLM model. | [#L2900-L2934](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2900-L2934) |
| [`MLXMultimodalLM.__repr__`](#contract-vllm_mlx.models.mllm.MLXMultimodalLM.__repr__) | method | `MLXMultimodalLM.__repr__() -> str` | Method `MLXMultimodalLM.__repr__` returns `f'<MLXMultimodalLM model={self.model_name} status={status}>'`. | [#L2936-L2938](https://github.com/waybarrios/vllm-mlx/blob/a69d47912bcb21d8fe04d48f75fa896b620ffcfa/vllm_mlx/models/mllm.py#L2936-L2938) |
