plugin manager

Plugin discovery, loading, and lifecycle management system

source

PluginManager

 PluginManager (plugin_interface:Type[cjm_transcription_plugin_system.plug
                in_interface.PluginInterface]=<class 'cjm_transcription_pl
                ugin_system.plugin_interface.PluginInterface'>,
                entry_point_group:str='transcription.plugins')

Manages plugin discovery, loading, and lifecycle.

Type Default Details
plugin_interface Type PluginInterface The base class/interface plugins must implement
entry_point_group str transcription.plugins The entry point group name for plugin discovery

source

reload_plugin

 reload_plugin (plugin_name:str, config:Optional[Dict[str,Any]]=None)

*Reload a plugin with optional new configuration.

This is useful when you want to completely restart a plugin, for example after updating its code during development.*

Type Default Details
plugin_name str Name of the plugin to reload
config Optional None Optional new configuration
Returns bool True if successful, False otherwise

source

get_all_plugin_schemas

 get_all_plugin_schemas ()

*Get configuration schemas for all loaded plugins.

Returns a dictionary where keys are plugin names and values are their configuration schemas.*


source

validate_plugin_config

 validate_plugin_config (plugin_name:str, config:Dict[str,Any])

*Validate a configuration dictionary for a plugin without applying it.

Returns: Tuple of (is_valid, error_message). If valid, error_message is None.*

Type Details
plugin_name str Name of the plugin
config Dict Configuration to validate
Returns Tuple (is_valid, error_message)

source

update_plugin_config

 update_plugin_config (plugin_name:str, config:Dict[str,Any],
                       merge:bool=True)

*Update a plugin’s configuration and reinitialize it.

Args: plugin_name: Name of the plugin to update config: New configuration dictionary merge: If True, merge with existing config. If False, replace entirely.

Returns: True if configuration was successfully updated, False otherwise.*

Type Default Details
plugin_name str Name of the plugin
config Dict New configuration
merge bool True Whether to merge with existing config or replace entirely
Returns bool True if successful, False otherwise

source

get_plugin_config

 get_plugin_config (plugin_name:str)

*Get the current configuration of a plugin.

Returns the actual configuration values being used by the plugin, including any defaults.*

Type Details
plugin_name str Name of the plugin
Returns Optional Current configuration or None if plugin not found

source

get_plugin_config_schema

 get_plugin_config_schema (plugin_name:str)

*Get the configuration schema for a plugin.

Returns the JSON Schema that describes all configuration options available for the specified plugin.*

Type Details
plugin_name str Name of the plugin
Returns Optional Configuration schema or None if plugin not found

source

get_streaming_plugins

 get_streaming_plugins ()

*Get a list of all loaded plugins that support streaming.

Returns: List of plugin names that have streaming capabilities.*


source

check_streaming_support

 check_streaming_support (plugin_name:str)

*Check if a plugin supports streaming transcription.

Returns: True if the plugin implements execute_stream and supports streaming, False otherwise.*

Type Details
plugin_name str Name of the plugin to check
Returns bool True if plugin supports streaming

source

execute_plugin_stream

 execute_plugin_stream (plugin_name:str, audio:Any, **kwargs)

*Execute a plugin with streaming support if available.

This method will use the plugin’s execute_stream method if the plugin supports streaming, otherwise it falls back to the regular execute method.

Args: plugin_name: Name of the plugin to execute audio: Audio data or path to audio file **kwargs: Additional plugin-specific parameters

Yields: str: Partial transcription text chunks as they become available

Returns: Final transcription result from the plugin

Example: >>> # Stream transcription in real-time >>> for chunk in manager.execute_plugin_stream(“gemini”, audio_file): … print(chunk, end=““, flush=True)*

Type Details
plugin_name str Name of the plugin to execute
audio Any Audio data or path
kwargs VAR_KEYWORD
Returns Generator Generator yielding text chunks, returns final result
logging.basicConfig(level=logging.INFO)
from nbdev.config import get_config
project_config = get_config()

test_files_dir = project_config.config_path/"test_files"
file_path = test_files_dir/"example_plugin.py"

# Create plugin manager
plugin_manager = PluginManager()

# Discover installed plugins
print("Discovering plugins...")
discovered = plugin_manager.discover_plugins()
print(f"Found {len(discovered)} plugins")

# Load discovered plugins
for plugin_meta in discovered:
    plugin_manager.load_plugin(plugin_meta, config={"debug": True})

print(plugin_manager.load_plugin_from_module(file_path))
example_plugin_name = plugin_manager.list_plugins()[0].name
print(f"Plugin Name: {example_plugin_name}")

# List loaded plugins
print("\nLoaded plugins:")
for meta in plugin_manager.list_plugins():
    print(f"  - {meta.name} v{meta.version} (enabled: {meta.enabled})")

# Execute a plugin
if plugin_manager.get_plugin(example_plugin_name):
    result = plugin_manager.execute_plugin(example_plugin_name, "test", key="value")
    print(f"\nPlugin result: {result}")

# Disable/enable plugins
plugin_manager.disable_plugin(example_plugin_name)
plugin_manager.enable_plugin(example_plugin_name)
INFO:example_plugin.WhisperPlugin:Initializing Whisper with config: {'model': 'base', 'device': 'auto', 'compute_type': 'default', 'language': None, 'task': 'transcribe', 'temperature': 0.0, 'beam_size': 5, 'best_of': 5, 'patience': 1.0, 'length_penalty': None, 'suppress_tokens': '-1', 'initial_prompt': None, 'condition_on_previous_text': True, 'no_speech_threshold': 0.6, 'compression_ratio_threshold': 2.4, 'logprob_threshold': -1.0, 'word_timestamps': False, 'prepend_punctuations': '"\'“¿([{-', 'append_punctuations': '"\'.。,,!!??::”)]}、', 'vad_filter': False, 'vad_parameters': {}}
INFO:__main__.PluginManager:Loaded plugin from module: whisper
INFO:example_plugin.WhisperPlugin:Transcribing with Whisper model: WhisperModel-base
INFO:example_plugin.WhisperPlugin:Execution config: {'model': 'base', 'device': 'auto', 'compute_type': 'default', 'language': None, 'task': 'transcribe', 'temperature': 0.0, 'beam_size': 5, 'best_of': 5, 'patience': 1.0, 'length_penalty': None, 'suppress_tokens': '-1', 'initial_prompt': None, 'condition_on_previous_text': True, 'no_speech_threshold': 0.6, 'compression_ratio_threshold': 2.4, 'logprob_threshold': -1.0, 'word_timestamps': False, 'prepend_punctuations': '"\'“¿([{-', 'append_punctuations': '"\'.。,,!!??::”)]}、', 'vad_filter': False, 'vad_parameters': {}, 'key': 'value'}
Discovering plugins...
Found 0 plugins
True
Plugin Name: whisper

Loaded plugins:
  - whisper v1.0.0 (enabled: True)

Plugin result: TranscriptionResult(text='Mock transcription using base model', confidence=0.95, segments=[{'start': 0.0, 'end': 2.5, 'text': 'Mock transcription', 'confidence': 0.96}, {'start': 2.5, 'end': 5.0, 'text': 'using base model', 'confidence': 0.94}], metadata={'model': 'base', 'language': None, 'device': 'auto', 'task': 'transcribe'})
True

Configuration Management Example

This section demonstrates how to use the configuration schema methods to manage plugin configurations.

# Demonstration of plugin configuration management
import json
from pathlib import Path

# Setup
logging.basicConfig(level=logging.INFO)
from nbdev.config import get_config
project_config = get_config()
test_files_dir = project_config.config_path/"test_files"
file_path = test_files_dir/"example_plugin.py"

# Create plugin manager and load the Whisper example plugin
plugin_manager = PluginManager()
plugin_manager.load_plugin_from_module(file_path)

print("="*60)
print("PLUGIN CONFIGURATION MANAGEMENT DEMONSTRATION")
print("="*60)

# 1. Get plugin configuration schema
schema = plugin_manager.get_plugin_config_schema("whisper")
print("\n1. Configuration Schema (first 5 properties):")
print("-" * 40)
if schema:
    props = list(schema.get("properties", {}).items())[:5]
    for prop_name, prop_schema in props:
        print(f"  {prop_name}:")
        print(f"    Type: {prop_schema.get('type')}")
        print(f"    Default: {prop_schema.get('default')}")
        if 'enum' in prop_schema:
            print(f"    Options: {prop_schema['enum'][:3]}...")

# 2. Get current plugin configuration
current_config = plugin_manager.get_plugin_config("whisper")
print("\n2. Current Configuration (subset):")
print("-" * 40)
if current_config:
    config_subset = {k: current_config[k] for k in ["model", "device", "language", "temperature"] if k in current_config}
    print(json.dumps(config_subset, indent=2))

# 3. Validate configurations
print("\n3. Configuration Validation:")
print("-" * 40)
test_configs = [
    ({"model": "small"}, "Valid partial config"),
    ({"model": "invalid"}, "Invalid model value"),
    ({"temperature": 2.0}, "Temperature out of range"),
]

for config, description in test_configs:
    is_valid, error = plugin_manager.validate_plugin_config("whisper", config)
    print(f"{description}:")
    print(f"  Config: {config}")
    print(f"  Valid: {is_valid}")
    if error:
        print(f"  Error: {error[:100]}...")  # Truncate long errors
    print()

# 4. Update plugin configuration
print("\n4. Updating Plugin Configuration:")
print("-" * 40)
new_config = {
    "model": "large-v3",
    "device": "cuda",
    "temperature": 0.2,
    "word_timestamps": True
}
success = plugin_manager.update_plugin_config("whisper", new_config, merge=True)
print(f"Update successful: {success}")

if success:
    updated_config = plugin_manager.get_plugin_config("whisper")
    config_subset = {k: updated_config[k] for k in ["model", "device", "temperature", "word_timestamps"] if k in updated_config}
    print("Updated configuration:")
    print(json.dumps(config_subset, indent=2))

# 5. Get all plugin schemas (useful for UI generation)
print("\n5. All Plugin Schemas:")
print("-" * 40)
all_schemas = plugin_manager.get_all_plugin_schemas()
for plugin_name, schema in all_schemas.items():
    print(f"Plugin: {plugin_name}")
    print(f"  Title: {schema.get('title', 'N/A')}")
    print(f"  Required fields: {schema.get('required', [])}")
    print(f"  Number of properties: {len(schema.get('properties', {}))}")

# 6. Execute plugin with runtime config override
print("\n6. Execute with Runtime Config Override:")
print("-" * 40)
result = plugin_manager.execute_plugin("whisper", "test_audio.wav", temperature=0.5, language="es")
print(f"Result: {result.text}")
INFO:example_plugin.WhisperPlugin:Initializing Whisper with config: {'model': 'base', 'device': 'auto', 'compute_type': 'default', 'language': None, 'task': 'transcribe', 'temperature': 0.0, 'beam_size': 5, 'best_of': 5, 'patience': 1.0, 'length_penalty': None, 'suppress_tokens': '-1', 'initial_prompt': None, 'condition_on_previous_text': True, 'no_speech_threshold': 0.6, 'compression_ratio_threshold': 2.4, 'logprob_threshold': -1.0, 'word_timestamps': False, 'prepend_punctuations': '"\'“¿([{-', 'append_punctuations': '"\'.。,,!!??::”)]}、', 'vad_filter': False, 'vad_parameters': {}}
INFO:__main__.PluginManager:Loaded plugin from module: whisper
INFO:example_plugin.WhisperPlugin:Cleaning up Whisper model
INFO:example_plugin.WhisperPlugin:Initializing Whisper with config: {'model': 'large-v3', 'device': 'cuda', 'compute_type': 'default', 'language': None, 'task': 'transcribe', 'temperature': 0.2, 'beam_size': 5, 'best_of': 5, 'patience': 1.0, 'length_penalty': None, 'suppress_tokens': '-1', 'initial_prompt': None, 'condition_on_previous_text': True, 'no_speech_threshold': 0.6, 'compression_ratio_threshold': 2.4, 'logprob_threshold': -1.0, 'word_timestamps': True, 'prepend_punctuations': '"\'“¿([{-', 'append_punctuations': '"\'.。,,!!??::”)]}、', 'vad_filter': False, 'vad_parameters': {'threshold': 0.5, 'min_speech_duration_ms': 250, 'max_speech_duration_s': 3600}}
INFO:__main__.PluginManager:Updated configuration for plugin: whisper
INFO:example_plugin.WhisperPlugin:Transcribing with Whisper model: WhisperModel-large-v3
INFO:example_plugin.WhisperPlugin:Execution config: {'model': 'large-v3', 'device': 'cuda', 'compute_type': 'default', 'language': 'es', 'task': 'transcribe', 'temperature': 0.5, 'beam_size': 5, 'best_of': 5, 'patience': 1.0, 'length_penalty': None, 'suppress_tokens': '-1', 'initial_prompt': None, 'condition_on_previous_text': True, 'no_speech_threshold': 0.6, 'compression_ratio_threshold': 2.4, 'logprob_threshold': -1.0, 'word_timestamps': True, 'prepend_punctuations': '"\'“¿([{-', 'append_punctuations': '"\'.。,,!!??::”)]}、', 'vad_filter': False, 'vad_parameters': {'threshold': 0.5, 'min_speech_duration_ms': 250, 'max_speech_duration_s': 3600}}
============================================================
PLUGIN CONFIGURATION MANAGEMENT DEMONSTRATION
============================================================

1. Configuration Schema (first 5 properties):
----------------------------------------

2. Current Configuration (subset):
----------------------------------------
{
  "model": "base",
  "device": "auto",
  "language": null,
  "temperature": 0.0
}

3. Configuration Validation:
----------------------------------------
Valid partial config:
  Config: {'model': 'small'}
  Valid: True

Invalid model value:
  Config: {'model': 'invalid'}
  Valid: False
  Error: 'invalid' is not one of ['tiny', 'tiny.en', 'base', 'base.en', 'small', 'small.en', 'medium', 'mediu...

Temperature out of range:
  Config: {'temperature': 2.0}
  Valid: False
  Error: 'model' is a required property

Failed validating 'required' in schema:
    {'$schema': 'http://json...


4. Updating Plugin Configuration:
----------------------------------------
Update successful: True
Updated configuration:
{
  "model": "large-v3",
  "device": "cuda",
  "temperature": 0.2,
  "word_timestamps": true
}

5. All Plugin Schemas:
----------------------------------------
Plugin: whisper
  Title: Whisper Configuration
  Required fields: ['model']
  Number of properties: 21

6. Execute with Runtime Config Override:
----------------------------------------
Result: Mock transcription using large-v3 model

Simple Configuration Workflow Example

# Simple example: Loading a plugin with configuration
from pathlib import Path

# Setup
from nbdev.config import get_config
project_config = get_config()
test_files_dir = project_config.config_path/"test_files"

# Create plugin manager
manager = PluginManager()

# Load plugin with initial configuration
initial_config = {
    "model": "tiny",  # Start with fast model
    "device": "cpu",
    "language": "en"
}

manager.load_plugin_from_module(
    test_files_dir/"example_plugin.py", 
    config=initial_config
)

# Check what configuration is being used
config = manager.get_plugin_config("whisper")
print(f"Model: {config['model']}")
print(f"Device: {config['device']}")

# Later, update to use a better model
manager.update_plugin_config("whisper", {"model": "base"})

# Execute transcription
result = manager.execute_plugin("whisper", "audio.wav")
print(f"Transcription: {result.text}")
INFO:example_plugin.WhisperPlugin:Initializing Whisper with config: {'model': 'tiny', 'device': 'cpu', 'compute_type': 'default', 'language': 'en', 'task': 'transcribe', 'temperature': 0.0, 'beam_size': 5, 'best_of': 5, 'patience': 1.0, 'length_penalty': None, 'suppress_tokens': '-1', 'initial_prompt': None, 'condition_on_previous_text': True, 'no_speech_threshold': 0.6, 'compression_ratio_threshold': 2.4, 'logprob_threshold': -1.0, 'word_timestamps': False, 'prepend_punctuations': '"\'“¿([{-', 'append_punctuations': '"\'.。,,!!??::”)]}、', 'vad_filter': False, 'vad_parameters': {}}
INFO:__main__.PluginManager:Loaded plugin from module: whisper
INFO:example_plugin.WhisperPlugin:Cleaning up Whisper model
INFO:example_plugin.WhisperPlugin:Initializing Whisper with config: {'model': 'base', 'device': 'cpu', 'compute_type': 'default', 'language': 'en', 'task': 'transcribe', 'temperature': 0.0, 'beam_size': 5, 'best_of': 5, 'patience': 1.0, 'length_penalty': None, 'suppress_tokens': '-1', 'initial_prompt': None, 'condition_on_previous_text': True, 'no_speech_threshold': 0.6, 'compression_ratio_threshold': 2.4, 'logprob_threshold': -1.0, 'word_timestamps': False, 'prepend_punctuations': '"\'“¿([{-', 'append_punctuations': '"\'.。,,!!??::”)]}、', 'vad_filter': False, 'vad_parameters': {'threshold': 0.5, 'min_speech_duration_ms': 250, 'max_speech_duration_s': 3600}}
INFO:__main__.PluginManager:Updated configuration for plugin: whisper
INFO:example_plugin.WhisperPlugin:Transcribing with Whisper model: WhisperModel-base
INFO:example_plugin.WhisperPlugin:Execution config: {'model': 'base', 'device': 'cpu', 'compute_type': 'default', 'language': 'en', 'task': 'transcribe', 'temperature': 0.0, 'beam_size': 5, 'best_of': 5, 'patience': 1.0, 'length_penalty': None, 'suppress_tokens': '-1', 'initial_prompt': None, 'condition_on_previous_text': True, 'no_speech_threshold': 0.6, 'compression_ratio_threshold': 2.4, 'logprob_threshold': -1.0, 'word_timestamps': False, 'prepend_punctuations': '"\'“¿([{-', 'append_punctuations': '"\'.。,,!!??::”)]}、', 'vad_filter': False, 'vad_parameters': {'threshold': 0.5, 'min_speech_duration_ms': 250, 'max_speech_duration_s': 3600}}
Model: tiny
Device: cpu
Transcription: Mock transcription using base model