mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 23:01:09 +03:00
Feature/seq agents (#2798)
* update build functions * sequential agents * update langchain to 0.2, added sequential agent nodes * add marketplace templates * update howto wordings * Merge branch 'main' into feature/Seq-Agents # Conflicts: # pnpm-lock.yaml * update deprecated functions and add new sequential nodes * add marketplace templates * update marketplace templates, add structured output to llm node * add multi agents template * update llm node with bindmodels * update cypress version * update templates sticky note wordings * update tool node to include human in loop action * update structured outputs error from models * update cohere package to resolve google genai pipeThrough bug * update mistral package version, added message reconstruction before invoke seq agent * add HITL to agent * update state messages restructuring * update load and split methods for s3 directory
This commit is contained in:
@@ -1,68 +0,0 @@
|
||||
import { BaseCache } from '@langchain/core/caches'
|
||||
import { BaseLLMParams } from '@langchain/core/language_models/llms'
|
||||
import { NIBittensorLLM, BittensorInput } from 'langchain/experimental/llms/bittensor'
|
||||
import { INode, INodeData, INodeParams } from '../../../src/Interface'
|
||||
import { getBaseClasses } from '../../../src/utils'
|
||||
|
||||
class Bittensor_LLMs implements INode {
|
||||
label: string
|
||||
name: string
|
||||
version: number
|
||||
type: string
|
||||
icon: string
|
||||
category: string
|
||||
description: string
|
||||
baseClasses: string[]
|
||||
inputs: INodeParams[]
|
||||
|
||||
constructor() {
|
||||
this.label = 'NIBittensorLLM'
|
||||
this.name = 'NIBittensorLLM'
|
||||
this.version = 2.0
|
||||
this.type = 'Bittensor'
|
||||
this.icon = 'NIBittensor.svg'
|
||||
this.category = 'LLMs'
|
||||
this.description = 'Wrapper around Bittensor subnet 1 large language models'
|
||||
this.baseClasses = [this.type, ...getBaseClasses(NIBittensorLLM)]
|
||||
this.inputs = [
|
||||
{
|
||||
label: 'Cache',
|
||||
name: 'cache',
|
||||
type: 'BaseCache',
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
label: 'System prompt',
|
||||
name: 'system_prompt',
|
||||
type: 'string',
|
||||
additionalParams: true,
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
label: 'Top Responses',
|
||||
name: 'topResponses',
|
||||
type: 'number',
|
||||
step: 1,
|
||||
optional: true,
|
||||
additionalParams: true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
async init(nodeData: INodeData, _: string): Promise<any> {
|
||||
const system_prompt = nodeData.inputs?.system_prompt as string
|
||||
const topResponses = Number(nodeData.inputs?.topResponses as number)
|
||||
const cache = nodeData.inputs?.cache as BaseCache
|
||||
|
||||
const obj: Partial<BittensorInput> & BaseLLMParams = {
|
||||
systemPrompt: system_prompt,
|
||||
topResponses: topResponses
|
||||
}
|
||||
if (cache) obj.cache = cache
|
||||
|
||||
const model = new NIBittensorLLM(obj)
|
||||
return model
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { nodeClass: Bittensor_LLMs }
|
||||
@@ -1 +0,0 @@
|
||||
<svg width="32" height="32" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M18.64 25.698V29H8l1.61-6.25a9.81 9.81 0 0 0-.045-4.5C9.027 15.808 8 15.394 8 10.824c.01-2.35.916-4.601 2.517-6.256C12.12 2.913 14.285 1.989 16.54 2c2.254.01 4.412.955 5.999 2.625 1.587 1.67 2.472 3.93 2.462 6.28V12l2 4h-2v4.208a3.821 3.821 0 0 1-1.08 2.373 3.531 3.531 0 0 1-2.306 1.054c-.165.01-.375.004-.606-.012-1.242-.085-2.367.83-2.367 2.075Z" fill="#000" stroke="#000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M21 13h-2l-1-2m3-1-1-2h-4m-3 1 2 4m-1 6 3-3h4" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
|
Before Width: | Height: | Size: 666 B |
@@ -1,7 +1,7 @@
|
||||
import { BaseCache } from '@langchain/core/caches'
|
||||
import { Cohere, CohereInput } from '@langchain/cohere'
|
||||
import { ICommonObject, INode, INodeData, INodeOptionsValue, INodeParams } from '../../../src/Interface'
|
||||
import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
|
||||
import { Cohere, CohereInput } from './core'
|
||||
import { getModels, MODEL_TYPE } from '../../../src/modelLoader'
|
||||
|
||||
class Cohere_LLMs implements INode {
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
import { LLM, BaseLLMParams } from '@langchain/core/language_models/llms'
|
||||
|
||||
export interface CohereInput extends BaseLLMParams {
|
||||
/** Sampling temperature to use */
|
||||
temperature?: number
|
||||
|
||||
/**
|
||||
* Maximum number of tokens to generate in the completion.
|
||||
*/
|
||||
maxTokens?: number
|
||||
|
||||
/** Model to use */
|
||||
model?: string
|
||||
|
||||
apiKey?: string
|
||||
}
|
||||
|
||||
export class Cohere extends LLM implements CohereInput {
|
||||
temperature = 0
|
||||
|
||||
maxTokens = 250
|
||||
|
||||
model: string
|
||||
|
||||
apiKey: string
|
||||
|
||||
constructor(fields?: CohereInput) {
|
||||
super(fields ?? {})
|
||||
|
||||
const apiKey = fields?.apiKey ?? undefined
|
||||
|
||||
if (!apiKey) {
|
||||
throw new Error('Please set the COHERE_API_KEY environment variable or pass it to the constructor as the apiKey field.')
|
||||
}
|
||||
|
||||
this.apiKey = apiKey
|
||||
this.maxTokens = fields?.maxTokens ?? this.maxTokens
|
||||
this.temperature = fields?.temperature ?? this.temperature
|
||||
this.model = fields?.model ?? this.model
|
||||
}
|
||||
|
||||
_llmType() {
|
||||
return 'cohere'
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
async _call(prompt: string, options: this['ParsedCallOptions']): Promise<string> {
|
||||
const { cohere } = await Cohere.imports()
|
||||
|
||||
cohere.init(this.apiKey)
|
||||
|
||||
// Hit the `generate` endpoint on the `large` model
|
||||
const generateResponse = await this.caller.callWithOptions({ signal: options.signal }, cohere.generate.bind(cohere), {
|
||||
prompt,
|
||||
model: this.model,
|
||||
max_tokens: this.maxTokens,
|
||||
temperature: this.temperature,
|
||||
end_sequences: options.stop
|
||||
})
|
||||
try {
|
||||
return generateResponse.body.generations[0].text
|
||||
} catch {
|
||||
throw new Error('Could not parse response.')
|
||||
}
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
static async imports(): Promise<{
|
||||
cohere: typeof import('cohere-ai')
|
||||
}> {
|
||||
try {
|
||||
const { default: cohere } = await import('cohere-ai')
|
||||
return { cohere }
|
||||
} catch (e) {
|
||||
throw new Error('Please install cohere-ai as a dependency with, e.g. `pnpm install cohere-ai`')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Replicate, ReplicateInput } from '@langchain/community/llms/replicate'
|
||||
import { BaseCache } from '@langchain/core/caches'
|
||||
import { BaseLLMParams } from '@langchain/core/language_models/llms'
|
||||
import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface'
|
||||
import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
|
||||
import { Replicate, ReplicateInput } from './core'
|
||||
|
||||
class Replicate_LLMs implements INode {
|
||||
label: string
|
||||
@@ -97,7 +97,7 @@ class Replicate_LLMs implements INode {
|
||||
}
|
||||
|
||||
async init(nodeData: INodeData, _: string, options: ICommonObject): Promise<any> {
|
||||
const modelName = nodeData.inputs?.model as string
|
||||
const modelName = nodeData.inputs?.model as `${string}/${string}` | `${string}/${string}:${string}`
|
||||
const temperature = nodeData.inputs?.temperature as string
|
||||
const maxTokens = nodeData.inputs?.maxTokens as string
|
||||
const topP = nodeData.inputs?.topP as string
|
||||
@@ -107,14 +107,10 @@ class Replicate_LLMs implements INode {
|
||||
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
||||
const apiKey = getCredentialParam('replicateApiKey', credentialData, nodeData)
|
||||
|
||||
const version = modelName.split(':').pop()
|
||||
const name = modelName.split(':')[0].split('/').pop()
|
||||
const org = modelName.split(':')[0].split('/')[0]
|
||||
|
||||
const cache = nodeData.inputs?.cache as BaseCache
|
||||
|
||||
const obj: ReplicateInput & BaseLLMParams = {
|
||||
model: `${org}/${name}:${version}`,
|
||||
model: modelName,
|
||||
apiKey
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
import { LLM, type BaseLLMParams } from '@langchain/core/language_models/llms'
|
||||
import { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager'
|
||||
import { GenerationChunk } from '@langchain/core/outputs'
|
||||
|
||||
import type ReplicateInstance from 'replicate'
|
||||
|
||||
export interface ReplicateInput {
|
||||
model: `${string}/${string}` | `${string}/${string}:${string}`
|
||||
input?: {
|
||||
// different models accept different inputs
|
||||
[key: string]: string | number | boolean
|
||||
}
|
||||
apiKey?: string
|
||||
promptKey?: string
|
||||
}
|
||||
|
||||
export class Replicate extends LLM implements ReplicateInput {
|
||||
lc_serializable = true
|
||||
|
||||
model: ReplicateInput['model']
|
||||
|
||||
input: ReplicateInput['input']
|
||||
|
||||
apiKey: string
|
||||
|
||||
promptKey?: string
|
||||
|
||||
constructor(fields: ReplicateInput & BaseLLMParams) {
|
||||
super(fields)
|
||||
|
||||
const apiKey = fields?.apiKey
|
||||
|
||||
if (!apiKey) {
|
||||
throw new Error('Please set the REPLICATE_API_TOKEN')
|
||||
}
|
||||
|
||||
this.apiKey = apiKey
|
||||
this.model = fields.model
|
||||
this.input = fields.input ?? {}
|
||||
this.promptKey = fields.promptKey
|
||||
}
|
||||
|
||||
_llmType() {
|
||||
return 'replicate'
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
async _call(prompt: string, options: this['ParsedCallOptions']): Promise<string> {
|
||||
const replicate = await this._prepareReplicate()
|
||||
const input = await this._getReplicateInput(replicate, prompt)
|
||||
|
||||
const output = await this.caller.callWithOptions({ signal: options.signal }, () =>
|
||||
replicate.run(this.model, {
|
||||
input
|
||||
})
|
||||
)
|
||||
|
||||
if (typeof output === 'string') {
|
||||
return output
|
||||
} else if (Array.isArray(output)) {
|
||||
return output.join('')
|
||||
} else {
|
||||
// Note this is a little odd, but the output format is not consistent
|
||||
// across models, so it makes some amount of sense.
|
||||
return String(output)
|
||||
}
|
||||
}
|
||||
|
||||
async *_streamResponseChunks(
|
||||
prompt: string,
|
||||
options: this['ParsedCallOptions'],
|
||||
runManager?: CallbackManagerForLLMRun
|
||||
): AsyncGenerator<GenerationChunk> {
|
||||
const replicate = await this._prepareReplicate()
|
||||
const input = await this._getReplicateInput(replicate, prompt)
|
||||
|
||||
const stream = await this.caller.callWithOptions({ signal: options?.signal }, async () =>
|
||||
replicate.stream(this.model, {
|
||||
input
|
||||
})
|
||||
)
|
||||
for await (const chunk of stream) {
|
||||
if (chunk.event === 'output') {
|
||||
yield new GenerationChunk({ text: chunk.data, generationInfo: chunk })
|
||||
await runManager?.handleLLMNewToken(chunk.data ?? '')
|
||||
}
|
||||
|
||||
// stream is done
|
||||
if (chunk.event === 'done')
|
||||
yield new GenerationChunk({
|
||||
text: '',
|
||||
generationInfo: { finished: true }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
static async imports(): Promise<{
|
||||
Replicate: typeof ReplicateInstance
|
||||
}> {
|
||||
try {
|
||||
const { default: Replicate } = await import('replicate')
|
||||
return { Replicate }
|
||||
} catch (e) {
|
||||
throw new Error('Please install replicate as a dependency with, e.g. `yarn add replicate`')
|
||||
}
|
||||
}
|
||||
|
||||
private async _prepareReplicate(): Promise<ReplicateInstance> {
|
||||
const imports = await Replicate.imports()
|
||||
|
||||
return new imports.Replicate({
|
||||
userAgent: 'flowise',
|
||||
auth: this.apiKey
|
||||
})
|
||||
}
|
||||
|
||||
private async _getReplicateInput(replicate: ReplicateInstance, prompt: string) {
|
||||
if (this.promptKey === undefined) {
|
||||
const [modelString, versionString] = this.model.split(':')
|
||||
if (versionString) {
|
||||
const version = await replicate.models.versions.get(modelString.split('/')[0], modelString.split('/')[1], versionString)
|
||||
const openapiSchema = version.openapi_schema
|
||||
const inputProperties: { 'x-order': number | undefined }[] = (openapiSchema as any)?.components?.schemas?.Input?.properties
|
||||
if (inputProperties === undefined) {
|
||||
this.promptKey = 'prompt'
|
||||
} else {
|
||||
const sortedInputProperties = Object.entries(inputProperties).sort(([_keyA, valueA], [_keyB, valueB]) => {
|
||||
const orderA = valueA['x-order'] || 0
|
||||
const orderB = valueB['x-order'] || 0
|
||||
return orderA - orderB
|
||||
})
|
||||
this.promptKey = sortedInputProperties[0][0] ?? 'prompt'
|
||||
}
|
||||
} else {
|
||||
this.promptKey = 'prompt'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
[this.promptKey!]: prompt,
|
||||
...this.input
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user