mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 13:00:56 +03:00
Merge branch 'main' into bugfix/webscrape-relative-links
This commit is contained in:
@@ -150,8 +150,8 @@ export interface IUsedTool {
|
||||
* Classes
|
||||
*/
|
||||
|
||||
import { PromptTemplate as LangchainPromptTemplate, PromptTemplateInput } from 'langchain/prompts'
|
||||
import { VectorStore } from 'langchain/vectorstores/base'
|
||||
import { PromptTemplate as LangchainPromptTemplate, PromptTemplateInput } from '@langchain/core/prompts'
|
||||
import { VectorStore } from '@langchain/core/vectorstores'
|
||||
|
||||
export class PromptTemplate extends LangchainPromptTemplate {
|
||||
promptValues: ICommonObject
|
||||
@@ -203,7 +203,7 @@ export class VectorStoreRetriever {
|
||||
/**
|
||||
* Implement abstract classes and interface for memory
|
||||
*/
|
||||
import { BaseMessage } from 'langchain/schema'
|
||||
import { BaseMessage } from '@langchain/core/messages'
|
||||
import { BufferMemory, BufferWindowMemory, ConversationSummaryMemory } from 'langchain/memory'
|
||||
|
||||
export interface MemoryMethods {
|
||||
|
||||
@@ -1,12 +1,25 @@
|
||||
import { flatten } from 'lodash'
|
||||
import { AgentExecutorInput, BaseSingleActionAgent, BaseMultiActionAgent, RunnableAgent, StoppingMethod } from 'langchain/agents'
|
||||
import { ChainValues, AgentStep, AgentAction, BaseMessage, FunctionMessage, AIMessage } from 'langchain/schema'
|
||||
import { OutputParserException } from 'langchain/schema/output_parser'
|
||||
import { CallbackManager, CallbackManagerForChainRun, Callbacks } from 'langchain/callbacks'
|
||||
import { ToolInputParsingException, Tool } from '@langchain/core/tools'
|
||||
import { Runnable } from 'langchain/schema/runnable'
|
||||
import { BaseChain, SerializedLLMChain } from 'langchain/chains'
|
||||
import { ChainValues } from '@langchain/core/utils/types'
|
||||
import { AgentStep, AgentAction } from '@langchain/core/agents'
|
||||
import { BaseMessage, FunctionMessage, AIMessage } from '@langchain/core/messages'
|
||||
import { OutputParserException } from '@langchain/core/output_parsers'
|
||||
import { BaseLanguageModel } from '@langchain/core/language_models/base'
|
||||
import { CallbackManager, CallbackManagerForChainRun, Callbacks } from '@langchain/core/callbacks/manager'
|
||||
import { ToolInputParsingException, Tool, StructuredToolInterface } from '@langchain/core/tools'
|
||||
import { Runnable, RunnableSequence, RunnablePassthrough } from '@langchain/core/runnables'
|
||||
import { Serializable } from '@langchain/core/load/serializable'
|
||||
import { renderTemplate } from '@langchain/core/prompts'
|
||||
import { BaseChain, SerializedLLMChain } from 'langchain/chains'
|
||||
import {
|
||||
CreateReactAgentParams,
|
||||
AgentExecutorInput,
|
||||
AgentActionOutputParser,
|
||||
BaseSingleActionAgent,
|
||||
BaseMultiActionAgent,
|
||||
RunnableAgent,
|
||||
StoppingMethod
|
||||
} from 'langchain/agents'
|
||||
import { formatLogToString } from 'langchain/agents/format_scratchpad/log'
|
||||
|
||||
export const SOURCE_DOCUMENTS_PREFIX = '\n\n----FLOWISE_SOURCE_DOCUMENTS----\n\n'
|
||||
type AgentFinish = {
|
||||
@@ -645,3 +658,110 @@ export const formatAgentSteps = (steps: AgentStep[]): BaseMessage[] =>
|
||||
return [new AIMessage(action.log)]
|
||||
}
|
||||
})
|
||||
|
||||
const renderTextDescription = (tools: StructuredToolInterface[]): string => {
|
||||
return tools.map((tool) => `${tool.name}: ${tool.description}`).join('\n')
|
||||
}
|
||||
|
||||
export const createReactAgent = async ({ llm, tools, prompt }: CreateReactAgentParams) => {
|
||||
const missingVariables = ['tools', 'tool_names', 'agent_scratchpad'].filter((v) => !prompt.inputVariables.includes(v))
|
||||
if (missingVariables.length > 0) {
|
||||
throw new Error(`Provided prompt is missing required input variables: ${JSON.stringify(missingVariables)}`)
|
||||
}
|
||||
const toolNames = tools.map((tool) => tool.name)
|
||||
const partialedPrompt = await prompt.partial({
|
||||
tools: renderTextDescription(tools),
|
||||
tool_names: toolNames.join(', ')
|
||||
})
|
||||
// TODO: Add .bind to core runnable interface.
|
||||
const llmWithStop = (llm as BaseLanguageModel).bind({
|
||||
stop: ['\nObservation:']
|
||||
})
|
||||
const agent = RunnableSequence.from([
|
||||
RunnablePassthrough.assign({
|
||||
//@ts-ignore
|
||||
agent_scratchpad: (input: { steps: AgentStep[] }) => formatLogToString(input.steps)
|
||||
}),
|
||||
partialedPrompt,
|
||||
llmWithStop,
|
||||
new ReActSingleInputOutputParser({
|
||||
toolNames
|
||||
})
|
||||
])
|
||||
return agent
|
||||
}
|
||||
|
||||
class ReActSingleInputOutputParser extends AgentActionOutputParser {
|
||||
lc_namespace = ['langchain', 'agents', 'react']
|
||||
|
||||
private toolNames: string[]
|
||||
private FINAL_ANSWER_ACTION = 'Final Answer:'
|
||||
private FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE = 'Parsing LLM output produced both a final answer and a parse-able action:'
|
||||
private FORMAT_INSTRUCTIONS = `Use the following format:
|
||||
|
||||
Question: the input question you must answer
|
||||
Thought: you should always think about what to do
|
||||
Action: the action to take, should be one of [{tool_names}]
|
||||
Action Input: the input to the action
|
||||
Observation: the result of the action
|
||||
... (this Thought/Action/Action Input/Observation can repeat N times)
|
||||
Thought: I now know the final answer
|
||||
Final Answer: the final answer to the original input question`
|
||||
|
||||
constructor(fields: { toolNames: string[] }) {
|
||||
super(...arguments)
|
||||
this.toolNames = fields.toolNames
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given text into an AgentAction or AgentFinish object. If an
|
||||
* output fixing parser is defined, uses it to parse the text.
|
||||
* @param text Text to parse.
|
||||
* @returns Promise that resolves to an AgentAction or AgentFinish object.
|
||||
*/
|
||||
async parse(text: string): Promise<AgentAction | AgentFinish> {
|
||||
const includesAnswer = text.includes(this.FINAL_ANSWER_ACTION)
|
||||
const regex = /Action\s*\d*\s*:[\s]*(.*?)[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)/
|
||||
const actionMatch = text.match(regex)
|
||||
if (actionMatch) {
|
||||
if (includesAnswer) {
|
||||
throw new Error(`${this.FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE}: ${text}`)
|
||||
}
|
||||
|
||||
const action = actionMatch[1]
|
||||
const actionInput = actionMatch[2]
|
||||
const toolInput = actionInput.trim().replace(/"/g, '')
|
||||
|
||||
return {
|
||||
tool: action,
|
||||
toolInput,
|
||||
log: text
|
||||
}
|
||||
}
|
||||
|
||||
if (includesAnswer) {
|
||||
const finalAnswerText = text.split(this.FINAL_ANSWER_ACTION)[1].trim()
|
||||
return {
|
||||
returnValues: {
|
||||
output: finalAnswerText
|
||||
},
|
||||
log: text
|
||||
}
|
||||
}
|
||||
|
||||
// Instead of throwing Error, we return a AgentFinish object
|
||||
return { returnValues: { output: text }, log: text }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format instructions as a string. If the 'raw' option is
|
||||
* true, returns the raw FORMAT_INSTRUCTIONS.
|
||||
* @param options Options for getting the format instructions.
|
||||
* @returns Format instructions as a string.
|
||||
*/
|
||||
getFormatInstructions(): string {
|
||||
return renderTemplate(this.FORMAT_INSTRUCTIONS, 'f-string', {
|
||||
tool_names: this.toolNames.join(', ')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
import { BaseTracer, Run, BaseCallbackHandler, LangChainTracer } from 'langchain/callbacks'
|
||||
import { AgentAction, ChainValues } from 'langchain/schema'
|
||||
import { Logger } from 'winston'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { Server } from 'socket.io'
|
||||
import { Client } from 'langsmith'
|
||||
import { LLMonitorHandler, LLMonitorHandlerFields } from 'langchain/callbacks/handlers/llmonitor'
|
||||
import { getCredentialData, getCredentialParam } from './utils'
|
||||
import { ICommonObject, INodeData } from './Interface'
|
||||
import CallbackHandler from 'langfuse-langchain'
|
||||
import { LangChainTracerFields } from '@langchain/core/tracers/tracer_langchain'
|
||||
import lunary from 'lunary'
|
||||
import { RunTree, RunTreeConfig, Client as LangsmithClient } from 'langsmith'
|
||||
import { Langfuse, LangfuseTraceClient, LangfuseSpanClient, LangfuseGenerationClient } from 'langfuse'
|
||||
import monitor from 'llmonitor'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
import { BaseCallbackHandler } from '@langchain/core/callbacks/base'
|
||||
import { LangChainTracer, LangChainTracerFields } from '@langchain/core/tracers/tracer_langchain'
|
||||
import { BaseTracer, Run } from '@langchain/core/tracers/base'
|
||||
import { ChainValues } from '@langchain/core/utils/types'
|
||||
import { AgentAction } from '@langchain/core/agents'
|
||||
import { LunaryHandler } from '@langchain/community/callbacks/handlers/lunary'
|
||||
|
||||
import { getCredentialData, getCredentialParam } from './utils'
|
||||
import { ICommonObject, INodeData } from './Interface'
|
||||
|
||||
interface AgentRun extends Run {
|
||||
actions: AgentAction[]
|
||||
@@ -268,20 +272,20 @@ export const additionalCallbacks = async (nodeData: INodeData, options: ICommonO
|
||||
|
||||
const handler = new CallbackHandler(langFuseOptions)
|
||||
callbacks.push(handler)
|
||||
} else if (provider === 'llmonitor') {
|
||||
const llmonitorAppId = getCredentialParam('llmonitorAppId', credentialData, nodeData)
|
||||
const llmonitorEndpoint = getCredentialParam('llmonitorEndpoint', credentialData, nodeData)
|
||||
} else if (provider === 'lunary') {
|
||||
const lunaryAppId = getCredentialParam('lunaryAppId', credentialData, nodeData)
|
||||
const lunaryEndpoint = getCredentialParam('lunaryEndpoint', credentialData, nodeData)
|
||||
|
||||
let llmonitorFields: LLMonitorHandlerFields = {
|
||||
appId: llmonitorAppId,
|
||||
apiUrl: llmonitorEndpoint ?? 'https://app.llmonitor.com'
|
||||
let lunaryFields = {
|
||||
appId: lunaryAppId,
|
||||
apiUrl: lunaryEndpoint ?? 'https://app.lunary.ai'
|
||||
}
|
||||
|
||||
if (nodeData?.inputs?.analytics?.llmonitor) {
|
||||
llmonitorFields = { ...llmonitorFields, ...nodeData?.inputs?.analytics?.llmonitor }
|
||||
if (nodeData?.inputs?.analytics?.lunary) {
|
||||
lunaryFields = { ...lunaryFields, ...nodeData?.inputs?.analytics?.lunary }
|
||||
}
|
||||
|
||||
const handler = new LLMonitorHandler(llmonitorFields)
|
||||
const handler = new LunaryHandler(lunaryFields)
|
||||
callbacks.push(handler)
|
||||
}
|
||||
}
|
||||
@@ -339,16 +343,16 @@ export class AnalyticHandler {
|
||||
release
|
||||
})
|
||||
this.handlers['langFuse'] = { client: langfuse }
|
||||
} else if (provider === 'llmonitor') {
|
||||
const llmonitorAppId = getCredentialParam('llmonitorAppId', credentialData, this.nodeData)
|
||||
const llmonitorEndpoint = getCredentialParam('llmonitorEndpoint', credentialData, this.nodeData)
|
||||
} else if (provider === 'lunary') {
|
||||
const lunaryAppId = getCredentialParam('lunaryAppId', credentialData, this.nodeData)
|
||||
const lunaryEndpoint = getCredentialParam('lunaryEndpoint', credentialData, this.nodeData)
|
||||
|
||||
monitor.init({
|
||||
appId: llmonitorAppId,
|
||||
apiUrl: llmonitorEndpoint
|
||||
lunary.init({
|
||||
appId: lunaryAppId,
|
||||
apiUrl: lunaryEndpoint
|
||||
})
|
||||
|
||||
this.handlers['llmonitor'] = { client: monitor }
|
||||
this.handlers['lunary'] = { client: lunary }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -361,7 +365,7 @@ export class AnalyticHandler {
|
||||
const returnIds: ICommonObject = {
|
||||
langSmith: {},
|
||||
langFuse: {},
|
||||
llmonitor: {}
|
||||
lunary: {}
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'langSmith')) {
|
||||
@@ -427,8 +431,8 @@ export class AnalyticHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'llmonitor')) {
|
||||
const monitor = this.handlers['llmonitor'].client
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'lunary')) {
|
||||
const monitor = this.handlers['lunary'].client
|
||||
|
||||
if (monitor) {
|
||||
const runId = uuidv4()
|
||||
@@ -437,10 +441,10 @@ export class AnalyticHandler {
|
||||
name,
|
||||
userId: this.options.chatId,
|
||||
input,
|
||||
...this.nodeData?.inputs?.analytics?.llmonitor
|
||||
...this.nodeData?.inputs?.analytics?.lunary
|
||||
})
|
||||
this.handlers['llmonitor'].chainEvent = { [runId]: runId }
|
||||
returnIds['llmonitor'].chainEvent = runId
|
||||
this.handlers['lunary'].chainEvent = { [runId]: runId }
|
||||
returnIds['lunary'].chainEvent = runId
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,9 +477,9 @@ export class AnalyticHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'llmonitor')) {
|
||||
const chainEventId = returnIds['llmonitor'].chainEvent
|
||||
const monitor = this.handlers['llmonitor'].client
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'lunary')) {
|
||||
const chainEventId = returnIds['lunary'].chainEvent
|
||||
const monitor = this.handlers['lunary'].client
|
||||
|
||||
if (monitor && chainEventId) {
|
||||
await monitor.trackEvent('chain', 'end', {
|
||||
@@ -514,9 +518,9 @@ export class AnalyticHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'llmonitor')) {
|
||||
const chainEventId = returnIds['llmonitor'].chainEvent
|
||||
const monitor = this.handlers['llmonitor'].client
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'lunary')) {
|
||||
const chainEventId = returnIds['lunary'].chainEvent
|
||||
const monitor = this.handlers['lunary'].client
|
||||
|
||||
if (monitor && chainEventId) {
|
||||
await monitor.trackEvent('chain', 'end', {
|
||||
@@ -531,7 +535,7 @@ export class AnalyticHandler {
|
||||
const returnIds: ICommonObject = {
|
||||
langSmith: {},
|
||||
langFuse: {},
|
||||
llmonitor: {}
|
||||
lunary: {}
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'langSmith')) {
|
||||
@@ -562,9 +566,9 @@ export class AnalyticHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'llmonitor')) {
|
||||
const monitor = this.handlers['llmonitor'].client
|
||||
const chainEventId: string = this.handlers['llmonitor'].chainEvent[parentIds['llmonitor'].chainEvent]
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'lunary')) {
|
||||
const monitor = this.handlers['lunary'].client
|
||||
const chainEventId: string = this.handlers['lunary'].chainEvent[parentIds['lunary'].chainEvent]
|
||||
|
||||
if (monitor && chainEventId) {
|
||||
const runId = uuidv4()
|
||||
@@ -575,8 +579,8 @@ export class AnalyticHandler {
|
||||
userId: this.options.chatId,
|
||||
input
|
||||
})
|
||||
this.handlers['llmonitor'].llmEvent = { [runId]: runId }
|
||||
returnIds['llmonitor'].llmEvent = runId
|
||||
this.handlers['lunary'].llmEvent = { [runId]: runId }
|
||||
returnIds['lunary'].llmEvent = runId
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,9 +609,9 @@ export class AnalyticHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'llmonitor')) {
|
||||
const llmEventId: string = this.handlers['llmonitor'].llmEvent[returnIds['llmonitor'].llmEvent]
|
||||
const monitor = this.handlers['llmonitor'].client
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'lunary')) {
|
||||
const llmEventId: string = this.handlers['lunary'].llmEvent[returnIds['lunary'].llmEvent]
|
||||
const monitor = this.handlers['lunary'].client
|
||||
|
||||
if (monitor && llmEventId) {
|
||||
await monitor.trackEvent('llm', 'end', {
|
||||
@@ -640,9 +644,9 @@ export class AnalyticHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'llmonitor')) {
|
||||
const llmEventId: string = this.handlers['llmonitor'].llmEvent[returnIds['llmonitor'].llmEvent]
|
||||
const monitor = this.handlers['llmonitor'].client
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'lunary')) {
|
||||
const llmEventId: string = this.handlers['lunary'].llmEvent[returnIds['lunary'].llmEvent]
|
||||
const monitor = this.handlers['lunary'].client
|
||||
|
||||
if (monitor && llmEventId) {
|
||||
await monitor.trackEvent('llm', 'end', {
|
||||
@@ -657,7 +661,7 @@ export class AnalyticHandler {
|
||||
const returnIds: ICommonObject = {
|
||||
langSmith: {},
|
||||
langFuse: {},
|
||||
llmonitor: {}
|
||||
lunary: {}
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'langSmith')) {
|
||||
@@ -688,9 +692,9 @@ export class AnalyticHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'llmonitor')) {
|
||||
const monitor = this.handlers['llmonitor'].client
|
||||
const chainEventId: string = this.handlers['llmonitor'].chainEvent[parentIds['llmonitor'].chainEvent]
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'lunary')) {
|
||||
const monitor = this.handlers['lunary'].client
|
||||
const chainEventId: string = this.handlers['lunary'].chainEvent[parentIds['lunary'].chainEvent]
|
||||
|
||||
if (monitor && chainEventId) {
|
||||
const runId = uuidv4()
|
||||
@@ -701,8 +705,8 @@ export class AnalyticHandler {
|
||||
userId: this.options.chatId,
|
||||
input
|
||||
})
|
||||
this.handlers['llmonitor'].toolEvent = { [runId]: runId }
|
||||
returnIds['llmonitor'].toolEvent = runId
|
||||
this.handlers['lunary'].toolEvent = { [runId]: runId }
|
||||
returnIds['lunary'].toolEvent = runId
|
||||
}
|
||||
}
|
||||
|
||||
@@ -731,9 +735,9 @@ export class AnalyticHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'llmonitor')) {
|
||||
const toolEventId: string = this.handlers['llmonitor'].toolEvent[returnIds['llmonitor'].toolEvent]
|
||||
const monitor = this.handlers['llmonitor'].client
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'lunary')) {
|
||||
const toolEventId: string = this.handlers['lunary'].toolEvent[returnIds['lunary'].toolEvent]
|
||||
const monitor = this.handlers['lunary'].client
|
||||
|
||||
if (monitor && toolEventId) {
|
||||
await monitor.trackEvent('tool', 'end', {
|
||||
@@ -766,9 +770,9 @@ export class AnalyticHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'llmonitor')) {
|
||||
const toolEventId: string = this.handlers['llmonitor'].llmEvent[returnIds['llmonitor'].toolEvent]
|
||||
const monitor = this.handlers['llmonitor'].client
|
||||
if (Object.prototype.hasOwnProperty.call(this.handlers, 'lunary')) {
|
||||
const toolEventId: string = this.handlers['lunary'].llmEvent[returnIds['lunary'].toolEvent]
|
||||
const monitor = this.handlers['lunary'].client
|
||||
|
||||
if (monitor && toolEventId) {
|
||||
await monitor.trackEvent('tool', 'end', {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { DataSource } from 'typeorm'
|
||||
import { ICommonObject, IDatabaseEntity, IMessage, INodeData, IVariable } from './Interface'
|
||||
import { AES, enc } from 'crypto-js'
|
||||
import { ChatMessageHistory } from 'langchain/memory'
|
||||
import { AIMessage, HumanMessage, BaseMessage } from 'langchain/schema'
|
||||
import { AIMessage, HumanMessage, BaseMessage } from '@langchain/core/messages'
|
||||
|
||||
export const numberOrExpressionRegex = '^(\\d+\\.?\\d*|{{.*}})$' //return true if string consists only numbers OR expression {{}}
|
||||
export const notEmptyRegex = '(.|\\s)*\\S(.|\\s)*' //return true if string is not empty or blank
|
||||
@@ -49,7 +49,7 @@ export const availableDependencies = [
|
||||
'langfuse',
|
||||
'langsmith',
|
||||
'linkifyjs',
|
||||
'llmonitor',
|
||||
'lunary',
|
||||
'mammoth',
|
||||
'moment',
|
||||
'mongodb',
|
||||
|
||||
Reference in New Issue
Block a user