Feature/Code Interpreter (#3183)

* Base changes for ServerSide Events (instead of socket.io)

* lint fixes

* adding of interface and separate methods for streaming events

* lint

* first draft, handles both internal and external prediction end points.

* lint fixes

* additional internal end point for streaming and associated changes

* return streamresponse as true to build agent flow

* 1) JSON formatting for internal events
2) other fixes

* 1) convert internal event to metadata to maintain consistency with external response

* fix action and metadata streaming

* fix for error when agent flow is aborted

* prevent subflows from streaming and other code cleanup

* prevent streaming from enclosed tools

* add fix for preventing chaintool streaming

* update lock file

* add open when hidden to sse

* Streaming errors

* Streaming errors

* add fix for showing error message

* add code interpreter

* add artifacts to view message dialog

* Update pnpm-lock.yaml

---------

Co-authored-by: Vinod Paidimarry <vinodkiran@outlook.in>
This commit is contained in:
Henry Heng
2024-09-17 08:44:56 +01:00
committed by GitHub
parent 26444ac3ae
commit b02f279e9d
21 changed files with 729 additions and 333 deletions
+1 -1
View File
@@ -415,7 +415,7 @@ export interface IServerSideEventStreamer {
streamAgentReasoningEvent(chatId: string, data: any): void
streamNextAgentEvent(chatId: string, data: any): void
streamActionEvent(chatId: string, data: any): void
streamArtifactsEvent(chatId: string, data: any): void
streamAbortEvent(chatId: string): void
streamEndEvent(chatId: string): void
}
+26 -4
View File
@@ -26,6 +26,8 @@ import { formatLogToString } from 'langchain/agents/format_scratchpad/log'
import { IUsedTool } from './Interface'
export const SOURCE_DOCUMENTS_PREFIX = '\n\n----FLOWISE_SOURCE_DOCUMENTS----\n\n'
export const ARTIFACTS_PREFIX = '\n\n----FLOWISE_ARTIFACTS----\n\n'
export type AgentFinish = {
returnValues: Record<string, any>
log: string
@@ -345,12 +347,14 @@ export class AgentExecutor extends BaseChain<ChainValues, AgentExecutorOutput> {
let iterations = 0
let sourceDocuments: Array<Document> = []
const usedTools: IUsedTool[] = []
let artifacts: any[] = []
const getOutput = async (finishStep: AgentFinish): Promise<AgentExecutorOutput> => {
const { returnValues } = finishStep
const additional = await this.agent.prepareForOutput(returnValues, steps)
if (sourceDocuments.length) additional.sourceDocuments = flatten(sourceDocuments)
if (usedTools.length) additional.usedTools = usedTools
if (artifacts.length) additional.artifacts = flatten(artifacts)
if (this.returnIntermediateSteps) {
return { ...returnValues, intermediateSteps: steps, ...additional }
}
@@ -426,13 +430,17 @@ export class AgentExecutor extends BaseChain<ChainValues, AgentExecutorOutput> {
state: inputs
}
)
let toolOutput = observation
if (typeof toolOutput === 'string' && toolOutput.includes(SOURCE_DOCUMENTS_PREFIX)) {
toolOutput = toolOutput.split(SOURCE_DOCUMENTS_PREFIX)[0]
}
if (typeof toolOutput === 'string' && toolOutput.includes(ARTIFACTS_PREFIX)) {
toolOutput = toolOutput.split(ARTIFACTS_PREFIX)[0]
}
usedTools.push({
tool: tool.name,
toolInput: action.toolInput as any,
toolOutput:
typeof observation === 'string' && observation.includes(SOURCE_DOCUMENTS_PREFIX)
? observation.split(SOURCE_DOCUMENTS_PREFIX)[0]
: observation
toolOutput
})
} else {
observation = `${action.tool} is not a valid tool, try another one.`
@@ -463,6 +471,16 @@ export class AgentExecutor extends BaseChain<ChainValues, AgentExecutorOutput> {
console.error('Error parsing source documents from tool')
}
}
if (typeof observation === 'string' && observation.includes(ARTIFACTS_PREFIX)) {
const observationArray = observation.split(ARTIFACTS_PREFIX)
observation = observationArray[0]
try {
const artifact = JSON.parse(observationArray[1])
artifacts.push(artifact)
} catch (e) {
console.error('Error parsing source documents from tool')
}
}
return { action, observation: observation ?? '' }
})
)
@@ -566,6 +584,10 @@ export class AgentExecutor extends BaseChain<ChainValues, AgentExecutorOutput> {
const observationArray = observation.split(SOURCE_DOCUMENTS_PREFIX)
observation = observationArray[0]
}
if (typeof observation === 'string' && observation.includes(ARTIFACTS_PREFIX)) {
const observationArray = observation.split(ARTIFACTS_PREFIX)
observation = observationArray[0]
}
} catch (e) {
if (e instanceof ToolInputParsingException) {
if (this.handleParsingErrors === true) {