|
| 1 | +"""Example plugin that adds a prefix to all user prompts.""" |
| 2 | + |
| 3 | +import asyncio |
| 4 | + |
| 5 | +from lmstudio.plugin import BaseConfigSchema, PromptPreprocessorController, config_field |
| 6 | +from lmstudio import UserMessage, UserMessageDict, TextDataDict |
| 7 | + |
| 8 | + |
| 9 | +# Assigning ConfigSchema = SomeOtherSchemaClass also works |
| 10 | +class ConfigSchema(BaseConfigSchema): |
| 11 | + """The name 'ConfigSchema' implicitly registers this as the per-chat plugin config schema.""" |
| 12 | + |
| 13 | + prefix: str = config_field( |
| 14 | + label="Prefix to insert", |
| 15 | + hint="This text will be inserted at the start of all user prompts", |
| 16 | + default="And now for something completely different: ", |
| 17 | + ) |
| 18 | + |
| 19 | + |
| 20 | +# Assigning GlobalConfigSchema = SomeOtherGlobalSchemaClass also works |
| 21 | +class GlobalConfigSchema(BaseConfigSchema): |
| 22 | + """The name 'GlobalConfigSchema' implicitly registers this as the global plugin config schema.""" |
| 23 | + |
| 24 | + enable_inplace_status_demo: bool = config_field( |
| 25 | + label="Enable in-place status demo", |
| 26 | + hint="The plugin will run an in-place task status updating demo when invoked", |
| 27 | + default=True, |
| 28 | + ) |
| 29 | + inplace_status_duration: float = config_field( |
| 30 | + label="In-place status total duration (s)", |
| 31 | + hint="The number of seconds to spend displaying the in-place task status update", |
| 32 | + default=5.0, |
| 33 | + ) |
| 34 | + |
| 35 | + |
| 36 | +# Assigning preprocess_prompt = some_other_callable also works |
| 37 | +async def preprocess_prompt( |
| 38 | + ctl: PromptPreprocessorController[ConfigSchema, GlobalConfigSchema], |
| 39 | + message: UserMessage, |
| 40 | +) -> UserMessageDict | None: |
| 41 | + """Naming the function 'preprocess_prompt' implicitly registers it.""" |
| 42 | + if ctl.global_config.enable_inplace_status_demo: |
| 43 | + # Run an in-place status prompt update demonstration |
| 44 | + status_block = await ctl.notify_start("Starting task (shows a static icon).") |
| 45 | + status_updates = ( |
| 46 | + (status_block.notify_working, "Task in progress (shows a dynamic icon)."), |
| 47 | + (status_block.notify_waiting, "Task is blocked (shows a static icon)."), |
| 48 | + (status_block.notify_error, "Reporting an error status."), |
| 49 | + (status_block.notify_canceled, "Reporting cancellation."), |
| 50 | + ( |
| 51 | + status_block.notify_done, |
| 52 | + "In-place status update demonstration completed.", |
| 53 | + ), |
| 54 | + ) |
| 55 | + status_duration = ctl.global_config.inplace_status_duration / len( |
| 56 | + status_updates |
| 57 | + ) |
| 58 | + async with status_block.notify_aborted("Task genuinely cancelled."): |
| 59 | + for notification, status_text in status_updates: |
| 60 | + await asyncio.sleep(status_duration) |
| 61 | + await notification(status_text) |
| 62 | + |
| 63 | + modified_message = message.to_dict() |
| 64 | + # Add a prefix to all user messages |
| 65 | + prefix_text = ctl.plugin_config.prefix |
| 66 | + prefix: TextDataDict = { |
| 67 | + "type": "text", |
| 68 | + "text": prefix_text, |
| 69 | + } |
| 70 | + modified_message["content"] = [prefix, *modified_message["content"]] |
| 71 | + # Demonstrate simple completion status reporting for non-blocking operations |
| 72 | + await ctl.notify_done(f"Added prefix {prefix_text!r} to user message.") |
| 73 | + return modified_message |
| 74 | + |
| 75 | + |
| 76 | +print(f"{__name__} initialized from {__file__}") |
0 commit comments