Caption: Improve Ollama models handling
| @@ -588,10 +588,12 @@ jQuery(async function () { | ||
| 588 | 588 | saveSettingsDebounced(); |
| 589 | 589 | }); |
| 590 | 590 | $('#caption_ollama_pull').on('click', (e) => { |
| 591 | 591 | const presetModel = extension_settings.caption.multimodal_modelselectedModel !== 'ollama_current' ? extension_settings.caption.multimodal_model : ''; |
| 592 | + const staticModels = { 'ollama_current': textgenerationwebui_settings.ollama_model, 'ollama_custom': extension_settings.caption.ollama_custom_model }; | |
| 593 | + const presetModel = staticModels[selectedModel] || selectedModel; | |
| 592 | 594 | e.preventDefault(); |
| 593 | 595 | $('#ollama_download_model').trigger('click'); |
| 594 | 596 | $('#dialogue_popup_input.popup .popup-input').val(presetModel); |
| 595 | 597 | }); |
| 596 | 598 | $('#caption_multimodal_api').on('change', async () => { |
| 597 | 599 | const api = String($('#caption_multimodal_api').val()); |
| @@ -616,6 +618,10 @@ jQuery(async function () { | ||
| 616 | 618 | extension_settings.caption.show_in_chat = !!$('#caption_show_in_chat').prop('checked'); |
| 617 | 619 | saveSettingsDebounced(); |
| 618 | 620 | }); |
| 621 | + $('#caption_ollama_custom_model').val(extension_settings.caption.ollama_custom_model || '').on('input', () => { | |
| 622 | + extension_settings.caption.ollama_custom_model = String($('#caption_ollama_custom_model').val()).trim(); | |
| 623 | + saveSettingsDebounced(); | |
| 624 | + }); | |
| 619 | 625 | |
| 620 | 626 | const onMessageEvent = async (index) => { |
| 621 | 627 | if (!extension_settings.caption.auto_mode) { |
| @@ -154,11 +154,20 @@ | ||
| 154 | 154 | <option data-type="groq" value="llama-3.2-90b-vision-preview">llama-3.2-90b-vision-preview</option> |
| 155 | 155 | <option data-type="groq" value="llava-v1.5-7b-4096-preview">llava-v1.5-7b-4096-preview</option> |
| 156 | 156 | <option data-type="ollama" value="ollama_current" data-i18n="currently_selected">[Currently selected]</option> |
| 157 | + <option data-type="ollama" value="ollama_custom" data-i18n="[Custom model]">[Custom model]</option> | |
| 157 | 158 | <option data-type="ollama" value="bakllava">bakllava</option> |
| 158 | 159 | <option data-type="ollama" value="llava">llava</option> |
| 159 | 160 | <option data-type="ollama" value="llava-llama3">llava-llama3</option> |
| 160 | 161 | <option data-type="ollama" value="llava-phi3">llava-phi3</option> |
| 161 | 162 | <option data-type="ollama" value="moondream">moondream</option> |
| 163 | + <option data-type="ollama" value="gemma3">gemma3</option> | |
| 164 | + <option data-type="ollama" value="minicpm-v">minicpm-v</option> | |
| 165 | + <option data-type="ollama" value="qwen2.5vl">qwen2.5vl</option> | |
| 166 | + <option data-type="ollama" value="granite3.2-vision">granite3.2-vision</option> | |
| 167 | + <option data-type="ollama" value="mistral-small3.1">mistral-small3.1</option> | |
| 168 | + <option data-type="ollama" value="mistral-small3.2">mistral-small3.2</option> | |
| 169 | + <option data-type="ollama" value="llama3.2-vision">llama3.2-vision</option> | |
| 170 | + <option data-type="ollama" value="llama4">llama4</option> | |
| 162 | 171 | <option data-type="llamacpp" value="llamacpp_current" data-i18n="currently_loaded">[Currently loaded]</option> |
| 163 | 172 | <option data-type="ooba" value="ooba_current" data-i18n="currently_loaded">[Currently loaded]</option> |
| 164 | 173 | <option data-type="koboldcpp" value="koboldcpp_current" data-i18n="currently_loaded">[Currently loaded]</option> |
| @@ -170,16 +179,25 @@ | ||
| 170 | 179 | </select> |
| 171 | 180 | </div> |
| 172 | 181 | <div data-type="ollama"> |
| 173 | - The model must be downloaded first! Do it with the <code>ollama pull</code> command or <a href="#" id="caption_ollama_pull">click here</a>. | |
| 182 | + <div> | |
| 183 | + The model must be downloaded first! Do it with the <code>ollama pull</code> command or <a href="#" id="caption_ollama_pull">click here</a>. | |
| 184 | + </div> | |
| 185 | + <div class="marginTop5"> | |
| 186 | + <label for="caption_ollama_custom_model"> | |
| 187 | + <span data-i18n="Custom Model Tag">Custom Model Tag</span> | |
| 188 | + <small data-i18n="(for [Custom model] option)">(for [Custom model] option)</small> | |
| 189 | + </label> | |
| 190 | + <input id="caption_ollama_custom_model" class="text_pole" type="text" placeholder="e.g. gemma3:latest" /> | |
| 191 | + </div> | |
| 174 | 192 | </div> |
| 175 | 193 | <label data-type="openai,anthropic,google,vertexai,mistral,xai" class="checkbox_label flexBasis100p" for="caption_allow_reverse_proxy" title="Allow using reverse proxy if defined and valid."> |
| 176 | 194 | <input id="caption_allow_reverse_proxy" type="checkbox" class="checkbox"> |
| 177 | 195 | <span data-i18n="Allow reverse proxy">Allow reverse proxy</span> |
| 178 | 196 | </label> |
| 179 | 197 | <div class="flexBasis100p m-b-1marginBot10"> |
| 180 | 198 | <small><b data-i18n="Hint:">Hint:</b> <span data-i18n="Set your API keys and endpoints in the 'API Connections' tab first.">Set your API keys and endpoints in the 'API Connections' tab first.</span></small> |
| 181 | 199 | </div> |
| 182 | 200 | <div data-type="koboldcpp,ollama,vllm,llamacpp,ooba" class="flex-container flexFlowColumn wide100p"> |
| 183 | 201 | <label for="caption_altEndpoint_enabled" class="checkbox_label"> |
| 184 | 202 | <input id="caption_altEndpoint_enabled" type="checkbox"> |
| 185 | 203 | <span data-i18n="Use secondary URL">Use secondary URL</span> |
| @@ -22,12 +22,6 @@ export async function getMultimodalCaption(base64Img, prompt) { | ||
| 22 | 22 | |
| 23 | 23 | throwIfInvalidModel(useReverseProxy); |
| 24 | 24 | |
| 25 | - const noPrefix = ['ollama'].includes(extension_settings.caption.multimodal_api); | |
| 26 | - | |
| 27 | - if (noPrefix && base64Img.startsWith('data:image/')) { | |
| 28 | - base64Img = base64Img.split(',')[1]; | |
| 29 | - } | |
| 30 | - | |
| 31 | 25 | // OpenRouter has a payload limit of ~2MB. Google is 4MB, but we love democracy. |
| 32 | 26 | // Ooba requires all images to be JPEGs. Koboldcpp just asked nicely. |
| 33 | 27 | const isOllama = extension_settings.caption.multimodal_api === 'ollama'; |
| @@ -47,6 +41,9 @@ export async function getMultimodalCaption(base64Img, prompt) { | ||
| 47 | 41 | } else if (!safeMimeTypes.includes(mimeType)) { |
| 48 | 42 | base64Img = await createThumbnail(base64Img, null, null); |
| 49 | 43 | } |
| 44 | + if (isOllama && base64Img.startsWith('data:image/')) { | |
| 45 | + base64Img = base64Img.split(',')[1]; | |
| 46 | + } | |
| 50 | 47 | |
| 51 | 48 | const proxyUrl = useReverseProxy ? oai_settings.reverse_proxy : ''; |
| 52 | 49 | const proxyPassword = useReverseProxy ? oai_settings.proxy_password : ''; |
| @@ -72,6 +69,10 @@ export async function getMultimodalCaption(base64Img, prompt) { | ||
| 72 | 69 | requestBody.model = textgenerationwebui_settings.ollama_model; |
| 73 | 70 | } |
| 74 | 71 | |
| 72 | + if (extension_settings.caption.multimodal_model === 'ollama_custom') { | |
| 73 | + requestBody.model = extension_settings.caption.ollama_custom_model; | |
| 74 | + } | |
| 75 | + | |
| 75 | 76 | requestBody.server_url = extension_settings.caption.alt_endpoint_enabled |
| 76 | 77 | ? extension_settings.caption.alt_endpoint_url |
| 77 | 78 | : textgenerationwebui_settings.server_urls[textgen_types.OLLAMA]; |
| @@ -211,6 +212,10 @@ function throwIfInvalidModel(useReverseProxy) { | ||
| 211 | 212 | throw new Error('Ollama model is not set.'); |
| 212 | 213 | } |
| 213 | 214 | |
| 215 | + if (multimodalApi === 'ollama' && multimodalModel === 'ollama_custom' && !extension_settings.caption.ollama_custom_model) { | |
| 216 | + throw new Error('Ollama custom model tag is not set.'); | |
| 217 | + } | |
| 218 | + | |
| 214 | 219 | if (multimodalApi === 'llamacpp' && !textgenerationwebui_settings.server_urls[textgen_types.LLAMACPP] && !altEndpointEnabled) { |
| 215 | 220 | throw new Error('LlamaCPP server URL is not set.'); |
| 216 | 221 | } |
| @@ -478,7 +478,8 @@ ollama.post('/caption-image', async function (request, response) { | ||
| 478 | 478 | }); |
| 479 | 479 | |
| 480 | 480 | if (!fetchResponse.ok) { |
| 481 | - console.error('Ollama caption error:', fetchResponse.status, fetchResponse.statusText); | |
| 481 | + const errorText = await fetchResponse.text(); | |
| 482 | + console.error('Ollama caption error:', fetchResponse.status, fetchResponse.statusText, errorText); | |
| 482 | 483 | return response.status(500).send({ error: true }); |
| 483 | 484 | } |
| 484 | 485 | |