# Whisper Capability


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

------------------------------------------------------------------------

### WhisperCapabilityConfig

``` python

def WhisperCapabilityConfig(
    model:str='base', device:str='auto', language:Optional=None, task:str='transcribe', temperature:float=0.0,
    temperature_increment_on_fallback:Optional=0.2, beam_size:int=5, best_of:int=5, patience:float=1.0,
    length_penalty:Optional=None, suppress_tokens:str='-1', initial_prompt:Optional=None,
    condition_on_previous_text:bool=False, fp16:bool=True, compression_ratio_threshold:float=2.4,
    logprob_threshold:float=-1.0, no_speech_threshold:float=0.6, word_timestamps:bool=False,
    prepend_punctuations:str='"\'“¿([{-', append_punctuations:str='"\'.。,，!！?？:：”)]}、', threads:int=0,
    model_dir:Optional=None, compile_model:bool=False
)->None:

```

*Configuration for Whisper transcription capability.*

------------------------------------------------------------------------

### WhisperLocalCapability

``` python

def WhisperLocalCapability(
    
):

```

*OpenAI Whisper transcription capability (stage 8: pure-compute tool
capability).*

Native-surface model (PILLAR 1c): this tool is PURE COMPUTE —
`transcribe` loads the model, runs inference, and builds the typed
`TranscriptionResult`. The cache-check + persistence bookends + the
per-call `force` control live in the generic transcription adapter
(cjm-transcription-adapter-interface); the result DTO lives in
cjm-capability-primitives; identity is derived from the installed
distribution. No `get_plugin_metadata`, no `self.storage`.

------------------------------------------------------------------------

### WhisperLocalCapability.is_available

``` python

def is_available(
    
)->bool: # True if Whisper and its dependencies are available

```

*Check if Whisper is available.*

------------------------------------------------------------------------

### WhisperLocalCapability.prefetch

``` python

def prefetch(
    
)->None:

```

*CR-4 (SG-19): eagerly load the model so the first execute() doesn’t
pay* the download/load cost. Idempotent via \_load_model’s None-guard.

------------------------------------------------------------------------

### WhisperLocalCapability.on_disable

``` python

def on_disable(
    
)->None:

```

*CR-2: release the GPU model when the operator disables the capability
(the* worker stays alive); lazy reload on the next execute after
re-enable.

------------------------------------------------------------------------

### WhisperLocalCapability.cleanup

``` python

def cleanup(
    
)->None:

```

*Release resources on unload.*

## Testing the Capability

``` python
# Basic functionality (stage-8: pure-compute ToolCapability).
from cjm_substrate.core.capability import ToolCapability

capability = WhisperLocalCapability()
assert isinstance(capability, ToolCapability)
print(f"Whisper available: {capability.is_available()}")
print(f"Capability version: {capability.version}")
print(f"Config class: {capability.config_class.__name__}")

# Native-surface model: pure-compute `transcribe` replaces the fused `execute`;
# cache/persist + identity moved out. `name` is derived from the installed dist
# at runtime (worker / in-env introspection), so it is NOT exercised in-notebook
# where __package__ is unset.
assert hasattr(capability, "transcribe") and not hasattr(capability, "execute")
assert not hasattr(capability, "supported_formats")
print("WhisperLocalCapability is a pure-compute ToolCapability (transcribe; no execute/cache/storage)")
```

    Whisper available: False
    Capability version: 0.0.41
    Config class: WhisperCapabilityConfig
    WhisperLocalCapability is a pure-compute ToolCapability (transcribe; no execute/cache/storage)

``` python
# Test configuration dataclass
from dataclasses import fields

print("Available models:")
model_field = next(f for f in fields(WhisperCapabilityConfig) if f.name == "model")
for model in model_field.metadata.get(SCHEMA_ENUM, []):
    print(f"  - {model}")
```

    Available models:
      - tiny
      - tiny.en
      - base
      - base.en
      - small
      - small.en
      - medium
      - medium.en
      - large
      - large-v1
      - large-v2
      - large-v3

``` python
# Test configuration validation
test_configs = [
    ({"model": "tiny"}, "Valid config"),
    ({"model": "invalid"}, "Invalid model"),
    ({"model": "tiny", "temperature": 1.5}, "Temperature out of range"),
]

for config, description in test_configs:
    try:
        test_cfg = dict_to_config(WhisperCapabilityConfig, config, validate=True)
        print(f"{description}: Valid=True")
    except ValueError as e:
        print(f"{description}: Valid=False")
        print(f"  Error: {str(e)[:100]}")
```

    Valid config: Valid=True
    Invalid model: Valid=False
      Error: model: 'invalid' is not one of ['tiny', 'tiny.en', 'base', 'base.en', 'small', 'small.en', 'medium',
    Temperature out of range: Valid=False
      Error: temperature: 1.5 is greater than maximum 1.0

``` python
# Test initialization and get_current_config (returns dict now)
capability.initialize({"model": "tiny", "device": "cpu"})
current_config = capability.get_current_config()
print(f"Current config (dict): {current_config}")
print(f"Current model: {current_config['model']}")
```

    Current config (dict): {'model': 'tiny', 'device': 'cpu', 'language': None, 'task': 'transcribe', 'temperature': 0.0, 'temperature_increment_on_fallback': 0.2, 'beam_size': 5, 'best_of': 5, 'patience': 1.0, 'length_penalty': None, 'suppress_tokens': '-1', 'initial_prompt': None, 'condition_on_previous_text': False, 'fp16': True, 'compression_ratio_threshold': 2.4, 'logprob_threshold': -1.0, 'no_speech_threshold': 0.6, 'word_timestamps': False, 'prepend_punctuations': '"\'“¿([{-', 'append_punctuations': '"\'.。,，!！?？:：”)]}、', 'threads': 0, 'model_dir': None, 'compile_model': False}
    Current model: tiny

``` python
# Test get_config_schema for UI generation
import json

schema = capability.get_config_schema()
print("JSON Schema for WhisperCapabilityConfig:")
print(f"  Name: {schema['name']}")
print(f"  Properties count: {len(schema['properties'])}")
print(f"  Model field enum: {schema['properties']['model'].get('enum', [])[:3]}...")
print(f"\nFull schema (truncated):")
print(json.dumps({k: v for k, v in list(schema['properties'].items())[:3]}, indent=2))
```

    JSON Schema for WhisperCapabilityConfig:
      Name: WhisperCapabilityConfig
      Properties count: 23
      Model field enum: ['tiny', 'tiny.en', 'base']...

    Full schema (truncated):
    {
      "model": {
        "type": "string",
        "title": "Model",
        "description": "Whisper model size. Larger models are more accurate but slower.",
        "enum": [
          "tiny",
          "tiny.en",
          "base",
          "base.en",
          "small",
          "small.en",
          "medium",
          "medium.en",
          "large",
          "large-v1",
          "large-v2",
          "large-v3"
        ],
        "default": "base"
      },
      "device": {
        "type": "string",
        "title": "Device",
        "description": "Device for inference (auto will use CUDA if available)",
        "enum": [
          "auto",
          "cpu",
          "cuda"
        ],
        "default": "auto"
      },
      "language": {
        "type": [
          "string",
          "null"
        ],
        "title": "Language",
        "description": "Language code (e.g., 'en', 'es', 'fr') or None for auto-detection",
        "default": null
      }
    }

``` python
# Test idempotent initialize - model unload on config change
import logging

# Enable logging to see model unload messages
logging.basicConfig(level=logging.INFO)

# Initialize with one model
capability.initialize({"model": "tiny", "device": "cpu"})
print(f"Initial config: model={capability.config.model}")

# Re-initialize with same model (no unload should happen)
print("\nRe-initializing with same model...")
capability.initialize({"model": "tiny", "device": "cpu"})

# Re-initialize with different model (unload should trigger)
print("\nRe-initializing with different model...")
capability.initialize({"model": "base", "device": "cpu"})
print(f"New config: model={capability.config.model}")
```

    INFO:__main__.WhisperLocalCapability:Initialized Whisper capability with model 'tiny' on device 'cpu'
    INFO:__main__.WhisperLocalCapability:Initialized Whisper capability with model 'tiny' on device 'cpu'
    INFO:__main__.WhisperLocalCapability:Config change: Model tiny -> base
    INFO:__main__.WhisperLocalCapability:Initialized Whisper capability with model 'base' on device 'cpu'

    Initial config: model=tiny

    Re-initializing with same model...

    Re-initializing with different model...
    New config: model=base
