feat: [Electron Hub] Support Vector Storage, Better searching for image engine (#4540) * feat: [Electron Hub] Add Vector Storage, Better searching for image model list * feat: [Electron Hub] Add quality parameter for Image Engine * fixed ESLint * Update public/scripts/extensions/vectors/index.js Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * small tweaks * Use default getOpenAIVector * Refactor and clean-up code * Move endpoint filtering logic to backend --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
Signed| @@ -1277,9 +1277,16 @@ async function validateComfyUrl() { | |||
| 1277 | } | 1277 | } |
| 1278 | 1278 | ||
| 1279 | async function onModelChange() { | 1279 | async function onModelChange() { |
| 1280 | extension_settings.sd.model = $('#sd_model').find(':selected').val(); | 1280 | const selectedModel = $('#sd_model').find(':selected'); |
| 1281 | extension_settings.sd.model = selectedModel.val(); | ||
| 1281 | saveSettingsDebounced(); | 1282 | saveSettingsDebounced(); |
| 1282 | 1283 | ||
| 1284 | if (extension_settings.sd.model && extension_settings.sd.source === sources.electronhub) { | ||
| 1285 | const cachedModel = selectedModel.data('model'); | ||
| 1286 | const models = cachedModel ? [cachedModel] : await loadElectronHubModels(); | ||
| 1287 | ensureElectronHubQualitySelect(models); | ||
| 1288 | } | ||
| 1289 | |||
| 1283 | const cloudSources = [ | 1290 | const cloudSources = [ |
| 1284 | sources.horde, | 1291 | sources.horde, |
| 1285 | sources.novel, | 1292 | sources.novel, |
| @@ -1726,11 +1733,16 @@ async function loadModels() { | |||
| 1726 | break; | 1733 | break; |
| 1727 | } | 1734 | } |
| 1728 | 1735 | ||
| 1736 | if (extension_settings.sd.source === sources.electronhub) { | ||
| 1737 | ensureElectronHubQualitySelect(models); | ||
| 1738 | } | ||
| 1739 | |||
| 1729 | for (const model of models) { | 1740 | for (const model of models) { |
| 1730 | const option = document.createElement('option'); | 1741 | const option = document.createElement('option'); |
| 1731 | option.innerText = model.text; | 1742 | option.innerText = model.text; |
| 1732 | option.value = model.value; | 1743 | option.value = model.value; |
| 1733 | option.selected = model.value === extension_settings.sd.model; | 1744 | option.selected = model.value === extension_settings.sd.model; |
| 1745 | $(option).data('model', model); | ||
| 1734 | $('#sd_model').append(option); | 1746 | $('#sd_model').append(option); |
| 1735 | } | 1747 | } |
| 1736 | 1748 | ||
| @@ -1740,6 +1752,49 @@ async function loadModels() { | |||
| 1740 | } | 1752 | } |
| 1741 | } | 1753 | } |
| 1742 | 1754 | ||
| 1755 | /** | ||
| 1756 | * Ensure the Electron Hub quality select is populated based on the selected model. | ||
| 1757 | * @param {any[]} models Array of models | ||
| 1758 | */ | ||
| 1759 | function ensureElectronHubQualitySelect(models) { | ||
| 1760 | try { | ||
| 1761 | const modelId = String(extension_settings.sd.model || ''); | ||
| 1762 | if (!modelId) return; | ||
| 1763 | |||
| 1764 | const model = Array.isArray(models) ? models.find(m => String(m?.id) === modelId) : undefined; | ||
| 1765 | const qualities = Array.isArray(model?.qualities) ? model.qualities : undefined; | ||
| 1766 | |||
| 1767 | const $qualityRow = $('#sd_electronhub_quality_row'); | ||
| 1768 | const $select = $('#sd_electronhub_quality'); | ||
| 1769 | |||
| 1770 | $qualityRow.toggle(!!qualities && qualities.length > 0); | ||
| 1771 | $select.empty(); | ||
| 1772 | |||
| 1773 | if (!qualities || qualities.length === 0) { | ||
| 1774 | extension_settings.sd.electronhub_quality = undefined; | ||
| 1775 | saveSettingsDebounced(); | ||
| 1776 | return; | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | for (const q of qualities) { | ||
| 1780 | const opt = document.createElement('option'); | ||
| 1781 | opt.value = String(q); | ||
| 1782 | opt.textContent = String(q); | ||
| 1783 | opt.selected = String(q) === String(extension_settings.sd.electronhub_quality || ''); | ||
| 1784 | $select.append(opt); | ||
| 1785 | } | ||
| 1786 | |||
| 1787 | if (!$select.val()) { | ||
| 1788 | const first = String(qualities[0]); | ||
| 1789 | extension_settings.sd.electronhub_quality = first; | ||
| 1790 | $select.val(first); | ||
| 1791 | saveSettingsDebounced(); | ||
| 1792 | } | ||
| 1793 | } catch (e) { | ||
| 1794 | console.error(e); | ||
| 1795 | } | ||
| 1796 | } | ||
| 1797 | |||
| 1743 | async function loadStabilityModels() { | 1798 | async function loadStabilityModels() { |
| 1744 | $('#sd_stability_key').toggleClass('success', !!secret_state[SECRET_KEYS.STABILITY]); | 1799 | $('#sd_stability_key').toggleClass('success', !!secret_state[SECRET_KEYS.STABILITY]); |
| 1745 | 1800 | ||
| @@ -1824,8 +1879,23 @@ async function loadElectronHubModels() { | |||
| 1824 | headers: getRequestHeaders(), | 1879 | headers: getRequestHeaders(), |
| 1825 | }); | 1880 | }); |
| 1826 | 1881 | ||
| 1882 | function getModelName(model) { | ||
| 1883 | const name = String(model?.name || model?.id || ''); | ||
| 1884 | const premium = model?.premium_model ? ' | Premium' : ''; | ||
| 1885 | let price = 'Unknown'; | ||
| 1886 | if (model?.pricing?.type === 'per_image') { | ||
| 1887 | const coeff = Number(model.pricing.coefficient); | ||
| 1888 | if (!isNaN(coeff)) { | ||
| 1889 | price = `$${coeff}/image`; | ||
| 1890 | } | ||
| 1891 | } | ||
| 1892 | return `${name} | ${price}${premium}`; | ||
| 1893 | } | ||
| 1894 | |||
| 1827 | if (result.ok) { | 1895 | if (result.ok) { |
| 1828 | return await result.json(); | 1896 | /** @type {any[]} */ |
| 1897 | const data = await result.json(); | ||
| 1898 | return Array.isArray(data) ? data.map(m => ({ ...m, text: getModelName(m) })) : []; | ||
| 1829 | } | 1899 | } |
| 1830 | 1900 | ||
| 1831 | return []; | 1901 | return []; |
| @@ -3665,6 +3735,7 @@ async function generateElectronHubImage(prompt, signal) { | |||
| 3665 | model: extension_settings.sd.model, | 3735 | model: extension_settings.sd.model, |
| 3666 | prompt: prompt, | 3736 | prompt: prompt, |
| 3667 | size: size, | 3737 | size: size, |
| 3738 | quality: String(extension_settings.sd.electronhub_quality || '').trim() || undefined, | ||
| 3668 | }), | 3739 | }), |
| 3669 | }); | 3740 | }); |
| 3670 | 3741 | ||
| @@ -4816,6 +4887,10 @@ jQuery(async () => { | |||
| 4816 | extension_settings.sd.google_enhance = $(this).prop('checked'); | 4887 | extension_settings.sd.google_enhance = $(this).prop('checked'); |
| 4817 | saveSettingsDebounced(); | 4888 | saveSettingsDebounced(); |
| 4818 | }); | 4889 | }); |
| 4890 | $('#sd_electronhub_quality').on('change', function () { | ||
| 4891 | extension_settings.sd.electronhub_quality = String($(this).val()); | ||
| 4892 | saveSettingsDebounced(); | ||
| 4893 | }); | ||
| 4819 | 4894 | ||
| 4820 | if (!CSS.supports('field-sizing', 'content')) { | 4895 | if (!CSS.supports('field-sizing', 'content')) { |
| 4821 | $('.sd_settings .inline-drawer-toggle').on('click', function () { | 4896 | $('.sd_settings .inline-drawer-toggle').on('click', function () { |
| @@ -96,6 +96,12 @@ | |||
| 96 | </div> | 96 | </div> |
| 97 | <div data-sd-source="electronhub"> | 97 | <div data-sd-source="electronhub"> |
| 98 | <i data-i18n="Hint: Save an API key in the Electron Hub (Chat Completion) API settings to use it here.">Hint: Save an API key in the Electron Hub (Chat Completion) API settings to use it here.</i> | 98 | <i data-i18n="Hint: Save an API key in the Electron Hub (Chat Completion) API settings to use it here.">Hint: Save an API key in the Electron Hub (Chat Completion) API settings to use it here.</i> |
| 99 | <div class="flex-container" id="sd_electronhub_quality_row"> | ||
| 100 | <div class="flex1"> | ||
| 101 | <label for="sd_electronhub_quality" data-i18n="Image Quality">Image Quality</label> | ||
| 102 | <select id="sd_electronhub_quality"></select> | ||
| 103 | </div> | ||
| 104 | </div> | ||
| 99 | </div> | 105 | </div> |
| 100 | <div data-sd-source="nanogpt"> | 106 | <div data-sd-source="nanogpt"> |
| 101 | <i data-i18n="Hint: Save an API key in the NanoGPT (Chat Completion) API settings to use it here.">Hint: Save an API key in the NanoGPT (Chat Completion) API settings to use it here.</i> | 107 | <i data-i18n="Hint: Save an API key in the NanoGPT (Chat Completion) API settings to use it here.">Hint: Save an API key in the NanoGPT (Chat Completion) API settings to use it here.</i> |
| @@ -61,6 +61,7 @@ const settings = { | |||
| 61 | include_wi: false, | 61 | include_wi: false, |
| 62 | togetherai_model: 'togethercomputer/m2-bert-80M-32k-retrieval', | 62 | togetherai_model: 'togethercomputer/m2-bert-80M-32k-retrieval', |
| 63 | openai_model: 'text-embedding-ada-002', | 63 | openai_model: 'text-embedding-ada-002', |
| 64 | electronhub_model: 'text-embedding-3-small', | ||
| 64 | cohere_model: 'embed-english-v3.0', | 65 | cohere_model: 'embed-english-v3.0', |
| 65 | ollama_model: 'mxbai-embed-large', | 66 | ollama_model: 'mxbai-embed-large', |
| 66 | ollama_keep: false, | 67 | ollama_keep: false, |
| @@ -771,6 +772,9 @@ function getVectorsRequestBody(args = {}) { | |||
| 771 | body.extrasUrl = extension_settings.apiUrl; | 772 | body.extrasUrl = extension_settings.apiUrl; |
| 772 | body.extrasKey = extension_settings.apiKey; | 773 | body.extrasKey = extension_settings.apiKey; |
| 773 | break; | 774 | break; |
| 775 | case 'electronhub': | ||
| 776 | body.model = extension_settings.vectors.electronhub_model; | ||
| 777 | break; | ||
| 774 | case 'togetherai': | 778 | case 'togetherai': |
| 775 | body.model = extension_settings.vectors.togetherai_model; | 779 | body.model = extension_settings.vectors.togetherai_model; |
| 776 | break; | 780 | break; |
| @@ -889,6 +893,7 @@ async function insertVectorItems(collectionId, items) { | |||
| 889 | */ | 893 | */ |
| 890 | function throwIfSourceInvalid() { | 894 | function throwIfSourceInvalid() { |
| 891 | if (settings.source === 'openai' && !secret_state[SECRET_KEYS.OPENAI] || | 895 | if (settings.source === 'openai' && !secret_state[SECRET_KEYS.OPENAI] || |
| 896 | settings.source === 'electronhub' && !secret_state[SECRET_KEYS.ELECTRONHUB] || | ||
| 892 | settings.source === 'palm' && !secret_state[SECRET_KEYS.MAKERSUITE] || | 897 | settings.source === 'palm' && !secret_state[SECRET_KEYS.MAKERSUITE] || |
| 893 | settings.source === 'vertexai' && !secret_state[SECRET_KEYS.VERTEXAI] && !secret_state[SECRET_KEYS.VERTEXAI_SERVICE_ACCOUNT] || | 898 | settings.source === 'vertexai' && !secret_state[SECRET_KEYS.VERTEXAI] && !secret_state[SECRET_KEYS.VERTEXAI_SERVICE_ACCOUNT] || |
| 894 | settings.source === 'mistral' && !secret_state[SECRET_KEYS.MISTRALAI] || | 899 | settings.source === 'mistral' && !secret_state[SECRET_KEYS.MISTRALAI] || |
| @@ -1101,6 +1106,7 @@ function toggleSettings() { | |||
| 1101 | $('#vectors_world_info_settings').toggle(!!settings.enabled_world_info); | 1106 | $('#vectors_world_info_settings').toggle(!!settings.enabled_world_info); |
| 1102 | $('#together_vectorsModel').toggle(settings.source === 'togetherai'); | 1107 | $('#together_vectorsModel').toggle(settings.source === 'togetherai'); |
| 1103 | $('#openai_vectorsModel').toggle(settings.source === 'openai'); | 1108 | $('#openai_vectorsModel').toggle(settings.source === 'openai'); |
| 1109 | $('#electronhub_vectorsModel').toggle(settings.source === 'electronhub'); | ||
| 1104 | $('#cohere_vectorsModel').toggle(settings.source === 'cohere'); | 1110 | $('#cohere_vectorsModel').toggle(settings.source === 'cohere'); |
| 1105 | $('#ollama_vectorsModel').toggle(settings.source === 'ollama'); | 1111 | $('#ollama_vectorsModel').toggle(settings.source === 'ollama'); |
| 1106 | $('#llamacpp_vectorsModel').toggle(settings.source === 'llamacpp'); | 1112 | $('#llamacpp_vectorsModel').toggle(settings.source === 'llamacpp'); |
| @@ -1110,12 +1116,56 @@ function toggleSettings() { | |||
| 1110 | $('#koboldcpp_vectorsModel').toggle(settings.source === 'koboldcpp'); | 1116 | $('#koboldcpp_vectorsModel').toggle(settings.source === 'koboldcpp'); |
| 1111 | $('#google_vectorsModel').toggle(settings.source === 'palm' || settings.source === 'vertexai'); | 1117 | $('#google_vectorsModel').toggle(settings.source === 'palm' || settings.source === 'vertexai'); |
| 1112 | $('#vector_altEndpointUrl').toggle(vectorApiRequiresUrl.includes(settings.source)); | 1118 | $('#vector_altEndpointUrl').toggle(vectorApiRequiresUrl.includes(settings.source)); |
| 1113 | if (settings.source === 'webllm') { | 1119 | switch (settings.source) { |
| 1114 | loadWebLlmModels(); | 1120 | case 'webllm': |
| 1121 | loadWebLlmModels(); | ||
| 1122 | break; | ||
| 1123 | case 'electronhub': | ||
| 1124 | loadElectronHubModels(); | ||
| 1125 | break; | ||
| 1126 | } | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | async function loadElectronHubModels() { | ||
| 1130 | try { | ||
| 1131 | const response = await fetch('/api/openai/electronhub/models', { | ||
| 1132 | method: 'POST', | ||
| 1133 | headers: getRequestHeaders(), | ||
| 1134 | }); | ||
| 1135 | if (!response.ok) { | ||
| 1136 | throw new Error(`HTTP ${response.status}`); | ||
| 1137 | } | ||
| 1138 | /** @type {Array<any>} */ | ||
| 1139 | const data = await response.json(); | ||
| 1140 | // filter by embeddings endpoint | ||
| 1141 | const models = Array.isArray(data) ? data.filter(m => Array.isArray(m?.endpoints) && m.endpoints.includes('/v1/embeddings')) : []; | ||
| 1142 | populateElectronHubModelSelect(models); | ||
| 1143 | } catch (err) { | ||
| 1144 | console.warn('Electron Hub models fetch failed', err); | ||
| 1145 | populateElectronHubModelSelect([]); | ||
| 1115 | } | 1146 | } |
| 1116 | } | 1147 | } |
| 1117 | 1148 | ||
| 1118 | /** | 1149 | /** |
| 1150 | * Populates the Electron Hub model select element. | ||
| 1151 | * @param {{ id: string, name: string }[]} models Electron Hub models | ||
| 1152 | */ | ||
| 1153 | function populateElectronHubModelSelect(models) { | ||
| 1154 | const select = $('#vectors_electronhub_model'); | ||
| 1155 | select.empty(); | ||
| 1156 | for (const m of models) { | ||
| 1157 | const option = document.createElement('option'); | ||
| 1158 | option.value = m.id; | ||
| 1159 | option.text = m.name || m.id; | ||
| 1160 | select.append(option); | ||
| 1161 | } | ||
| 1162 | if (!settings.electronhub_model && models.length) { | ||
| 1163 | settings.electronhub_model = models[0].id; | ||
| 1164 | } | ||
| 1165 | $('#vectors_electronhub_model').val(settings.electronhub_model); | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | /** | ||
| 1119 | * Executes a function with WebLLM error handling. | 1169 | * Executes a function with WebLLM error handling. |
| 1120 | * @param {function(): Promise<T>} func Function to execute | 1170 | * @param {function(): Promise<T>} func Function to execute |
| 1121 | * @returns {Promise<T>} | 1171 | * @returns {Promise<T>} |
| @@ -1513,6 +1563,11 @@ jQuery(async () => { | |||
| 1513 | Object.assign(extension_settings.vectors, settings); | 1563 | Object.assign(extension_settings.vectors, settings); |
| 1514 | saveSettingsDebounced(); | 1564 | saveSettingsDebounced(); |
| 1515 | }); | 1565 | }); |
| 1566 | $('#vectors_electronhub_model').val(settings.electronhub_model).on('change', () => { | ||
| 1567 | settings.electronhub_model = String($('#vectors_electronhub_model').val()); | ||
| 1568 | Object.assign(extension_settings.vectors, settings); | ||
| 1569 | saveSettingsDebounced(); | ||
| 1570 | }); | ||
| 1516 | $('#vectors_cohere_model').val(settings.cohere_model).on('change', () => { | 1571 | $('#vectors_cohere_model').val(settings.cohere_model).on('change', () => { |
| 1517 | settings.cohere_model = String($('#vectors_cohere_model').val()); | 1572 | settings.cohere_model = String($('#vectors_cohere_model').val()); |
| 1518 | Object.assign(extension_settings.vectors, settings); | 1573 | Object.assign(extension_settings.vectors, settings); |
| @@ -11,6 +11,7 @@ | |||
| 11 | </label> | 11 | </label> |
| 12 | <select id="vectors_source" class="text_pole"> | 12 | <select id="vectors_source" class="text_pole"> |
| 13 | <option value="cohere">Cohere</option> | 13 | <option value="cohere">Cohere</option> |
| 14 | <option value="electronhub">Electron Hub</option> | ||
| 14 | <option value="extras">Extras (deprecated)</option> | 15 | <option value="extras">Extras (deprecated)</option> |
| 15 | <option value="palm">Google AI Studio</option> | 16 | <option value="palm">Google AI Studio</option> |
| 16 | <option value="vertexai">Google Vertex AI</option> | 17 | <option value="vertexai">Google Vertex AI</option> |
| @@ -26,6 +27,15 @@ | |||
| 26 | <option value="webllm" data-i18n="WebLLM Extension">WebLLM Extension</option> | 27 | <option value="webllm" data-i18n="WebLLM Extension">WebLLM Extension</option> |
| 27 | </select> | 28 | </select> |
| 28 | </div> | 29 | </div> |
| 30 | <div class="flex-container flexFlowColumn" id="electronhub_vectorsModel"> | ||
| 31 | <label for="vectors_electronhub_model" data-i18n="Vectorization Model"> | ||
| 32 | Vectorization Model | ||
| 33 | </label> | ||
| 34 | <select id="vectors_electronhub_model" class="text_pole"></select> | ||
| 35 | <i data-i18n="Hint: Set your Electron Hub API key in API Connections."> | ||
| 36 | Hint: Set your Electron Hub API key in API Connections. | ||
| 37 | </i> | ||
| 38 | </div> | ||
| 29 | <div class="flex-container flexFlowColumn" id="vector_altEndpointUrl"> | 39 | <div class="flex-container flexFlowColumn" id="vector_altEndpointUrl"> |
| 30 | <label class="checkbox_label" for="vector_altEndpointUrl_enabled" title="Enable secondary endpoint URL usage, instead of the main one."> | 40 | <label class="checkbox_label" for="vector_altEndpointUrl_enabled" title="Enable secondary endpoint URL usage, instead of the main one."> |
| 31 | <input id="vector_altEndpointUrl_enabled" type="checkbox" class="checkbox"> | 41 | <input id="vector_altEndpointUrl_enabled" type="checkbox" class="checkbox"> |
| @@ -4820,7 +4820,7 @@ function getElectronHubMaxContext(model, isUnlocked) { | |||
| 4820 | return modelInfo.tokens; | 4820 | return modelInfo.tokens; |
| 4821 | } | 4821 | } |
| 4822 | } | 4822 | } |
| 4823 | return max_8k; | 4823 | return max_128k; |
| 4824 | } | 4824 | } |
| 4825 | 4825 | ||
| 4826 | /** | 4826 | /** |
| @@ -983,7 +983,15 @@ electronhub.post('/models', async (request, response) => { | |||
| 983 | 983 | ||
| 984 | /** @type {any} */ | 984 | /** @type {any} */ |
| 985 | const data = await modelsResponse.json(); | 985 | const data = await modelsResponse.json(); |
| 986 | const models = data.data.filter(x => x.endpoints.includes('/v1/images/generations')).map(x => ({ value: x.id, text: x.name })); | 986 | |
| 987 | if (!Array.isArray(data?.data)) { | ||
| 988 | console.warn('Electron Hub returned invalid data.'); | ||
| 989 | return response.sendStatus(500); | ||
| 990 | } | ||
| 991 | |||
| 992 | const models = data.data | ||
| 993 | .filter(x => x && Array.isArray(x.endpoints) && x.endpoints.includes('/v1/images/generations')) | ||
| 994 | .map(x => ({ ...x, value: x.id, text: x.name })); | ||
| 987 | return response.send(models); | 995 | return response.send(models); |
| 988 | } catch (error) { | 996 | } catch (error) { |
| 989 | console.error(error); | 997 | console.error(error); |
| @@ -1010,6 +1018,12 @@ electronhub.post('/generate', async (request, response) => { | |||
| 1010 | bodyParams.size = request.body.size; | 1018 | bodyParams.size = request.body.size; |
| 1011 | } | 1019 | } |
| 1012 | 1020 | ||
| 1021 | if (request.body.quality) { | ||
| 1022 | bodyParams.quality = request.body.quality; | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | console.debug('Electron Hub request:', bodyParams); | ||
| 1026 | |||
| 1013 | const result = await fetch('https://api.electronhub.ai/v1/images/generations', { | 1027 | const result = await fetch('https://api.electronhub.ai/v1/images/generations', { |
| 1014 | method: 'POST', | 1028 | method: 'POST', |
| 1015 | headers: { | 1029 | headers: { |
| @@ -34,6 +34,7 @@ const SOURCES = [ | |||
| 34 | 'webllm', | 34 | 'webllm', |
| 35 | 'koboldcpp', | 35 | 'koboldcpp', |
| 36 | 'vertexai', | 36 | 'vertexai', |
| 37 | 'electronhub', | ||
| 37 | ]; | 38 | ]; |
| 38 | 39 | ||
| 39 | /** | 40 | /** |
| @@ -53,6 +54,8 @@ async function getVector(source, sourceSettings, text, isQuery, directories) { | |||
| 53 | case 'mistral': | 54 | case 'mistral': |
| 54 | case 'openai': | 55 | case 'openai': |
| 55 | return getOpenAIVector(text, source, directories, sourceSettings.model); | 56 | return getOpenAIVector(text, source, directories, sourceSettings.model); |
| 57 | case 'electronhub': | ||
| 58 | return getOpenAIVector(text, source, directories, sourceSettings.model); | ||
| 56 | case 'transformers': | 59 | case 'transformers': |
| 57 | return getTransformersVector(text); | 60 | return getTransformersVector(text); |
| 58 | case 'extras': | 61 | case 'extras': |
| @@ -102,6 +105,9 @@ async function getBatchVector(source, sourceSettings, texts, isQuery, directorie | |||
| 102 | case 'openai': | 105 | case 'openai': |
| 103 | results.push(...await getOpenAIBatchVector(batch, source, directories, sourceSettings.model)); | 106 | results.push(...await getOpenAIBatchVector(batch, source, directories, sourceSettings.model)); |
| 104 | break; | 107 | break; |
| 108 | case 'electronhub': | ||
| 109 | results.push(...await getOpenAIBatchVector(batch, source, directories, sourceSettings.model)); | ||
| 110 | break; | ||
| 105 | case 'transformers': | 111 | case 'transformers': |
| 106 | results.push(...await getTransformersBatchVector(batch)); | 112 | results.push(...await getTransformersBatchVector(batch)); |
| 107 | break; | 113 | break; |
| @@ -156,6 +162,10 @@ function getSourceSettings(source, request) { | |||
| 156 | return { | 162 | return { |
| 157 | model: String(request.body.model), | 163 | model: String(request.body.model), |
| 158 | }; | 164 | }; |
| 165 | case 'electronhub': | ||
| 166 | return { | ||
| 167 | model: String(request.body.model || 'text-embedding-3-small'), | ||
| 168 | }; | ||
| 159 | case 'cohere': | 169 | case 'cohere': |
| 160 | return { | 170 | return { |
| 161 | model: String(request.body.model), | 171 | model: String(request.body.model), |
| @@ -17,6 +17,11 @@ const SOURCES = { | |||
| 17 | url: 'api.openai.com', | 17 | url: 'api.openai.com', |
| 18 | model: 'text-embedding-ada-002', | 18 | model: 'text-embedding-ada-002', |
| 19 | }, | 19 | }, |
| 20 | 'electronhub': { | ||
| 21 | secretKey: SECRET_KEYS.ELECTRONHUB, | ||
| 22 | url: 'api.electronhub.ai', | ||
| 23 | model: 'text-embedding-3-small', | ||
| 24 | }, | ||
| 20 | }; | 25 | }; |
| 21 | 26 | ||
| 22 | /** | 27 | /** |