Added block entropy endpoints for chat and image
| @@ -2427,6 +2427,7 @@ | ||
| 2427 | 2427 | <optgroup> |
| 2428 | 2428 | <option value="01ai">01.AI (Yi)</option> |
| 2429 | 2429 | <option value="ai21">AI21</option> |
| 2430 | + <option value="blockentropy">Block Entropy</option> | |
| 2430 | 2431 | <option value="claude">Claude</option> |
| 2431 | 2432 | <option value="cohere">Cohere</option> |
| 2432 | 2433 | <option value="groq">Groq</option> |
| @@ -2938,6 +2939,20 @@ | ||
| 2938 | 2939 | </select> |
| 2939 | 2940 | </div> |
| 2940 | 2941 | </form> |
| 2942 | + <form id="blockentropy_form" data-source="blockentropy"> | |
| 2943 | + <h4 data-i18n="Block Entropy API Key">Block Entropy API Key</h4> | |
| 2944 | + <div class="flex-container"> | |
| 2945 | + <input id="api_key_blockentropy" name="api_key_blockentropy" class="text_pole flex1" maxlength="500" value="" type="text" autocomplete="off"> | |
| 2946 | + <div title="Clear your API key" data-i18n="[title]Clear your API key" class="menu_button fa-solid fa-circle-xmark clear-api-key" data-key="api_key_blockentropy"></div> | |
| 2947 | + </div> | |
| 2948 | + <div data-for="api_key_blockentropy" class="neutral_warning" data-i18n="For privacy reasons, your API key will be hidden after you reload the page."> | |
| 2949 | + For privacy reasons, your API key will be hidden after you reload the page. | |
| 2950 | + </div> | |
| 2951 | + <h4 data-i18n="Available Models">Select a Model</h4> | |
| 2952 | + <div class="flex-container"> | |
| 2953 | + <select id="model_blockentropy_select" class="text_pole model_blockentropy_select"></select> | |
| 2954 | + </div> | |
| 2955 | + </form> | |
| 2941 | 2956 | <form id="custom_form" data-source="custom"> |
| 2942 | 2957 | <h4 data-i18n="Custom Endpoint (Base URL)">Custom Endpoint (Base URL)</h4> |
| 2943 | 2958 | <div class="flex-container"> |
| @@ -378,6 +378,7 @@ function RA_autoconnect(PrevApi) { | ||
| 378 | 378 | || (secret_state[SECRET_KEYS.PERPLEXITY] && oai_settings.chat_completion_source == chat_completion_sources.PERPLEXITY) |
| 379 | 379 | || (secret_state[SECRET_KEYS.GROQ] && oai_settings.chat_completion_source == chat_completion_sources.GROQ) |
| 380 | 380 | || (secret_state[SECRET_KEYS.ZEROONEAI] && oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI) |
| 381 | + || (secret_state[SECRET_KEYS.BLOCKENTROPY] && oai_settings.chat_completion_source == chat_completion_sources.BLOCKENTROPY) | |
| 381 | 382 | || (isValidUrl(oai_settings.custom_url) && oai_settings.chat_completion_source == chat_completion_sources.CUSTOM) |
| 382 | 383 | ) { |
| 383 | 384 | $('#api_button_openai').trigger('click'); |
| @@ -50,6 +50,7 @@ const sources = { | ||
| 50 | 50 | drawthings: 'drawthings', |
| 51 | 51 | pollinations: 'pollinations', |
| 52 | 52 | stability: 'stability', |
| 53 | + blockentropy: 'blockentropy', | |
| 53 | 54 | }; |
| 54 | 55 | |
| 55 | 56 | const initiators = { |
| @@ -1221,7 +1222,7 @@ async function onModelChange() { | ||
| 1221 | 1222 | extension_settings.sd.model = $('#sd_model').find(':selected').val(); |
| 1222 | 1223 | saveSettingsDebounced(); |
| 1223 | 1224 | |
| 1224 | 1225 | const cloudSources = [sources.horde, sources.novel, sources.openai, sources.togetherai, sources.pollinations, sources.stability, sources.blockentropy]; |
| 1225 | 1226 | |
| 1226 | 1227 | if (cloudSources.includes(extension_settings.sd.source)) { |
| 1227 | 1228 | return; |
| @@ -1433,6 +1434,9 @@ async function loadSamplers() { | ||
| 1433 | 1434 | case sources.stability: |
| 1434 | 1435 | samplers = ['N/A']; |
| 1435 | 1436 | break; |
| 1437 | + case sources.blockentropy: | |
| 1438 | + samplers = ['N/A']; | |
| 1439 | + break; | |
| 1436 | 1440 | } |
| 1437 | 1441 | |
| 1438 | 1442 | for (const sampler of samplers) { |
| @@ -1619,6 +1623,9 @@ async function loadModels() { | ||
| 1619 | 1623 | case sources.stability: |
| 1620 | 1624 | models = await loadStabilityModels(); |
| 1621 | 1625 | break; |
| 1626 | + case sources.blockentropy: | |
| 1627 | + models = await loadBlockEntropyModels(); | |
| 1628 | + break; | |
| 1622 | 1629 | } |
| 1623 | 1630 | |
| 1624 | 1631 | for (const model of models) { |
| @@ -1713,6 +1720,26 @@ async function loadTogetherAIModels() { | ||
| 1713 | 1720 | return []; |
| 1714 | 1721 | } |
| 1715 | 1722 | |
| 1723 | +async function loadBlockEntropyModels() { | |
| 1724 | + if (!secret_state[SECRET_KEYS.BLOCKENTROPY]) { | |
| 1725 | + console.debug('Block Entropy API key is not set.'); | |
| 1726 | + return []; | |
| 1727 | + } | |
| 1728 | + | |
| 1729 | + const result = await fetch('/api/sd/blockentropy/models', { | |
| 1730 | + method: 'POST', | |
| 1731 | + headers: getRequestHeaders(), | |
| 1732 | + }); | |
| 1733 | + console.log(result); | |
| 1734 | + if (result.ok) { | |
| 1735 | + const data = await result.json(); | |
| 1736 | + console.log(data); | |
| 1737 | + return data; | |
| 1738 | + } | |
| 1739 | + | |
| 1740 | + return []; | |
| 1741 | +} | |
| 1742 | + | |
| 1716 | 1743 | async function loadHordeModels() { |
| 1717 | 1744 | const result = await fetch('/api/horde/sd-models', { |
| 1718 | 1745 | method: 'POST', |
| @@ -1979,6 +2006,9 @@ async function loadSchedulers() { | ||
| 1979 | 2006 | case sources.stability: |
| 1980 | 2007 | schedulers = ['N/A']; |
| 1981 | 2008 | break; |
| 2009 | + case sources.blockentropy: | |
| 2010 | + schedulers = ['N/A']; | |
| 2011 | + break; | |
| 1982 | 2012 | } |
| 1983 | 2013 | |
| 1984 | 2014 | for (const scheduler of schedulers) { |
| @@ -2055,6 +2085,9 @@ async function loadVaes() { | ||
| 2055 | 2085 | case sources.stability: |
| 2056 | 2086 | vaes = ['N/A']; |
| 2057 | 2087 | break; |
| 2088 | + case sources.blockentropy: | |
| 2089 | + vaes = ['N/A']; | |
| 2090 | + break; | |
| 2058 | 2091 | } |
| 2059 | 2092 | |
| 2060 | 2093 | for (const vae of vaes) { |
| @@ -2583,6 +2616,9 @@ async function sendGenerationRequest(generationType, prompt, additionalNegativeP | ||
| 2583 | 2616 | case sources.stability: |
| 2584 | 2617 | result = await generateStabilityImage(prefixedPrompt, negativePrompt, signal); |
| 2585 | 2618 | break; |
| 2619 | + case sources.blockentropy: | |
| 2620 | + result = await generateBlockEntropyImage(prefixedPrompt, negativePrompt, signal); | |
| 2621 | + break; | |
| 2586 | 2622 | } |
| 2587 | 2623 | |
| 2588 | 2624 | if (!result.data) { |
| @@ -2638,6 +2674,31 @@ async function generateTogetherAIImage(prompt, negativePrompt, signal) { | ||
| 2638 | 2674 | } |
| 2639 | 2675 | } |
| 2640 | 2676 | |
| 2677 | +async function generateBlockEntropyImage(prompt, negativePrompt, signal) { | |
| 2678 | + const result = await fetch('/api/sd/blockentropy/generate', { | |
| 2679 | + method: 'POST', | |
| 2680 | + headers: getRequestHeaders(), | |
| 2681 | + signal: signal, | |
| 2682 | + body: JSON.stringify({ | |
| 2683 | + prompt: prompt, | |
| 2684 | + negative_prompt: negativePrompt, | |
| 2685 | + model: extension_settings.sd.model, | |
| 2686 | + steps: extension_settings.sd.steps, | |
| 2687 | + width: extension_settings.sd.width, | |
| 2688 | + height: extension_settings.sd.height, | |
| 2689 | + seed: extension_settings.sd.seed >= 0 ? extension_settings.sd.seed : undefined, | |
| 2690 | + }), | |
| 2691 | + }); | |
| 2692 | + | |
| 2693 | + if (result.ok) { | |
| 2694 | + const data = await result.json(); | |
| 2695 | + return { format: 'png', data: data.images[0] }; | |
| 2696 | + } else { | |
| 2697 | + const text = await result.text(); | |
| 2698 | + throw new Error(text); | |
| 2699 | + } | |
| 2700 | +} | |
| 2701 | + | |
| 2641 | 2702 | /** |
| 2642 | 2703 | * Generates an image using the Pollinations API. |
| 2643 | 2704 | * @param {string} prompt - The main instruction used to guide the image generation. |
| @@ -3451,6 +3512,8 @@ function isValidState() { | ||
| 3451 | 3512 | return true; |
| 3452 | 3513 | case sources.stability: |
| 3453 | 3514 | return secret_state[SECRET_KEYS.STABILITY]; |
| 3515 | + case sources.blockentropy: | |
| 3516 | + return secret_state[SECRET_KEYS.BLOCKENTROPY]; | |
| 3454 | 3517 | } |
| 3455 | 3518 | } |
| 3456 | 3519 | |
| @@ -48,6 +48,7 @@ | ||
| 48 | 48 | <option value="auto">Stable Diffusion Web UI (AUTOMATIC1111)</option> |
| 49 | 49 | <option value="horde">Stable Horde</option> |
| 50 | 50 | <option value="togetherai">TogetherAI</option> |
| 51 | + <option value="blockentropy">Block Entropy</option> | |
| 51 | 52 | </select> |
| 52 | 53 | <div data-sd-source="auto"> |
| 53 | 54 | <label for="sd_auto_url">SD Web UI URL</label> |
| @@ -378,7 +379,7 @@ | ||
| 378 | 379 | </label> |
| 379 | 380 | </div> |
| 380 | 381 | |
| 381 | 382 | <div data-sd-source="novel,togetherai,pollinations,comfy,drawthings,vlad,auto,horde,extras,stability,blockentropy" class="marginTop5"> |
| 382 | 383 | <label for="sd_seed"> |
| 383 | 384 | <span data-i18n="Seed">Seed</span> |
| 384 | 385 | <small data-i18n="(-1 for random)">(-1 for random)</small> |
| @@ -185,6 +185,7 @@ export const chat_completion_sources = { | ||
| 185 | 185 | PERPLEXITY: 'perplexity', |
| 186 | 186 | GROQ: 'groq', |
| 187 | 187 | ZEROONEAI: '01ai', |
| 188 | + BLOCKENTROPY: 'blockentropy', | |
| 188 | 189 | }; |
| 189 | 190 | |
| 190 | 191 | const character_names_behavior = { |
| @@ -267,6 +268,7 @@ const default_settings = { | ||
| 267 | 268 | perplexity_model: 'llama-3-70b-instruct', |
| 268 | 269 | groq_model: 'llama3-70b-8192', |
| 269 | 270 | zerooneai_model: 'yi-large', |
| 271 | + blockentropy_model: 'be-70b-base-llama3.1', | |
| 270 | 272 | custom_model: '', |
| 271 | 273 | custom_url: '', |
| 272 | 274 | custom_include_body: '', |
| @@ -347,6 +349,7 @@ const oai_settings = { | ||
| 347 | 349 | perplexity_model: 'llama-3-70b-instruct', |
| 348 | 350 | groq_model: 'llama3-70b-8192', |
| 349 | 351 | zerooneai_model: 'yi-large', |
| 352 | + blockentropy_model: 'be-70b-base-llama3.1', | |
| 350 | 353 | custom_model: '', |
| 351 | 354 | custom_url: '', |
| 352 | 355 | custom_include_body: '', |
| @@ -1541,6 +1544,8 @@ function getChatCompletionModel() { | ||
| 1541 | 1544 | return oai_settings.groq_model; |
| 1542 | 1545 | case chat_completion_sources.ZEROONEAI: |
| 1543 | 1546 | return oai_settings.zerooneai_model; |
| 1547 | + case chat_completion_sources.BLOCKENTROPY: | |
| 1548 | + return oai_settings.blockentropy_model; | |
| 1544 | 1549 | default: |
| 1545 | 1550 | throw new Error(`Unknown chat completion source: ${oai_settings.chat_completion_source}`); |
| 1546 | 1551 | } |
| @@ -1654,6 +1659,23 @@ function saveModelList(data) { | ||
| 1654 | 1659 | |
| 1655 | 1660 | $('#model_01ai_select').val(oai_settings.zerooneai_model).trigger('change'); |
| 1656 | 1661 | } |
| 1662 | + | |
| 1663 | + if (oai_settings.chat_completion_source == chat_completion_sources.BLOCKENTROPY) { | |
| 1664 | + $('.model_blockentropy_select').empty(); | |
| 1665 | + model_list.forEach((model) => { | |
| 1666 | + $('.model_blockentropy_select').append( | |
| 1667 | + $('<option>', { | |
| 1668 | + value: model.id, | |
| 1669 | + text: model.id, | |
| 1670 | + })); | |
| 1671 | + }); | |
| 1672 | + | |
| 1673 | + if (!oai_settings.blockentropy_model && model_list.length > 0) { | |
| 1674 | + oai_settings.blockentropy_model = model_list[0].id; | |
| 1675 | + } | |
| 1676 | + | |
| 1677 | + $('#model_blockentropy_select').val(oai_settings.blockentropy_model).trigger('change'); | |
| 1678 | + } | |
| 1657 | 1679 | } |
| 1658 | 1680 | |
| 1659 | 1681 | function appendOpenRouterOptions(model_list, groupModels = false, sort = false) { |
| @@ -4037,6 +4059,12 @@ async function onModelChange() { | ||
| 4037 | 4059 | oai_settings.zerooneai_model = value; |
| 4038 | 4060 | } |
| 4039 | 4061 | |
| 4062 | + if (value && $(this).is('#model_blockentropy_select')) { | |
| 4063 | + console.log('Block Entropy model changed to', value); | |
| 4064 | + oai_settings.blockentropy_model = value; | |
| 4065 | + $('#blockentropy_model_id').val(value).trigger('input'); | |
| 4066 | + } | |
| 4067 | + | |
| 4040 | 4068 | if (value && $(this).is('#model_custom_select')) { |
| 4041 | 4069 | console.log('Custom model changed to', value); |
| 4042 | 4070 | oai_settings.custom_model = value; |
| @@ -4302,6 +4330,19 @@ async function onModelChange() { | ||
| 4302 | 4330 | oai_settings.temp_openai = Math.min(oai_max_temp, oai_settings.temp_openai); |
| 4303 | 4331 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); |
| 4304 | 4332 | } |
| 4333 | + if (oai_settings.chat_completion_source === chat_completion_sources.BLOCKENTROPY) { | |
| 4334 | + if (oai_settings.max_context_unlocked) { | |
| 4335 | + $('#openai_max_context').attr('max', unlocked_max); | |
| 4336 | + } else { | |
| 4337 | + $('#openai_max_context').attr('max', max_32k); | |
| 4338 | + } | |
| 4339 | + | |
| 4340 | + oai_settings.openai_max_context = Math.min(oai_settings.openai_max_context, Number($('#openai_max_context').attr('max'))); | |
| 4341 | + $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input'); | |
| 4342 | + | |
| 4343 | + oai_settings.temp_openai = Math.min(oai_max_temp, oai_settings.temp_openai); | |
| 4344 | + $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); | |
| 4345 | + } | |
| 4305 | 4346 | |
| 4306 | 4347 | $('#openai_max_context_counter').attr('max', Number($('#openai_max_context').attr('max'))); |
| 4307 | 4348 | |
| @@ -4509,6 +4550,18 @@ async function onConnectButtonClick(e) { | ||
| 4509 | 4550 | return; |
| 4510 | 4551 | } |
| 4511 | 4552 | } |
| 4553 | + if (oai_settings.chat_completion_source == chat_completion_sources.BLOCKENTROPY) { | |
| 4554 | + const api_key_blockentropy = String($('#api_key_blockentropy').val()).trim(); | |
| 4555 | + | |
| 4556 | + if (api_key_blockentropy.length) { | |
| 4557 | + await writeSecret(SECRET_KEYS.BLOCKENTROPY, api_key_blockentropy); | |
| 4558 | + } | |
| 4559 | + | |
| 4560 | + if (!secret_state[SECRET_KEYS.BLOCKENTROPY]) { | |
| 4561 | + console.log('No secret key saved for Block Entropy'); | |
| 4562 | + return; | |
| 4563 | + } | |
| 4564 | + } | |
| 4512 | 4565 | |
| 4513 | 4566 | startStatusLoading(); |
| 4514 | 4567 | saveSettingsDebounced(); |
| @@ -5282,6 +5335,7 @@ $(document).ready(async function () { | ||
| 5282 | 5335 | $('#model_perplexity_select').on('change', onModelChange); |
| 5283 | 5336 | $('#model_groq_select').on('change', onModelChange); |
| 5284 | 5337 | $('#model_01ai_select').on('change', onModelChange); |
| 5338 | + $('#model_blockentropy_select').on('change', onModelChange); | |
| 5285 | 5339 | $('#model_custom_select').on('change', onModelChange); |
| 5286 | 5340 | $('#settings_preset_openai').on('change', onSettingsPresetChange); |
| 5287 | 5341 | $('#new_oai_preset').on('click', onNewPresetClick); |
| @@ -32,6 +32,7 @@ export const SECRET_KEYS = { | ||
| 32 | 32 | ZEROONEAI: 'api_key_01ai', |
| 33 | 33 | HUGGINGFACE: 'api_key_huggingface', |
| 34 | 34 | STABILITY: 'api_key_stability', |
| 35 | + BLOCKENTROPY: 'api_key_blockentropy', | |
| 35 | 36 | }; |
| 36 | 37 | |
| 37 | 38 | const INPUT_MAP = { |
| @@ -63,6 +64,7 @@ const INPUT_MAP = { | ||
| 63 | 64 | [SECRET_KEYS.FEATHERLESS]: '#api_key_featherless', |
| 64 | 65 | [SECRET_KEYS.ZEROONEAI]: '#api_key_01ai', |
| 65 | 66 | [SECRET_KEYS.HUGGINGFACE]: '#api_key_huggingface', |
| 67 | + [SECRET_KEYS.BLOCKENTROPY]: '#api_key_blockentropy', | |
| 66 | 68 | }; |
| 67 | 69 | |
| 68 | 70 | async function clearSecret() { |
| @@ -3190,6 +3190,7 @@ function getModelOptions() { | ||
| 3190 | 3190 | { id: 'model_perplexity_select', api: 'openai', type: chat_completion_sources.PERPLEXITY }, |
| 3191 | 3191 | { id: 'model_groq_select', api: 'openai', type: chat_completion_sources.GROQ }, |
| 3192 | 3192 | { id: 'model_01ai_select', api: 'openai', type: chat_completion_sources.ZEROONEAI }, |
| 3193 | + { id: 'model_blockentropy_select', api: 'openai', type: chat_completion_sources.BLOCKENTROPY }, | |
| 3193 | 3194 | { id: 'model_novel_select', api: 'novel', type: null }, |
| 3194 | 3195 | { id: 'horde_model', api: 'koboldhorde', type: null }, |
| 3195 | 3196 | ]; |
| @@ -549,6 +549,15 @@ export function getTokenizerModel() { | ||
| 549 | 549 | return yiTokenizer; |
| 550 | 550 | } |
| 551 | 551 | |
| 552 | + if (oai_settings.chat_completion_source === chat_completion_sources.BLOCKENTROPY) { | |
| 553 | + if (oai_settings.blockentropy_model.includes('llama3')) { | |
| 554 | + return llama3Tokenizer; | |
| 555 | + } | |
| 556 | + if (oai_settings.blockentropy_model.includes('miqu') || oai_settings.blockentropy_model.includes('mixtral')) { | |
| 557 | + return mistralTokenizer; | |
| 558 | + } | |
| 559 | + } | |
| 560 | + | |
| 552 | 561 | // Default to Turbo 3.5 |
| 553 | 562 | return turboTokenizer; |
| 554 | 563 | } |
| @@ -195,6 +195,7 @@ const CHAT_COMPLETION_SOURCES = { | ||
| 195 | 195 | PERPLEXITY: 'perplexity', |
| 196 | 196 | GROQ: 'groq', |
| 197 | 197 | ZEROONEAI: '01ai', |
| 198 | + BLOCKENTROPY: 'blockentropy', | |
| 198 | 199 | }; |
| 199 | 200 | |
| 200 | 201 | /** |
| @@ -18,6 +18,7 @@ const API_PERPLEXITY = 'https://api.perplexity.ai'; | ||
| 18 | 18 | const API_GROQ = 'https://api.groq.com/openai/v1'; |
| 19 | 19 | const API_MAKERSUITE = 'https://generativelanguage.googleapis.com'; |
| 20 | 20 | const API_01AI = 'https://api.01.ai/v1'; |
| 21 | +const API_BLOCKENTROPY = 'https://api.blockentropy.ai/v1'; | |
| 21 | 22 | |
| 22 | 23 | /** |
| 23 | 24 | * Applies a post-processing step to the generated messages. |
| @@ -675,6 +676,10 @@ router.post('/status', jsonParser, async function (request, response_getstatus_o | ||
| 675 | 676 | api_url = API_01AI; |
| 676 | 677 | api_key_openai = readSecret(request.user.directories, SECRET_KEYS.ZEROONEAI); |
| 677 | 678 | headers = {}; |
| 679 | + } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.BLOCKENTROPY) { | |
| 680 | + api_url = API_BLOCKENTROPY; | |
| 681 | + api_key_openai = readSecret(request.user.directories, SECRET_KEYS.BLOCKENTROPY); | |
| 682 | + headers = {}; | |
| 678 | 683 | } else { |
| 679 | 684 | console.log('This chat completion source is not supported yet.'); |
| 680 | 685 | return response_getstatus_openai.status(400).send({ error: true }); |
| @@ -941,6 +946,11 @@ router.post('/generate', jsonParser, function (request, response) { | ||
| 941 | 946 | apiKey = readSecret(request.user.directories, SECRET_KEYS.ZEROONEAI); |
| 942 | 947 | headers = {}; |
| 943 | 948 | bodyParams = {}; |
| 949 | + } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.BLOCKENTROPY) { | |
| 950 | + apiUrl = API_BLOCKENTROPY; | |
| 951 | + apiKey = readSecret(request.user.directories, SECRET_KEYS.BLOCKENTROPY); | |
| 952 | + headers = {}; | |
| 953 | + bodyParams = {}; | |
| 944 | 954 | } else { |
| 945 | 955 | console.log('This chat completion source is not supported yet.'); |
| 946 | 956 | return response.status(400).send({ error: true }); |
| @@ -44,6 +44,7 @@ const SECRET_KEYS = { | ||
| 44 | 44 | ZEROONEAI: 'api_key_01ai', |
| 45 | 45 | HUGGINGFACE: 'api_key_huggingface', |
| 46 | 46 | STABILITY: 'api_key_stability', |
| 47 | + BLOCKENTROPY: 'api_key_blockentropy', | |
| 47 | 48 | }; |
| 48 | 49 | |
| 49 | 50 | // These are the keys that are safe to expose, even if allowKeysExposure is false |
| @@ -8,6 +8,7 @@ const writeFileAtomicSync = require('write-file-atomic').sync; | ||
| 8 | 8 | const { jsonParser } = require('../express-common'); |
| 9 | 9 | const { readSecret, SECRET_KEYS } = require('./secrets.js'); |
| 10 | 10 | const FormData = require('form-data'); |
| 11 | +const { scheduler } = require('timers/promises'); | |
| 11 | 12 | |
| 12 | 13 | /** |
| 13 | 14 | * Sanitizes a string. |
| @@ -908,10 +909,102 @@ stability.post('/generate', jsonParser, async (request, response) => { | ||
| 908 | 909 | } |
| 909 | 910 | }); |
| 910 | 911 | |
| 912 | +const blockentropy = express.Router(); | |
| 913 | + | |
| 914 | +blockentropy.post('/models', jsonParser, async (request, response) => { | |
| 915 | + try { | |
| 916 | + const key = readSecret(request.user.directories, SECRET_KEYS.BLOCKENTROPY); | |
| 917 | + | |
| 918 | + if (!key) { | |
| 919 | + console.log('Block Entropy key not found.'); | |
| 920 | + return response.sendStatus(400); | |
| 921 | + } | |
| 922 | + | |
| 923 | + const modelsResponse = await fetch('https://api.blockentropy.ai/sdapi/v1/schedulers', { | |
| 924 | + method: 'GET', | |
| 925 | + headers: { | |
| 926 | + 'Authorization': `Bearer ${key}`, | |
| 927 | + }, | |
| 928 | + }); | |
| 929 | + | |
| 930 | + if (!modelsResponse.ok) { | |
| 931 | + console.log('Block Entropy returned an error.'); | |
| 932 | + return response.sendStatus(500); | |
| 933 | + } | |
| 934 | + | |
| 935 | + const data = await modelsResponse.json(); | |
| 936 | + | |
| 937 | + if (!Array.isArray(data)) { | |
| 938 | + console.log('Block Entropy returned invalid data.'); | |
| 939 | + return response.sendStatus(500); | |
| 940 | + } | |
| 941 | + const models = data.map(x => ({ value: x.name, text: x.name })); | |
| 942 | + return response.send(models); | |
| 943 | + | |
| 944 | + } catch (error) { | |
| 945 | + console.log(error); | |
| 946 | + return response.sendStatus(500); | |
| 947 | + } | |
| 948 | +}); | |
| 949 | + | |
| 950 | +blockentropy.post('/generate', jsonParser, async (request, response) => { | |
| 951 | + try { | |
| 952 | + const key = readSecret(request.user.directories, SECRET_KEYS.BLOCKENTROPY); | |
| 953 | + | |
| 954 | + if (!key) { | |
| 955 | + console.log('Block Entropy key not found.'); | |
| 956 | + return response.sendStatus(400); | |
| 957 | + } | |
| 958 | + | |
| 959 | + console.log('Block Entropy request:', request.body); | |
| 960 | + | |
| 961 | + const result = await fetch('https://api.blockentropy.ai/sdapi/v1/txt2img', { | |
| 962 | + method: 'POST', | |
| 963 | + body: JSON.stringify({ | |
| 964 | + request_type: 'image-model-inference', | |
| 965 | + prompt: request.body.prompt, | |
| 966 | + negative_prompt: request.body.negative_prompt, | |
| 967 | + height: request.body.height, | |
| 968 | + width: request.body.width, | |
| 969 | + model: request.body.model, | |
| 970 | + steps: request.body.steps, | |
| 971 | + scheduler: request.body.scheduler, | |
| 972 | + n: 1, | |
| 973 | + // Limited to 10000 on playground, works fine with more. | |
| 974 | + seed: request.body.seed >= 0 ? request.body.seed : Math.floor(Math.random() * 10_000_000), | |
| 975 | + }), | |
| 976 | + headers: { | |
| 977 | + 'Content-Type': 'application/json', | |
| 978 | + 'Authorization': `Bearer ${key}`, | |
| 979 | + }, | |
| 980 | + }); | |
| 981 | + | |
| 982 | + if (!result.ok) { | |
| 983 | + console.log('Block Entropy returned an error.'); | |
| 984 | + return response.sendStatus(500); | |
| 985 | + } | |
| 986 | + | |
| 987 | + const data = await result.json(); | |
| 988 | + console.log('Block Entropy response:', data); | |
| 989 | + | |
| 990 | + //if (data.status !== 'finished') { | |
| 991 | + // console.log('Block Entropy job failed.'); | |
| 992 | + // return response.sendStatus(500); | |
| 993 | + //} | |
| 994 | + | |
| 995 | + return response.send(data); | |
| 996 | + } catch (error) { | |
| 997 | + console.log(error); | |
| 998 | + return response.sendStatus(500); | |
| 999 | + } | |
| 1000 | +}); | |
| 1001 | + | |
| 1002 | + | |
| 911 | 1003 | router.use('/comfy', comfy); |
| 912 | 1004 | router.use('/together', together); |
| 913 | 1005 | router.use('/drawthings', drawthings); |
| 914 | 1006 | router.use('/pollinations', pollinations); |
| 915 | 1007 | router.use('/stability', stability); |
| 1008 | +router.use('/blockentropy', blockentropy); | |
| 916 | 1009 | |
| 917 | 1010 | module.exports = { router }; |