update autogpt
This commit is contained in:
parent
0423fc25ac
commit
a4f9b75d04
|
|
@ -2,8 +2,15 @@ import { INode, INodeData, INodeParams } from '../../../src/Interface'
|
|||
import { BaseChatModel } from 'langchain/chat_models/base'
|
||||
import { AutoGPT } from 'langchain/experimental/autogpt'
|
||||
import { Tool } from 'langchain/tools'
|
||||
import { AIMessage, HumanMessage, SystemMessage } from 'langchain/schema'
|
||||
import { VectorStoreRetriever } from 'langchain/vectorstores/base'
|
||||
import { flatten } from 'lodash'
|
||||
import { StructuredTool } from 'langchain/tools'
|
||||
import { LLMChain } from 'langchain/chains'
|
||||
import { PromptTemplate } from 'langchain/prompts'
|
||||
|
||||
type ObjectTool = StructuredTool
|
||||
const FINISH_NAME = 'finish'
|
||||
|
||||
class AutoGPT_Agents implements INode {
|
||||
label: string
|
||||
|
|
@ -88,13 +95,107 @@ class AutoGPT_Agents implements INode {
|
|||
|
||||
async run(nodeData: INodeData, input: string): Promise<string> {
|
||||
const executor = nodeData.instance as AutoGPT
|
||||
const model = nodeData.inputs?.model as BaseChatModel
|
||||
|
||||
try {
|
||||
let totalAssistantReply = ''
|
||||
executor.run = async (goals: string[]): Promise<string | undefined> => {
|
||||
const user_input = 'Determine which next command to use, and respond using the format specified above:'
|
||||
let loopCount = 0
|
||||
while (loopCount < executor.maxIterations) {
|
||||
loopCount += 1
|
||||
|
||||
const { text: assistantReply } = await executor.chain.call({
|
||||
goals,
|
||||
user_input,
|
||||
memory: executor.memory,
|
||||
messages: executor.fullMessageHistory
|
||||
})
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('\x1b[92m\x1b[1m\n*****AutoGPT*****\n\x1b[0m\x1b[0m')
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(assistantReply)
|
||||
totalAssistantReply += assistantReply + '\n'
|
||||
executor.fullMessageHistory.push(new HumanMessage(user_input))
|
||||
executor.fullMessageHistory.push(new AIMessage(assistantReply))
|
||||
|
||||
const action = await executor.outputParser.parse(assistantReply)
|
||||
const tools = executor.tools.reduce((acc, tool) => ({ ...acc, [tool.name]: tool }), {} as { [key: string]: ObjectTool })
|
||||
if (action.name === FINISH_NAME) {
|
||||
return action.args.response
|
||||
}
|
||||
let result: string
|
||||
if (action.name in tools) {
|
||||
const tool = tools[action.name]
|
||||
let observation
|
||||
try {
|
||||
observation = await tool.call(action.args)
|
||||
} catch (e) {
|
||||
observation = `Error in args: ${e}`
|
||||
}
|
||||
result = `Command ${tool.name} returned: ${observation}`
|
||||
} else if (action.name === 'ERROR') {
|
||||
result = `Error: ${action.args}. `
|
||||
} else {
|
||||
result = `Unknown command '${action.name}'. Please refer to the 'COMMANDS' list for available commands and only respond in the specified JSON format.`
|
||||
}
|
||||
|
||||
let memoryToAdd = `Assistant Reply: ${assistantReply}\nResult: ${result} `
|
||||
if (executor.feedbackTool) {
|
||||
const feedback = `\n${await executor.feedbackTool.call('Input: ')}`
|
||||
if (feedback === 'q' || feedback === 'stop') {
|
||||
return 'EXITING'
|
||||
}
|
||||
memoryToAdd += feedback
|
||||
}
|
||||
|
||||
const documents = await executor.textSplitter.createDocuments([memoryToAdd])
|
||||
await executor.memory.addDocuments(documents)
|
||||
executor.fullMessageHistory.push(new SystemMessage(result))
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
const res = await executor.run([input])
|
||||
return res || 'I have completed all my tasks.'
|
||||
|
||||
if (!res) {
|
||||
const sentence = `Unfortunately I was not able to complete all the task. Here is the chain of thoughts:`
|
||||
return `${await rephraseString(sentence, model)}\n\`\`\`javascript\n${totalAssistantReply}\n\`\`\`\n`
|
||||
}
|
||||
|
||||
const sentence = `I have completed all my tasks. Here is the chain of thoughts:`
|
||||
let writeFilePath = ''
|
||||
const writeTool = executor.tools.find((tool) => tool.name === 'write_file')
|
||||
if (executor.tools.length && writeTool) {
|
||||
writeFilePath = (writeTool as any).store.basePath
|
||||
}
|
||||
return `${await rephraseString(
|
||||
sentence,
|
||||
model
|
||||
)}\n\`\`\`javascript\n${totalAssistantReply}\n\`\`\`\nAnd the final result:\n\`\`\`javascript\n${res}\n\`\`\`\n${
|
||||
writeFilePath
|
||||
? await rephraseString(
|
||||
`You can download the final result displayed above, or see if a new file has been successfully written to \`${writeFilePath}\``,
|
||||
model
|
||||
)
|
||||
: ''
|
||||
}`
|
||||
} catch (e) {
|
||||
throw new Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const rephraseString = async (sentence: string, model: BaseChatModel) => {
|
||||
const promptTemplate = new PromptTemplate({
|
||||
template: 'You are a helpful Assistant that rephrase a sentence: {sentence}',
|
||||
inputVariables: ['sentence']
|
||||
})
|
||||
const chain = new LLMChain({ llm: model, prompt: promptTemplate })
|
||||
const res = await chain.call({ sentence })
|
||||
return res?.text
|
||||
}
|
||||
|
||||
module.exports = { nodeClass: AutoGPT_Agents }
|
||||
|
|
|
|||
|
|
@ -481,7 +481,7 @@ export const isStartNodeDependOnInput = (startingNodes: IReactFlowNode[], nodes:
|
|||
if (inputVariables.length > 0) return true
|
||||
}
|
||||
}
|
||||
const whitelistNodeNames = ['vectorStoreToDocument']
|
||||
const whitelistNodeNames = ['vectorStoreToDocument', 'autoGPT']
|
||||
for (const node of nodes) {
|
||||
if (whitelistNodeNames.includes(node.data.name)) return true
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue