add handleEscapeChar

This commit is contained in:
Henry 2023-07-25 00:32:50 +01:00
parent f74d81e14b
commit 2f10d46abc
7 changed files with 60 additions and 10 deletions

View File

@ -1,5 +1,5 @@
import { ICommonObject, INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface'
import { getBaseClasses } from '../../../src/utils'
import { getBaseClasses, handleEscapeCharacters } from '../../../src/utils'
import { LLMChain } from 'langchain/chains'
import { BaseLanguageModel } from 'langchain/base_language'
import { ConsoleCallbackHandler, CustomChainHandler } from '../../../src/handler'
@ -73,7 +73,12 @@ class LLMChain_Chains implements INode {
console.log('\x1b[92m\x1b[1m\n*****OUTPUT PREDICTION*****\n\x1b[0m\x1b[0m')
// eslint-disable-next-line no-console
console.log(res)
return res
/**
* Apply string transformation to convert special chars:
* FROM: hello i am ben\n\n\thow are you?
* TO: hello i am benFLOWISE_NEWLINEFLOWISE_NEWLINEFLOWISE_TABhow are you?
*/
return handleEscapeCharacters(res, false)
}
}
@ -81,7 +86,6 @@ class LLMChain_Chains implements INode {
const inputVariables = nodeData.instance.prompt.inputVariables as string[] // ["product"]
const chain = nodeData.instance as LLMChain
const promptValues = nodeData.inputs?.prompt.promptValues as ICommonObject
const res = await runPrediction(inputVariables, chain, input, promptValues, options)
// eslint-disable-next-line no-console
console.log('\x1b[93m\x1b[1m\n*****FINAL RESULT*****\n\x1b[0m\x1b[0m')
@ -95,7 +99,7 @@ const runPrediction = async (
inputVariables: string[],
chain: LLMChain,
input: string,
promptValues: ICommonObject,
promptValuesRaw: ICommonObject,
options: ICommonObject
) => {
const loggerHandler = new ConsoleCallbackHandler(options.logger)
@ -103,6 +107,13 @@ const runPrediction = async (
const socketIO = isStreaming ? options.socketIO : undefined
const socketIOClientId = isStreaming ? options.socketIOClientId : ''
/**
* Apply string transformation to reverse converted special chars:
* FROM: { "value": "hello i am benFLOWISE_NEWLINEFLOWISE_NEWLINEFLOWISE_TABhow are you?" }
* TO: { "value": "hello i am ben\n\n\thow are you?" }
*/
const promptValues = handleEscapeCharacters(promptValuesRaw, true)
if (inputVariables.length === 1) {
if (isStreaming) {
const handler = new CustomChainHandler(socketIO, socketIOClientId)

View File

@ -58,7 +58,7 @@ class ChatPromptTemplate_Prompts implements INode {
let promptValues: ICommonObject = {}
if (promptValuesStr) {
promptValues = JSON.parse(promptValuesStr.replace(/\s/g, ''))
promptValues = JSON.parse(promptValuesStr)
}
// @ts-ignore
prompt.promptValues = promptValues

View File

@ -86,7 +86,7 @@ class FewShotPromptTemplate_Prompts implements INode {
const examplePrompt = nodeData.inputs?.examplePrompt as PromptTemplate
const inputVariables = getInputVariables(suffix)
const examples: Example[] = JSON.parse(examplesStr.replace(/\s/g, ''))
const examples: Example[] = JSON.parse(examplesStr)
try {
const obj: FewShotPromptTemplateInput = {

View File

@ -45,7 +45,7 @@ class PromptTemplate_Prompts implements INode {
let promptValues: ICommonObject = {}
if (promptValuesStr) {
promptValues = JSON.parse(promptValuesStr.replace(/\s/g, ''))
promptValues = JSON.parse(promptValuesStr)
}
const inputVariables = getInputVariables(template)

View File

@ -347,6 +347,40 @@ export const getEnvironmentVariable = (name: string): string | undefined => {
}
}
// reference https://www.freeformatter.com/json-escape.html
const jsonEscapeCharacters = [
{ escape: '"', value: 'FLOWISE_DOUBLE_QUOTE' },
{ escape: '\n', value: 'FLOWISE_NEWLINE' },
{ escape: '\b', value: 'FLOWISE_BACKSPACE' },
{ escape: '\f', value: 'FLOWISE_FORM_FEED' },
{ escape: '\r', value: 'FLOWISE_CARRIAGE_RETURN' },
{ escape: '\t', value: 'FLOWISE_TAB' },
{ escape: '\\', value: 'FLOWISE_BACKSLASH' }
]
function handleEscapesJSONParse(input: string, reverse: Boolean): string {
for (const element of jsonEscapeCharacters) {
input = reverse ? input.replaceAll(element.value, element.escape) : input.replaceAll(element.escape, element.value)
}
return input
}
function iterateEscapesJSONParse(input: any, reverse: Boolean): any {
for (const element in input) {
const type = typeof input[element]
if (type === 'string') input[element] = handleEscapesJSONParse(input[element], reverse)
else if (type === 'object') input[element] = iterateEscapesJSONParse(input[element], reverse)
}
return input
}
export function handleEscapeCharacters(input: any, reverse: Boolean): any {
const type = typeof input
if (type === 'string') return handleEscapesJSONParse(input, reverse)
else if (type === 'object') return iterateEscapesJSONParse(input, reverse)
return input
}
/*
* List of dependencies allowed to be import in vm2
*/

View File

@ -1,6 +1,6 @@
{
"compilerOptions": {
"lib": ["ES2020"],
"lib": ["ES2020", "ES2021.String"],
"experimentalDecorators": true /* Enable experimental support for TC39 stage 2 draft decorators. */,
"emitDecoratorMetadata": true /* Emit design-type metadata for decorated declarations in source files. */,
"target": "ES2020", // or higher

View File

@ -16,7 +16,7 @@ import {
IOverrideConfig
} from '../Interface'
import { cloneDeep, get, omit, merge } from 'lodash'
import { ICommonObject, getInputVariables, IDatabaseEntity } from 'flowise-components'
import { ICommonObject, getInputVariables, IDatabaseEntity, handleEscapeCharacters } from 'flowise-components'
import { scryptSync, randomBytes, timingSafeEqual } from 'crypto'
import { ChatFlow } from '../entity/ChatFlow'
import { ChatMessage } from '../entity/ChatMessage'
@ -325,8 +325,13 @@ export const getVariableValue = (paramValue: string, reactFlowNodes: IReactFlowN
const variableEndIdx = startIdx
const variableFullPath = returnVal.substring(variableStartIdx, variableEndIdx)
/**
* Apply string transformation to convert special chars:
* FROM: hello i am ben\n\n\thow are you?
* TO: hello i am benFLOWISE_NEWLINEFLOWISE_NEWLINEFLOWISE_TABhow are you?
*/
if (isAcceptVariable && variableFullPath === QUESTION_VAR_PREFIX) {
variableDict[`{{${variableFullPath}}}`] = question
variableDict[`{{${variableFullPath}}}`] = handleEscapeCharacters(question, false)
}
// Split by first occurrence of '.' to get just nodeId