feat: 优化工作流字段化参数配置
- 开始节点固定 user_input 并区分系统入口与自定义参数 - LLM 与知识库节点切换为字段值加上游引用配置 - 单节点调试改为字段预览与上游引用输入模式
This commit is contained in:
@@ -9,8 +9,14 @@
|
||||
import {getOptions} from '../utils/NodeUtils';
|
||||
import {onMount} from 'svelte';
|
||||
import OutputDefList from '../core/OutputDefList.svelte';
|
||||
import type {SelectItem} from '#types';
|
||||
import type {Parameter, SelectItem} from '#types';
|
||||
import ParamTokenEditor from '../core/ParamTokenEditor.svelte';
|
||||
import {
|
||||
buildEditorReferenceParameters,
|
||||
FIELD_BINDING_META_KEY,
|
||||
syncManagedParametersForFields,
|
||||
updateFieldBindingMeta,
|
||||
} from '../../utils/workflowNodeFields';
|
||||
|
||||
const { data, ...rest }: {
|
||||
data: NodeProps['data'],
|
||||
@@ -20,11 +26,14 @@
|
||||
const currentNodeId = getCurrentNodeId();
|
||||
let currentNode = useNodesData(currentNodeId);
|
||||
const { addParameter } = useAddParameter();
|
||||
const { nodes } = $derived(useStore());
|
||||
const { nodes, edges } = $derived(useStore());
|
||||
const editorParameters = $derived.by(() => {
|
||||
const parameters = [
|
||||
...(((currentNode?.current?.data?.parameters as Array<any>) || data.parameters || []) as Array<any>)
|
||||
];
|
||||
const parameters = buildEditorReferenceParameters(
|
||||
currentNodeId,
|
||||
nodes || [],
|
||||
edges || [],
|
||||
(((currentNode?.current?.data?.parameters as Array<Parameter>) || data.parameters || []) as Array<Parameter>)
|
||||
);
|
||||
if (queryContextNodeIds.length > 0) {
|
||||
parameters.push({
|
||||
id: 'queryDataContext',
|
||||
@@ -109,6 +118,23 @@
|
||||
});
|
||||
|
||||
const { updateNodeData } = useSvelteFlow();
|
||||
const syncFieldValue = (fieldName: 'systemPrompt' | 'userPrompt', nextValue: string) => {
|
||||
const currentData = ((currentNode?.current?.data as Record<string, any>) || data || {}) as Record<string, any>;
|
||||
const nextFieldValues = {
|
||||
systemPrompt: fieldName === 'systemPrompt' ? nextValue : (currentData.systemPrompt || ''),
|
||||
userPrompt: fieldName === 'userPrompt' ? nextValue : (currentData.userPrompt || ''),
|
||||
};
|
||||
updateNodeData(currentNodeId, {
|
||||
[fieldName]: nextValue,
|
||||
parameters: syncManagedParametersForFields(
|
||||
(currentData.parameters as Array<Parameter>) || [],
|
||||
editorParameters,
|
||||
nextFieldValues
|
||||
),
|
||||
[FIELD_BINDING_META_KEY]: updateFieldBindingMeta(currentData, fieldName, nextValue),
|
||||
});
|
||||
};
|
||||
|
||||
const setOutType = (value: string) => {
|
||||
updateNodeData(currentNodeId, () => {
|
||||
return {
|
||||
@@ -175,7 +201,7 @@
|
||||
</script>
|
||||
|
||||
|
||||
<NodeWrapper {data} {...rest}>
|
||||
<NodeWrapper {data} {...rest} wrapperClass="tf-node-wrapper--llm">
|
||||
|
||||
{#snippet icon()}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
||||
@@ -185,18 +211,6 @@
|
||||
{/snippet}
|
||||
|
||||
<div class="heading">
|
||||
<Heading level={3}>输入参数</Heading>
|
||||
<Button class="input-btn-more" style="margin-left: auto" onclick={()=>{
|
||||
addParameter(currentNodeId)
|
||||
}}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M11 11V5H13V11H19V13H13V19H11V13H5V11H11Z"></path>
|
||||
</svg>
|
||||
</Button>
|
||||
</div>
|
||||
<RefParameterList />
|
||||
|
||||
<div class="heading" style="padding-top: 10px">
|
||||
<Heading level={3}>图片识别</Heading>
|
||||
<Button class="input-btn-more" style="margin-left: auto" onclick={()=>{
|
||||
addParameter(currentNodeId, "images")
|
||||
@@ -250,7 +264,7 @@
|
||||
max="1"
|
||||
step="0.1"
|
||||
value={data.temperature ?? 0.7}
|
||||
oninput={(e) => updateNodeData(currentNodeId, { temperature: parseFloat(e.target.value) })}
|
||||
oninput={(e) => updateNodeData(currentNodeId, { temperature: parseFloat((e.target as HTMLInputElement).value) })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -265,7 +279,7 @@
|
||||
max="1"
|
||||
step="0.1"
|
||||
value={data.topP ?? 0.9}
|
||||
oninput={(e) => updateNodeData(currentNodeId, { topP: parseFloat(e.target.value) })}
|
||||
oninput={(e) => updateNodeData(currentNodeId, { topP: parseFloat((e.target as HTMLInputElement).value) })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -280,7 +294,7 @@
|
||||
max="100"
|
||||
step="1"
|
||||
value={data.topK ?? 50}
|
||||
oninput={(e) => updateNodeData(currentNodeId, { topK: parseInt(e.target.value) })}
|
||||
oninput={(e) => updateNodeData(currentNodeId, { topK: parseInt((e.target as HTMLInputElement).value) })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -298,11 +312,9 @@
|
||||
placeholder="请输入系统提示词"
|
||||
style="width: 100%"
|
||||
parameters={editorParameters}
|
||||
value={data.systemPrompt || ''}
|
||||
oninput={(e)=>{
|
||||
updateNodeData(currentNodeId, {
|
||||
systemPrompt: e.target.value
|
||||
});
|
||||
value={String(data.systemPrompt || '')}
|
||||
oninput={(e: any)=>{
|
||||
syncFieldValue('systemPrompt', e.target.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -315,11 +327,9 @@
|
||||
placeholder="请输入用户提示词"
|
||||
style="width: 100%"
|
||||
parameters={editorParameters}
|
||||
value={data.userPrompt || ''}
|
||||
oninput={(e)=>{
|
||||
updateNodeData(currentNodeId, {
|
||||
userPrompt: e.target.value
|
||||
});
|
||||
value={String(data.userPrompt || '')}
|
||||
oninput={(e: any)=>{
|
||||
syncFieldValue('userPrompt', e.target.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -333,7 +343,7 @@
|
||||
label: 'JSON',
|
||||
value: 'json'
|
||||
}]} style="width: 100px;margin-left: auto" onSelect={(item)=>{
|
||||
setOutType(item.value);
|
||||
setOutType(String(item.value));
|
||||
}} value={data.outType ? [data.outType] : []} />
|
||||
</div>
|
||||
<OutputDefList />
|
||||
|
||||
Reference in New Issue
Block a user