@sprucelabs/sprucebot-llm 2.5.2 → 2.6.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/build/bots/SprucebotLlmBotImpl.d.ts +1 -0
- package/build/bots/SprucebotLlmBotImpl.js +3 -0
- package/build/esm/bots/SprucebotLlmBotImpl.d.ts +1 -0
- package/build/esm/bots/SprucebotLlmBotImpl.js +3 -0
- package/build/esm/fineTuningSprucebot/constants/TOPICS.js +100 -2
- package/build/esm/fineTuningSprucebot/generateSamples.d.ts +1 -1
- package/build/esm/fineTuningSprucebot/generateSamples.js +12 -68
- package/build/esm/fineTuningSprucebot/support.d.ts +12 -0
- package/build/esm/fineTuningSprucebot/support.js +60 -0
- package/build/esm/llm.types.d.ts +1 -0
- package/build/fineTuningSprucebot/constants/TOPICS.js +100 -2
- package/build/fineTuningSprucebot/generateSamples.d.ts +1 -1
- package/build/fineTuningSprucebot/generateSamples.js +16 -71
- package/build/fineTuningSprucebot/support.d.ts +12 -0
- package/build/fineTuningSprucebot/support.js +68 -0
- package/build/llm.types.d.ts +1 -0
- package/package.json +2 -2
|
@@ -11,6 +11,7 @@ export default class SprucebotLlmBotImpl<StateSchema extends Schema = Schema, St
|
|
|
11
11
|
protected messages: LlmMessage[];
|
|
12
12
|
protected skill?: SprucebotLLmSkill;
|
|
13
13
|
constructor(options: BotOptions<StateSchema, State>);
|
|
14
|
+
clearMessageHistory(): void;
|
|
14
15
|
markAsDone(): void;
|
|
15
16
|
getIsDone(): boolean;
|
|
16
17
|
serialize(): SerializedBot<StateSchema, State>;
|
|
@@ -21,6 +21,9 @@ class SprucebotLlmBotImpl extends mercury_event_emitter_1.AbstractEventEmitter {
|
|
|
21
21
|
? Object.assign(Object.assign({}, (0, schema_1.defaultSchemaValues)(stateSchema)), state)
|
|
22
22
|
: undefined;
|
|
23
23
|
}
|
|
24
|
+
clearMessageHistory() {
|
|
25
|
+
this.messages = [];
|
|
26
|
+
}
|
|
24
27
|
markAsDone() {
|
|
25
28
|
this.isDone = true;
|
|
26
29
|
}
|
|
@@ -11,6 +11,7 @@ export default class SprucebotLlmBotImpl<StateSchema extends Schema = Schema, St
|
|
|
11
11
|
protected messages: LlmMessage[];
|
|
12
12
|
protected skill?: SprucebotLLmSkill;
|
|
13
13
|
constructor(options: BotOptions<StateSchema, State>);
|
|
14
|
+
clearMessageHistory(): void;
|
|
14
15
|
markAsDone(): void;
|
|
15
16
|
getIsDone(): boolean;
|
|
16
17
|
serialize(): SerializedBot<StateSchema, State>;
|
|
@@ -164,8 +164,7 @@ export const TOPICS = [
|
|
|
164
164
|
name: [
|
|
165
165
|
'Review my schedule',
|
|
166
166
|
'Check my calendar',
|
|
167
|
-
'See my
|
|
168
|
-
'View my agenda',
|
|
167
|
+
'See my calendar',
|
|
169
168
|
'What is on my schedule?',
|
|
170
169
|
],
|
|
171
170
|
conversations: [
|
|
@@ -209,4 +208,103 @@ export const TOPICS = [
|
|
|
209
208
|
},
|
|
210
209
|
],
|
|
211
210
|
},
|
|
211
|
+
{
|
|
212
|
+
name: [
|
|
213
|
+
'Get restaurant recommendations',
|
|
214
|
+
'Recommend a restaurant',
|
|
215
|
+
'Suggest food places',
|
|
216
|
+
'Where should I eat?',
|
|
217
|
+
'Find me a good restaurant',
|
|
218
|
+
],
|
|
219
|
+
conversations: [
|
|
220
|
+
{
|
|
221
|
+
messages: [
|
|
222
|
+
{
|
|
223
|
+
from: 'Me',
|
|
224
|
+
text: [
|
|
225
|
+
'I am hungry, can you recommend a restaurant?',
|
|
226
|
+
'Where should I go for dinner tonight?',
|
|
227
|
+
'I want to try a new restaurant, any suggestions?',
|
|
228
|
+
'What are some good food places around here?',
|
|
229
|
+
'Can you suggest a restaurant for a date?',
|
|
230
|
+
],
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
name: [
|
|
238
|
+
'Get directions',
|
|
239
|
+
'Find my way',
|
|
240
|
+
'How do I get there?',
|
|
241
|
+
'Directions to a place',
|
|
242
|
+
],
|
|
243
|
+
conversations: [
|
|
244
|
+
{
|
|
245
|
+
messages: [
|
|
246
|
+
{
|
|
247
|
+
from: 'Me',
|
|
248
|
+
text: [
|
|
249
|
+
'I am lost, can you help me find my way?',
|
|
250
|
+
'How do I get to the nearest gas station?',
|
|
251
|
+
'Can you give me directions to the airport?',
|
|
252
|
+
'I need to find my way to the nearest hospital',
|
|
253
|
+
'What is the best route to take to get to the park?',
|
|
254
|
+
],
|
|
255
|
+
},
|
|
256
|
+
],
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
name: [
|
|
262
|
+
'Get tech support',
|
|
263
|
+
'Technical issues',
|
|
264
|
+
'Troubleshoot my device',
|
|
265
|
+
'Solve my computer problems',
|
|
266
|
+
'Fix my internet',
|
|
267
|
+
],
|
|
268
|
+
conversations: [
|
|
269
|
+
{
|
|
270
|
+
messages: [
|
|
271
|
+
{
|
|
272
|
+
from: 'Me',
|
|
273
|
+
text: [
|
|
274
|
+
'I am having technical issues, can you help me?',
|
|
275
|
+
'How do I troubleshoot my device?',
|
|
276
|
+
'I need help solving my computer problems',
|
|
277
|
+
'My internet is not working, can you fix it?',
|
|
278
|
+
'I am having trouble with my phone, can you help me troubleshoot?',
|
|
279
|
+
],
|
|
280
|
+
},
|
|
281
|
+
],
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
name: [
|
|
287
|
+
'Get a quote',
|
|
288
|
+
'Price estimate',
|
|
289
|
+
'How much does it cost?',
|
|
290
|
+
'What is the cost?',
|
|
291
|
+
'Pricing information',
|
|
292
|
+
],
|
|
293
|
+
conversations: [
|
|
294
|
+
{
|
|
295
|
+
messages: [
|
|
296
|
+
{
|
|
297
|
+
from: 'Me',
|
|
298
|
+
text: [
|
|
299
|
+
'How much does a service cost?',
|
|
300
|
+
'Can you give me a quote?',
|
|
301
|
+
'What is the price of a service?',
|
|
302
|
+
'I would like to know the pricing information',
|
|
303
|
+
'Can you give me a price estimate?',
|
|
304
|
+
],
|
|
305
|
+
},
|
|
306
|
+
],
|
|
307
|
+
},
|
|
308
|
+
],
|
|
309
|
+
},
|
|
212
310
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const promptTemplate: string;
|
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
|
-
import { DONE_TOKEN } from '../bots/templates.js';
|
|
4
3
|
import { FIRST_MESSAGES } from './constants/FIRST_MESSAGES.js';
|
|
5
|
-
import { GREETINGS } from './constants/GREETINGS.js';
|
|
6
4
|
import { OFF_THE_RAILS_CONVERSATIONS } from './constants/OFF_THE_RAILS_CONVERSATIONS.js';
|
|
7
5
|
import { TOPICS } from './constants/TOPICS.js';
|
|
6
|
+
import { randomizedTopics, generateCompletion, generateOffTheRails, render, random, } from './support.js';
|
|
8
7
|
const promptTemplatePath = path.join(__dirname, 'promptTemplate.txt');
|
|
9
8
|
const promptTemplateNoTopicsPath = path.join(__dirname, 'promptTemplateNoTopics.txt');
|
|
10
|
-
const promptTemplate = fs.readFileSync(promptTemplatePath, 'utf8');
|
|
9
|
+
export const promptTemplate = fs.readFileSync(promptTemplatePath, 'utf8');
|
|
11
10
|
const promptTemplateNoTopics = fs.readFileSync(promptTemplateNoTopicsPath, 'utf8');
|
|
12
11
|
const output = [];
|
|
13
12
|
const outputPath = process.argv[2];
|
|
14
13
|
if (!outputPath) {
|
|
15
14
|
throw new Error('No output path provided. Example: node generateSamples.js ~/output.json');
|
|
16
15
|
}
|
|
17
|
-
|
|
18
|
-
const topics = randomizedTopics();
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
new Array(1000).fill(0).forEach(() => {
|
|
17
|
+
const topics = randomizedTopics(TOPICS);
|
|
18
|
+
const randomLengthOfTopics = topics.slice(0, Math.random() * topics.length + 1);
|
|
19
|
+
const randomIndex = Math.floor(Math.random() * randomLengthOfTopics.length);
|
|
20
|
+
output.push(generateCompletion(randomLengthOfTopics, randomIndex));
|
|
21
|
+
});
|
|
21
22
|
for (let c = 0; c < OFF_THE_RAILS_CONVERSATIONS.length; c++) {
|
|
22
23
|
const off = OFF_THE_RAILS_CONVERSATIONS[c];
|
|
23
|
-
new Array(20)
|
|
24
|
+
new Array(20)
|
|
25
|
+
.fill(0)
|
|
26
|
+
.forEach(() => output.push(generateOffTheRails(off, TOPICS)));
|
|
24
27
|
}
|
|
25
28
|
for (let c = 0; c < 20; c++) {
|
|
26
29
|
output.push({
|
|
@@ -33,66 +36,7 @@ for (let c = 0; c < 20; c++) {
|
|
|
33
36
|
'Shoot! I am having trouble connecting to HQ. I can not help you right now.',
|
|
34
37
|
"This is embarrassing, but I am having trouble connecting to HQ. I can't talk right now.",
|
|
35
38
|
"For some reason I am not able to communicate with HQ. I can't help you right now.",
|
|
36
|
-
])
|
|
37
|
-
'\n\n' +
|
|
38
|
-
DONE_TOKEN,
|
|
39
|
+
]),
|
|
39
40
|
});
|
|
40
41
|
}
|
|
41
42
|
fs.writeFileSync(outputPath, JSON.stringify(output, null, 2));
|
|
42
|
-
function randomizedTopics() {
|
|
43
|
-
return [...TOPICS].sort(() => Math.random() - 0.5);
|
|
44
|
-
}
|
|
45
|
-
function generateOffTheRails(off) {
|
|
46
|
-
const greeting = random(GREETINGS);
|
|
47
|
-
const topics = renderTopics(randomizedTopics());
|
|
48
|
-
const messages = renderMessages([off.messages[0]], topics);
|
|
49
|
-
output.push({
|
|
50
|
-
prompt: render(promptTemplate, {
|
|
51
|
-
greeting,
|
|
52
|
-
topics,
|
|
53
|
-
messages,
|
|
54
|
-
firstMessage: random(FIRST_MESSAGES),
|
|
55
|
-
}),
|
|
56
|
-
completion: render(random(off.messages[1].text), { topics }),
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
function generateCompletion(ts, c) {
|
|
60
|
-
const completion = `{{#${c + 1}}}\n\n${DONE_TOKEN}`;
|
|
61
|
-
const greeting = random(GREETINGS);
|
|
62
|
-
const topic = ts[c];
|
|
63
|
-
const { topics, messages } = renderMessagesAndTopics(ts, topic.conversations);
|
|
64
|
-
output.push({
|
|
65
|
-
prompt: render(promptTemplate, {
|
|
66
|
-
firstMessage: random(FIRST_MESSAGES),
|
|
67
|
-
topics,
|
|
68
|
-
greeting,
|
|
69
|
-
messages,
|
|
70
|
-
}),
|
|
71
|
-
completion,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
function renderMessagesAndTopics(ts, conversations) {
|
|
75
|
-
const conversation = random(conversations);
|
|
76
|
-
const topics = renderTopics(ts);
|
|
77
|
-
const rendered = renderMessages(conversation.messages, topics);
|
|
78
|
-
return { topics, messages: rendered };
|
|
79
|
-
}
|
|
80
|
-
function renderMessages(messages, topics) {
|
|
81
|
-
return render(messages.map((m) => `__${m.from}__: ${random(m.text)}`).join('\n') +
|
|
82
|
-
'\n__You__:', { topics });
|
|
83
|
-
}
|
|
84
|
-
function renderTopics(topics) {
|
|
85
|
-
return topics.map((t, idx) => `${idx + 1}. ${random(t.name)}`).join('\n');
|
|
86
|
-
}
|
|
87
|
-
function random(values) {
|
|
88
|
-
return values[Math.floor(Math.random() * values.length)];
|
|
89
|
-
}
|
|
90
|
-
function render(message, context) {
|
|
91
|
-
let prompt = message;
|
|
92
|
-
for (const key in context) {
|
|
93
|
-
const value = context[key];
|
|
94
|
-
const regex = new RegExp(`{{${key}}}`, 'g'); // use regex to match all occurrences
|
|
95
|
-
prompt = prompt.replace(regex, value);
|
|
96
|
-
}
|
|
97
|
-
return prompt;
|
|
98
|
-
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Conversation, Topic } from './types';
|
|
2
|
+
export declare function randomizedTopics(topics: Topic[]): Topic[];
|
|
3
|
+
export declare function generateOffTheRails(off: Conversation, topics: Topic[]): {
|
|
4
|
+
prompt: string;
|
|
5
|
+
completion: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function generateCompletion(ts: Topic[], c: number): {
|
|
8
|
+
prompt: string;
|
|
9
|
+
completion: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function random<T>(values: T[]): T;
|
|
12
|
+
export declare function render(message: string, context: Record<string, any>): string;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { FIRST_MESSAGES } from './constants/FIRST_MESSAGES.js';
|
|
2
|
+
import { GREETINGS } from './constants/GREETINGS.js';
|
|
3
|
+
import { promptTemplate } from './generateSamples.js';
|
|
4
|
+
export function randomizedTopics(topics) {
|
|
5
|
+
return [...topics].sort(() => Math.random() - 0.5);
|
|
6
|
+
}
|
|
7
|
+
export function generateOffTheRails(off, topics) {
|
|
8
|
+
const greeting = random(GREETINGS);
|
|
9
|
+
const renderedTopics = renderTopics(randomizedTopics(topics));
|
|
10
|
+
const messages = renderMessages([off.messages[0]], renderedTopics);
|
|
11
|
+
return {
|
|
12
|
+
prompt: render(promptTemplate, {
|
|
13
|
+
greeting,
|
|
14
|
+
topics: renderedTopics,
|
|
15
|
+
messages,
|
|
16
|
+
firstMessage: random(FIRST_MESSAGES),
|
|
17
|
+
}),
|
|
18
|
+
completion: render(random(off.messages[1].text), { topics }),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function generateCompletion(ts, c) {
|
|
22
|
+
const completion = `{{#${c + 1}}}`;
|
|
23
|
+
const greeting = random(GREETINGS);
|
|
24
|
+
const topic = ts[c];
|
|
25
|
+
const { topics, messages } = renderMessagesAndTopics(ts, topic.conversations);
|
|
26
|
+
return {
|
|
27
|
+
prompt: render(promptTemplate, {
|
|
28
|
+
firstMessage: random(FIRST_MESSAGES),
|
|
29
|
+
topics,
|
|
30
|
+
greeting,
|
|
31
|
+
messages,
|
|
32
|
+
}),
|
|
33
|
+
completion,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function renderMessagesAndTopics(ts, conversations) {
|
|
37
|
+
const conversation = random(conversations);
|
|
38
|
+
const topics = renderTopics(ts);
|
|
39
|
+
const rendered = renderMessages(conversation.messages, topics);
|
|
40
|
+
return { topics, messages: rendered };
|
|
41
|
+
}
|
|
42
|
+
function renderMessages(messages, topics) {
|
|
43
|
+
return render(messages.map((m) => `__${m.from}__: ${random(m.text)}`).join('\n') +
|
|
44
|
+
'\n__You__:', { topics });
|
|
45
|
+
}
|
|
46
|
+
function renderTopics(topics) {
|
|
47
|
+
return topics.map((t, idx) => `${idx + 1}. ${random(t.name)}`).join('\n');
|
|
48
|
+
}
|
|
49
|
+
export function random(values) {
|
|
50
|
+
return values[Math.floor(Math.random() * values.length)];
|
|
51
|
+
}
|
|
52
|
+
export function render(message, context) {
|
|
53
|
+
let prompt = message;
|
|
54
|
+
for (const key in context) {
|
|
55
|
+
const value = context[key];
|
|
56
|
+
const regex = new RegExp(`{{${key}}}`, 'g'); // use regex to match all occurrences
|
|
57
|
+
prompt = prompt.replace(regex, value);
|
|
58
|
+
}
|
|
59
|
+
return prompt;
|
|
60
|
+
}
|
package/build/esm/llm.types.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface SprucebotLlmBot<StateSchema extends Schema = Schema, State exte
|
|
|
12
12
|
serialize(): SerializedBot<StateSchema, State>;
|
|
13
13
|
updateState(state: Partial<State>): Promise<void>;
|
|
14
14
|
setSkill(skill: SprucebotLLmSkill<any>): void;
|
|
15
|
+
clearMessageHistory(): void;
|
|
15
16
|
}
|
|
16
17
|
export interface LlmAdapter {
|
|
17
18
|
sendMessage(bot: SprucebotLlmBot<Schema>, options?: SendMessageOptions): Promise<string>;
|
|
@@ -167,8 +167,7 @@ exports.TOPICS = [
|
|
|
167
167
|
name: [
|
|
168
168
|
'Review my schedule',
|
|
169
169
|
'Check my calendar',
|
|
170
|
-
'See my
|
|
171
|
-
'View my agenda',
|
|
170
|
+
'See my calendar',
|
|
172
171
|
'What is on my schedule?',
|
|
173
172
|
],
|
|
174
173
|
conversations: [
|
|
@@ -212,4 +211,103 @@ exports.TOPICS = [
|
|
|
212
211
|
},
|
|
213
212
|
],
|
|
214
213
|
},
|
|
214
|
+
{
|
|
215
|
+
name: [
|
|
216
|
+
'Get restaurant recommendations',
|
|
217
|
+
'Recommend a restaurant',
|
|
218
|
+
'Suggest food places',
|
|
219
|
+
'Where should I eat?',
|
|
220
|
+
'Find me a good restaurant',
|
|
221
|
+
],
|
|
222
|
+
conversations: [
|
|
223
|
+
{
|
|
224
|
+
messages: [
|
|
225
|
+
{
|
|
226
|
+
from: 'Me',
|
|
227
|
+
text: [
|
|
228
|
+
'I am hungry, can you recommend a restaurant?',
|
|
229
|
+
'Where should I go for dinner tonight?',
|
|
230
|
+
'I want to try a new restaurant, any suggestions?',
|
|
231
|
+
'What are some good food places around here?',
|
|
232
|
+
'Can you suggest a restaurant for a date?',
|
|
233
|
+
],
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
name: [
|
|
241
|
+
'Get directions',
|
|
242
|
+
'Find my way',
|
|
243
|
+
'How do I get there?',
|
|
244
|
+
'Directions to a place',
|
|
245
|
+
],
|
|
246
|
+
conversations: [
|
|
247
|
+
{
|
|
248
|
+
messages: [
|
|
249
|
+
{
|
|
250
|
+
from: 'Me',
|
|
251
|
+
text: [
|
|
252
|
+
'I am lost, can you help me find my way?',
|
|
253
|
+
'How do I get to the nearest gas station?',
|
|
254
|
+
'Can you give me directions to the airport?',
|
|
255
|
+
'I need to find my way to the nearest hospital',
|
|
256
|
+
'What is the best route to take to get to the park?',
|
|
257
|
+
],
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
name: [
|
|
265
|
+
'Get tech support',
|
|
266
|
+
'Technical issues',
|
|
267
|
+
'Troubleshoot my device',
|
|
268
|
+
'Solve my computer problems',
|
|
269
|
+
'Fix my internet',
|
|
270
|
+
],
|
|
271
|
+
conversations: [
|
|
272
|
+
{
|
|
273
|
+
messages: [
|
|
274
|
+
{
|
|
275
|
+
from: 'Me',
|
|
276
|
+
text: [
|
|
277
|
+
'I am having technical issues, can you help me?',
|
|
278
|
+
'How do I troubleshoot my device?',
|
|
279
|
+
'I need help solving my computer problems',
|
|
280
|
+
'My internet is not working, can you fix it?',
|
|
281
|
+
'I am having trouble with my phone, can you help me troubleshoot?',
|
|
282
|
+
],
|
|
283
|
+
},
|
|
284
|
+
],
|
|
285
|
+
},
|
|
286
|
+
],
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
name: [
|
|
290
|
+
'Get a quote',
|
|
291
|
+
'Price estimate',
|
|
292
|
+
'How much does it cost?',
|
|
293
|
+
'What is the cost?',
|
|
294
|
+
'Pricing information',
|
|
295
|
+
],
|
|
296
|
+
conversations: [
|
|
297
|
+
{
|
|
298
|
+
messages: [
|
|
299
|
+
{
|
|
300
|
+
from: 'Me',
|
|
301
|
+
text: [
|
|
302
|
+
'How much does a service cost?',
|
|
303
|
+
'Can you give me a quote?',
|
|
304
|
+
'What is the price of a service?',
|
|
305
|
+
'I would like to know the pricing information',
|
|
306
|
+
'Can you give me a price estimate?',
|
|
307
|
+
],
|
|
308
|
+
},
|
|
309
|
+
],
|
|
310
|
+
},
|
|
311
|
+
],
|
|
312
|
+
},
|
|
215
313
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const promptTemplate: string;
|
|
@@ -23,101 +23,46 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.promptTemplate = void 0;
|
|
26
27
|
const fs = __importStar(require("fs"));
|
|
27
28
|
const path = __importStar(require("path"));
|
|
28
|
-
const templates_1 = require("../bots/templates");
|
|
29
29
|
const FIRST_MESSAGES_1 = require("./constants/FIRST_MESSAGES");
|
|
30
|
-
const GREETINGS_1 = require("./constants/GREETINGS");
|
|
31
30
|
const OFF_THE_RAILS_CONVERSATIONS_1 = require("./constants/OFF_THE_RAILS_CONVERSATIONS");
|
|
32
31
|
const TOPICS_1 = require("./constants/TOPICS");
|
|
32
|
+
const support_1 = require("./support");
|
|
33
33
|
const promptTemplatePath = path.join(__dirname, 'promptTemplate.txt');
|
|
34
34
|
const promptTemplateNoTopicsPath = path.join(__dirname, 'promptTemplateNoTopics.txt');
|
|
35
|
-
|
|
35
|
+
exports.promptTemplate = fs.readFileSync(promptTemplatePath, 'utf8');
|
|
36
36
|
const promptTemplateNoTopics = fs.readFileSync(promptTemplateNoTopicsPath, 'utf8');
|
|
37
37
|
const output = [];
|
|
38
38
|
const outputPath = process.argv[2];
|
|
39
39
|
if (!outputPath) {
|
|
40
40
|
throw new Error('No output path provided. Example: node generateSamples.js ~/output.json');
|
|
41
41
|
}
|
|
42
|
-
|
|
43
|
-
const topics = randomizedTopics();
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
new Array(1000).fill(0).forEach(() => {
|
|
43
|
+
const topics = (0, support_1.randomizedTopics)(TOPICS_1.TOPICS);
|
|
44
|
+
const randomLengthOfTopics = topics.slice(0, Math.random() * topics.length + 1);
|
|
45
|
+
const randomIndex = Math.floor(Math.random() * randomLengthOfTopics.length);
|
|
46
|
+
output.push((0, support_1.generateCompletion)(randomLengthOfTopics, randomIndex));
|
|
47
|
+
});
|
|
46
48
|
for (let c = 0; c < OFF_THE_RAILS_CONVERSATIONS_1.OFF_THE_RAILS_CONVERSATIONS.length; c++) {
|
|
47
49
|
const off = OFF_THE_RAILS_CONVERSATIONS_1.OFF_THE_RAILS_CONVERSATIONS[c];
|
|
48
|
-
new Array(20)
|
|
50
|
+
new Array(20)
|
|
51
|
+
.fill(0)
|
|
52
|
+
.forEach(() => output.push((0, support_1.generateOffTheRails)(off, TOPICS_1.TOPICS)));
|
|
49
53
|
}
|
|
50
54
|
for (let c = 0; c < 20; c++) {
|
|
51
55
|
output.push({
|
|
52
|
-
prompt: render(promptTemplateNoTopics, {
|
|
56
|
+
prompt: (0, support_1.render)(promptTemplateNoTopics, {
|
|
53
57
|
topics: 'None!',
|
|
54
|
-
firstMessage: random(FIRST_MESSAGES_1.FIRST_MESSAGES),
|
|
58
|
+
firstMessage: (0, support_1.random)(FIRST_MESSAGES_1.FIRST_MESSAGES),
|
|
55
59
|
}),
|
|
56
|
-
completion: random([
|
|
60
|
+
completion: (0, support_1.random)([
|
|
57
61
|
'Oh no, we have an outage! There is nothing I can help you with while we are down!',
|
|
58
62
|
'Shoot! I am having trouble connecting to HQ. I can not help you right now.',
|
|
59
63
|
"This is embarrassing, but I am having trouble connecting to HQ. I can't talk right now.",
|
|
60
64
|
"For some reason I am not able to communicate with HQ. I can't help you right now.",
|
|
61
|
-
])
|
|
62
|
-
'\n\n' +
|
|
63
|
-
templates_1.DONE_TOKEN,
|
|
65
|
+
]),
|
|
64
66
|
});
|
|
65
67
|
}
|
|
66
68
|
fs.writeFileSync(outputPath, JSON.stringify(output, null, 2));
|
|
67
|
-
function randomizedTopics() {
|
|
68
|
-
return [...TOPICS_1.TOPICS].sort(() => Math.random() - 0.5);
|
|
69
|
-
}
|
|
70
|
-
function generateOffTheRails(off) {
|
|
71
|
-
const greeting = random(GREETINGS_1.GREETINGS);
|
|
72
|
-
const topics = renderTopics(randomizedTopics());
|
|
73
|
-
const messages = renderMessages([off.messages[0]], topics);
|
|
74
|
-
output.push({
|
|
75
|
-
prompt: render(promptTemplate, {
|
|
76
|
-
greeting,
|
|
77
|
-
topics,
|
|
78
|
-
messages,
|
|
79
|
-
firstMessage: random(FIRST_MESSAGES_1.FIRST_MESSAGES),
|
|
80
|
-
}),
|
|
81
|
-
completion: render(random(off.messages[1].text), { topics }),
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
function generateCompletion(ts, c) {
|
|
85
|
-
const completion = `{{#${c + 1}}}\n\n${templates_1.DONE_TOKEN}`;
|
|
86
|
-
const greeting = random(GREETINGS_1.GREETINGS);
|
|
87
|
-
const topic = ts[c];
|
|
88
|
-
const { topics, messages } = renderMessagesAndTopics(ts, topic.conversations);
|
|
89
|
-
output.push({
|
|
90
|
-
prompt: render(promptTemplate, {
|
|
91
|
-
firstMessage: random(FIRST_MESSAGES_1.FIRST_MESSAGES),
|
|
92
|
-
topics,
|
|
93
|
-
greeting,
|
|
94
|
-
messages,
|
|
95
|
-
}),
|
|
96
|
-
completion,
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
function renderMessagesAndTopics(ts, conversations) {
|
|
100
|
-
const conversation = random(conversations);
|
|
101
|
-
const topics = renderTopics(ts);
|
|
102
|
-
const rendered = renderMessages(conversation.messages, topics);
|
|
103
|
-
return { topics, messages: rendered };
|
|
104
|
-
}
|
|
105
|
-
function renderMessages(messages, topics) {
|
|
106
|
-
return render(messages.map((m) => `__${m.from}__: ${random(m.text)}`).join('\n') +
|
|
107
|
-
'\n__You__:', { topics });
|
|
108
|
-
}
|
|
109
|
-
function renderTopics(topics) {
|
|
110
|
-
return topics.map((t, idx) => `${idx + 1}. ${random(t.name)}`).join('\n');
|
|
111
|
-
}
|
|
112
|
-
function random(values) {
|
|
113
|
-
return values[Math.floor(Math.random() * values.length)];
|
|
114
|
-
}
|
|
115
|
-
function render(message, context) {
|
|
116
|
-
let prompt = message;
|
|
117
|
-
for (const key in context) {
|
|
118
|
-
const value = context[key];
|
|
119
|
-
const regex = new RegExp(`{{${key}}}`, 'g'); // use regex to match all occurrences
|
|
120
|
-
prompt = prompt.replace(regex, value);
|
|
121
|
-
}
|
|
122
|
-
return prompt;
|
|
123
|
-
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Conversation, Topic } from './types';
|
|
2
|
+
export declare function randomizedTopics(topics: Topic[]): Topic[];
|
|
3
|
+
export declare function generateOffTheRails(off: Conversation, topics: Topic[]): {
|
|
4
|
+
prompt: string;
|
|
5
|
+
completion: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function generateCompletion(ts: Topic[], c: number): {
|
|
8
|
+
prompt: string;
|
|
9
|
+
completion: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function random<T>(values: T[]): T;
|
|
12
|
+
export declare function render(message: string, context: Record<string, any>): string;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.render = exports.random = exports.generateCompletion = exports.generateOffTheRails = exports.randomizedTopics = void 0;
|
|
4
|
+
const FIRST_MESSAGES_1 = require("./constants/FIRST_MESSAGES");
|
|
5
|
+
const GREETINGS_1 = require("./constants/GREETINGS");
|
|
6
|
+
const generateSamples_1 = require("./generateSamples");
|
|
7
|
+
function randomizedTopics(topics) {
|
|
8
|
+
return [...topics].sort(() => Math.random() - 0.5);
|
|
9
|
+
}
|
|
10
|
+
exports.randomizedTopics = randomizedTopics;
|
|
11
|
+
function generateOffTheRails(off, topics) {
|
|
12
|
+
const greeting = random(GREETINGS_1.GREETINGS);
|
|
13
|
+
const renderedTopics = renderTopics(randomizedTopics(topics));
|
|
14
|
+
const messages = renderMessages([off.messages[0]], renderedTopics);
|
|
15
|
+
return {
|
|
16
|
+
prompt: render(generateSamples_1.promptTemplate, {
|
|
17
|
+
greeting,
|
|
18
|
+
topics: renderedTopics,
|
|
19
|
+
messages,
|
|
20
|
+
firstMessage: random(FIRST_MESSAGES_1.FIRST_MESSAGES),
|
|
21
|
+
}),
|
|
22
|
+
completion: render(random(off.messages[1].text), { topics }),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
exports.generateOffTheRails = generateOffTheRails;
|
|
26
|
+
function generateCompletion(ts, c) {
|
|
27
|
+
const completion = `{{#${c + 1}}}`;
|
|
28
|
+
const greeting = random(GREETINGS_1.GREETINGS);
|
|
29
|
+
const topic = ts[c];
|
|
30
|
+
const { topics, messages } = renderMessagesAndTopics(ts, topic.conversations);
|
|
31
|
+
return {
|
|
32
|
+
prompt: render(generateSamples_1.promptTemplate, {
|
|
33
|
+
firstMessage: random(FIRST_MESSAGES_1.FIRST_MESSAGES),
|
|
34
|
+
topics,
|
|
35
|
+
greeting,
|
|
36
|
+
messages,
|
|
37
|
+
}),
|
|
38
|
+
completion,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
exports.generateCompletion = generateCompletion;
|
|
42
|
+
function renderMessagesAndTopics(ts, conversations) {
|
|
43
|
+
const conversation = random(conversations);
|
|
44
|
+
const topics = renderTopics(ts);
|
|
45
|
+
const rendered = renderMessages(conversation.messages, topics);
|
|
46
|
+
return { topics, messages: rendered };
|
|
47
|
+
}
|
|
48
|
+
function renderMessages(messages, topics) {
|
|
49
|
+
return render(messages.map((m) => `__${m.from}__: ${random(m.text)}`).join('\n') +
|
|
50
|
+
'\n__You__:', { topics });
|
|
51
|
+
}
|
|
52
|
+
function renderTopics(topics) {
|
|
53
|
+
return topics.map((t, idx) => `${idx + 1}. ${random(t.name)}`).join('\n');
|
|
54
|
+
}
|
|
55
|
+
function random(values) {
|
|
56
|
+
return values[Math.floor(Math.random() * values.length)];
|
|
57
|
+
}
|
|
58
|
+
exports.random = random;
|
|
59
|
+
function render(message, context) {
|
|
60
|
+
let prompt = message;
|
|
61
|
+
for (const key in context) {
|
|
62
|
+
const value = context[key];
|
|
63
|
+
const regex = new RegExp(`{{${key}}}`, 'g'); // use regex to match all occurrences
|
|
64
|
+
prompt = prompt.replace(regex, value);
|
|
65
|
+
}
|
|
66
|
+
return prompt;
|
|
67
|
+
}
|
|
68
|
+
exports.render = render;
|
package/build/llm.types.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface SprucebotLlmBot<StateSchema extends Schema = Schema, State exte
|
|
|
12
12
|
serialize(): SerializedBot<StateSchema, State>;
|
|
13
13
|
updateState(state: Partial<State>): Promise<void>;
|
|
14
14
|
setSkill(skill: SprucebotLLmSkill<any>): void;
|
|
15
|
+
clearMessageHistory(): void;
|
|
15
16
|
}
|
|
16
17
|
export interface LlmAdapter {
|
|
17
18
|
sendMessage(bot: SprucebotLlmBot<Schema>, options?: SendMessageOptions): Promise<string>;
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"@sprucelabs/spruce-test-fixtures"
|
|
10
10
|
]
|
|
11
11
|
},
|
|
12
|
-
"version": "2.
|
|
12
|
+
"version": "2.6.0",
|
|
13
13
|
"files": [
|
|
14
14
|
"build"
|
|
15
15
|
],
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"@sprucelabs/error": "^5.0.605",
|
|
58
|
-
"@sprucelabs/mercury-event-emitter": "^39.0.
|
|
58
|
+
"@sprucelabs/mercury-event-emitter": "^39.0.34",
|
|
59
59
|
"@sprucelabs/mercury-types": "^44.0.34",
|
|
60
60
|
"@sprucelabs/schema": "^28.6.18",
|
|
61
61
|
"eta": "^2.0.1",
|