@statelyai/agent 0.0.7 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/launch.json +12 -1
- package/CHANGELOG.md +47 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +282 -71
- package/dist/index.js +4389 -183
- package/dist/index.mjs +7 -0
- package/examples/chatbot.ts +79 -0
- package/examples/cot.ts +91 -0
- package/examples/email.ts +118 -0
- package/examples/example.ts +81 -0
- package/examples/goal.ts +94 -0
- package/examples/joke.ts +117 -110
- package/examples/multi.ts +103 -0
- package/examples/newspaper.ts +324 -0
- package/examples/number.ts +102 -0
- package/examples/raffle.ts +105 -0
- package/examples/simple.ts +39 -0
- package/examples/support.ts +147 -0
- package/examples/ticTacToe.ts +89 -124
- package/examples/todo.ts +132 -0
- package/examples/tutor.ts +100 -0
- package/examples/verify.ts +120 -0
- package/examples/weather.ts +65 -47
- package/examples/wiki.ts +30 -0
- package/examples/word.ts +168 -0
- package/package.json +18 -11
- package/readme.md +9 -38
- package/src/adapters/vercel.ts +7 -0
- package/src/agent-experimental.ts +221 -0
- package/src/agent.test.ts +187 -0
- package/src/agent.ts +260 -6
- package/src/decision.test.ts +179 -0
- package/src/decision.ts +83 -0
- package/src/index.ts +3 -2
- package/src/memory.ts +25 -0
- package/src/planners/shortestPathPlanner.ts +22 -0
- package/src/planners/simplePlanner.ts +126 -0
- package/src/schemas.ts +13 -38
- package/src/strategies/chain-of-note.ts +155 -0
- package/src/templates/defaultText.ts +18 -0
- package/src/templates/defaultToolCall.ts +10 -0
- package/src/text.ts +232 -0
- package/src/types.ts +363 -46
- package/src/utils.ts +13 -50
- package/tsconfig.json +1 -1
- package/examples/multiAgentCollaboration.ts +0 -0
- package/examples/numberGuesser.ts +0 -128
- package/examples/wordGuesser.ts +0 -156
- package/src/adapter.test.ts +0 -217
- package/src/adapters/openai.ts +0 -298
package/examples/todo.ts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { assign, setup, assertEvent, createActor, createMachine } from 'xstate';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { createAgent, fromDecision } from '../src';
|
|
4
|
+
import { openai } from '@ai-sdk/openai';
|
|
5
|
+
import { getFromTerminal } from './helpers/helpers';
|
|
6
|
+
|
|
7
|
+
const agent = createAgent({
|
|
8
|
+
name: 'todo',
|
|
9
|
+
model: openai('gpt-4o'),
|
|
10
|
+
events: {
|
|
11
|
+
addTodo: z.object({
|
|
12
|
+
message: z.string().min(1).max(100).describe('The message of the todo'),
|
|
13
|
+
}),
|
|
14
|
+
deleteTodo: z.object({
|
|
15
|
+
index: z.number().describe('The index of the todo to delete'),
|
|
16
|
+
}),
|
|
17
|
+
toggleTodo: z
|
|
18
|
+
.object({
|
|
19
|
+
index: z.number().describe('The index of the todo to toggle'),
|
|
20
|
+
})
|
|
21
|
+
.describe('Toggle whether the todo item is done or not'),
|
|
22
|
+
doNothing: z.object({}).describe('Do nothing'),
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
interface Todo {
|
|
27
|
+
message: string;
|
|
28
|
+
done: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const machine = setup({
|
|
32
|
+
types: {
|
|
33
|
+
context: {} as {
|
|
34
|
+
todos: Todo[];
|
|
35
|
+
command: string | null;
|
|
36
|
+
},
|
|
37
|
+
events: {} as typeof agent.eventTypes | { type: 'assist'; command: string },
|
|
38
|
+
},
|
|
39
|
+
actors: { agent: fromDecision(agent), getFromTerminal },
|
|
40
|
+
}).createMachine({
|
|
41
|
+
context: {
|
|
42
|
+
command: null,
|
|
43
|
+
todos: [],
|
|
44
|
+
},
|
|
45
|
+
on: {
|
|
46
|
+
addTodo: {
|
|
47
|
+
actions: assign({
|
|
48
|
+
todos: ({ context, event }) => [
|
|
49
|
+
...context.todos,
|
|
50
|
+
{
|
|
51
|
+
message: event.message,
|
|
52
|
+
done: false,
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
command: null,
|
|
56
|
+
}),
|
|
57
|
+
target: '.idle',
|
|
58
|
+
},
|
|
59
|
+
deleteTodo: {
|
|
60
|
+
actions: assign({
|
|
61
|
+
todos: ({ context, event }) => {
|
|
62
|
+
const todos = [...context.todos];
|
|
63
|
+
todos.splice(event.index, 1);
|
|
64
|
+
return todos;
|
|
65
|
+
},
|
|
66
|
+
command: null,
|
|
67
|
+
}),
|
|
68
|
+
target: '.idle',
|
|
69
|
+
},
|
|
70
|
+
toggleTodo: {
|
|
71
|
+
actions: assign({
|
|
72
|
+
todos: ({ context, event }) => {
|
|
73
|
+
const todos = context.todos.map((todo, i) => {
|
|
74
|
+
if (i === event.index) {
|
|
75
|
+
return {
|
|
76
|
+
...todo,
|
|
77
|
+
done: !todo.done,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return todo;
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return todos;
|
|
84
|
+
},
|
|
85
|
+
command: null,
|
|
86
|
+
}),
|
|
87
|
+
target: '.idle',
|
|
88
|
+
},
|
|
89
|
+
doNothing: { target: '.idle' },
|
|
90
|
+
},
|
|
91
|
+
initial: 'idle',
|
|
92
|
+
states: {
|
|
93
|
+
idle: {
|
|
94
|
+
invoke: {
|
|
95
|
+
src: 'getFromTerminal',
|
|
96
|
+
input: '\nEnter a command:',
|
|
97
|
+
onDone: {
|
|
98
|
+
actions: assign({
|
|
99
|
+
command: ({ event }) => event.output,
|
|
100
|
+
}),
|
|
101
|
+
target: 'assisting',
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
on: {
|
|
105
|
+
assist: {
|
|
106
|
+
target: 'assisting',
|
|
107
|
+
actions: assign({
|
|
108
|
+
command: ({ event }) => event.command,
|
|
109
|
+
}),
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
assisting: {
|
|
114
|
+
invoke: {
|
|
115
|
+
src: 'agent',
|
|
116
|
+
input: (x) => ({
|
|
117
|
+
context: {
|
|
118
|
+
command: x.context.command,
|
|
119
|
+
todos: x.context.todos,
|
|
120
|
+
},
|
|
121
|
+
goal: 'Interpret the command as an action for this todo list; for example, "I need donuts" would add a todo item with the message "Get donuts".',
|
|
122
|
+
}),
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const actor = createActor(machine);
|
|
129
|
+
actor.subscribe((s) => {
|
|
130
|
+
console.log(s.context.todos);
|
|
131
|
+
});
|
|
132
|
+
actor.start();
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { assign, createActor, log, setup } from 'xstate';
|
|
2
|
+
import { getFromTerminal } from './helpers/helpers';
|
|
3
|
+
import { createAgent, fromDecision } from '../src';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { openai } from '@ai-sdk/openai';
|
|
6
|
+
|
|
7
|
+
const agent = createAgent({
|
|
8
|
+
name: 'tutor',
|
|
9
|
+
model: openai('gpt-4-1106-preview'),
|
|
10
|
+
events: {
|
|
11
|
+
teach: z.object({
|
|
12
|
+
instruction: z
|
|
13
|
+
.string()
|
|
14
|
+
.describe(
|
|
15
|
+
'The feedback to give the human, correcting any grammatical errors, misspellings, etc.'
|
|
16
|
+
),
|
|
17
|
+
}),
|
|
18
|
+
respond: z.object({
|
|
19
|
+
response: z.string().describe('The response to the human in Spanish'),
|
|
20
|
+
}),
|
|
21
|
+
},
|
|
22
|
+
system:
|
|
23
|
+
'You are an expert Spanish tutor. You will respond to the human in Spanish.',
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const machine = setup({
|
|
27
|
+
types: {
|
|
28
|
+
context: {} as {
|
|
29
|
+
conversation: string[];
|
|
30
|
+
},
|
|
31
|
+
events: agent.eventTypes,
|
|
32
|
+
},
|
|
33
|
+
actors: { agent: fromDecision(agent), getFromTerminal },
|
|
34
|
+
}).createMachine({
|
|
35
|
+
initial: 'human',
|
|
36
|
+
context: {
|
|
37
|
+
conversation: [],
|
|
38
|
+
},
|
|
39
|
+
states: {
|
|
40
|
+
human: {
|
|
41
|
+
invoke: {
|
|
42
|
+
src: 'getFromTerminal',
|
|
43
|
+
input: 'Say something in Spanish:',
|
|
44
|
+
onDone: {
|
|
45
|
+
actions: assign({
|
|
46
|
+
conversation: (x) =>
|
|
47
|
+
x.context.conversation.concat(`User: ` + x.event.output),
|
|
48
|
+
}),
|
|
49
|
+
target: 'ai',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
ai: {
|
|
54
|
+
initial: 'teaching',
|
|
55
|
+
states: {
|
|
56
|
+
teaching: {
|
|
57
|
+
invoke: {
|
|
58
|
+
src: 'agent',
|
|
59
|
+
input: (x) => ({
|
|
60
|
+
context: true,
|
|
61
|
+
goal: 'Give brief feedback to the human based on the most recent response of the conversation',
|
|
62
|
+
maxTokens: 100,
|
|
63
|
+
}),
|
|
64
|
+
},
|
|
65
|
+
on: {
|
|
66
|
+
teach: {
|
|
67
|
+
actions: (x) => console.log(x.event.instruction),
|
|
68
|
+
target: 'responding',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
responding: {
|
|
73
|
+
invoke: {
|
|
74
|
+
src: 'agent',
|
|
75
|
+
input: (x) => ({
|
|
76
|
+
context: true,
|
|
77
|
+
goal: 'Respond to the last message of the conversation in Spanish',
|
|
78
|
+
}),
|
|
79
|
+
},
|
|
80
|
+
on: {
|
|
81
|
+
respond: {
|
|
82
|
+
actions: [
|
|
83
|
+
assign({
|
|
84
|
+
conversation: (x) =>
|
|
85
|
+
x.context.conversation.concat(`Agent: ` + x.event.response),
|
|
86
|
+
}),
|
|
87
|
+
log((x) => x.event.response),
|
|
88
|
+
],
|
|
89
|
+
target: 'done',
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
done: { type: 'final' },
|
|
94
|
+
},
|
|
95
|
+
onDone: { target: 'human' },
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
createActor(machine).start();
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { assign, createActor, setup, log } from 'xstate';
|
|
2
|
+
import { getFromTerminal } from './helpers/helpers';
|
|
3
|
+
import { createAgent, fromDecision } from '../src';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { openai } from '@ai-sdk/openai';
|
|
6
|
+
|
|
7
|
+
const agent = createAgent({
|
|
8
|
+
name: 'verifier',
|
|
9
|
+
model: openai('gpt-3.5-turbo-16k-0613'),
|
|
10
|
+
events: {
|
|
11
|
+
'agent.validateAnswer': z.object({
|
|
12
|
+
isValid: z.boolean(),
|
|
13
|
+
feedback: z.string(),
|
|
14
|
+
}),
|
|
15
|
+
'agent.answerQuestion': z.object({
|
|
16
|
+
answer: z.string().describe('The answer from the agent'),
|
|
17
|
+
}),
|
|
18
|
+
'agent.validateQuestion': z.object({
|
|
19
|
+
isValid: z
|
|
20
|
+
.boolean()
|
|
21
|
+
.describe(
|
|
22
|
+
'Whether the question is a valid question; that is, is it possible to even answer this question in a verifiably correct way?'
|
|
23
|
+
),
|
|
24
|
+
explanation: z
|
|
25
|
+
.string()
|
|
26
|
+
.describe('An explanation for why the question is or is not valid'),
|
|
27
|
+
}),
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const machine = setup({
|
|
32
|
+
types: {
|
|
33
|
+
context: {} as {
|
|
34
|
+
question: string | null;
|
|
35
|
+
answer: string | null;
|
|
36
|
+
validation: string | null;
|
|
37
|
+
},
|
|
38
|
+
events: agent.eventTypes,
|
|
39
|
+
},
|
|
40
|
+
actors: {
|
|
41
|
+
getFromTerminal,
|
|
42
|
+
agent: fromDecision(agent),
|
|
43
|
+
},
|
|
44
|
+
}).createMachine({
|
|
45
|
+
initial: 'askQuestion',
|
|
46
|
+
context: { question: null, answer: null, validation: null },
|
|
47
|
+
states: {
|
|
48
|
+
askQuestion: {
|
|
49
|
+
invoke: {
|
|
50
|
+
src: 'getFromTerminal',
|
|
51
|
+
input: 'Ask a (potentially silly) question',
|
|
52
|
+
onDone: {
|
|
53
|
+
actions: assign({
|
|
54
|
+
question: ({ event }) => event.output,
|
|
55
|
+
}),
|
|
56
|
+
target: 'validateQuestion',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
validateQuestion: {
|
|
61
|
+
invoke: {
|
|
62
|
+
src: 'agent',
|
|
63
|
+
input: ({ context }) => ({
|
|
64
|
+
goal: `Validate this question: ${context.question!}`,
|
|
65
|
+
}),
|
|
66
|
+
},
|
|
67
|
+
on: {
|
|
68
|
+
'agent.validateQuestion': [
|
|
69
|
+
{
|
|
70
|
+
target: 'askQuestion',
|
|
71
|
+
guard: ({ event }) => !event.isValid,
|
|
72
|
+
actions: log(({ event }) => event.explanation),
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
target: 'answerQuestion',
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
answerQuestion: {
|
|
81
|
+
invoke: {
|
|
82
|
+
src: 'agent',
|
|
83
|
+
input: ({ context }) => ({
|
|
84
|
+
goal: `Answer this question: ${context.question}`,
|
|
85
|
+
}),
|
|
86
|
+
},
|
|
87
|
+
on: {
|
|
88
|
+
'agent.answerQuestion': {
|
|
89
|
+
actions: assign({
|
|
90
|
+
answer: ({ event }) => event.answer,
|
|
91
|
+
}),
|
|
92
|
+
target: 'validateAnswer',
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
validateAnswer: {
|
|
97
|
+
invoke: {
|
|
98
|
+
src: 'agent',
|
|
99
|
+
input: ({ context }) => ({
|
|
100
|
+
goal: `Validate if this is a good answer to the question: ${context.question}\nAnswer provided: ${context.answer}`,
|
|
101
|
+
}),
|
|
102
|
+
},
|
|
103
|
+
on: {
|
|
104
|
+
'agent.validateAnswer': {
|
|
105
|
+
actions: assign({
|
|
106
|
+
validation: ({ event }) => event.feedback,
|
|
107
|
+
}),
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const actor = createActor(machine, {});
|
|
115
|
+
|
|
116
|
+
actor.subscribe((s) => {
|
|
117
|
+
console.log(s.value, s.context);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
actor.start();
|
package/examples/weather.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { assign, fromPromise, log, setup } from 'xstate';
|
|
1
|
+
import { createAgent, fromDecision } from '../src';
|
|
2
|
+
import { assign, createActor, fromPromise, log, setup } from 'xstate';
|
|
4
3
|
import { getFromTerminal } from './helpers/helpers';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { openai } from '@ai-sdk/openai';
|
|
5
6
|
|
|
6
7
|
async function searchTavily(
|
|
7
8
|
input: string,
|
|
@@ -36,38 +37,6 @@ async function searchTavily(
|
|
|
36
37
|
return JSON.stringify(json.results);
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
const openai = new OpenAI({
|
|
40
|
-
apiKey: process.env.OPENAI_API_KEY,
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
const schemas = createSchemas({
|
|
44
|
-
context: {
|
|
45
|
-
location: { type: 'string' },
|
|
46
|
-
history: { type: 'array', items: { type: 'string' } },
|
|
47
|
-
count: { type: 'number' },
|
|
48
|
-
},
|
|
49
|
-
events: {
|
|
50
|
-
getWeather: {
|
|
51
|
-
description: 'Get the weather for a location',
|
|
52
|
-
properties: {
|
|
53
|
-
location: {
|
|
54
|
-
type: 'string',
|
|
55
|
-
description: 'The location to get the weather for',
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
doSomethingElse: {
|
|
60
|
-
description:
|
|
61
|
-
'Do something else, because the user did not provide a location',
|
|
62
|
-
properties: {},
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
const adapter = createOpenAIAdapter(openai, {
|
|
68
|
-
model: 'gpt-4-1106-preview',
|
|
69
|
-
});
|
|
70
|
-
|
|
71
40
|
const getWeather = fromPromise(async ({ input }: { input: string }) => {
|
|
72
41
|
const results = await searchTavily(
|
|
73
42
|
`Get the weather for this location: ${input}`,
|
|
@@ -79,15 +48,41 @@ const getWeather = fromPromise(async ({ input }: { input: string }) => {
|
|
|
79
48
|
return results;
|
|
80
49
|
});
|
|
81
50
|
|
|
51
|
+
const agent = createAgent({
|
|
52
|
+
name: 'weather',
|
|
53
|
+
model: openai('gpt-4-1106-preview'),
|
|
54
|
+
events: {
|
|
55
|
+
'agent.getWeather': z.object({
|
|
56
|
+
location: z.string().describe('The location to get the weather for'),
|
|
57
|
+
}),
|
|
58
|
+
'agent.reportWeather': z.object({
|
|
59
|
+
location: z
|
|
60
|
+
.string()
|
|
61
|
+
.describe('The location the weather is being reported for'),
|
|
62
|
+
highF: z.number().describe('The high temperature today in Fahrenheit'),
|
|
63
|
+
lowF: z.number().describe('The low temperature today in Fahrenheit'),
|
|
64
|
+
summary: z.string().describe('A summary of the weather conditions'),
|
|
65
|
+
}),
|
|
66
|
+
'agent.doSomethingElse': z
|
|
67
|
+
.object({})
|
|
68
|
+
.describe(
|
|
69
|
+
'Do something else, because the user did not provide a location'
|
|
70
|
+
),
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
82
74
|
const machine = setup({
|
|
83
|
-
|
|
84
|
-
|
|
75
|
+
types: {
|
|
76
|
+
context: {} as {
|
|
77
|
+
location: string;
|
|
78
|
+
history: string[];
|
|
79
|
+
count: number;
|
|
80
|
+
},
|
|
81
|
+
events: agent.eventTypes,
|
|
82
|
+
},
|
|
85
83
|
actors: {
|
|
84
|
+
agent: fromDecision(agent),
|
|
86
85
|
getWeather,
|
|
87
|
-
decide: adapter.fromEvent(
|
|
88
|
-
(input: string) =>
|
|
89
|
-
`Decide what to do based on the given input, which may or may not be a location: ${input}`
|
|
90
|
-
),
|
|
91
86
|
getFromTerminal,
|
|
92
87
|
},
|
|
93
88
|
}).createMachine({
|
|
@@ -117,15 +112,20 @@ const machine = setup({
|
|
|
117
112
|
decide: {
|
|
118
113
|
entry: log('Deciding...'),
|
|
119
114
|
invoke: {
|
|
120
|
-
src: '
|
|
121
|
-
input: ({ context }) =>
|
|
115
|
+
src: 'agent',
|
|
116
|
+
input: ({ context }) => ({
|
|
117
|
+
context: {
|
|
118
|
+
location: context.location,
|
|
119
|
+
},
|
|
120
|
+
goal: `Decide what to do based on the given location, which may or may not be a location`,
|
|
121
|
+
}),
|
|
122
122
|
},
|
|
123
123
|
on: {
|
|
124
|
-
getWeather: {
|
|
124
|
+
'agent.getWeather': {
|
|
125
125
|
actions: log(({ event }) => event),
|
|
126
126
|
target: 'gettingWeather',
|
|
127
127
|
},
|
|
128
|
-
doSomethingElse: 'getLocation',
|
|
128
|
+
'agent.doSomethingElse': 'getLocation',
|
|
129
129
|
},
|
|
130
130
|
},
|
|
131
131
|
gettingWeather: {
|
|
@@ -140,6 +140,20 @@ const machine = setup({
|
|
|
140
140
|
count: ({ context }) => context.count + 1,
|
|
141
141
|
}),
|
|
142
142
|
],
|
|
143
|
+
target: 'reportWeather',
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
reportWeather: {
|
|
148
|
+
invoke: {
|
|
149
|
+
src: 'agent',
|
|
150
|
+
input: ({ context }) => ({
|
|
151
|
+
goal: 'Report the weather', // TODO
|
|
152
|
+
}),
|
|
153
|
+
},
|
|
154
|
+
on: {
|
|
155
|
+
'agent.reportWeather': {
|
|
156
|
+
actions: log(({ event }) => event),
|
|
143
157
|
target: 'getLocation',
|
|
144
158
|
},
|
|
145
159
|
},
|
|
@@ -153,8 +167,12 @@ const machine = setup({
|
|
|
153
167
|
},
|
|
154
168
|
});
|
|
155
169
|
|
|
156
|
-
|
|
170
|
+
const actor = createActor(machine, {
|
|
157
171
|
input: {
|
|
158
172
|
location: 'New York',
|
|
159
173
|
},
|
|
160
|
-
})
|
|
174
|
+
});
|
|
175
|
+
actor.subscribe((s) => {
|
|
176
|
+
console.log(s.value);
|
|
177
|
+
});
|
|
178
|
+
actor.start();
|
package/examples/wiki.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createAgent } from '../src';
|
|
3
|
+
import { openai } from '@ai-sdk/openai';
|
|
4
|
+
|
|
5
|
+
const agent = createAgent({
|
|
6
|
+
name: 'wiki',
|
|
7
|
+
model: openai('gpt-4-turbo'),
|
|
8
|
+
events: {
|
|
9
|
+
provideAnswer: z.object({
|
|
10
|
+
answer: z.string().describe('The answer'),
|
|
11
|
+
}),
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
async function main() {
|
|
16
|
+
const response1 = await agent.generateText({
|
|
17
|
+
prompt: 'When was Deadpool 2 released?',
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
console.log(response1.text);
|
|
21
|
+
|
|
22
|
+
const response2 = await agent.generateText({
|
|
23
|
+
messages: true,
|
|
24
|
+
prompt: 'What about the first one?',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
console.log(response2.text);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
main();
|
package/examples/word.ts
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { assign, createActor, log, setup } from 'xstate';
|
|
2
|
+
import { getFromTerminal } from './helpers/helpers';
|
|
3
|
+
import { createAgent, fromDecision } from '../src';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { openai } from '@ai-sdk/openai';
|
|
6
|
+
|
|
7
|
+
const context = {
|
|
8
|
+
word: null as string | null,
|
|
9
|
+
guessedWord: null as string | null,
|
|
10
|
+
lettersGuessed: [] as string[],
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const agent = createAgent({
|
|
14
|
+
name: 'word',
|
|
15
|
+
model: openai('gpt-4-1106-preview'),
|
|
16
|
+
events: {
|
|
17
|
+
'agent.guessLetter': z.object({
|
|
18
|
+
letter: z.string().min(1).max(1).describe('The letter guessed'),
|
|
19
|
+
reasoning: z.string().describe('The reasoning behind the guess'),
|
|
20
|
+
}),
|
|
21
|
+
|
|
22
|
+
'agent.guessWord': z.object({
|
|
23
|
+
word: z.string().describe('The word guessed'),
|
|
24
|
+
}),
|
|
25
|
+
|
|
26
|
+
'agent.respond': z.object({
|
|
27
|
+
response: z
|
|
28
|
+
.string()
|
|
29
|
+
.describe(
|
|
30
|
+
'The response from the agent, detailing why the guess was correct or incorrect based on the letters guessed.'
|
|
31
|
+
),
|
|
32
|
+
}),
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const wordGuesserMachine = setup({
|
|
37
|
+
types: {
|
|
38
|
+
context: {} as typeof context,
|
|
39
|
+
events: agent.eventTypes,
|
|
40
|
+
},
|
|
41
|
+
actors: {
|
|
42
|
+
agent: fromDecision(agent),
|
|
43
|
+
getFromTerminal,
|
|
44
|
+
},
|
|
45
|
+
}).createMachine({
|
|
46
|
+
initial: 'providingWord',
|
|
47
|
+
context,
|
|
48
|
+
states: {
|
|
49
|
+
providingWord: {
|
|
50
|
+
entry: assign(context),
|
|
51
|
+
invoke: {
|
|
52
|
+
src: 'getFromTerminal',
|
|
53
|
+
input: 'Enter a word, and an agent will try to guess it.',
|
|
54
|
+
onDone: {
|
|
55
|
+
actions: assign({
|
|
56
|
+
word: ({ event }) => event.output,
|
|
57
|
+
}),
|
|
58
|
+
target: 'guessing',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
guessing: {
|
|
63
|
+
always: {
|
|
64
|
+
guard: ({ context }) => context.lettersGuessed.length > 10,
|
|
65
|
+
target: 'finalGuess',
|
|
66
|
+
},
|
|
67
|
+
invoke: {
|
|
68
|
+
src: 'agent',
|
|
69
|
+
input: ({ context }) => ({
|
|
70
|
+
context: {
|
|
71
|
+
wordLength: context.word!.length,
|
|
72
|
+
lettersGuessed: context.lettersGuessed,
|
|
73
|
+
lettersMatched: context
|
|
74
|
+
.word!.split('')
|
|
75
|
+
.map((letter) =>
|
|
76
|
+
context.lettersGuessed.includes(letter.toUpperCase())
|
|
77
|
+
? letter.toUpperCase()
|
|
78
|
+
: '_'
|
|
79
|
+
)
|
|
80
|
+
.join(''),
|
|
81
|
+
},
|
|
82
|
+
goal: `You are trying to guess the word. Please make your next guess - guess a letter or, if you think you know the word, guess the full word. You can only make 10 total guesses. If you are confident you know the word, it is better to guess the word.`,
|
|
83
|
+
}),
|
|
84
|
+
},
|
|
85
|
+
on: {
|
|
86
|
+
'agent.guessLetter': {
|
|
87
|
+
actions: [
|
|
88
|
+
assign({
|
|
89
|
+
lettersGuessed: ({ context, event }) => {
|
|
90
|
+
return [...context.lettersGuessed, event.letter.toUpperCase()];
|
|
91
|
+
},
|
|
92
|
+
}),
|
|
93
|
+
log(({ event }) => event),
|
|
94
|
+
],
|
|
95
|
+
target: 'guessing',
|
|
96
|
+
reenter: true,
|
|
97
|
+
},
|
|
98
|
+
'agent.guessWord': {
|
|
99
|
+
actions: [
|
|
100
|
+
assign({
|
|
101
|
+
guessedWord: ({ event }) => event.word,
|
|
102
|
+
}),
|
|
103
|
+
log(({ event }) => event),
|
|
104
|
+
],
|
|
105
|
+
target: 'gameOver',
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
finalGuess: {
|
|
110
|
+
invoke: {
|
|
111
|
+
src: 'agent',
|
|
112
|
+
input: ({ context }) => ({
|
|
113
|
+
context: {
|
|
114
|
+
lettersGuessed: context.lettersGuessed,
|
|
115
|
+
},
|
|
116
|
+
goal: `You have used all 10 guesses. These letters matched: ${context
|
|
117
|
+
.word!.split('')
|
|
118
|
+
.map((letter) =>
|
|
119
|
+
context.lettersGuessed.includes(letter.toUpperCase())
|
|
120
|
+
? letter.toUpperCase()
|
|
121
|
+
: '_'
|
|
122
|
+
)
|
|
123
|
+
.join('')}. Guess the word.`,
|
|
124
|
+
}),
|
|
125
|
+
},
|
|
126
|
+
on: {
|
|
127
|
+
'agent.guessWord': {
|
|
128
|
+
actions: [
|
|
129
|
+
assign({
|
|
130
|
+
guessedWord: ({ event }) => event.word,
|
|
131
|
+
}),
|
|
132
|
+
log(({ event }) => event),
|
|
133
|
+
],
|
|
134
|
+
target: 'gameOver',
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
gameOver: {
|
|
139
|
+
invoke: {
|
|
140
|
+
src: 'agent',
|
|
141
|
+
input: ({ context }) => ({
|
|
142
|
+
context,
|
|
143
|
+
goal: `Why do you think you won or lost?`,
|
|
144
|
+
}),
|
|
145
|
+
},
|
|
146
|
+
entry: log(({ context }) => {
|
|
147
|
+
if (
|
|
148
|
+
context.guessedWord?.toUpperCase() === context.word?.toUpperCase()
|
|
149
|
+
) {
|
|
150
|
+
return 'The agent won!';
|
|
151
|
+
} else {
|
|
152
|
+
return 'The agent lost! The word was ' + context.word;
|
|
153
|
+
}
|
|
154
|
+
}),
|
|
155
|
+
on: {
|
|
156
|
+
'agent.respond': {
|
|
157
|
+
actions: log(({ event }) => event.response),
|
|
158
|
+
target: 'providingWord',
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
exit: () => process.exit(),
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const game = createActor(wordGuesserMachine);
|
|
167
|
+
|
|
168
|
+
game.start();
|