@statelyai/agent
Version:
Stateful agents that make decisions based on finite-state machine models
121 lines (115 loc) • 3.01 kB
text/typescript
import { assign, createActor, setup, log } from 'xstate';
import { getFromTerminal } from './helpers/helpers';
import { createAgent, fromDecision } from '../src';
import { z } from 'zod';
import { openai } from '@ai-sdk/openai';
const agent = createAgent({
name: 'verifier',
model: openai('gpt-3.5-turbo-16k-0613'),
events: {
'agent.validateAnswer': z.object({
isValid: z.boolean(),
feedback: z.string(),
}),
'agent.answerQuestion': z.object({
answer: z.string().describe('The answer from the agent'),
}),
'agent.validateQuestion': z.object({
isValid: z
.boolean()
.describe(
'Whether the question is a valid question; that is, is it possible to even answer this question in a verifiably correct way?'
),
explanation: z
.string()
.describe('An explanation for why the question is or is not valid'),
}),
},
});
const machine = setup({
types: {
context: {} as {
question: string | null;
answer: string | null;
validation: string | null;
},
events: agent.types.events,
},
actors: {
getFromTerminal,
agent: fromDecision(agent),
},
}).createMachine({
initial: 'askQuestion',
context: { question: null, answer: null, validation: null },
states: {
askQuestion: {
invoke: {
src: 'getFromTerminal',
input: 'Ask a (potentially silly) question',
onDone: {
actions: assign({
question: ({ event }) => event.output,
}),
target: 'validateQuestion',
},
},
},
validateQuestion: {
invoke: {
src: 'agent',
input: ({ context }) => ({
goal: `Validate this question: ${context.question!}`,
}),
},
on: {
'agent.validateQuestion': [
{
target: 'askQuestion',
guard: ({ event }) => !event.isValid,
actions: log(({ event }) => event.explanation),
},
{
target: 'answerQuestion',
},
],
},
},
answerQuestion: {
invoke: {
src: 'agent',
input: ({ context }) => ({
goal: `Answer this question: ${context.question}`,
}),
},
on: {
'agent.answerQuestion': {
actions: assign({
answer: ({ event }) => event.answer,
}),
target: 'validateAnswer',
},
},
},
validateAnswer: {
invoke: {
src: 'agent',
input: ({ context }) => ({
goal: `Validate if this is a good answer to the question: ${context.question}\nAnswer provided: ${context.answer}`,
}),
},
on: {
'agent.validateAnswer': {
actions: assign({
validation: ({ event }) => event.feedback,
}),
},
},
},
},
});
const actor = createActor(machine, {});
actor.subscribe((s) => {
console.log(s.value, s.context);
});
actor.start();