@statelyai/agent
Version:
Stateful agents that make decisions based on finite-state machine models
101 lines (97 loc) • 2.58 kB
text/typescript
import { assign, createActor, log, setup } 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: 'tutor',
model: openai('gpt-4-1106-preview'),
events: {
teach: z.object({
instruction: z
.string()
.describe(
'The feedback to give the human, correcting any grammatical errors, misspellings, etc.'
),
}),
respond: z.object({
response: z.string().describe('The response to the human in Spanish'),
}),
},
system:
'You are an expert Spanish tutor. You will respond to the human in Spanish.',
});
const machine = setup({
types: {
context: {} as {
conversation: string[];
},
events: agent.types.events,
},
actors: { agent: fromDecision(agent), getFromTerminal },
}).createMachine({
initial: 'human',
context: {
conversation: [],
},
states: {
human: {
invoke: {
src: 'getFromTerminal',
input: 'Say something in Spanish:',
onDone: {
actions: assign({
conversation: (x) =>
x.context.conversation.concat(`User: ` + x.event.output),
}),
target: 'ai',
},
},
},
ai: {
initial: 'teaching',
states: {
teaching: {
invoke: {
src: 'agent',
input: (x) => ({
context: true,
goal: 'Give brief feedback to the human based on the most recent response of the conversation',
maxTokens: 100,
}),
},
on: {
teach: {
actions: (x) => console.log(x.event.instruction),
target: 'responding',
},
},
},
responding: {
invoke: {
src: 'agent',
input: (x) => ({
context: true,
goal: 'Respond to the last message of the conversation in Spanish',
}),
},
on: {
respond: {
actions: [
assign({
conversation: (x) =>
x.context.conversation.concat(`Agent: ` + x.event.response),
}),
log((x) => x.event.response),
],
target: 'done',
},
},
},
done: { type: 'final' },
},
onDone: { target: 'human' },
},
},
});
createActor(machine).start();