This commit is contained in:
Chris Kanich 2025-03-11 20:51:23 +00:00 committed by GitHub
commit 21d99b14b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 165 additions and 10 deletions

View File

@ -397,7 +397,12 @@ async def chat_action(request: Request, action_id: str, form_data: dict, user: A
if hasattr(function_module, "valves") and hasattr(function_module, "Valves"):
valves = Functions.get_function_valves_by_id(action_id)
function_module.valves = function_module.Valves(**(valves if valves else {}))
model_valves = (
model.get("info", {}).get("meta", {}).get("valves", {}).get(action_id, {})
)
function_module.valves = function_module.Valves(
**(valves if valves else {}), **model_valves
)
if hasattr(function_module, "action"):
try:

View File

@ -61,6 +61,17 @@ async def process_filter_functions(
# Apply valves to the function
if hasattr(function_module, "valves") and hasattr(function_module, "Valves"):
valves = Functions.get_function_valves_by_id(filter_id)
# overwrite global valves with model valves
model_valves = (
extra_params.get("__model__", {})
.get("info", {})
.get("meta", {})
.get("valves", {})
.get("functions", {})
.get(filter_id, {})
)
valves = {**valves, **model_valves}
function_module.valves = function_module.Valves(
**(valves if valves else {})
)

View File

@ -53,6 +53,18 @@ def get_tools(
extra_params["__id__"] = tool_id
if hasattr(module, "valves") and hasattr(module, "Valves"):
valves = Tools.get_tool_valves_by_id(tool_id) or {}
# overwrite global valves with model valves
valves = {
**valves,
**(
extra_params.get("__model__", {})
.get("info", {})
.get("meta", {})
.get("valves", {})
.get("tools", {})
.get(tool_id, {})
),
}
module.valves = module.Valves(**valves)
if hasattr(module, "UserValves"):

View File

@ -95,12 +95,12 @@
{/if}
</div>
</div>
{/if}
{#if (valvesSpec.properties[property]?.description ?? null) !== null}
<div class="text-xs text-gray-500">
{valvesSpec.properties[property].description}
</div>
{#if (valvesSpec.properties[property]?.description ?? null) !== null}
<div class="text-xs text-gray-500">
{valvesSpec.properties[property].description}
</div>
{/if}
{/if}
</div>
{/each}

View File

@ -2,12 +2,17 @@
import { getContext, onMount } from 'svelte';
import Checkbox from '$lib/components/common/Checkbox.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import Collapsible from '$lib/components/common/Collapsible.svelte';
import Valves from '$lib/components/common/Valves.svelte';
const i18n = getContext('i18n');
export let actions = [];
export let selectedActionIds = [];
export let valvesSpecs = {};
export let valves = {};
let _actions = {};
onMount(() => {
@ -33,7 +38,7 @@
<div class="flex flex-col">
{#if actions.length > 0}
<div class=" flex items-center mt-2 flex-wrap">
<div class=" flex flex-col items-left mt-2 flex-wrap">
{#each Object.keys(_actions) as action, actionIdx}
<div class=" flex items-center gap-2 mr-3">
<div class="self-center flex items-center">
@ -52,6 +57,18 @@
</Tooltip>
</div>
</div>
{#if _actions[action].selected}
<Collapsible
title={$i18n.t('Valves')}
open={false}
buttonClassName="w-full"
className="mt-2"
>
<div slot="content">
<Valves valvesSpec={valvesSpecs[action]} bind:valves={valves[action]} />
</div>
</Collapsible>
{/if}
{/each}
</div>
{/if}

View File

@ -2,15 +2,22 @@
import { getContext, onMount } from 'svelte';
import Checkbox from '$lib/components/common/Checkbox.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import Collapsible from '$lib/components/common/Collapsible.svelte';
import Valves from '$lib/components/common/Valves.svelte';
const i18n = getContext('i18n');
export let filters = [];
export let selectedFilterIds = [];
export let valvesSpecs = {};
export let valves = {};
let _filters = {};
onMount(() => {
console.log(`valvesSpecs: ${JSON.stringify(valvesSpecs)}`);
console.log(`valves: ${JSON.stringify(valves)}`);
_filters = filters.reduce((acc, filter) => {
acc[filter.id] = {
...filter,
@ -34,7 +41,7 @@
<!-- TODO: Filer order matters -->
<div class="flex flex-col">
{#if filters.length > 0}
<div class=" flex items-center mt-2 flex-wrap">
<div class=" flex flex-col items-left mt-2 flex-wrap">
{#each Object.keys(_filters) as filter, filterIdx}
<div class=" flex items-center gap-2 mr-3">
<div class="self-center flex items-center">
@ -56,6 +63,19 @@
</Tooltip>
</div>
</div>
{#if _filters[filter].selected}
<Collapsible
title={$i18n.t('Valves')}
open={false}
buttonClassName="w-full"
className="mt-2"
>
<div slot="content">
<Valves valvesSpec={valvesSpecs[filter]} bind:valves={valves[filter]} />
</div>
</Collapsible>
{/if}
{/each}
</div>
{/if}

View File

@ -1,6 +1,7 @@
<script lang="ts">
import { onMount, getContext, tick } from 'svelte';
import { models, tools, functions, knowledge as knowledgeCollections, user } from '$lib/stores';
import { get } from 'svelte/store';
import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte';
import Tags from '$lib/components/common/Tags.svelte';
@ -13,6 +14,8 @@
import { getTools } from '$lib/apis/tools';
import { getFunctions } from '$lib/apis/functions';
import { getKnowledgeBases } from '$lib/apis/knowledge';
import { getToolValvesSpecById } from '$lib/apis/tools';
import { getFunctionValvesSpecById } from '$lib/apis/functions';
import AccessControl from '../common/AccessControl.svelte';
import { stringify } from 'postcss';
import { toast } from 'svelte-sonner';
@ -84,6 +87,10 @@
let toolIds = [];
let filterIds = [];
let actionIds = [];
let toolValvesSpecs = {};
let functionValvesSpecs = {};
let functionValves = {};
let toolValves = {};
let accessControl = {};
@ -105,6 +112,10 @@
info.id = id;
info.name = name;
info.meta.valves = {};
console.log(`submitting with new toolValves: ${JSON.stringify(toolValves)}`);
console.log(`submitting with new functionValves: ${JSON.stringify(functionValves)}`);
if (id === '') {
toast.error('Model ID is required.');
@ -131,6 +142,7 @@
}
}
info.meta.valves.tools = toolValves;
if (toolIds.length > 0) {
info.meta.toolIds = toolIds;
} else {
@ -139,6 +151,7 @@
}
}
info.meta.valves.functions = functionValves;
if (filterIds.length > 0) {
info.meta.filterIds = filterIds;
} else {
@ -173,6 +186,57 @@
await functions.set(await getFunctions(localStorage.token));
await knowledgeCollections.set(await getKnowledgeBases(localStorage.token));
// Populate the tool valve specs
try {
const currentTools = get(tools) ?? [];
const toolValvePromises = currentTools.map((tool) =>
getToolValvesSpecById(localStorage.token, tool.id)
);
const resolvedToolValves = await Promise.all(toolValvePromises);
console.log(`resolvedToolValves: ${resolvedToolValves}`);
// Convert array of results to an object with tool IDs as keys
toolValvesSpecs = resolvedToolValves.reduce((acc, spec, index) => {
if (spec) {
console.log(
`setting index ${index} to ${spec} from ${JSON.stringify(currentTools[index])}`
);
acc[currentTools[index].id] = spec;
}
return acc;
}, {});
console.log(`toolValvesSpecs: ${JSON.stringify(toolValvesSpecs)}`);
// Initialize tool valves with default values from specs for the selected tools
toolValves = model?.meta?.valves?.tools ?? {};
} catch (error) {
console.error('Error loading tool valve specs:', error);
}
// Populate the function valve specs
try {
// Use get() to access the store's current value in non-reactive context
const currentFunctions = get(functions) ?? [];
console.log(JSON.stringify(currentFunctions));
const functionValvePromises = currentFunctions.map((func) =>
getFunctionValvesSpecById(localStorage.token, func.id)
);
const resolvedFunctionValves = await Promise.all(functionValvePromises);
console.log(resolvedFunctionValves);
// Convert array of results to an object with function IDs as keys
functionValvesSpecs = resolvedFunctionValves.reduce((acc, spec, index) => {
if (spec) {
acc[currentFunctions[index].id] = spec;
}
return acc;
}, {});
console.log(`functionValvesSpecs: ${JSON.stringify(functionValvesSpecs)}`);
functionValves = model?.meta?.valves?.functions ?? {};
} catch (error) {
console.error('Error loading function valve specs:', error);
}
// Scroll to top 'workspace-container' element
const workspaceContainer = document.getElementById('workspace-container');
if (workspaceContainer) {
@ -692,11 +756,18 @@
</div>
<div class="my-2">
<ToolsSelector bind:selectedToolIds={toolIds} tools={$tools} />
<ToolsSelector
valvesSpecs={toolValvesSpecs}
bind:valves={toolValves}
bind:selectedToolIds={toolIds}
tools={$tools}
/>
</div>
<div class="my-2">
<FiltersSelector
valvesSpecs={functionValvesSpecs}
bind:valves={functionValves}
bind:selectedFilterIds={filterIds}
filters={$functions.filter((func) => func.type === 'filter')}
/>
@ -704,6 +775,8 @@
<div class="my-2">
<ActionsSelector
valvesSpecs={functionValvesSpecs}
bind:valves={functionValves}
bind:selectedActionIds={actionIds}
actions={$functions.filter((func) => func.type === 'action')}
/>

View File

@ -1,9 +1,14 @@
<script lang="ts">
import Checkbox from '$lib/components/common/Checkbox.svelte';
import { getContext, onMount } from 'svelte';
import Collapsible from '$lib/components/common/Collapsible.svelte';
import Valves from '$lib/components/common/Valves.svelte';
export let tools = [];
export let valvesSpecs = {};
export let valves = {};
let _tools = {};
export let selectedToolIds = [];
@ -33,7 +38,7 @@
<div class="flex flex-col">
{#if tools.length > 0}
<div class=" flex items-center mt-2 flex-wrap">
<div class=" flex flex-col items-left mt-2 flex-wrap">
{#each Object.keys(_tools) as tool, toolIdx}
<div class=" flex items-center gap-2 mr-3">
<div class="self-center flex items-center">
@ -50,6 +55,18 @@
{_tools[tool].name}
</div>
</div>
{#if _tools[tool].selected}
<Collapsible
title={$i18n.t('Valves')}
open={false}
buttonClassName="w-full"
className="mt-2"
>
<div slot="content">
<Valves valvesSpec={valvesSpecs[tool]} bind:valves={valves[tool]} />
</div>
</Collapsible>
{/if}
{/each}
</div>
{/if}