Wenn Sie "Interrupt" verwendet, gefolgt von 'neuJavaScript

Javascript-Forum
Anonymous
 Wenn Sie "Interrupt" verwendet, gefolgt von 'neu

Post by Anonymous »

Wenn ich ein Diagramm aufreiche, das Interrupt s in einem seiner Knoten enthält, scheint es mit dem folgenden Fehler in einen ungültigen/nicht wiederbeschreibbaren Zustand zu geraten:

Code: Select all

        return chatGeneration.message;
^

TypeError: Cannot read properties of undefined (reading 'message')
at ChatOpenAI.invoke (file:///Users/user/code/lgdemo//node_modules/@langchain/core/dist/language_models/chat_models.js:64:31)
Die erste Begegnung des Interrupt scheint gut zu laufen, aber nach der zweiten Begegnung tritt dies auf. />
  • Wenn der Benutzer mit y antwortet, fährt er zu dem ToolsNode , den der AgentNode angefordert hat. End ,
    Der nachfolgende Aufruf von Graph.invoke Ergebnisse in diesem Fehler. angefordert. (Wie zuvor)
  • Wenn der Benutzer mit etwas anderem reagiert (z. B. n ), fährt er zu AgentNode zurück. (Dies hat sich geändert)
(und ich ändere den Hauptdiagramm entsprechend, um diesen aktualisierten Fluss widerzuspiegeln)
Dies führt jedoch zu dem gleichen Fehler wie oben, nur dass es nach dem ersten Interrupt statt der zweiten Interrupt . Der Workflow habe ich gültig definiert? Gibt es einen besseren Weg, um es zu strukturieren? />[*]https://langchain-ai.github.io/langgrap ... -or-reject
https /> < /ul>

Hauptdiagramm: < /p>

Code: Select all

const workflow = new StateGraph(MessagesAnnotation)
.addNode('agent', agentNode)
.addNode('tools', toolsNode)
.addNode('approve', approveNode, {
ends: ['tools', END],
})
.addEdge(START, 'agent')
.addEdge('tools', 'agent')
.addConditionalEdges('agent', agentRouter, ['approve', END]);
const checkpointer = new MemorySaver();
const graph = workflow.compile({
checkpointer,
});
const graphConfig = {
configurable: { thread_id: '0x0004' },
};
< /code>
Tools, Knoten und Router: < /p>
const cmdFooTool = tool(async function(inputs) {
console.log('===TOOL CMD_FOO===');
return inputs.name;
}, {
name: 'CMD_FOO',
description: 'Invoke when you want to do a Foo.',
schema: z.object({
name: z.string('Any string'),
}),
});
const cmdBarTool = tool(async function(inputs) {
console.log('===TOOL QRY_BAR===');
return inputs.name;
}, {
name: 'QRY_BAR',
description: 'Invoke when you want to query a Bar.',
schema: z.object({
name: z.string('Any string'),
}),
});
const tools = [cmdFooTool, cmdBarTool];
const llmWithTools = llm.bindTools(tools);

const toolsNode = new ToolNode(tools);

async function agentNode(state) {
console.log('===AGENT NODE===');
const response = await llmWithTools.invoke(state.messages);
console.log('=RESPONSE=',
'\ncontent:', response.content,
'\ntool_calls:', response.tool_calls.map((toolCall) => (toolCall.name)));
return { messages: [response] };
}

async function approveNode (state) {
console.log('===APPROVE NODE===');
const lastMsg = state.messages.at(-1);
const toolCall = lastMsg.tool_calls.at(-1);

const interruptMessage = `Please review the following tool invocation:
${toolCall.name} with inputs ${JSON.stringify(toolCall.args, undefined, 2)}
Do you approve (y/N)`;

console.log('=INTERRUPT PRE=');
const interruptResponse = interrupt(interruptMessage);
console.log('=INTERRUPT POST=');

const isApproved = (interruptResponse.trim().charAt(0).toLowerCase() === 'y');
const goto = (isApproved) ? 'tools' : END;
console.log('=RESULT=\n', { isApproved, goto });
return new Command({ goto });
}

function hasToolCalls(message) {
return message?.tool_calls?.length >  0;
}

async function agentRouter (state) {
const lastMsg = state.messages.at(-1);
if (hasToolCalls(lastMsg)) {
return 'approve';
}
return END;
}
< /code>
Simulieren Sie einen Lauf: < /p>
let state;
let agentResult;
let inputText;
let invokeWith;

// step 1: prompt
inputText = 'Pls perform a Foo with name "ASDF".';
console.log('===HUMAN PROMPT===\n', inputText);
invokeWith = { messages: [new HumanMessage(inputText)] };
agentResult = await graph.invoke(invokeWith, graphConfig);

state = await graph.getState(graphConfig);
console.log('===STATE NEXT===\n', state.next);
console.log('=LAST MSG=\n', agentResult.messages.at(-1).content);
console.log('=LAST TOOL CALLS=\n', agentResult.messages.at(-1).tool_calls);

// step 2: interrupted in the 'approve' node, human in the loop authorises
inputText = 'yes'
console.log('===HUMAN INTERRUPT RESPONSE===\n', inputText);
invokeWith = new Command({ resume: inputText });
agentResult = await graph.invoke(invokeWith, graphConfig);

state = await graph.getState(graphConfig);
console.log('===STATE NEXT===\n', state.next);
console.log('=LAST MSG=\n', agentResult.messages.at(-1).content);
console.log('=LAST TOOL CALLS=\n', agentResult.messages.at(-1).tool_calls);

// step 3: prompt
inputText = 'Pls perform a Foo with name "ZXCV".';
console.log('===HUMAN PROMPT===\n', inputText);
invokeWith = { messages: [new HumanMessage(inputText)] };
agentResult = await graph.invoke(invokeWith, graphConfig);

state = await graph.getState(graphConfig);
console.log('===STATE NEXT===\n', state.next);
console.log('=LAST MSG=\n', agentResult.messages.at(-1).content);
console.log('=LAST TOOL CALLS=\n', agentResult.messages.at(-1).tool_calls);

// step 4: interrupted in the 'approve' node, human in the loop does not authorise
inputText = 'no';
console.log('===HUMAN INTERRUPT RESPONSE===\n', inputText);
invokeWith = new Command({ resume: inputText });
agentResult = await graph.invoke(invokeWith, graphConfig);

state = await graph.getState(graphConfig);
console.log('===STATE NEXT===\n', state.next);
console.log('=LAST MSG=\n', agentResult.messages.at(-1).content);
console.log('=LAST TOOL CALLS=\n', agentResult.messages.at(-1).tool_calls);

// step 5: prompt
inputText = 'Pls perform a Foo with name "GHJK".';
console.log('===HUMAN PROMPT===\n', inputText);
invokeWith = { messages: [new HumanMessage(inputText)] };
agentResult = await graph.invoke(invokeWith, graphConfig);

state = await graph.getState(graphConfig);
console.log('===STATE NEXT===\n', state.next);
console.log('=LAST MSG=\n', agentResult.messages.at(-1).content);
console.log('=LAST TOOL CALLS=\n', agentResult.messages.at(-1).tool_calls);

< /code>
Vollständige Ausgabe: < /p>
===HUMAN PROMPT===
Pls perform a Foo with name "ASDF".
===AGENT NODE===
(node:58990) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
=RESPONSE=
content:
tool_calls: [ 'CMD_FOO' ]
===APPROVE NODE===
=INTERRUPT PRE=
===STATE NEXT===
[ 'approve' ]
=LAST MSG=

=LAST TOOL CALLS=
[
{
name: 'CMD_FOO',
args: { name: 'ASDF' },
type: 'tool_call',
id: 'call_u7CIyWdTesFATZ5bGG2uaVUZ'
}
]
===HUMAN INTERRUPT RESPONSE===
yes
===APPROVE NODE===
=INTERRUPT PRE=
=INTERRUPT POST=
=RESULT=
{ isApproved: true, goto: 'tools' }
===TOOL CMD_FOO===
===AGENT NODE===
=RESPONSE=
content: The Foo operation has been performed with the name "ASDF".
tool_calls: []
===STATE NEXT===
[]
=LAST MSG=
The Foo operation has been performed with the name "ASDF".
=LAST TOOL CALLS=
[]
===HUMAN PROMPT===
Pls perform a Foo with name "ZXCV".
===AGENT NODE===
=RESPONSE=
content:
tool_calls: [ 'CMD_FOO' ]
===APPROVE NODE===
=INTERRUPT PRE=
===STATE NEXT===
[ 'approve' ]
=LAST MSG=

=LAST TOOL CALLS=
[
{
name: 'CMD_FOO',
args: { name: 'ZXCV' },
type: 'tool_call',
id: 'call_kKF91c8G6enWwlrLFON8TYLJ'
}
]
===HUMAN INTERRUPT RESPONSE===
no
===APPROVE NODE===
=INTERRUPT PRE=
=INTERRUPT POST=
=RESULT=
{ isApproved: false, goto: '__end__' }
===STATE NEXT===
[]
=LAST MSG=

=LAST TOOL CALLS=
[
{
name: 'CMD_FOO',
args: { name: 'ZXCV' },
type: 'tool_call',
id: 'call_kKF91c8G6enWwlrLFON8TYLJ'
}
]
===HUMAN PROMPT===
Pls perform a Foo with name "GHJK".
===AGENT NODE===
file:///Users/user/code/lgdemo/node_modules/@langchain/core/dist/language_models/chat_models.js:64
return chatGeneration.message;
^

TypeError: Cannot read properties of undefined (reading 'message')
at ChatOpenAI.invoke (file:///Users/user/code/lgdemo//node_modules/@langchain/core/dist/language_models/chat_models.js:64:31)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async RunnableCallable.agentNode [as func] (file:///Users/user/code/lgdemo//test.js:51:20)
at async RunnableCallable.invoke (file:///Users/user/code/lgdemo//node_modules/@langchain/langgraph/dist/utils.js:79:27)
at async RunnableSequence.invoke (file:///Users/user/code/lgdemo//node_modules/@langchain/core/dist/runnables/base.js:1274:33)
at async _runWithRetry (file:///Users/user/code/lgdemo//node_modules/@langchain/langgraph/dist/pregel/retry.js:67:22)
at async PregelRunner._executeTasksWithRetry (file:///Users/user/code/lgdemo//node_modules/@langchain/langgraph/dist/pregel/runner.js:217:33)
at async PregelRunner.tick (file:///Users/user/code/lgdemo//node_modules/@langchain/langgraph/dist/pregel/runner.js:45:40)
at async CompiledStateGraph._runLoop (file:///Users/user/code/lgdemo//node_modules/@langchain/langgraph/dist/pregel/index.js:1296:17)
at async createAndRunLoop (file:///Users/user/code/lgdemo//node_modules/@langchain/langgraph/dist/pregel/index.js:1195:17) {
pregelTaskId: '7bd60c12-4beb-54b7-85a7-9bc1461600f5'
}

Node.js v23.3.0

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post