Add a function tool for image generation
| @@ -32,6 +32,7 @@ import { debounce_timeout } from '../../constants.js'; | ||
| 32 | 32 | import { SlashCommandEnumValue } from '../../slash-commands/SlashCommandEnumValue.js'; |
| 33 | 33 | import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from '../../popup.js'; |
| 34 | 34 | import { commonEnumProviders } from '../../slash-commands/SlashCommandCommonEnumsProvider.js'; |
| 35 | +import { ToolManager } from '../../tool-calling.js'; | |
| 35 | 36 | export { MODULE_NAME }; |
| 36 | 37 | |
| 37 | 38 | const MODULE_NAME = 'sd'; |
| @@ -62,6 +63,7 @@ const initiators = { | ||
| 62 | 63 | interactive: 'interactive', |
| 63 | 64 | wand: 'wand', |
| 64 | 65 | swipe: 'swipe', |
| 66 | + tool: 'tool', | |
| 65 | 67 | }; |
| 66 | 68 | |
| 67 | 69 | const generationMode = { |
| @@ -226,6 +228,7 @@ const defaultSettings = { | ||
| 226 | 228 | multimodal_captioning: false, |
| 227 | 229 | snap: false, |
| 228 | 230 | free_extend: false, |
| 231 | + function_tool: false, | |
| 229 | 232 | |
| 230 | 233 | prompts: promptTemplates, |
| 231 | 234 | |
| @@ -291,6 +294,10 @@ const defaultSettings = { | ||
| 291 | 294 | const writePromptFieldsDebounced = debounce(writePromptFields, debounce_timeout.relaxed); |
| 292 | 295 | |
| 293 | 296 | function processTriggers(chat, _, abort) { |
| 297 | + if (extension_settings.sd.function_tool && ToolManager.isToolCallingSupported()) { | |
| 298 | + return; | |
| 299 | + } | |
| 300 | + | |
| 294 | 301 | if (!extension_settings.sd.interactive_mode) { |
| 295 | 302 | return; |
| 296 | 303 | } |
| @@ -447,6 +454,7 @@ async function loadSettings() { | ||
| 447 | 454 | $('#sd_interactive_visible').prop('checked', extension_settings.sd.interactive_visible); |
| 448 | 455 | $('#sd_stability_style_preset').val(extension_settings.sd.stability_style_preset); |
| 449 | 456 | $('#sd_huggingface_model_id').val(extension_settings.sd.huggingface_model_id); |
| 457 | + $('#sd_function_tool').prop('checked', extension_settings.sd.function_tool); | |
| 450 | 458 | |
| 451 | 459 | for (const style of extension_settings.sd.styles) { |
| 452 | 460 | const option = document.createElement('option'); |
| @@ -461,6 +469,7 @@ async function loadSettings() { | ||
| 461 | 469 | |
| 462 | 470 | toggleSourceControls(); |
| 463 | 471 | addPromptTemplates(); |
| 472 | + registerFunctionTool(); | |
| 464 | 473 | |
| 465 | 474 | await loadSettingOptions(); |
| 466 | 475 | } |
| @@ -910,6 +919,12 @@ async function onSourceChange() { | ||
| 910 | 919 | await loadSettingOptions(); |
| 911 | 920 | } |
| 912 | 921 | |
| 922 | +function onFunctionToolInput() { | |
| 923 | + extension_settings.sd.function_tool = !!$(this).prop('checked'); | |
| 924 | + saveSettingsDebounced(); | |
| 925 | + registerFunctionTool(); | |
| 926 | +} | |
| 927 | + | |
| 913 | 928 | async function onOpenAiStyleSelect() { |
| 914 | 929 | extension_settings.sd.openai_style = String($('#sd_openai_style').find(':selected').val()); |
| 915 | 930 | saveSettingsDebounced(); |
| @@ -3822,6 +3837,44 @@ function applyCommandArguments(args) { | ||
| 3822 | 3837 | return currentSettings; |
| 3823 | 3838 | } |
| 3824 | 3839 | |
| 3840 | +function registerFunctionTool() { | |
| 3841 | + if (!extension_settings.sd.function_tool) { | |
| 3842 | + return ToolManager.unregisterFunctionTool('GenerateImage'); | |
| 3843 | + } | |
| 3844 | + | |
| 3845 | + ToolManager.registerFunctionTool({ | |
| 3846 | + name: 'GenerateImage', | |
| 3847 | + displayName: 'Generate Image', | |
| 3848 | + description: [ | |
| 3849 | + 'Generate an image from a given text prompt.', | |
| 3850 | + 'Use when a user asks for an image, a selfie, to picture a scene, etc.', | |
| 3851 | + ].join(' '), | |
| 3852 | + parameters: Object.freeze({ | |
| 3853 | + $schema: 'http://json-schema.org/draft-04/schema#', | |
| 3854 | + type: 'object', | |
| 3855 | + properties: { | |
| 3856 | + prompt: { | |
| 3857 | + type: 'string', | |
| 3858 | + description: [ | |
| 3859 | + 'The text prompt used to generate the image.', | |
| 3860 | + 'Must represent an exhaustive description of the desired image that will allow an artist or a photographer to perfectly recreate it.', | |
| 3861 | + ], | |
| 3862 | + }, | |
| 3863 | + }, | |
| 3864 | + required: [ | |
| 3865 | + 'prompt', | |
| 3866 | + ], | |
| 3867 | + }), | |
| 3868 | + action: async (args) => { | |
| 3869 | + if (!isValidState()) throw new Error('Image generation is not configured.'); | |
| 3870 | + if (!args) throw new Error('Missing arguments'); | |
| 3871 | + if (!args.prompt) throw new Error('Missing prompt'); | |
| 3872 | + return generatePicture(initiators.tool, {}, args.prompt); | |
| 3873 | + }, | |
| 3874 | + formatMessage: () => 'Generating an image...', | |
| 3875 | + }); | |
| 3876 | +} | |
| 3877 | + | |
| 3825 | 3878 | jQuery(async () => { |
| 3826 | 3879 | await addSDGenButtons(); |
| 3827 | 3880 | |
| @@ -4175,6 +4228,7 @@ jQuery(async () => { | ||
| 4175 | 4228 | $('#sd_stability_key').on('click', onStabilityKeyClick); |
| 4176 | 4229 | $('#sd_stability_style_preset').on('change', onStabilityStylePresetChange); |
| 4177 | 4230 | $('#sd_huggingface_model_id').on('input', onHFModelInput); |
| 4231 | + $('#sd_function_tool').on('input', onFunctionToolInput); | |
| 4178 | 4232 | |
| 4179 | 4233 | if (!CSS.supports('field-sizing', 'content')) { |
| 4180 | 4234 | $('.sd_settings .inline-drawer-toggle').on('click', function () { |
| @@ -18,6 +18,10 @@ | ||
| 18 | 18 | <input id="sd_interactive_mode" type="checkbox" /> |
| 19 | 19 | <span data-i18n="sd_interactive_mode_txt">Interactive mode</span> |
| 20 | 20 | </label> |
| 21 | + <label for="sd_function_tool" class="checkbox_label" data-i18n="[title]sd_function_tool" title="Use the function tool to automatically detect intents to generate images."> | |
| 22 | + <input id="sd_function_tool" type="checkbox" /> | |
| 23 | + <span data-i18n="sd_function_tool_txt">Enable function tool</span> | |
| 24 | + </label> | |
| 21 | 25 | <label for="sd_multimodal_captioning" class="checkbox_label" data-i18n="[title]sd_multimodal_captioning" title="Use multimodal captioning to generate prompts for user and character portraits based on their avatars."> |
| 22 | 26 | <input id="sd_multimodal_captioning" type="checkbox" /> |
| 23 | 27 | <span data-i18n="sd_multimodal_captioning_txt">Use multimodal captioning for portraits</span> |