ModelSelector.svelte 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. <script lang="ts">
  2. import { models, showSettings, settings, user, mobile, config } from '$lib/stores';
  3. import { onMount, tick, getContext } from 'svelte';
  4. import { toast } from 'svelte-sonner';
  5. import Selector from './ModelSelector/Selector.svelte';
  6. import Tooltip from '../common/Tooltip.svelte';
  7. import { updateUserSettings } from '$lib/apis/users';
  8. const i18n = getContext('i18n');
  9. export let selectedModels = [''];
  10. export let disabled = false;
  11. export let showSetDefault = true;
  12. const saveDefaultModel = async () => {
  13. const hasEmptyModel = selectedModels.filter((it) => it === '');
  14. if (hasEmptyModel.length) {
  15. toast.error($i18n.t('Choose a model before saving...'));
  16. return;
  17. }
  18. settings.set({ ...$settings, models: selectedModels });
  19. await updateUserSettings(localStorage.token, { ui: $settings });
  20. toast.success($i18n.t('Default model updated'));
  21. };
  22. const pinModelHandler = async (modelId) => {
  23. let pinnedModels = $settings?.pinnedModels ?? [];
  24. if (pinnedModels.includes(modelId)) {
  25. pinnedModels = pinnedModels.filter((id) => id !== modelId);
  26. } else {
  27. pinnedModels = [...new Set([...pinnedModels, modelId])];
  28. }
  29. settings.set({ ...$settings, pinnedModels: pinnedModels });
  30. await updateUserSettings(localStorage.token, { ui: $settings });
  31. };
  32. $: if (selectedModels.length > 0 && $models.length > 0) {
  33. const _selectedModels = selectedModels.map((model) =>
  34. $models.map((m) => m.id).includes(model) ? model : ''
  35. );
  36. if (JSON.stringify(_selectedModels) !== JSON.stringify(selectedModels)) {
  37. selectedModels = _selectedModels;
  38. }
  39. }
  40. </script>
  41. <div class="flex flex-col w-full items-start">
  42. {#each selectedModels as selectedModel, selectedModelIdx}
  43. <div class="flex w-full max-w-fit">
  44. <div class="overflow-hidden w-full">
  45. <div class="max-w-full {($settings?.highContrastMode ?? false) ? 'm-1' : 'mr-1'}">
  46. <Selector
  47. id={`${selectedModelIdx}`}
  48. placeholder={$i18n.t('Select a model')}
  49. items={$models.map((model) => ({
  50. value: model.id,
  51. label: model.name,
  52. model: model
  53. }))}
  54. {pinModelHandler}
  55. bind:value={selectedModel}
  56. />
  57. </div>
  58. </div>
  59. {#if $user?.role === 'admin' || ($user?.permissions?.chat?.multiple_models ?? true)}
  60. {#if selectedModelIdx === 0}
  61. <div
  62. class=" self-center mx-1 disabled:text-gray-600 disabled:hover:text-gray-600 -translate-y-[0.5px]"
  63. >
  64. <Tooltip content={$i18n.t('Add Model')}>
  65. <button
  66. class=" "
  67. {disabled}
  68. on:click={() => {
  69. selectedModels = [...selectedModels, ''];
  70. }}
  71. aria-label="Add Model"
  72. >
  73. <svg
  74. xmlns="http://www.w3.org/2000/svg"
  75. fill="none"
  76. viewBox="0 0 24 24"
  77. stroke-width="2"
  78. stroke="currentColor"
  79. class="size-3.5"
  80. >
  81. <path stroke-linecap="round" stroke-linejoin="round" d="M12 6v12m6-6H6" />
  82. </svg>
  83. </button>
  84. </Tooltip>
  85. </div>
  86. {:else}
  87. <div
  88. class=" self-center mx-1 disabled:text-gray-600 disabled:hover:text-gray-600 -translate-y-[0.5px]"
  89. >
  90. <Tooltip content={$i18n.t('Remove Model')}>
  91. <button
  92. {disabled}
  93. on:click={() => {
  94. selectedModels.splice(selectedModelIdx, 1);
  95. selectedModels = selectedModels;
  96. }}
  97. aria-label="Remove Model"
  98. >
  99. <svg
  100. xmlns="http://www.w3.org/2000/svg"
  101. fill="none"
  102. viewBox="0 0 24 24"
  103. stroke-width="2"
  104. stroke="currentColor"
  105. class="size-3"
  106. >
  107. <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 12h-15" />
  108. </svg>
  109. </button>
  110. </Tooltip>
  111. </div>
  112. {/if}
  113. {/if}
  114. </div>
  115. {/each}
  116. </div>
  117. {#if showSetDefault}
  118. <div
  119. class="relative text-left mt-[1px] ml-1 text-[0.7rem] text-gray-600 dark:text-gray-400 font-primary"
  120. >
  121. <button on:click={saveDefaultModel}> {$i18n.t('Set as default')}</button>
  122. </div>
  123. {/if}