mirror of
https://github.com/labring/FastGPT.git
synced 2025-10-16 16:04:34 +00:00
perf: variabel replace;Feat: prompt optimizer code (#5453)
* feat: add prompt optimizer (#5444) * feat: add prompt optimizer * fix * perf: variabel replace * perf: prompt optimizer code * feat: init charts shell * perf: user error remove --------- Co-authored-by: heheer <heheer@sealos.io>
This commit is contained in:
6
packages/global/core/chat/type.d.ts
vendored
6
packages/global/core/chat/type.d.ts
vendored
@@ -20,7 +20,7 @@ import type { WorkflowInteractiveResponseType } from '../workflow/template/syste
|
||||
import type { FlowNodeInputItemType } from '../workflow/type/io';
|
||||
import type { FlowNodeTemplateType } from '../workflow/type/node.d';
|
||||
|
||||
export type ChatSchema = {
|
||||
export type ChatSchemaType = {
|
||||
_id: string;
|
||||
chatId: string;
|
||||
userId: string;
|
||||
@@ -33,6 +33,8 @@ export type ChatSchema = {
|
||||
customTitle: string;
|
||||
top: boolean;
|
||||
source: `${ChatSourceEnum}`;
|
||||
sourceName?: string;
|
||||
|
||||
shareId?: string;
|
||||
outLinkUid?: string;
|
||||
|
||||
@@ -43,7 +45,7 @@ export type ChatSchema = {
|
||||
metadata?: Record<string, any>;
|
||||
};
|
||||
|
||||
export type ChatWithAppSchema = Omit<ChatSchema, 'appId'> & {
|
||||
export type ChatWithAppSchema = Omit<ChatSchemaType, 'appId'> & {
|
||||
appId: AppSchema;
|
||||
};
|
||||
|
||||
|
@@ -467,27 +467,63 @@ export const formatVariableValByType = (val: any, valueType?: WorkflowIOValueTyp
|
||||
|
||||
return val;
|
||||
};
|
||||
|
||||
// replace {{$xx.xx$}} variables for text
|
||||
export function replaceEditorVariable({
|
||||
text,
|
||||
nodes,
|
||||
variables
|
||||
variables,
|
||||
depth = 0
|
||||
}: {
|
||||
text: any;
|
||||
nodes: RuntimeNodeItemType[];
|
||||
variables: Record<string, any>; // global variables
|
||||
depth?: number;
|
||||
}) {
|
||||
if (typeof text !== 'string') return text;
|
||||
if (text === '') return text;
|
||||
|
||||
const MAX_REPLACEMENT_DEPTH = 10;
|
||||
const processedVariables = new Set<string>();
|
||||
|
||||
// Prevent infinite recursion
|
||||
if (depth > MAX_REPLACEMENT_DEPTH) {
|
||||
return text;
|
||||
}
|
||||
|
||||
text = replaceVariable(text, variables);
|
||||
|
||||
// Check for circular references in variable values
|
||||
const hasCircularReference = (value: any, targetKey: string): boolean => {
|
||||
if (typeof value !== 'string') return false;
|
||||
|
||||
// Check if the value contains the target variable pattern (direct self-reference)
|
||||
const selfRefPattern = new RegExp(
|
||||
`\\{\\{\\$${targetKey.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\$\\}\\}`,
|
||||
'g'
|
||||
);
|
||||
return selfRefPattern.test(value);
|
||||
};
|
||||
|
||||
const variablePattern = /\{\{\$([^.]+)\.([^$]+)\$\}\}/g;
|
||||
const matches = [...text.matchAll(variablePattern)];
|
||||
if (matches.length === 0) return text;
|
||||
|
||||
matches.forEach((match) => {
|
||||
let result = text;
|
||||
let hasReplacements = false;
|
||||
|
||||
// Build replacement map first to avoid modifying string during iteration
|
||||
const replacements: Array<{ pattern: string; replacement: string }> = [];
|
||||
|
||||
for (const match of matches) {
|
||||
const nodeId = match[1];
|
||||
const id = match[2];
|
||||
const variableKey = `${nodeId}.${id}`;
|
||||
|
||||
// Skip if already processed to avoid immediate circular reference
|
||||
if (processedVariables.has(variableKey)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const variableVal = (() => {
|
||||
if (nodeId === VARIABLE_NODE_ID) {
|
||||
@@ -505,13 +541,35 @@ export function replaceEditorVariable({
|
||||
if (input) return getReferenceVariableValue({ value: input.value, nodes, variables });
|
||||
})();
|
||||
|
||||
const formatVal = valToStr(variableVal);
|
||||
// Check for direct circular reference
|
||||
if (hasCircularReference(String(variableVal), variableKey)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const regex = new RegExp(`\\{\\{\\$(${nodeId}\\.${id})\\$\\}\\}`, 'g');
|
||||
text = text.replace(regex, () => formatVal);
|
||||
const formatVal = valToStr(variableVal);
|
||||
const escapedNodeId = nodeId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
const escapedId = id.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
|
||||
replacements.push({
|
||||
pattern: `\\{\\{\\$(${escapedNodeId}\\.${escapedId})\\$\\}\\}`,
|
||||
replacement: formatVal
|
||||
});
|
||||
|
||||
processedVariables.add(variableKey);
|
||||
hasReplacements = true;
|
||||
}
|
||||
|
||||
// Apply all replacements
|
||||
replacements.forEach(({ pattern, replacement }) => {
|
||||
result = result.replace(new RegExp(pattern, 'g'), replacement);
|
||||
});
|
||||
|
||||
return text || '';
|
||||
// If we made replacements and there might be nested variables, recursively process
|
||||
if (hasReplacements && /\{\{\$[^.]+\.[^$]+\$\}\}/.test(result)) {
|
||||
result = replaceEditorVariable({ text: result, nodes, variables, depth: depth + 1 });
|
||||
}
|
||||
|
||||
return result || '';
|
||||
}
|
||||
|
||||
export const textAdaptGptResponse = ({
|
||||
|
Reference in New Issue
Block a user