diff --git a/Assets/settings.js b/Assets/settings.js index c0f905c..aff315a 100644 --- a/Assets/settings.js +++ b/Assets/settings.js @@ -9,6 +9,9 @@ // Define backends that don't need base URL configuration const FIXED_URL_BACKENDS = ['openai', 'anthropic', 'openrouter', 'grok']; +// Define the default max token limit for requests +const DEFAULT_MAX_TOKENS = 1024; + // Define default feature to instruction mappings const DEFAULT_FEATURE_MAPPINGS = { 'enhance-prompt': 'prompt', @@ -74,6 +77,7 @@ async function loadSettings() { serverSettings.backend || 'ollama', visionmodel: serverSettings.visionmodel || '', + max_tokens: Number(serverSettings.max_tokens) || DEFAULT_MAX_TOKENS, linkChatAndVisionModels: serverSettings.linkChatAndVisionModels !== false, // Default to true if not set // Backends - merge using spread operator which does a "deep merge" of two objects @@ -190,6 +194,7 @@ async function saveSettings(skipFeatureMappings = false) { const visionTimeout = isLinked ? chatTimeout : parseInt(document.getElementById('visionTimeout')?.value, 10); + const maxTokens = parseInt(document.getElementById('maxTokens')?.value, 10); // Create settings object matching exact structure expected by C# DefaultSettings const settings = { // Core settings @@ -197,6 +202,7 @@ async function saveSettings(skipFeatureMappings = false) { model: chatModel, visionbackend: visionBackendId, visionmodel: visionModel, + max_tokens: !isNaN(maxTokens) && maxTokens > 0 ? maxTokens : MP.settings.max_tokens, linkChatAndVisionModels: isLinked, backends: { ...MP.settings.backends, @@ -1821,6 +1827,10 @@ function initSettingsModal() { const defaultChatTimeout = currentBackend === 'ollama' || currentBackend === 'openaiapi' ? 120 : 60; chatTimeoutInput.value = MP.settings.backends[currentBackend]?.timeout ?? defaultChatTimeout; } + const maxTokensInput = document.getElementById('maxTokens'); + if (maxTokensInput) { + maxTokensInput.value = MP.settings.max_tokens ?? DEFAULT_MAX_TOKENS; + } const currentVisionBackend = MP.settings.visionbackend || 'ollama'; const currentVisionBackendRadio = document.getElementById( `${currentVisionBackend}VisionBtn` diff --git a/BackendSchema.cs b/BackendSchema.cs index 98f7e39..4da4119 100644 --- a/BackendSchema.cs +++ b/BackendSchema.cs @@ -10,6 +10,8 @@ namespace Hartsy.Extensions.MagicPromptExtension; public static class BackendSchema { + public static readonly int DefaultMaxTokens = 1024; + public enum MessageType { Text, @@ -37,7 +39,7 @@ public class MediaContent /// Model name to use /// Type of message (Text or Vision) /// Returns an object with the schema type for the backend. - public static object GetSchemaType(string type, MessageContent content, string model, MessageType messageType = MessageType.Text, long seed = -1) + public static object GetSchemaType(string type, MessageContent content, string model, MessageType messageType = MessageType.Text, long seed = -1, int? maxTokens = null) { if (content == null || string.IsNullOrEmpty(model)) { @@ -48,9 +50,9 @@ public static object GetSchemaType(string type, MessageContent content, string m return type switch { "ollama" => OllamaRequestBody(content, model, messageType, seed), - "grok" => OpenAICompatibleRequestBody(content, model, messageType, preferPngForBase64: true, seed), - "openai" or "openaiapi" or "openrouter" => OpenAICompatibleRequestBody(content, model, messageType, preferPngForBase64: false, seed), - "anthropic" => AnthropicRequestBody(content, model, messageType), + "grok" => OpenAICompatibleRequestBody(content, model, messageType, preferPngForBase64: true, seed, maxTokens), + "openai" or "openaiapi" or "openrouter" => OpenAICompatibleRequestBody(content, model, messageType, preferPngForBase64: false, seed, maxTokens), + "anthropic" => AnthropicRequestBody(content, model, messageType, maxTokens), _ => throw new ArgumentException($"Unsupported backend type: {type}") }; } @@ -139,7 +141,7 @@ private static object OllamaRequestBody(MessageContent content, string model, Me } /// Generates a request body for OpenAI and compatible backends. - private static object OpenAICompatibleRequestBody(MessageContent content, string model, MessageType messageType, bool preferPngForBase64, long seed = -1) + private static object OpenAICompatibleRequestBody(MessageContent content, string model, MessageType messageType, bool preferPngForBase64, long seed = -1, int? maxTokens = null) { List messages = []; // Add system message if instructions exist @@ -178,7 +180,7 @@ private static object OpenAICompatibleRequestBody(MessageContent content, string { model, messages = messages.ToArray(), - max_tokens = 1000, + max_tokens = maxTokens ?? DefaultMaxTokens, temperature = 1.0, stream = false, seed @@ -189,7 +191,7 @@ private static object OpenAICompatibleRequestBody(MessageContent content, string { model, messages = messages.ToArray(), - max_tokens = 1000, + max_tokens = maxTokens ?? DefaultMaxTokens, temperature = 1.0, stream = false }; @@ -202,7 +204,7 @@ private static object OpenAICompatibleRequestBody(MessageContent content, string { model, messages = messages.ToArray(), - max_tokens = 1000, + max_tokens = maxTokens ?? DefaultMaxTokens, temperature = 1.0, stream = false, seed @@ -214,14 +216,14 @@ private static object OpenAICompatibleRequestBody(MessageContent content, string model, messages = messages.ToArray(), temperature = 1.0, - max_tokens = 1000, + max_tokens = maxTokens ?? DefaultMaxTokens, top_p = 0.9, stream = false }; } /// Generates a request body for the Anthropic (Claude) API. - private static object AnthropicRequestBody(MessageContent content, string model, MessageType messageType) + private static object AnthropicRequestBody(MessageContent content, string model, MessageType messageType, int? maxTokens = null) { List messages = []; if (messageType == MessageType.Vision && content.Media?.Any() == true) @@ -258,7 +260,7 @@ private static object AnthropicRequestBody(MessageContent content, string model, model, messages = messages.ToArray(), system = content.Instructions, - max_tokens = 1024 + max_tokens = maxTokens ?? DefaultMaxTokens }; } messages.Add(new { role = "user", content = content.Text }); @@ -267,7 +269,7 @@ private static object AnthropicRequestBody(MessageContent content, string model, model, messages = messages.ToArray(), system = content.Instructions, - max_tokens = 1024 + max_tokens = maxTokens ?? DefaultMaxTokens }; } -} \ No newline at end of file +} diff --git a/Tabs/Text2Image/MagicPrompt.html b/Tabs/Text2Image/MagicPrompt.html index 65a92b9..3666da9 100644 --- a/Tabs/Text2Image/MagicPrompt.html +++ b/Tabs/Text2Image/MagicPrompt.html @@ -181,7 +181,7 @@
Chat LLM Settings
-
+
@@ -190,6 +190,10 @@
Chat LLM Settings
+
+ + +
diff --git a/WebAPI/LLMAPICalls.cs b/WebAPI/LLMAPICalls.cs index af500c4..5442c8b 100644 --- a/WebAPI/LLMAPICalls.cs +++ b/WebAPI/LLMAPICalls.cs @@ -544,7 +544,14 @@ public static async Task MagicPromptPhoneHome(JObject requestData, Sess object requestBody; try { - requestBody = GetSchemaType(backend, messageContent, modelId, messageType, seed); + int maxTokens = BackendSchema.DefaultMaxTokens; + if (long.TryParse(settings["max_tokens"]?.ToString(), out long parsedMaxTokens) + && parsedMaxTokens >= 1 + && parsedMaxTokens <= int.MaxValue) + { + maxTokens = (int)parsedMaxTokens; + } + requestBody = GetSchemaType(backend, messageContent, modelId, messageType, seed, maxTokens); } catch (ArgumentException ex) { diff --git a/WebAPI/SessionSettings.cs b/WebAPI/SessionSettings.cs index 1bb377c..7955dc2 100644 --- a/WebAPI/SessionSettings.cs +++ b/WebAPI/SessionSettings.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json.Linq; +using SwarmUI.Backends; using SwarmUI.Core; using SwarmUI.Utils; @@ -82,6 +83,7 @@ public class SessionSettings : MagicPromptAPI ["visionbackend"] = "ollama", ["model"] = "llama3.2-vision:latest", ["visionmodel"] = "llama3.2-vision:latest", + ["max_tokens"] = BackendSchema.DefaultMaxTokens, ["instructions"] = new JObject { ["chat"] = "You are a chatbot named Hartsy. Come up with a random backstory as to why you were created and how you were made to help the user with Stable Diffusion. You will respond to any questions or chats in this character. You will include tips on how to make good prompts for stable diffusion. Never break character and randomly end your response with \"Thank you for choosing Hartsy!\"",