Browse Source

feat: chat valves

Timothy J. Baek 10 months ago
parent
commit
97098edfeb

+ 14 - 1
src/lib/components/chat/Chat.svelte

@@ -104,6 +104,7 @@
 	};
 	};
 
 
 	let params = {};
 	let params = {};
+	let valves = {};
 
 
 	$: if (history.currentId !== null) {
 	$: if (history.currentId !== null) {
 		let _messages = [];
 		let _messages = [];
@@ -1541,6 +1542,18 @@
 			</div>
 			</div>
 		</div>
 		</div>
 
 
-		<ChatControls bind:show={showControls} bind:params />
+		<ChatControls
+			models={selectedModelIds.reduce((a, e, i, arr) => {
+				const model = $models.find((m) => m.id === e);
+
+				if (model) {
+					return [...a, model];
+				}
+				return a;
+			}, [])}
+			bind:show={showControls}
+			bind:params
+			bind:valves
+		/>
 	</div>
 	</div>
 {/if}
 {/if}

+ 8 - 0
src/lib/components/chat/ChatControls.svelte

@@ -6,7 +6,11 @@
 
 
 	export let show = false;
 	export let show = false;
 
 
+	export let models = [];
+
 	export let chatId = null;
 	export let chatId = null;
+	export let valves = {};
+
 	export let params = {};
 	export let params = {};
 
 
 	let largeScreen = false;
 	let largeScreen = false;
@@ -43,6 +47,8 @@
 						on:close={() => {
 						on:close={() => {
 							show = false;
 							show = false;
 						}}
 						}}
+						{models}
+						bind:valves
 						bind:params
 						bind:params
 					/>
 					/>
 				</div>
 				</div>
@@ -56,6 +62,8 @@
 				on:close={() => {
 				on:close={() => {
 					show = false;
 					show = false;
 				}}
 				}}
+				{models}
+				bind:valves
 				bind:params
 				bind:params
 			/>
 			/>
 		</div>
 		</div>

+ 15 - 0
src/lib/components/chat/Controls/Controls.svelte

@@ -5,7 +5,10 @@
 
 
 	import XMark from '$lib/components/icons/XMark.svelte';
 	import XMark from '$lib/components/icons/XMark.svelte';
 	import AdvancedParams from '../Settings/Advanced/AdvancedParams.svelte';
 	import AdvancedParams from '../Settings/Advanced/AdvancedParams.svelte';
+	import Valves from '$lib/components/common/Valves.svelte';
 
 
+	export let models = [];
+	export let valves = {};
 	export let params = {};
 	export let params = {};
 </script>
 </script>
 
 
@@ -23,6 +26,18 @@
 	</div>
 	</div>
 
 
 	<div class=" dark:text-gray-200 text-sm font-primary">
 	<div class=" dark:text-gray-200 text-sm font-primary">
+		{#if models.length === 1 && models[0]?.pipe?.valves_spec}
+			<div>
+				<div class=" font-medium">Valves</div>
+
+				<div>
+					<Valves valvesSpec={models[0]?.pipe?.valves_spec} bind:valves />
+				</div>
+			</div>
+
+			<hr class="my-2 border-gray-100 dark:border-gray-800" />
+		{/if}
+
 		<div>
 		<div>
 			<div class="mb-1.5 font-medium">System Prompt</div>
 			<div class="mb-1.5 font-medium">System Prompt</div>
 
 

+ 2 - 85
src/lib/components/chat/Settings/Valves.svelte

@@ -19,6 +19,7 @@
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import Spinner from '$lib/components/common/Spinner.svelte';
 	import Spinner from '$lib/components/common/Spinner.svelte';
 	import Switch from '$lib/components/common/Switch.svelte';
 	import Switch from '$lib/components/common/Switch.svelte';
+	import Valves from '$lib/components/common/Valves.svelte';
 
 
 	const dispatch = createEventDispatcher();
 	const dispatch = createEventDispatcher();
 
 
@@ -170,91 +171,7 @@
 
 
 			<div>
 			<div>
 				{#if !loading}
 				{#if !loading}
-					{#if valvesSpec}
-						{#each Object.keys(valvesSpec.properties) as property, idx}
-							<div class=" py-0.5 w-full justify-between">
-								<div class="flex w-full justify-between">
-									<div class=" self-center text-xs font-medium">
-										{valvesSpec.properties[property].title}
-
-										{#if (valvesSpec?.required ?? []).includes(property)}
-											<span class=" text-gray-500">*required</span>
-										{/if}
-									</div>
-
-									<button
-										class="p-1 px-3 text-xs flex rounded transition"
-										type="button"
-										on:click={() => {
-											valves[property] =
-												(valves[property] ?? null) === null
-													? valvesSpec.properties[property]?.default ?? ''
-													: null;
-										}}
-									>
-										{#if (valves[property] ?? null) === null}
-											<span class="ml-2 self-center">
-												{#if (valvesSpec?.required ?? []).includes(property)}
-													{$i18n.t('None')}
-												{:else}
-													{$i18n.t('Default')}
-												{/if}
-											</span>
-										{:else}
-											<span class="ml-2 self-center"> {$i18n.t('Custom')} </span>
-										{/if}
-									</button>
-								</div>
-
-								{#if (valves[property] ?? null) !== null}
-									<!-- {valves[property]} -->
-									<div class="flex mt-0.5 mb-1.5 space-x-2">
-										<div class=" flex-1">
-											{#if valvesSpec.properties[property]?.enum ?? null}
-												<select
-													class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
-													bind:value={valves[property]}
-												>
-													{#each valvesSpec.properties[property].enum as option}
-														<option value={option} selected={option === valves[property]}>
-															{option}
-														</option>
-													{/each}
-												</select>
-											{:else if (valvesSpec.properties[property]?.type ?? null) === 'boolean'}
-												<div class="flex justify-between items-center">
-													<div class="text-xs text-gray-500">
-														{valves[property] ? 'Enabled' : 'Disabled'}
-													</div>
-
-													<div class=" pr-2">
-														<Switch bind:state={valves[property]} />
-													</div>
-												</div>
-											{:else}
-												<input
-													class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
-													type="text"
-													placeholder={valvesSpec.properties[property].title}
-													bind:value={valves[property]}
-													autocomplete="off"
-													required
-												/>
-											{/if}
-										</div>
-									</div>
-								{/if}
-
-								{#if (valvesSpec.properties[property]?.description ?? null) !== null}
-									<div class="text-xs text-gray-500">
-										{valvesSpec.properties[property].description}
-									</div>
-								{/if}
-							</div>
-						{/each}
-					{:else}
-						<div>No valves</div>
-					{/if}
+					<Valves {valvesSpec} bind:valves />
 				{:else}
 				{:else}
 					<Spinner className="size-5" />
 					<Spinner className="size-5" />
 				{/if}
 				{/if}

+ 95 - 0
src/lib/components/common/Valves.svelte

@@ -0,0 +1,95 @@
+<script>
+	import { onMount, getContext } from 'svelte';
+	const i18n = getContext('i18n');
+
+	import Switch from './Switch.svelte';
+
+	export let valvesSpec = null;
+	export let valves = {};
+</script>
+
+{#if valvesSpec}
+	{#each Object.keys(valvesSpec.properties) as property, idx}
+		<div class=" py-0.5 w-full justify-between">
+			<div class="flex w-full justify-between">
+				<div class=" self-center text-xs font-medium">
+					{valvesSpec.properties[property].title}
+
+					{#if (valvesSpec?.required ?? []).includes(property)}
+						<span class=" text-gray-500">*required</span>
+					{/if}
+				</div>
+
+				<button
+					class="p-1 px-3 text-xs flex rounded transition"
+					type="button"
+					on:click={() => {
+						valves[property] =
+							(valves[property] ?? null) === null
+								? valvesSpec.properties[property]?.default ?? ''
+								: null;
+					}}
+				>
+					{#if (valves[property] ?? null) === null}
+						<span class="ml-2 self-center">
+							{#if (valvesSpec?.required ?? []).includes(property)}
+								{$i18n.t('None')}
+							{:else}
+								{$i18n.t('Default')}
+							{/if}
+						</span>
+					{:else}
+						<span class="ml-2 self-center"> {$i18n.t('Custom')} </span>
+					{/if}
+				</button>
+			</div>
+
+			{#if (valves[property] ?? null) !== null}
+				<!-- {valves[property]} -->
+				<div class="flex mt-0.5 mb-1.5 space-x-2">
+					<div class=" flex-1">
+						{#if valvesSpec.properties[property]?.enum ?? null}
+							<select
+								class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none border border-gray-100 dark:border-gray-800"
+								bind:value={valves[property]}
+							>
+								{#each valvesSpec.properties[property].enum as option}
+									<option value={option} selected={option === valves[property]}>
+										{option}
+									</option>
+								{/each}
+							</select>
+						{:else if (valvesSpec.properties[property]?.type ?? null) === 'boolean'}
+							<div class="flex justify-between items-center">
+								<div class="text-xs text-gray-500">
+									{valves[property] ? 'Enabled' : 'Disabled'}
+								</div>
+
+								<div class=" pr-2">
+									<Switch bind:state={valves[property]} />
+								</div>
+							</div>
+						{:else}
+							<input
+								class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none border border-gray-100 dark:border-gray-800"
+								type="text"
+								placeholder={valvesSpec.properties[property].title}
+								bind:value={valves[property]}
+								autocomplete="off"
+								required
+							/>
+						{/if}
+					</div>
+				</div>
+			{/if}
+
+			{#if (valvesSpec.properties[property]?.description ?? null) !== null}
+				<div class="text-xs text-gray-500">
+					{valvesSpec.properties[property].description}
+				</div>
+			{/if}
+		</div>
+	{/each}
+{:else}
+	<div class="text-sm">No valves</div>
+{/if}

+ 2 - 85
src/lib/components/workspace/common/ValvesModal.svelte

@@ -13,6 +13,7 @@
 	import { getToolValvesById, getToolValvesSpecById, updateToolValvesById } from '$lib/apis/tools';
 	import { getToolValvesById, getToolValvesSpecById, updateToolValvesById } from '$lib/apis/tools';
 	import Spinner from '../../common/Spinner.svelte';
 	import Spinner from '../../common/Spinner.svelte';
 	import Switch from '$lib/components/common/Switch.svelte';
 	import Switch from '$lib/components/common/Switch.svelte';
+	import Valves from '$lib/components/common/Valves.svelte';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 	const dispatch = createEventDispatcher();
 	const dispatch = createEventDispatcher();
@@ -127,91 +128,7 @@
 				>
 				>
 					<div class="px-1">
 					<div class="px-1">
 						{#if !loading}
 						{#if !loading}
-							{#if valvesSpec}
-								{#each Object.keys(valvesSpec.properties) as property, idx}
-									<div class=" py-0.5 w-full justify-between">
-										<div class="flex w-full justify-between">
-											<div class=" self-center text-xs font-medium">
-												{valvesSpec.properties[property].title}
-
-												{#if (valvesSpec?.required ?? []).includes(property)}
-													<span class=" text-gray-500">*required</span>
-												{/if}
-											</div>
-
-											<button
-												class="p-1 px-3 text-xs flex rounded transition"
-												type="button"
-												on:click={() => {
-													valves[property] =
-														(valves[property] ?? null) === null
-															? valvesSpec.properties[property]?.default ?? ''
-															: null;
-												}}
-											>
-												{#if (valves[property] ?? null) === null}
-													<span class="ml-2 self-center">
-														{#if (valvesSpec?.required ?? []).includes(property)}
-															{$i18n.t('None')}
-														{:else}
-															{$i18n.t('Default')}
-														{/if}
-													</span>
-												{:else}
-													<span class="ml-2 self-center"> {$i18n.t('Custom')} </span>
-												{/if}
-											</button>
-										</div>
-
-										{#if (valves[property] ?? null) !== null}
-											<!-- {valves[property]} -->
-											<div class="flex mt-0.5 mb-1.5 space-x-2">
-												<div class=" flex-1">
-													{#if valvesSpec.properties[property]?.enum ?? null}
-														<select
-															class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
-															bind:value={valves[property]}
-														>
-															{#each valvesSpec.properties[property].enum as option}
-																<option value={option} selected={option === valves[property]}>
-																	{option}
-																</option>
-															{/each}
-														</select>
-													{:else if (valvesSpec.properties[property]?.type ?? null) === 'boolean'}
-														<div class="flex justify-between items-center">
-															<div class="text-xs text-gray-500">
-																{valves[property] ? 'Enabled' : 'Disabled'}
-															</div>
-
-															<div class=" pr-2">
-																<Switch bind:state={valves[property]} />
-															</div>
-														</div>
-													{:else}
-														<input
-															class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
-															type="text"
-															placeholder={valvesSpec.properties[property].title}
-															bind:value={valves[property]}
-															autocomplete="off"
-															required
-														/>
-													{/if}
-												</div>
-											</div>
-										{/if}
-
-										{#if (valvesSpec.properties[property]?.description ?? null) !== null}
-											<div class="text-xs text-gray-500">
-												{valvesSpec.properties[property].description}
-											</div>
-										{/if}
-									</div>
-								{/each}
-							{:else}
-								<div class="text-sm">No valves</div>
-							{/if}
+							<Valves {valvesSpec} bind:valves />
 						{:else}
 						{:else}
 							<Spinner className="size-5" />
 							<Spinner className="size-5" />
 						{/if}
 						{/if}