From f1a57dfe38c4e1b0835aed4215f378d9d08c1ac7 Mon Sep 17 00:00:00 2001 From: Henry Date: Sat, 20 Apr 2024 02:11:44 +0100 Subject: [PATCH] update google genai, remove aiplugin --- package.json | 3 +- .../ReActAgentChat.ts} | 6 +- .../agent.svg | 0 .../ReActAgentLLM.ts} | 6 +- .../{MRKLAgentLLM => ReActAgentLLM}/agent.svg | 0 .../nodes/agents/ToolAgent/ToolAgent.ts | 4 +- .../nodes/agents/ToolAgent/function.svg | 9 - .../nodes/agents/ToolAgent/toolAgent.png | Bin 0 -> 17519 bytes .../ChatGoogleGenerativeAI.ts | 3 +- .../FlowiseChatGoogleGenerativeAI.ts | 522 +++++++++++++++++- .../ChatOpenAI/FlowiseChatOpenAI.ts | 6 +- .../nodes/tools/AIPlugin/AIPlugin.ts | 45 -- .../nodes/tools/AIPlugin/aiplugin.svg | 6 - .../marketplaces/chatflows/ChatGPTPlugin.json | 500 ----------------- .../marketplaces/chatflows/ReAct Agent.json | 46 +- packages/server/src/utils/getUploadsConfig.ts | 2 +- pnpm-lock.yaml | 26 +- 17 files changed, 573 insertions(+), 611 deletions(-) rename packages/components/nodes/agents/{MRKLAgentChat/MRKLAgentChat.ts => ReActAgentChat/ReActAgentChat.ts} (97%) rename packages/components/nodes/agents/{MRKLAgentChat => ReActAgentChat}/agent.svg (100%) rename packages/components/nodes/agents/{MRKLAgentLLM/MRKLAgentLLM.ts => ReActAgentLLM/ReActAgentLLM.ts} (96%) rename packages/components/nodes/agents/{MRKLAgentLLM => ReActAgentLLM}/agent.svg (100%) delete mode 100644 packages/components/nodes/agents/ToolAgent/function.svg create mode 100644 packages/components/nodes/agents/ToolAgent/toolAgent.png delete mode 100644 packages/components/nodes/tools/AIPlugin/AIPlugin.ts delete mode 100644 packages/components/nodes/tools/AIPlugin/aiplugin.svg delete mode 100644 packages/server/marketplaces/chatflows/ChatGPTPlugin.json diff --git a/package.json b/package.json index 33471e385cf..a436da9efe4 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "node": ">=18.15.0 <19.0.0 || ^20" }, "resolutions": { - "@qdrant/openapi-typescript-fetch": "1.2.1" + "@qdrant/openapi-typescript-fetch": "1.2.1", + "@google/generative-ai": "^0.7.0" } } diff --git a/packages/components/nodes/agents/MRKLAgentChat/MRKLAgentChat.ts b/packages/components/nodes/agents/ReActAgentChat/ReActAgentChat.ts similarity index 97% rename from packages/components/nodes/agents/MRKLAgentChat/MRKLAgentChat.ts rename to packages/components/nodes/agents/ReActAgentChat/ReActAgentChat.ts index 94811a728bf..be91b380abb 100644 --- a/packages/components/nodes/agents/MRKLAgentChat/MRKLAgentChat.ts +++ b/packages/components/nodes/agents/ReActAgentChat/ReActAgentChat.ts @@ -13,7 +13,7 @@ import { addImagesToMessages, llmSupportsVision } from '../../../src/multiModalU import { checkInputs, Moderation } from '../../moderation/Moderation' import { formatResponse } from '../../outputparsers/OutputParserHelpers' -class MRKLAgentChat_Agents implements INode { +class ReActAgentChat_Agents implements INode { label: string name: string version: number @@ -27,7 +27,7 @@ class MRKLAgentChat_Agents implements INode { constructor(fields?: { sessionId?: string }) { this.label = 'ReAct Agent for Chat Models' - this.name = 'mrklAgentChat' + this.name = 'reactAgentChat' this.version = 4.0 this.type = 'AgentExecutor' this.category = 'Agents' @@ -157,4 +157,4 @@ class MRKLAgentChat_Agents implements INode { } } -module.exports = { nodeClass: MRKLAgentChat_Agents } +module.exports = { nodeClass: ReActAgentChat_Agents } diff --git a/packages/components/nodes/agents/MRKLAgentChat/agent.svg b/packages/components/nodes/agents/ReActAgentChat/agent.svg similarity index 100% rename from packages/components/nodes/agents/MRKLAgentChat/agent.svg rename to packages/components/nodes/agents/ReActAgentChat/agent.svg diff --git a/packages/components/nodes/agents/MRKLAgentLLM/MRKLAgentLLM.ts b/packages/components/nodes/agents/ReActAgentLLM/ReActAgentLLM.ts similarity index 96% rename from packages/components/nodes/agents/MRKLAgentLLM/MRKLAgentLLM.ts rename to packages/components/nodes/agents/ReActAgentLLM/ReActAgentLLM.ts index a1fb36e9ec3..7547c807d91 100644 --- a/packages/components/nodes/agents/MRKLAgentLLM/MRKLAgentLLM.ts +++ b/packages/components/nodes/agents/ReActAgentLLM/ReActAgentLLM.ts @@ -11,7 +11,7 @@ import { createReactAgent } from '../../../src/agents' import { checkInputs, Moderation } from '../../moderation/Moderation' import { formatResponse } from '../../outputparsers/OutputParserHelpers' -class MRKLAgentLLM_Agents implements INode { +class ReActAgentLLM_Agents implements INode { label: string name: string version: number @@ -24,7 +24,7 @@ class MRKLAgentLLM_Agents implements INode { constructor() { this.label = 'ReAct Agent for LLMs' - this.name = 'mrklAgentLLM' + this.name = 'reactAgentLLM' this.version = 2.0 this.type = 'AgentExecutor' this.category = 'Agents' @@ -107,4 +107,4 @@ class MRKLAgentLLM_Agents implements INode { } } -module.exports = { nodeClass: MRKLAgentLLM_Agents } +module.exports = { nodeClass: ReActAgentLLM_Agents } diff --git a/packages/components/nodes/agents/MRKLAgentLLM/agent.svg b/packages/components/nodes/agents/ReActAgentLLM/agent.svg similarity index 100% rename from packages/components/nodes/agents/MRKLAgentLLM/agent.svg rename to packages/components/nodes/agents/ReActAgentLLM/agent.svg diff --git a/packages/components/nodes/agents/ToolAgent/ToolAgent.ts b/packages/components/nodes/agents/ToolAgent/ToolAgent.ts index 20713f185e5..1c5605a9772 100644 --- a/packages/components/nodes/agents/ToolAgent/ToolAgent.ts +++ b/packages/components/nodes/agents/ToolAgent/ToolAgent.ts @@ -33,8 +33,8 @@ class ToolAgent_Agents implements INode { this.version = 1.0 this.type = 'AgentExecutor' this.category = 'Agents' - this.icon = 'function.svg' - this.description = `Agent that uses OpenAI Function Calling to pick the tools and args to call` + this.icon = 'toolAgent.png' + this.description = `Agent that uses Function Calling to pick the tools and args to call` this.baseClasses = [this.type, ...getBaseClasses(AgentExecutor)] this.badge = 'NEW' this.inputs = [ diff --git a/packages/components/nodes/agents/ToolAgent/function.svg b/packages/components/nodes/agents/ToolAgent/function.svg deleted file mode 100644 index 9e283b91ff3..00000000000 --- a/packages/components/nodes/agents/ToolAgent/function.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/packages/components/nodes/agents/ToolAgent/toolAgent.png b/packages/components/nodes/agents/ToolAgent/toolAgent.png new file mode 100644 index 0000000000000000000000000000000000000000..7bf44339bcb68396d8acc5709280507439abc901 GIT binary patch literal 17519 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 literal 0 HcmV?d00001 diff --git a/packages/components/nodes/chatmodels/ChatGoogleGenerativeAI/ChatGoogleGenerativeAI.ts b/packages/components/nodes/chatmodels/ChatGoogleGenerativeAI/ChatGoogleGenerativeAI.ts index 7255ced9fec..76287229377 100644 --- a/packages/components/nodes/chatmodels/ChatGoogleGenerativeAI/ChatGoogleGenerativeAI.ts +++ b/packages/components/nodes/chatmodels/ChatGoogleGenerativeAI/ChatGoogleGenerativeAI.ts @@ -1,11 +1,10 @@ import { HarmBlockThreshold, HarmCategory } from '@google/generative-ai' import type { SafetySetting } from '@google/generative-ai' -import { GoogleGenerativeAIChatInput } from '@langchain/google-genai' import { BaseCache } from '@langchain/core/caches' import { ICommonObject, IMultiModalOption, INode, INodeData, INodeOptionsValue, INodeParams } from '../../../src/Interface' import { convertMultiOptionsToStringArray, getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils' import { getModels, MODEL_TYPE } from '../../../src/modelLoader' -import { ChatGoogleGenerativeAI } from './FlowiseChatGoogleGenerativeAI' +import { ChatGoogleGenerativeAI, GoogleGenerativeAIChatInput } from './FlowiseChatGoogleGenerativeAI' class GoogleGenerativeAI_ChatModels implements INode { label: string diff --git a/packages/components/nodes/chatmodels/ChatGoogleGenerativeAI/FlowiseChatGoogleGenerativeAI.ts b/packages/components/nodes/chatmodels/ChatGoogleGenerativeAI/FlowiseChatGoogleGenerativeAI.ts index 633c144c74a..47425ed273c 100644 --- a/packages/components/nodes/chatmodels/ChatGoogleGenerativeAI/FlowiseChatGoogleGenerativeAI.ts +++ b/packages/components/nodes/chatmodels/ChatGoogleGenerativeAI/FlowiseChatGoogleGenerativeAI.ts @@ -1,5 +1,283 @@ -import { ChatGoogleGenerativeAI as LangchainChatGoogleGenerativeAI, GoogleGenerativeAIChatInput } from '@langchain/google-genai' -import { IMultiModalOption, IVisionChatModal } from '../../../src' +import { BaseMessage, AIMessage, AIMessageChunk, isBaseMessage, ChatMessage, MessageContent } from '@langchain/core/messages' +import { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager' +import { BaseChatModel, type BaseChatModelParams } from '@langchain/core/language_models/chat_models' +import { ChatGeneration, ChatGenerationChunk, ChatResult } from '@langchain/core/outputs' +import { ToolCall } from '@langchain/core/messages/tool' +import { NewTokenIndices } from '@langchain/core/callbacks/base' +import { + EnhancedGenerateContentResponse, + Content, + Part, + Tool, + GenerativeModel, + GoogleGenerativeAI as GenerativeAI +} from '@google/generative-ai' +import type { SafetySetting } from '@google/generative-ai' +import { ICommonObject, IMultiModalOption, IVisionChatModal } from '../../../src' +import { StructuredToolInterface } from '@langchain/core/tools' +import { isStructuredTool } from '@langchain/core/utils/function_calling' +import { zodToJsonSchema } from 'zod-to-json-schema' + +interface TokenUsage { + completionTokens?: number + promptTokens?: number + totalTokens?: number +} + +export interface GoogleGenerativeAIChatInput extends BaseChatModelParams { + modelName?: string + model?: string + temperature?: number + maxOutputTokens?: number + topP?: number + topK?: number + stopSequences?: string[] + safetySettings?: SafetySetting[] + apiKey?: string + streaming?: boolean +} + +class LangchainChatGoogleGenerativeAI extends BaseChatModel implements GoogleGenerativeAIChatInput { + modelName = 'gemini-pro' + + temperature?: number + + maxOutputTokens?: number + + topP?: number + + topK?: number + + stopSequences: string[] = [] + + safetySettings?: SafetySetting[] + + apiKey?: string + + streaming = false + + private client: GenerativeModel + + get _isMultimodalModel() { + return this.modelName.includes('vision') || this.modelName.startsWith('gemini-1.5') + } + + constructor(fields?: GoogleGenerativeAIChatInput) { + super(fields ?? {}) + + this.modelName = fields?.model?.replace(/^models\//, '') ?? fields?.modelName?.replace(/^models\//, '') ?? 'gemini-pro' + + this.maxOutputTokens = fields?.maxOutputTokens ?? this.maxOutputTokens + + if (this.maxOutputTokens && this.maxOutputTokens < 0) { + throw new Error('`maxOutputTokens` must be a positive integer') + } + + this.temperature = fields?.temperature ?? this.temperature + if (this.temperature && (this.temperature < 0 || this.temperature > 1)) { + throw new Error('`temperature` must be in the range of [0.0,1.0]') + } + + this.topP = fields?.topP ?? this.topP + if (this.topP && this.topP < 0) { + throw new Error('`topP` must be a positive integer') + } + + if (this.topP && this.topP > 1) { + throw new Error('`topP` must be below 1.') + } + + this.topK = fields?.topK ?? this.topK + if (this.topK && this.topK < 0) { + throw new Error('`topK` must be a positive integer') + } + + this.stopSequences = fields?.stopSequences ?? this.stopSequences + + this.apiKey = fields?.apiKey ?? process.env['GOOGLE_API_KEY'] + if (!this.apiKey) { + throw new Error( + 'Please set an API key for Google GenerativeAI ' + + 'in the environment variable GOOGLE_API_KEY ' + + 'or in the `apiKey` field of the ' + + 'ChatGoogleGenerativeAI constructor' + ) + } + + this.safetySettings = fields?.safetySettings ?? this.safetySettings + if (this.safetySettings && this.safetySettings.length > 0) { + const safetySettingsSet = new Set(this.safetySettings.map((s) => s.category)) + if (safetySettingsSet.size !== this.safetySettings.length) { + throw new Error('The categories in `safetySettings` array must be unique') + } + } + + this.streaming = fields?.streaming ?? this.streaming + + this.getClient() + } + + getClient(tools?: Tool[]) { + this.client = new GenerativeAI(this.apiKey ?? '').getGenerativeModel({ + model: this.modelName, + tools, + safetySettings: this.safetySettings as SafetySetting[], + generationConfig: { + candidateCount: 1, + stopSequences: this.stopSequences, + maxOutputTokens: this.maxOutputTokens, + temperature: this.temperature, + topP: this.topP, + topK: this.topK + } + }) + } + + _combineLLMOutput() { + return [] + } + + _llmType() { + return 'googlegenerativeai' + } + + override bindTools(tools: (StructuredToolInterface | Record)[], kwargs?: Partial) { + //@ts-ignore + return this.bind({ tools: convertToGeminiTools(tools), ...kwargs }) + } + + convertFunctionResponse(prompts: Content[]) { + for (let i = 0; i < prompts.length; i += 1) { + if (prompts[i].role === 'function') { + if (prompts[i - 1].role === 'model') { + const toolName = prompts[i - 1].parts[0].functionCall?.name ?? '' + prompts[i].parts = [ + { + functionResponse: { + name: toolName, + response: { + name: toolName, + content: prompts[i].parts[0].text + } + } + } + ] + } + } + } + } + + async _generateNonStreaming( + prompt: Content[], + options: this['ParsedCallOptions'], + _runManager?: CallbackManagerForLLMRun + ): Promise { + //@ts-ignore + const tools = options.tools ?? [] + + this.convertFunctionResponse(prompt) + + if (tools.length > 0) { + this.getClient(tools) + } else { + this.getClient() + } + const res = await this.caller.callWithOptions({ signal: options?.signal }, async () => { + let output + try { + output = await this.client.generateContent({ + contents: prompt + }) + } catch (e: any) { + if (e.message?.includes('400 Bad Request')) { + e.status = 400 + } + throw e + } + return output + }) + const generationResult = mapGenerateContentResultToChatResult(res.response) + await _runManager?.handleLLMNewToken(generationResult.generations?.length ? generationResult.generations[0].text : '') + return generationResult + } + + async _generate( + messages: BaseMessage[], + options: this['ParsedCallOptions'], + runManager?: CallbackManagerForLLMRun + ): Promise { + const prompt = convertBaseMessagesToContent(messages, this._isMultimodalModel) + + // Handle streaming + if (this.streaming) { + const tokenUsage: TokenUsage = {} + const stream = this._streamResponseChunks(messages, options, runManager) + const finalChunks: Record = {} + for await (const chunk of stream) { + const index = (chunk.generationInfo as NewTokenIndices)?.completion ?? 0 + if (finalChunks[index] === undefined) { + finalChunks[index] = chunk + } else { + finalChunks[index] = finalChunks[index].concat(chunk) + } + } + const generations = Object.entries(finalChunks) + .sort(([aKey], [bKey]) => parseInt(aKey, 10) - parseInt(bKey, 10)) + .map(([_, value]) => value) + + return { generations, llmOutput: { estimatedTokenUsage: tokenUsage } } + } + return this._generateNonStreaming(prompt, options, runManager) + } + + async *_streamResponseChunks( + messages: BaseMessage[], + options: this['ParsedCallOptions'], + runManager?: CallbackManagerForLLMRun + ): AsyncGenerator { + const prompt = convertBaseMessagesToContent(messages, this._isMultimodalModel) + //@ts-ignore + if (options.tools !== undefined && options.tools.length > 0) { + const result = await this._generateNonStreaming(prompt, options, runManager) + const generationMessage = result.generations[0].message as AIMessage + if (generationMessage === undefined) { + throw new Error('Could not parse Groq output.') + } + const toolCallChunks = generationMessage.tool_calls?.map((toolCall, i) => ({ + name: toolCall.name, + args: JSON.stringify(toolCall.args), + id: toolCall.id, + index: i + })) + yield new ChatGenerationChunk({ + message: new AIMessageChunk({ + content: generationMessage.content, + additional_kwargs: generationMessage.additional_kwargs, + tool_call_chunks: toolCallChunks + }), + text: generationMessage.tool_calls?.length ? '' : (generationMessage.content as string) + }) + } else { + const stream = await this.caller.callWithOptions({ signal: options?.signal }, async () => { + this.getClient() + const { stream } = await this.client.generateContentStream({ + contents: prompt + }) + return stream + }) + + for await (const response of stream) { + const chunk = convertResponseContentToChatGenerationChunk(response) + if (!chunk) { + continue + } + + yield chunk + await runManager?.handleLLMNewToken(chunk.text ?? '') + } + } + } +} export class ChatGoogleGenerativeAI extends LangchainChatGoogleGenerativeAI implements IVisionChatModal { configuredModel: string @@ -30,3 +308,243 @@ export class ChatGoogleGenerativeAI extends LangchainChatGoogleGenerativeAI impl } } } + +function getMessageAuthor(message: BaseMessage) { + const type = message._getType() + if (ChatMessage.isInstance(message)) { + return message.role + } + return message.name ?? type +} + +function convertAuthorToRole(author: string) { + switch (author) { + /** + * Note: Gemini currently is not supporting system messages + * we will convert them to human messages and merge with following + * */ + case 'ai': + case 'model': // getMessageAuthor returns message.name. code ex.: return message.name ?? type; + return 'model' + case 'system': + case 'human': + return 'user' + case 'function': + case 'tool': + return 'function' + default: + throw new Error(`Unknown / unsupported author: ${author}`) + } +} + +function convertMessageContentToParts(content: MessageContent, isMultimodalModel: boolean): Part[] { + if (typeof content === 'string') { + return [{ text: content }] + } + + return content.map((c) => { + if (c.type === 'text') { + return { + text: c.text + } + } + + if (c.type === 'tool_use') { + return { + functionCall: c.functionCall + } + } + + /*if (c.type === "tool_use" || c.type === "tool_result") { + // TODO: Fix when SDK types are fixed + return { + ...contentPart, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any; + }*/ + + if (c.type === 'image_url') { + if (!isMultimodalModel) { + throw new Error(`This model does not support images`) + } + let source + if (typeof c.image_url === 'string') { + source = c.image_url + } else if (typeof c.image_url === 'object' && 'url' in c.image_url) { + source = c.image_url.url + } else { + throw new Error('Please provide image as base64 encoded data URL') + } + const [dm, data] = source.split(',') + if (!dm.startsWith('data:')) { + throw new Error('Please provide image as base64 encoded data URL') + } + + const [mimeType, encoding] = dm.replace(/^data:/, '').split(';') + if (encoding !== 'base64') { + throw new Error('Please provide image as base64 encoded data URL') + } + + return { + inlineData: { + data, + mimeType + } + } + } + throw new Error(`Unknown content type ${(c as { type: string }).type}`) + }) +} + +function convertBaseMessagesToContent(messages: BaseMessage[], isMultimodalModel: boolean) { + return messages.reduce<{ + content: Content[] + mergeWithPreviousContent: boolean + }>( + (acc, message, index) => { + if (!isBaseMessage(message)) { + throw new Error('Unsupported message input') + } + const author = getMessageAuthor(message) + if (author === 'system' && index !== 0) { + throw new Error('System message should be the first one') + } + const role = convertAuthorToRole(author) + + const prevContent = acc.content[acc.content.length] + if (!acc.mergeWithPreviousContent && prevContent && prevContent.role === role) { + throw new Error('Google Generative AI requires alternate messages between authors') + } + + const parts = convertMessageContentToParts(message.content, isMultimodalModel) + + if (acc.mergeWithPreviousContent) { + const prevContent = acc.content[acc.content.length - 1] + if (!prevContent) { + throw new Error('There was a problem parsing your system message. Please try a prompt without one.') + } + prevContent.parts.push(...parts) + + return { + mergeWithPreviousContent: false, + content: acc.content + } + } + const content: Content = { + role, + parts + } + return { + mergeWithPreviousContent: author === 'system', + content: [...acc.content, content] + } + }, + { content: [], mergeWithPreviousContent: false } + ).content +} + +function mapGenerateContentResultToChatResult(response: EnhancedGenerateContentResponse): ChatResult { + // if rejected or error, return empty generations with reason in filters + if (!response.candidates || response.candidates.length === 0 || !response.candidates[0]) { + return { + generations: [], + llmOutput: { + filters: response?.promptFeedback + } + } + } + + const [candidate] = response.candidates + const { content, ...generationInfo } = candidate + const text = content.parts.map(({ text }) => text).join('') + + if (content.parts.some((part) => part.functionCall)) { + const toolCalls: ToolCall[] = [] + for (const fcPart of content.parts) { + const fc = fcPart.functionCall + if (fc) { + const { name, args } = fc + toolCalls.push({ name, args }) + } + } + + const functionCalls = toolCalls.map((tool) => { + return { functionCall: { name: tool.name, args: tool.args }, type: 'tool_use' } + }) + const generation: ChatGeneration = { + text, + message: new AIMessage({ + content: functionCalls, + name: !content ? undefined : content.role, + additional_kwargs: generationInfo, + tool_calls: toolCalls + }), + generationInfo + } + return { + generations: [generation] + } + } else { + const generation: ChatGeneration = { + text, + message: new AIMessage({ + content: text, + name: !content ? undefined : content.role, + additional_kwargs: generationInfo + }), + generationInfo + } + + return { + generations: [generation] + } + } +} + +function convertResponseContentToChatGenerationChunk(response: EnhancedGenerateContentResponse): ChatGenerationChunk | null { + if (!response.candidates || response.candidates.length === 0) { + return null + } + const [candidate] = response.candidates + const { content, ...generationInfo } = candidate + const text = content?.parts[0]?.text ?? '' + + return new ChatGenerationChunk({ + text, + message: new AIMessageChunk({ + content: text, + name: !content ? undefined : content.role, + // Each chunk can have unique "generationInfo", and merging strategy is unclear, + // so leave blank for now. + additional_kwargs: {} + }), + generationInfo + }) +} + +function zodToGeminiParameters(zodObj: any) { + // Gemini doesn't accept either the $schema or additionalProperties + // attributes, so we need to explicitly remove them. + const jsonSchema: any = zodToJsonSchema(zodObj) + // eslint-disable-next-line unused-imports/no-unused-vars + const { $schema, additionalProperties, ...rest } = jsonSchema + return rest +} + +function convertToGeminiTools(structuredTools: (StructuredToolInterface | Record)[]) { + return [ + { + functionDeclarations: structuredTools.map((structuredTool) => { + if (isStructuredTool(structuredTool)) { + const jsonSchema = zodToGeminiParameters(structuredTool.schema) + return { + name: structuredTool.name, + description: structuredTool.description, + parameters: jsonSchema + } + } + return structuredTool + }) + } + ] +} diff --git a/packages/components/nodes/chatmodels/ChatOpenAI/FlowiseChatOpenAI.ts b/packages/components/nodes/chatmodels/ChatOpenAI/FlowiseChatOpenAI.ts index 03482503a44..61448a08488 100644 --- a/packages/components/nodes/chatmodels/ChatOpenAI/FlowiseChatOpenAI.ts +++ b/packages/components/nodes/chatmodels/ChatOpenAI/FlowiseChatOpenAI.ts @@ -33,7 +33,9 @@ export class ChatOpenAI extends LangchainChatOpenAI implements IVisionChatModal } setVisionModel(): void { - super.modelName = 'gpt-4-turbo' - super.maxTokens = this.configuredMaxToken ? this.configuredMaxToken : 1024 + if (this.modelName !== 'gpt-4-turbo' && !this.modelName.includes('vision')) { + super.modelName = 'gpt-4-turbo' + super.maxTokens = this.configuredMaxToken ? this.configuredMaxToken : 1024 + } } } diff --git a/packages/components/nodes/tools/AIPlugin/AIPlugin.ts b/packages/components/nodes/tools/AIPlugin/AIPlugin.ts deleted file mode 100644 index f9afe0fed32..00000000000 --- a/packages/components/nodes/tools/AIPlugin/AIPlugin.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { AIPluginTool } from '@langchain/community/tools/aiplugin' -import { INode, INodeData, INodeParams } from '../../../src/Interface' -import { getBaseClasses } from '../../../src/utils' - -class AIPlugin implements INode { - label: string - name: string - version: number - description: string - type: string - icon: string - category: string - baseClasses: string[] - inputs?: INodeParams[] - badge: string - - constructor() { - this.label = 'AI Plugin' - this.name = 'aiPlugin' - this.version = 1.0 - this.type = 'AIPlugin' - this.icon = 'aiplugin.svg' - this.category = 'Tools' - this.description = 'Execute actions using ChatGPT Plugin Url' - this.baseClasses = [this.type, ...getBaseClasses(AIPluginTool)] - this.badge = 'DEPRECATING' - this.inputs = [ - { - label: 'Plugin Url', - name: 'pluginUrl', - type: 'string', - placeholder: 'https://www.klarna.com/.well-known/ai-plugin.json' - } - ] - } - - async init(nodeData: INodeData): Promise { - const pluginUrl = nodeData.inputs?.pluginUrl as string - const aiplugin = await AIPluginTool.fromPluginUrl(pluginUrl) - - return aiplugin - } -} - -module.exports = { nodeClass: AIPlugin } diff --git a/packages/components/nodes/tools/AIPlugin/aiplugin.svg b/packages/components/nodes/tools/AIPlugin/aiplugin.svg deleted file mode 100644 index a48cb717181..00000000000 --- a/packages/components/nodes/tools/AIPlugin/aiplugin.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/server/marketplaces/chatflows/ChatGPTPlugin.json b/packages/server/marketplaces/chatflows/ChatGPTPlugin.json deleted file mode 100644 index b7dbdb00bde..00000000000 --- a/packages/server/marketplaces/chatflows/ChatGPTPlugin.json +++ /dev/null @@ -1,500 +0,0 @@ -{ - "description": "Use ChatGPT Plugins within LangChain abstractions with GET and POST Tools", - "categories": "ChatGPT Plugin,HTTP GET/POST,ChatOpenAI,MRKL Agent,Langchain", - "framework": "Langchain", - "nodes": [ - { - "width": 300, - "height": 278, - "id": "aiPlugin_0", - "position": { - "x": 1086.2925487205378, - "y": 84.92168014974317 - }, - "type": "customNode", - "data": { - "id": "aiPlugin_0", - "label": "AI Plugin", - "name": "aiPlugin", - "version": 1, - "type": "AIPlugin", - "baseClasses": ["AIPlugin", "Tool"], - "category": "Tools", - "description": "Execute actions using ChatGPT Plugin Url", - "inputParams": [ - { - "label": "Plugin Url", - "name": "pluginUrl", - "type": "string", - "placeholder": "https://www.klarna.com/.well-known/ai-plugin.json" - } - ], - "inputAnchors": [], - "inputs": { - "pluginUrl": "https://www.klarna.com/.well-known/ai-plugin.json" - }, - "outputAnchors": [ - { - "id": "aiPlugin_0-output-aiPlugin-AIPlugin|Tool", - "name": "aiPlugin", - "label": "AIPlugin", - "type": "AIPlugin | Tool" - } - ], - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1086.2925487205378, - "y": 84.92168014974317 - }, - "dragging": false - }, - { - "width": 300, - "height": 251, - "id": "requestsGet_0", - "position": { - "x": 761.713884489628, - "y": 170.84830553778124 - }, - "type": "customNode", - "data": { - "id": "requestsGet_0", - "label": "Requests Get", - "name": "requestsGet", - "version": 1, - "type": "RequestsGet", - "baseClasses": ["RequestsGet", "Tool", "StructuredTool", "BaseLangChain"], - "category": "Tools", - "description": "Execute HTTP GET requests", - "inputParams": [ - { - "label": "URL", - "name": "url", - "type": "string", - "description": "Agent will make call to this exact URL. If not specified, agent will try to figure out itself from AIPlugin if provided", - "additionalParams": true, - "optional": true, - "id": "requestsGet_0-input-url-string" - }, - { - "label": "Description", - "name": "description", - "type": "string", - "rows": 4, - "default": "A portal to the internet. Use this when you need to get specific content from a website. \nInput should be a url (i.e. https://www.google.com). The output will be the text response of the GET request.", - "description": "Acts like a prompt to tell agent when it should use this tool", - "additionalParams": true, - "optional": true, - "id": "requestsGet_0-input-description-string" - }, - { - "label": "Headers", - "name": "headers", - "type": "json", - "additionalParams": true, - "optional": true, - "id": "requestsGet_0-input-headers-json" - } - ], - "inputAnchors": [], - "inputs": { - "url": "", - "description": "A portal to the internet. Use this when you need to get specific content from a website. \nInput should be a url (i.e. https://www.google.com). The output will be the text response of the GET request.", - "headers": "" - }, - "outputAnchors": [ - { - "id": "requestsGet_0-output-requestsGet-RequestsGet|Tool|StructuredTool|BaseLangChain", - "name": "requestsGet", - "label": "RequestsGet", - "type": "RequestsGet | Tool | StructuredTool | BaseLangChain" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 761.713884489628, - "y": 170.84830553778124 - }, - "dragging": false - }, - { - "width": 300, - "height": 251, - "id": "requestsPost_0", - "position": { - "x": 436.4125209312256, - "y": 306.87715502984184 - }, - "type": "customNode", - "data": { - "id": "requestsPost_0", - "label": "Requests Post", - "name": "requestsPost", - "version": 1, - "type": "RequestsPost", - "baseClasses": ["RequestsPost", "Tool", "StructuredTool", "BaseLangChain"], - "category": "Tools", - "description": "Execute HTTP POST requests", - "inputParams": [ - { - "label": "URL", - "name": "url", - "type": "string", - "description": "Agent will make call to this exact URL. If not specified, agent will try to figure out itself from AIPlugin if provided", - "additionalParams": true, - "optional": true, - "id": "requestsPost_0-input-url-string" - }, - { - "label": "Body", - "name": "body", - "type": "json", - "description": "JSON body for the POST request. If not specified, agent will try to figure out itself from AIPlugin if provided", - "additionalParams": true, - "optional": true, - "id": "requestsPost_0-input-body-json" - }, - { - "label": "Description", - "name": "description", - "type": "string", - "rows": 4, - "default": "Use this when you want to POST to a website.\nInput should be a json string with two keys: \"url\" and \"data\".\nThe value of \"url\" should be a string, and the value of \"data\" should be a dictionary of \nkey-value pairs you want to POST to the url as a JSON body.\nBe careful to always use double quotes for strings in the json string\nThe output will be the text response of the POST request.", - "description": "Acts like a prompt to tell agent when it should use this tool", - "additionalParams": true, - "optional": true, - "id": "requestsPost_0-input-description-string" - }, - { - "label": "Headers", - "name": "headers", - "type": "json", - "additionalParams": true, - "optional": true, - "id": "requestsPost_0-input-headers-json" - } - ], - "inputAnchors": [], - "inputs": { - "url": "", - "body": "", - "description": "Use this when you want to POST to a website.\nInput should be a json string with two keys: \"url\" and \"data\".\nThe value of \"url\" should be a string, and the value of \"data\" should be a dictionary of \nkey-value pairs you want to POST to the url as a JSON body.\nBe careful to always use double quotes for strings in the json string\nThe output will be the text response of the POST request.", - "headers": "" - }, - "outputAnchors": [ - { - "id": "requestsPost_0-output-requestsPost-RequestsPost|Tool|StructuredTool|BaseLangChain", - "name": "requestsPost", - "label": "RequestsPost", - "type": "RequestsPost | Tool | StructuredTool | BaseLangChain" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 436.4125209312256, - "y": 306.87715502984184 - }, - "dragging": false - }, - { - "width": 300, - "height": 523, - "id": "chatOpenAI_0", - "position": { - "x": 802.0103755177098, - "y": 576.0760341170851 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_0", - "label": "ChatOpenAI", - "name": "chatOpenAI", - "version": 6.0, - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_0-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "default": 0.9, - "optional": true, - "id": "chatOpenAI_0-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_0-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_0-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_0-input-cache-BaseCache" - } - ], - "inputs": { - "modelName": "gpt-3.5-turbo", - "temperature": 0.9, - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 802.0103755177098, - "y": 576.0760341170851 - }, - "dragging": false - }, - { - "width": 300, - "height": 280, - "id": "mrklAgentChat_0", - "position": { - "x": 1425.5853300862047, - "y": 441.06218012993924 - }, - "type": "customNode", - "data": { - "id": "mrklAgentChat_0", - "label": "MRKL Agent for Chat Models", - "name": "mrklAgentChat", - "version": 2, - "type": "AgentExecutor", - "baseClasses": ["AgentExecutor", "BaseChain"], - "category": "Agents", - "description": "Agent that uses the ReAct Framework to decide what action to take, optimized to be used with Chat Models", - "inputParams": [], - "inputAnchors": [ - { - "label": "Allowed Tools", - "name": "tools", - "type": "Tool", - "list": true, - "id": "mrklAgentChat_0-input-tools-Tool" - }, - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "mrklAgentChat_0-input-model-BaseLanguageModel" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "mrklAgentChat_0-input-inputModeration-Moderation" - }, - { - "label": "Max Iterations", - "name": "maxIterations", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "mrklAgentChat_0-input-maxIterations-number" - } - ], - "inputs": { - "inputModeration": "", - "tools": ["{{requestsGet_0.data.instance}}", "{{requestsPost_0.data.instance}}", "{{aiPlugin_0.data.instance}}"], - "model": "{{chatOpenAI_0.data.instance}}" - }, - "outputAnchors": [ - { - "id": "mrklAgentChat_0-output-mrklAgentChat-AgentExecutor|BaseChain", - "name": "mrklAgentChat", - "label": "AgentExecutor", - "type": "AgentExecutor | BaseChain" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1425.5853300862047, - "y": 441.06218012993924 - }, - "dragging": false - } - ], - "edges": [ - { - "source": "aiPlugin_0", - "sourceHandle": "aiPlugin_0-output-aiPlugin-AIPlugin|Tool", - "target": "mrklAgentChat_0", - "targetHandle": "mrklAgentChat_0-input-tools-Tool", - "type": "buttonedge", - "id": "aiPlugin_0-aiPlugin_0-output-aiPlugin-AIPlugin|Tool-mrklAgentChat_0-mrklAgentChat_0-input-tools-Tool", - "data": { - "label": "" - } - }, - { - "source": "requestsGet_0", - "sourceHandle": "requestsGet_0-output-requestsGet-RequestsGet|Tool|StructuredTool|BaseLangChain", - "target": "mrklAgentChat_0", - "targetHandle": "mrklAgentChat_0-input-tools-Tool", - "type": "buttonedge", - "id": "requestsGet_0-requestsGet_0-output-requestsGet-RequestsGet|Tool|StructuredTool|BaseLangChain-mrklAgentChat_0-mrklAgentChat_0-input-tools-Tool", - "data": { - "label": "" - } - }, - { - "source": "requestsPost_0", - "sourceHandle": "requestsPost_0-output-requestsPost-RequestsPost|Tool|StructuredTool|BaseLangChain", - "target": "mrklAgentChat_0", - "targetHandle": "mrklAgentChat_0-input-tools-Tool", - "type": "buttonedge", - "id": "requestsPost_0-requestsPost_0-output-requestsPost-RequestsPost|Tool|StructuredTool|BaseLangChain-mrklAgentChat_0-mrklAgentChat_0-input-tools-Tool", - "data": { - "label": "" - } - }, - { - "source": "chatOpenAI_0", - "sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel", - "target": "mrklAgentChat_0", - "targetHandle": "mrklAgentChat_0-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel-mrklAgentChat_0-mrklAgentChat_0-input-model-BaseLanguageModel", - "data": { - "label": "" - } - } - ] -} diff --git a/packages/server/marketplaces/chatflows/ReAct Agent.json b/packages/server/marketplaces/chatflows/ReAct Agent.json index 9a5a9a8229a..78ac415c8c0 100644 --- a/packages/server/marketplaces/chatflows/ReAct Agent.json +++ b/packages/server/marketplaces/chatflows/ReAct Agent.json @@ -1,6 +1,6 @@ { "description": "An agent that uses ReAct logic to decide what action to take", - "categories": "Calculator Tool,SerpAPI,ChatOpenAI,MRKL Agent,Langchain", + "categories": "Calculator Tool,SerpAPI,ChatOpenAI,ReAct Agent,Langchain", "framework": "Langchain", "nodes": [ { @@ -43,17 +43,17 @@ "dragging": false }, { - "id": "mrklAgentChat_0", + "id": "reactAgentChat_0", "position": { "x": 905.8535326018256, "y": 388.58312223652564 }, "type": "customNode", "data": { - "id": "mrklAgentChat_0", + "id": "reactAgentChat_0", "label": "ReAct Agent for Chat Models", "version": 4, - "name": "mrklAgentChat", + "name": "reactAgentChat", "type": "AgentExecutor", "baseClasses": ["AgentExecutor", "BaseChain", "Runnable"], "category": "Agents", @@ -65,19 +65,19 @@ "name": "tools", "type": "Tool", "list": true, - "id": "mrklAgentChat_0-input-tools-Tool" + "id": "reactAgentChat_0-input-tools-Tool" }, { "label": "Chat Model", "name": "model", "type": "BaseChatModel", - "id": "mrklAgentChat_0-input-model-BaseChatModel" + "id": "reactAgentChat_0-input-model-BaseChatModel" }, { "label": "Memory", "name": "memory", "type": "BaseChatMemory", - "id": "mrklAgentChat_0-input-memory-BaseChatMemory" + "id": "reactAgentChat_0-input-memory-BaseChatMemory" }, { "label": "Input Moderation", @@ -86,7 +86,7 @@ "type": "Moderation", "optional": true, "list": true, - "id": "mrklAgentChat_0-input-inputModeration-Moderation" + "id": "reactAgentChat_0-input-inputModeration-Moderation" }, { "label": "Max Iterations", @@ -94,7 +94,7 @@ "type": "number", "optional": true, "additionalParams": true, - "id": "mrklAgentChat_0-input-maxIterations-number" + "id": "reactAgentChat_0-input-maxIterations-number" } ], "inputs": { @@ -105,8 +105,8 @@ }, "outputAnchors": [ { - "id": "mrklAgentChat_0-output-mrklAgentChat-AgentExecutor|BaseChain|Runnable", - "name": "mrklAgentChat", + "id": "reactAgentChat_0-output-reactAgentChat-AgentExecutor|BaseChain|Runnable", + "name": "reactAgentChat", "label": "AgentExecutor", "description": "Agent that uses the ReAct logic to decide what action to take, optimized to be used with Chat Models", "type": "AgentExecutor | BaseChain | Runnable" @@ -447,34 +447,34 @@ { "source": "calculator_1", "sourceHandle": "calculator_1-output-calculator-Calculator|Tool|StructuredTool|BaseLangChain", - "target": "mrklAgentChat_0", - "targetHandle": "mrklAgentChat_0-input-tools-Tool", + "target": "reactAgentChat_0", + "targetHandle": "reactAgentChat_0-input-tools-Tool", "type": "buttonedge", - "id": "calculator_1-calculator_1-output-calculator-Calculator|Tool|StructuredTool|BaseLangChain-mrklAgentChat_0-mrklAgentChat_0-input-tools-Tool" + "id": "calculator_1-calculator_1-output-calculator-Calculator|Tool|StructuredTool|BaseLangChain-reactAgentChat_0-reactAgentChat_0-input-tools-Tool" }, { "source": "RedisBackedChatMemory_0", "sourceHandle": "RedisBackedChatMemory_0-output-RedisBackedChatMemory-RedisBackedChatMemory|BaseChatMemory|BaseMemory", - "target": "mrklAgentChat_0", - "targetHandle": "mrklAgentChat_0-input-memory-BaseChatMemory", + "target": "reactAgentChat_0", + "targetHandle": "reactAgentChat_0-input-memory-BaseChatMemory", "type": "buttonedge", - "id": "RedisBackedChatMemory_0-RedisBackedChatMemory_0-output-RedisBackedChatMemory-RedisBackedChatMemory|BaseChatMemory|BaseMemory-mrklAgentChat_0-mrklAgentChat_0-input-memory-BaseChatMemory" + "id": "RedisBackedChatMemory_0-RedisBackedChatMemory_0-output-RedisBackedChatMemory-RedisBackedChatMemory|BaseChatMemory|BaseMemory-reactAgentChat_0-reactAgentChat_0-input-memory-BaseChatMemory" }, { "source": "chatOpenAI_0", "sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "target": "mrklAgentChat_0", - "targetHandle": "mrklAgentChat_0-input-model-BaseChatModel", + "target": "reactAgentChat_0", + "targetHandle": "reactAgentChat_0-input-model-BaseChatModel", "type": "buttonedge", - "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-mrklAgentChat_0-mrklAgentChat_0-input-model-BaseChatModel" + "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-reactAgentChat_0-reactAgentChat_0-input-model-BaseChatModel" }, { "source": "serper_0", "sourceHandle": "serper_0-output-serper-Serper|Tool|StructuredTool|Runnable", - "target": "mrklAgentChat_0", - "targetHandle": "mrklAgentChat_0-input-tools-Tool", + "target": "reactAgentChat_0", + "targetHandle": "reactAgentChat_0-input-tools-Tool", "type": "buttonedge", - "id": "serper_0-serper_0-output-serper-Serper|Tool|StructuredTool|Runnable-mrklAgentChat_0-mrklAgentChat_0-input-tools-Tool" + "id": "serper_0-serper_0-output-serper-Serper|Tool|StructuredTool|Runnable-reactAgentChat_0-reactAgentChat_0-input-tools-Tool" } ] } diff --git a/packages/server/src/utils/getUploadsConfig.ts b/packages/server/src/utils/getUploadsConfig.ts index 9d123a413ec..13d18eb9d64 100644 --- a/packages/server/src/utils/getUploadsConfig.ts +++ b/packages/server/src/utils/getUploadsConfig.ts @@ -18,7 +18,7 @@ export const utilGetUploadsConfig = async (chatflowid: string): Promise => throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Chatflow ${chatflowid} not found`) } - const uploadAllowedNodes = ['llmChain', 'conversationChain', 'mrklAgentChat', 'conversationalAgent'] + const uploadAllowedNodes = ['llmChain', 'conversationChain', 'reactAgentChat', 'conversationalAgent', 'toolAgent'] const uploadProcessingNodes = ['chatOpenAI', 'chatAnthropic', 'awsChatBedrock', 'azureChatOpenAI', 'chatGoogleGenerativeAI'] const flowObj = JSON.parse(chatflow.flowData) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9b6001fd1a5..d158fd85c67 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,7 @@ onlyBuiltDependencies: overrides: '@qdrant/openapi-typescript-fetch': 1.2.1 + '@google/generative-ai': ^0.7.0 importers: .: @@ -600,10 +601,10 @@ importers: version: 16.4.5 flowise-embed: specifier: latest - version: 1.2.1 + version: 1.2.2 flowise-embed-react: specifier: latest - version: 1.0.2(flowise-embed@1.2.1)(react-dom@18.2.0)(react@18.2.0)(sass@1.71.1)(typescript@4.9.5) + version: 1.0.2(flowise-embed@1.2.2)(react-dom@18.2.0)(react@18.2.0)(sass@1.71.1)(typescript@4.9.5) flowise-react-json-view: specifier: '*' version: 1.21.7(@types/react@18.2.65)(react-dom@18.2.0)(react@18.2.0) @@ -4295,11 +4296,6 @@ packages: - supports-color dev: false - /@google/generative-ai@0.1.3: - resolution: { integrity: sha512-Cm4uJX1sKarpm1mje/MiOIinM7zdUUrQp/5/qGPAgznbdd/B9zup5ehT6c1qGqycFcSopTA1J1HpqHS5kJR8hQ== } - engines: { node: '>=18.0.0' } - dev: false - /@google/generative-ai@0.7.0: resolution: { integrity: sha512-+1kNkKbkDJftrvwfULQphkyC2ZQ42exlyR+TFARMuykuu6y8XyevbX0dDarqt1GVpZDm55yg0TBq6I1J65X6OA== } engines: { node: '>=18.0.0' } @@ -5523,7 +5519,7 @@ packages: resolution: { integrity: sha512-neFuCoMew9t8IYM5srh6RVUFQsZxqPtAFVJ0mWtZqHXtb627MECs5FYr+xw1ptPKSbhIAN5H8sgdObqes4bN3A== } engines: { node: '>=18' } dependencies: - '@google/generative-ai': 0.1.3 + '@google/generative-ai': 0.7.0 '@langchain/core': 0.1.57 dev: false @@ -13350,6 +13346,11 @@ packages: - supports-color dev: true + /device-detector-js@3.0.3: + resolution: { integrity: sha512-jM89LJAvP6uOd84at8OlD9dWP8KeYCCHUde0RT0HQo/stdoRH4b54Xl/fntx2nEXCmqiFhmo+/cJetS2VGUHPw== } + engines: { node: '>= 8.11.4' } + dev: false + /devlop@1.1.0: resolution: { integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA== } dependencies: @@ -15421,14 +15422,14 @@ packages: resolution: { integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== } dev: true - /flowise-embed-react@1.0.2(flowise-embed@1.2.1)(react-dom@18.2.0)(react@18.2.0)(sass@1.71.1)(typescript@4.9.5): + /flowise-embed-react@1.0.2(flowise-embed@1.2.2)(react-dom@18.2.0)(react@18.2.0)(sass@1.71.1)(typescript@4.9.5): resolution: { integrity: sha512-M6rDofJWTWI9rtZN7G3oTlqAcQaHoF/IUIoW1YitHsjKly24awq5sky+0Wfkcg4VfoXz3SiLHMZ/XOF4PDuvqA== } peerDependencies: flowise-embed: '*' react: 18.x dependencies: '@ladle/react': 2.5.1(react-dom@18.2.0)(react@18.2.0)(sass@1.71.1)(typescript@4.9.5) - flowise-embed: 1.2.1 + flowise-embed: 1.2.2 react: 18.2.0 transitivePeerDependencies: - '@types/node' @@ -15443,11 +15444,12 @@ packages: - typescript dev: false - /flowise-embed@1.2.1: - resolution: { integrity: sha512-sn8An0dseo398RXx/yzQ3lC//+FpY5o/094yaWZs3NmYy6am+duCZJ18lhcYF5A4oCucrIoZCcCz5mxViYtznw== } + /flowise-embed@1.2.2: + resolution: { integrity: sha512-9LBOnkdUyeFbm7ntsE9h09+g/pLinMxOk3AXGMmRYG5IO/YA8wsdd0/iZPvXbBSey7QnV53twRaM6cJD8XqLcQ== } dependencies: '@babel/core': 7.24.0 '@ts-stack/markdown': 1.5.0 + device-detector-js: 3.0.3 lodash: 4.17.21 prettier: 3.2.5 socket.io-client: 4.7.4