agentlang 0.9.5 → 0.9.7
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/out/cli/main.d.ts.map +1 -1
- package/out/cli/main.js +8 -3
- package/out/cli/main.js.map +1 -1
- package/out/language/generated/ast.d.ts +80 -3
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +62 -0
- package/out/language/generated/ast.js.map +1 -1
- package/out/language/generated/grammar.d.ts.map +1 -1
- package/out/language/generated/grammar.js +432 -218
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/main.cjs +485 -218
- package/out/language/main.cjs.map +2 -2
- package/out/language/parser.js +8 -8
- package/out/language/parser.js.map +1 -1
- package/out/runtime/agents/common.d.ts +7 -1
- package/out/runtime/agents/common.d.ts.map +1 -1
- package/out/runtime/agents/common.js +101 -0
- package/out/runtime/agents/common.js.map +1 -1
- package/out/runtime/agents/impl/anthropic.js +4 -4
- package/out/runtime/agents/impl/anthropic.js.map +1 -1
- package/out/runtime/agents/impl/openai.js +4 -4
- package/out/runtime/agents/impl/openai.js.map +1 -1
- package/out/runtime/docs.d.ts.map +1 -1
- package/out/runtime/docs.js +109 -7
- package/out/runtime/docs.js.map +1 -1
- package/out/runtime/embeddings/chunker.d.ts +9 -0
- package/out/runtime/embeddings/chunker.d.ts.map +1 -0
- package/out/runtime/embeddings/chunker.js +41 -0
- package/out/runtime/embeddings/chunker.js.map +1 -0
- package/out/runtime/embeddings/index.d.ts +6 -0
- package/out/runtime/embeddings/index.d.ts.map +1 -0
- package/out/runtime/embeddings/index.js +6 -0
- package/out/runtime/embeddings/index.js.map +1 -0
- package/out/runtime/embeddings/openai.d.ts +15 -0
- package/out/runtime/embeddings/openai.d.ts.map +1 -0
- package/out/runtime/embeddings/openai.js +34 -0
- package/out/runtime/embeddings/openai.js.map +1 -0
- package/out/runtime/embeddings/provider.d.ts +20 -0
- package/out/runtime/embeddings/provider.d.ts.map +1 -0
- package/out/runtime/embeddings/provider.js +17 -0
- package/out/runtime/embeddings/provider.js.map +1 -0
- package/out/runtime/embeddings/registry.d.ts +3 -0
- package/out/runtime/embeddings/registry.d.ts.map +1 -0
- package/out/runtime/embeddings/registry.js +16 -0
- package/out/runtime/embeddings/registry.js.map +1 -0
- package/out/runtime/exec-graph.d.ts.map +1 -1
- package/out/runtime/exec-graph.js +5 -0
- package/out/runtime/exec-graph.js.map +1 -1
- package/out/runtime/interpreter.d.ts +4 -0
- package/out/runtime/interpreter.d.ts.map +1 -1
- package/out/runtime/interpreter.js +27 -7
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +42 -5
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/module.d.ts +22 -4
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +76 -10
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/ai.d.ts +20 -2
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +333 -37
- package/out/runtime/modules/ai.js.map +1 -1
- package/out/runtime/modules/auth.d.ts.map +1 -1
- package/out/runtime/modules/auth.js +11 -5
- package/out/runtime/modules/auth.js.map +1 -1
- package/out/runtime/resolvers/interface.d.ts +1 -1
- package/out/runtime/resolvers/interface.d.ts.map +1 -1
- package/out/runtime/resolvers/interface.js.map +1 -1
- package/out/runtime/resolvers/sqldb/database.d.ts +1 -1
- package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/database.js +139 -50
- package/out/runtime/resolvers/sqldb/database.js.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts +22 -2
- package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.js +178 -47
- package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
- package/out/runtime/state.d.ts +1 -0
- package/out/runtime/state.d.ts.map +1 -1
- package/out/runtime/state.js +3 -0
- package/out/runtime/state.js.map +1 -1
- package/out/syntaxes/agentlang.monarch.js +1 -1
- package/out/syntaxes/agentlang.monarch.js.map +1 -1
- package/package.json +188 -185
- package/public/pdf.worker.mjs +65152 -0
- package/src/cli/main.ts +7 -2
- package/src/language/agentlang.langium +8 -2
- package/src/language/generated/ast.ts +96 -2
- package/src/language/generated/grammar.ts +432 -218
- package/src/language/parser.ts +8 -8
- package/src/runtime/agents/common.ts +107 -0
- package/src/runtime/agents/impl/anthropic.ts +4 -4
- package/src/runtime/agents/impl/openai.ts +4 -4
- package/src/runtime/docs.ts +120 -9
- package/src/runtime/embeddings/chunker.ts +50 -0
- package/src/runtime/embeddings/index.ts +5 -0
- package/src/runtime/embeddings/openai.ts +49 -0
- package/src/runtime/embeddings/provider.ts +37 -0
- package/src/runtime/embeddings/registry.ts +17 -0
- package/src/runtime/exec-graph.ts +4 -0
- package/src/runtime/interpreter.ts +39 -16
- package/src/runtime/loader.ts +42 -3
- package/src/runtime/module.ts +127 -41
- package/src/runtime/modules/ai.ts +467 -38
- package/src/runtime/modules/auth.ts +11 -5
- package/src/runtime/resolvers/interface.ts +1 -1
- package/src/runtime/resolvers/sqldb/database.ts +146 -56
- package/src/runtime/resolvers/sqldb/impl.ts +238 -61
- package/src/runtime/state.ts +4 -0
- package/src/syntaxes/agentlang.monarch.ts +1 -1
- package/out/setupClassic.d.ts +0 -98
- package/out/setupClassic.d.ts.map +0 -1
- package/out/setupClassic.js +0 -38
- package/out/setupClassic.js.map +0 -1
- package/out/setupCommon.d.ts +0 -2
- package/out/setupCommon.d.ts.map +0 -1
- package/out/setupCommon.js +0 -33
- package/out/setupCommon.js.map +0 -1
- package/out/setupExtended.d.ts +0 -40
- package/out/setupExtended.d.ts.map +0 -1
- package/out/setupExtended.js +0 -67
- package/out/setupExtended.js.map +0 -1
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
makeCoreModuleName,
|
|
6
6
|
makeFqName,
|
|
7
7
|
nameToPath,
|
|
8
|
+
restoreSpecialChars,
|
|
8
9
|
sleepMilliseconds,
|
|
9
10
|
splitFqName,
|
|
10
11
|
} from '../util.js';
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
parseAndEvaluateStatement,
|
|
16
17
|
} from '../interpreter.js';
|
|
17
18
|
import {
|
|
19
|
+
AgentEvaluator,
|
|
18
20
|
asJSONSchema,
|
|
19
21
|
Decision,
|
|
20
22
|
fetchModule,
|
|
@@ -38,24 +40,26 @@ import {
|
|
|
38
40
|
humanMessage,
|
|
39
41
|
systemMessage,
|
|
40
42
|
} from '../agents/provider.js';
|
|
41
|
-
import { AIMessage, BaseMessage, HumanMessage } from '@langchain/core/messages';
|
|
43
|
+
import { AIMessage, BaseMessage, HumanMessage, SystemMessage } from '@langchain/core/messages';
|
|
42
44
|
import {
|
|
43
45
|
AgentCondition,
|
|
44
46
|
AgentGlossaryEntry,
|
|
45
47
|
AgentScenario,
|
|
48
|
+
AgentSummary as AgentLearningResult,
|
|
46
49
|
DecisionAgentInstructions,
|
|
50
|
+
EvalInstructions,
|
|
47
51
|
FlowExecInstructions,
|
|
48
52
|
getAgentDirectives,
|
|
49
53
|
getAgentGlossary,
|
|
50
54
|
getAgentResponseSchema,
|
|
51
55
|
getAgentScenarios,
|
|
52
56
|
getAgentScratchNames,
|
|
57
|
+
LearningAgentInstructions as LearnerAgentInstructions,
|
|
53
58
|
newAgentDirective,
|
|
54
59
|
newAgentGlossaryEntry,
|
|
55
60
|
newAgentScenario,
|
|
56
61
|
PlannerInstructions,
|
|
57
62
|
} from '../agents/common.js';
|
|
58
|
-
import { PathAttributeNameQuery } from '../defs.js';
|
|
59
63
|
import { logger } from '../logger.js';
|
|
60
64
|
import { FlowStep } from '../agents/flows.js';
|
|
61
65
|
import Handlebars from 'handlebars';
|
|
@@ -65,9 +69,14 @@ import { isMonitoringEnabled, TtlCache } from '../state.js';
|
|
|
65
69
|
export const CoreAIModuleName = makeCoreModuleName('ai');
|
|
66
70
|
export const AgentEntityName = 'Agent';
|
|
67
71
|
export const LlmEntityName = 'LLM';
|
|
72
|
+
export const AgentLearnerType = 'learner';
|
|
73
|
+
|
|
74
|
+
const AgentEvalType = 'eval';
|
|
68
75
|
|
|
69
76
|
export default `module ${CoreAIModuleName}
|
|
70
77
|
|
|
78
|
+
import "./modules/ai.js" @as ai
|
|
79
|
+
|
|
71
80
|
entity ${LlmEntityName} {
|
|
72
81
|
name String @id,
|
|
73
82
|
service String @default("openai"),
|
|
@@ -77,7 +86,7 @@ entity ${LlmEntityName} {
|
|
|
77
86
|
entity ${AgentEntityName} {
|
|
78
87
|
name String @id,
|
|
79
88
|
moduleName String @default("${CoreAIModuleName}"),
|
|
80
|
-
type @enum("chat", "planner", "flow-exec") @default("chat"),
|
|
89
|
+
type @enum("chat", "planner", "flow-exec", "${AgentEvalType}", "${AgentLearnerType}") @default("chat"),
|
|
81
90
|
runWorkflows Boolean @default(true),
|
|
82
91
|
instruction String @optional,
|
|
83
92
|
tools String @optional, // comma-separated list of tool names
|
|
@@ -136,8 +145,122 @@ entity GlossaryEntry {
|
|
|
136
145
|
meaning String,
|
|
137
146
|
synonyms String @optional
|
|
138
147
|
}
|
|
148
|
+
|
|
149
|
+
entity EvaluationResult {
|
|
150
|
+
id UUID @id @default(uuid()),
|
|
151
|
+
agentFqName String @indexed,
|
|
152
|
+
userRequest String,
|
|
153
|
+
score Int,
|
|
154
|
+
summary String
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
entity AgentLearningResult {
|
|
158
|
+
id UUID @id @default(uuid()),
|
|
159
|
+
agentFqName String @indexed,
|
|
160
|
+
data String,
|
|
161
|
+
summary String
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
@public event agentLearning{
|
|
165
|
+
agentName String,
|
|
166
|
+
agentModuleName String,
|
|
167
|
+
instruction String
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
workflow agentLearning {
|
|
171
|
+
await ai.processAgentLearning(agentLearning.agentModuleName, agentLearning.agentName, agentLearning.instruction)
|
|
172
|
+
}
|
|
139
173
|
`;
|
|
140
174
|
|
|
175
|
+
enum AgentCacheType {
|
|
176
|
+
DIRECTIVE,
|
|
177
|
+
GLOSSARY,
|
|
178
|
+
SCENARIO,
|
|
179
|
+
SUMMARY,
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
type AgentInstructionActivator = {
|
|
183
|
+
provider: AgentServiceProvider;
|
|
184
|
+
userMessage: string;
|
|
185
|
+
agentInstruction: string;
|
|
186
|
+
agentRole: string | undefined;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const MAX_USER_DEFINED_GLOSSARY = 20;
|
|
190
|
+
const MAX_USER_DEFINED_DIRECTIVES = 20;
|
|
191
|
+
const MAX_USER_DEFINED_SCENARIOS = 5;
|
|
192
|
+
const MAX_USER_DEFINED_SUMMARIES = 5;
|
|
193
|
+
|
|
194
|
+
async function activatedUserDefinedAgentLearnings<T>(
|
|
195
|
+
objLabel: string,
|
|
196
|
+
learningObjects: T[],
|
|
197
|
+
activator: AgentInstructionActivator,
|
|
198
|
+
maxResults: number
|
|
199
|
+
): Promise<T[]> {
|
|
200
|
+
const msg = `Consider the following ${objLabel} (in JSON format):
|
|
201
|
+
${JSON.stringify(learningObjects)}
|
|
202
|
+
|
|
203
|
+
Return the indices of the ${objLabel} relevant for the following text:
|
|
204
|
+
|
|
205
|
+
${activator.userMessage}
|
|
206
|
+
|
|
207
|
+
Return the relevant indices and a JSON array of integers with the index starting at zero (0). Do not return any additional comments
|
|
208
|
+
or text.
|
|
209
|
+
`;
|
|
210
|
+
const msgs = new Array<BaseMessage>();
|
|
211
|
+
msgs.push(
|
|
212
|
+
new SystemMessage(
|
|
213
|
+
'You are an agent that filters a JSON array and return relevant indices as a JSON array of integers.'
|
|
214
|
+
)
|
|
215
|
+
);
|
|
216
|
+
msgs.push(new HumanMessage(msg));
|
|
217
|
+
const response: AIResponse = await activator.provider.invoke(msgs, undefined);
|
|
218
|
+
const indices: number[] = JSON.parse(normalizeGeneratedCode(response.content));
|
|
219
|
+
if (indices.length == 0 || indices.length == learningObjects.length) return learningObjects;
|
|
220
|
+
const result = new Array<T>();
|
|
221
|
+
for (let i = 0; i < indices.length; ++i) {
|
|
222
|
+
if (i >= maxResults) break;
|
|
223
|
+
result.push(learningObjects[indices[i]]);
|
|
224
|
+
}
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async function activatedUserDefinedAgentGlossary(
|
|
229
|
+
gls: AgentGlossaryEntry[],
|
|
230
|
+
activator: AgentInstructionActivator
|
|
231
|
+
): Promise<AgentGlossaryEntry[]> {
|
|
232
|
+
return await activatedUserDefinedAgentLearnings<AgentGlossaryEntry>(
|
|
233
|
+
'glossary entries',
|
|
234
|
+
gls,
|
|
235
|
+
activator,
|
|
236
|
+
MAX_USER_DEFINED_GLOSSARY
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async function activatedUserDefinedAgentScenarios(
|
|
241
|
+
scns: AgentScenario[],
|
|
242
|
+
activator: AgentInstructionActivator
|
|
243
|
+
): Promise<AgentScenario[]> {
|
|
244
|
+
return await activatedUserDefinedAgentLearnings<AgentScenario>(
|
|
245
|
+
'scenarios',
|
|
246
|
+
scns,
|
|
247
|
+
activator,
|
|
248
|
+
MAX_USER_DEFINED_SCENARIOS
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
async function activatedUserDefinedAgentDirectives(
|
|
253
|
+
dirs: AgentCondition[],
|
|
254
|
+
activator: AgentInstructionActivator
|
|
255
|
+
): Promise<AgentCondition[]> {
|
|
256
|
+
return await activatedUserDefinedAgentLearnings<AgentCondition>(
|
|
257
|
+
'directives or conditions',
|
|
258
|
+
dirs,
|
|
259
|
+
activator,
|
|
260
|
+
MAX_USER_DEFINED_DIRECTIVES
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
|
|
141
264
|
export const AgentFqName = makeFqName(CoreAIModuleName, AgentEntityName);
|
|
142
265
|
|
|
143
266
|
const ProviderDb = new Map<string, AgentServiceProvider>();
|
|
@@ -276,10 +399,18 @@ export class AgentInstance {
|
|
|
276
399
|
return this.hasModuleTools || this.type == 'planner';
|
|
277
400
|
}
|
|
278
401
|
|
|
402
|
+
isLearner(): boolean {
|
|
403
|
+
return this.type === 'learner';
|
|
404
|
+
}
|
|
405
|
+
|
|
279
406
|
isFlowExecutor(): boolean {
|
|
280
407
|
return this.type == 'flow-exec';
|
|
281
408
|
}
|
|
282
409
|
|
|
410
|
+
isEvaluator(): boolean {
|
|
411
|
+
return this.type == AgentEvalType;
|
|
412
|
+
}
|
|
413
|
+
|
|
283
414
|
markAsDecisionExecutor(): AgentInstance {
|
|
284
415
|
this.decisionExecutor = true;
|
|
285
416
|
return this;
|
|
@@ -301,14 +432,22 @@ export class AgentInstance {
|
|
|
301
432
|
let r: AgentCondition[] = [];
|
|
302
433
|
if (result && result.length > 0) {
|
|
303
434
|
r = result.map((inst: Instance) => {
|
|
304
|
-
return newAgentDirective(
|
|
435
|
+
return newAgentDirective(
|
|
436
|
+
restoreSpecialChars(inst.lookup('condition')),
|
|
437
|
+
restoreSpecialChars(inst.lookup('consequent'))
|
|
438
|
+
);
|
|
305
439
|
});
|
|
306
440
|
}
|
|
307
441
|
return AgentInstance.DirectivesCache.set(fqName, r);
|
|
308
442
|
}
|
|
309
443
|
|
|
310
|
-
private async directivesAsString(
|
|
311
|
-
|
|
444
|
+
private async directivesAsString(
|
|
445
|
+
fqName: string,
|
|
446
|
+
activator: AgentInstructionActivator
|
|
447
|
+
): Promise<string> {
|
|
448
|
+
let userDirs = await this.getUserDefinedAgentDirectives(fqName);
|
|
449
|
+
if (userDirs.length > MAX_USER_DEFINED_DIRECTIVES)
|
|
450
|
+
userDirs = await activatedUserDefinedAgentDirectives(userDirs, activator);
|
|
312
451
|
const dirs = getAgentDirectives(fqName) || [];
|
|
313
452
|
const conds = dirs.concat(userDirs);
|
|
314
453
|
if (conds.length > 0) {
|
|
@@ -341,7 +480,7 @@ export class AgentInstance {
|
|
|
341
480
|
r = result.map((inst: Instance) => {
|
|
342
481
|
return newAgentGlossaryEntry(
|
|
343
482
|
inst.lookup('name'),
|
|
344
|
-
inst.lookup('meaning'),
|
|
483
|
+
restoreSpecialChars(inst.lookup('meaning')),
|
|
345
484
|
inst.lookup('synonyms')
|
|
346
485
|
);
|
|
347
486
|
});
|
|
@@ -349,6 +488,23 @@ export class AgentInstance {
|
|
|
349
488
|
return AgentInstance.GlossaryCache.set(fqName, r);
|
|
350
489
|
}
|
|
351
490
|
|
|
491
|
+
private static SummariesCache = new TtlCache<AgentLearningResult[]>(AgentInstance.CACHE_TTL_MS);
|
|
492
|
+
|
|
493
|
+
private async getUserDefinedAgentLearningResults(fqName: string): Promise<AgentLearningResult[]> {
|
|
494
|
+
const cached = AgentInstance.SummariesCache.get(fqName);
|
|
495
|
+
if (cached !== undefined) return cached;
|
|
496
|
+
const result: Instance[] = await parseAndEvaluateStatement(
|
|
497
|
+
`{${CoreAIModuleName}/AgentLearningResult {agentFqName? "${fqName}"}}`
|
|
498
|
+
);
|
|
499
|
+
let r: AgentLearningResult[] = [];
|
|
500
|
+
if (result && result.length > 0) {
|
|
501
|
+
r = result.map((inst: Instance) => {
|
|
502
|
+
return { data: inst.lookup('data'), summary: inst.lookup('summary') };
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
return AgentInstance.SummariesCache.set(fqName, r);
|
|
506
|
+
}
|
|
507
|
+
|
|
352
508
|
private static ScenariosCache = new TtlCache<AgentScenario[]>(AgentInstance.CACHE_TTL_MS);
|
|
353
509
|
|
|
354
510
|
private async getUserDefinedAgentScenarios(fqName: string): Promise<AgentScenario[]> {
|
|
@@ -366,12 +522,34 @@ export class AgentInstance {
|
|
|
366
522
|
return AgentInstance.ScenariosCache.set(fqName, r);
|
|
367
523
|
}
|
|
368
524
|
|
|
369
|
-
|
|
525
|
+
public static ResetCache(fqName: string, type: AgentCacheType) {
|
|
526
|
+
switch (type) {
|
|
527
|
+
case AgentCacheType.DIRECTIVE:
|
|
528
|
+
AgentInstance.DirectivesCache.delete(fqName);
|
|
529
|
+
break;
|
|
530
|
+
case AgentCacheType.GLOSSARY:
|
|
531
|
+
AgentInstance.GlossaryCache.delete(fqName);
|
|
532
|
+
break;
|
|
533
|
+
case AgentCacheType.SCENARIO:
|
|
534
|
+
AgentInstance.ScenariosCache.delete(fqName);
|
|
535
|
+
break;
|
|
536
|
+
case AgentCacheType.SUMMARY:
|
|
537
|
+
AgentInstance.SummariesCache.delete(fqName);
|
|
538
|
+
break;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
private async getFullInstructions(
|
|
543
|
+
env: Environment,
|
|
544
|
+
activator: AgentInstructionActivator
|
|
545
|
+
): Promise<string> {
|
|
370
546
|
const fqName = this.getFqName();
|
|
371
547
|
const ins = this.role ? `${this.role}\n${this.instruction || ''}` : this.instruction || '';
|
|
372
|
-
let finalInstruction = `${ins} ${await this.directivesAsString(fqName)}`;
|
|
548
|
+
let finalInstruction = `${ins} ${await this.directivesAsString(fqName, activator)}`;
|
|
373
549
|
const staticGls = getAgentGlossary(fqName) || [];
|
|
374
|
-
|
|
550
|
+
let userGls = await this.getUserDefinedAgentGlossary(fqName);
|
|
551
|
+
if (userGls.length > MAX_USER_DEFINED_GLOSSARY)
|
|
552
|
+
userGls = await activatedUserDefinedAgentGlossary(userGls, activator);
|
|
375
553
|
const gls = staticGls.concat(userGls);
|
|
376
554
|
if (gls.length > 0) {
|
|
377
555
|
const glss = new Array<string>();
|
|
@@ -384,7 +562,9 @@ export class AgentInstance {
|
|
|
384
562
|
${glss.join('\n')}\n`;
|
|
385
563
|
}
|
|
386
564
|
const staticScns = getAgentScenarios(fqName) || [];
|
|
387
|
-
|
|
565
|
+
let userScns = await this.getUserDefinedAgentScenarios(fqName);
|
|
566
|
+
if (userScns.length > MAX_USER_DEFINED_SCENARIOS)
|
|
567
|
+
userScns = await activatedUserDefinedAgentScenarios(userScns, activator);
|
|
388
568
|
const scenarios = staticScns.concat(userScns);
|
|
389
569
|
if (scenarios.length > 0) {
|
|
390
570
|
const scs = new Array<string>();
|
|
@@ -398,6 +578,20 @@ export class AgentInstance {
|
|
|
398
578
|
});
|
|
399
579
|
finalInstruction = `${finalInstruction}\nHere are some example user requests and the corresponding responses you are supposed to produce:\n${scs.join('\n')}`;
|
|
400
580
|
}
|
|
581
|
+
const summaries = await this.getUserDefinedAgentLearningResults(fqName);
|
|
582
|
+
if (summaries.length > 0) {
|
|
583
|
+
let s: string[] = summaries.map((sa: AgentLearningResult) => {
|
|
584
|
+
return restoreSpecialChars(sa.summary);
|
|
585
|
+
});
|
|
586
|
+
if (s.length > MAX_USER_DEFINED_SUMMARIES)
|
|
587
|
+
s = await activatedUserDefinedAgentLearnings<string>(
|
|
588
|
+
'summaries',
|
|
589
|
+
s,
|
|
590
|
+
activator,
|
|
591
|
+
MAX_USER_DEFINED_SUMMARIES
|
|
592
|
+
);
|
|
593
|
+
finalInstruction = `${finalInstruction}\nAlso keep in mind the following points:\n\n${s.join('\n')}\n\n`;
|
|
594
|
+
}
|
|
401
595
|
const responseSchema = getAgentResponseSchema(fqName);
|
|
402
596
|
if (responseSchema) {
|
|
403
597
|
finalInstruction = `${finalInstruction}\nReturn your response in the following JSON schema:\n${asJSONSchema(responseSchema)}
|
|
@@ -430,7 +624,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
430
624
|
if (response) {
|
|
431
625
|
const responseSchema = getAgentResponseSchema(this.getFqName());
|
|
432
626
|
if (responseSchema) {
|
|
433
|
-
const attrs = JSON.parse(
|
|
627
|
+
const attrs = JSON.parse(normalizeGeneratedCode(response));
|
|
434
628
|
const parts = nameToPath(responseSchema);
|
|
435
629
|
const moduleName = parts.getModuleName();
|
|
436
630
|
const entryName = parts.getEntryName();
|
|
@@ -495,16 +689,78 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
495
689
|
return this;
|
|
496
690
|
}
|
|
497
691
|
|
|
692
|
+
private static AgentEvaluators = new Map<string, AgentInstance>();
|
|
693
|
+
|
|
694
|
+
public static RegisterEvaluator(e: AgentEvaluator): AgentInstance {
|
|
695
|
+
const n = e.normalizedName();
|
|
696
|
+
const agentFqName = isFqName(n) ? n : makeFqName(e.moduleName, n);
|
|
697
|
+
const instruction = e.instruction;
|
|
698
|
+
let llm = e.llm;
|
|
699
|
+
const [agentModule, agentName] = splitFqName(agentFqName);
|
|
700
|
+
if (llm === undefined) llm = `${agentName}_llm`;
|
|
701
|
+
const inst = makeInstance(
|
|
702
|
+
CoreAIModuleName,
|
|
703
|
+
AgentEntityName,
|
|
704
|
+
newInstanceAttributes()
|
|
705
|
+
.set('llm', llm)
|
|
706
|
+
.set('name', agentName)
|
|
707
|
+
.set('moduleName', agentModule)
|
|
708
|
+
.set(
|
|
709
|
+
'instruction',
|
|
710
|
+
instruction || 'You are an agent that evaluates the performance of another agent.'
|
|
711
|
+
)
|
|
712
|
+
.set('type', AgentEvalType)
|
|
713
|
+
);
|
|
714
|
+
const einst = AgentInstance.FromInstance(inst).disableSession();
|
|
715
|
+
this.AgentEvaluators.set(agentFqName, einst);
|
|
716
|
+
return einst;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
private static async maybeEvaluateResponse(
|
|
720
|
+
agent: AgentInstance,
|
|
721
|
+
userRequest: string,
|
|
722
|
+
fullRequest: string,
|
|
723
|
+
response: string,
|
|
724
|
+
env: Environment
|
|
725
|
+
): Promise<void> {
|
|
726
|
+
const fqn = agent.getFqName();
|
|
727
|
+
const e: AgentInstance | undefined = AgentInstance.AgentEvaluators.get(fqn);
|
|
728
|
+
if (e !== undefined) {
|
|
729
|
+
await e.invoke(
|
|
730
|
+
JSON.stringify({ requestToAgent: fullRequest, responseFromAgent: response }),
|
|
731
|
+
env
|
|
732
|
+
);
|
|
733
|
+
try {
|
|
734
|
+
const r = JSON.parse(normalizeGeneratedCode(env.getLastResult()));
|
|
735
|
+
const score = r.score;
|
|
736
|
+
if (score === undefined || score === null) {
|
|
737
|
+
logger.warn(`Evaluation for agent ${fqn} failed to generate a valid score`);
|
|
738
|
+
} else {
|
|
739
|
+
await parseAndEvaluateStatement(`{${CoreAIModuleName}/EvaluationResult {
|
|
740
|
+
agentFqName "${fqn}",
|
|
741
|
+
userRequest "${escapeSpecialChars(userRequest)}",
|
|
742
|
+
score ${score},
|
|
743
|
+
summary "${escapeSpecialChars(r.summary)}"
|
|
744
|
+
}}`);
|
|
745
|
+
}
|
|
746
|
+
} catch (reason: any) {
|
|
747
|
+
logger.warn(`Failed to save evaluation for agent ${fqn} - ${reason}`);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
498
752
|
async invoke(message: string, env: Environment) {
|
|
499
753
|
const p = await findProviderForLLM(this.llm, env);
|
|
500
754
|
const agentName = this.name;
|
|
501
755
|
const chatId = env.getAgentChatId() || agentName;
|
|
502
756
|
let isplnr = this.isPlanner();
|
|
503
757
|
const isflow = !isplnr && this.isFlowExecutor();
|
|
504
|
-
|
|
758
|
+
const iseval = !isplnr && !isflow && this.isEvaluator();
|
|
759
|
+
const islearner = !isflow && !isplnr && !iseval && this.isLearner();
|
|
760
|
+
if ((isplnr || islearner || iseval) && this.withSession) {
|
|
505
761
|
this.withSession = false;
|
|
506
762
|
}
|
|
507
|
-
if (isflow) {
|
|
763
|
+
if (isflow || islearner) {
|
|
508
764
|
this.withSession = false;
|
|
509
765
|
}
|
|
510
766
|
if (this.withSession && env.getFlowContext()) {
|
|
@@ -520,19 +776,31 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
520
776
|
const sess: Instance | null = this.withSession ? await findAgentChatSession(chatId, env) : null;
|
|
521
777
|
let msgs: BaseMessage[] | undefined;
|
|
522
778
|
let cachedMsg: string | undefined = undefined;
|
|
779
|
+
const activator: AgentInstructionActivator = {
|
|
780
|
+
provider: p,
|
|
781
|
+
userMessage: message,
|
|
782
|
+
agentInstruction: this.instruction,
|
|
783
|
+
agentRole: this.role,
|
|
784
|
+
};
|
|
523
785
|
if (sess) {
|
|
524
786
|
msgs = sess.lookup('messages');
|
|
525
787
|
} else {
|
|
526
|
-
cachedMsg = await this.getFullInstructions(env);
|
|
788
|
+
cachedMsg = await this.getFullInstructions(env, activator);
|
|
527
789
|
msgs = [systemMessage(cachedMsg || '')];
|
|
528
790
|
}
|
|
529
791
|
if (msgs) {
|
|
530
792
|
try {
|
|
531
793
|
const sysMsg = msgs[0];
|
|
532
|
-
if (isplnr || isflow) {
|
|
533
|
-
const s = isplnr
|
|
794
|
+
if (isplnr || isflow || iseval || islearner) {
|
|
795
|
+
const s = isplnr
|
|
796
|
+
? PlannerInstructions
|
|
797
|
+
: isflow
|
|
798
|
+
? FlowExecInstructions
|
|
799
|
+
: iseval
|
|
800
|
+
? EvalInstructions
|
|
801
|
+
: LearnerAgentInstructions;
|
|
534
802
|
const ts = this.toolsAsString();
|
|
535
|
-
const msg = `${s}\n${ts}\n${cachedMsg || (await this.getFullInstructions(env))}`;
|
|
803
|
+
const msg = `${s}\n${ts}\n${cachedMsg || (await this.getFullInstructions(env, activator))}`;
|
|
536
804
|
const newSysMsg = systemMessage(msg);
|
|
537
805
|
msgs[0] = newSysMsg;
|
|
538
806
|
}
|
|
@@ -570,6 +838,14 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
570
838
|
if (v) {
|
|
571
839
|
response = await this.handleValidation(response, v, msgs, p);
|
|
572
840
|
}
|
|
841
|
+
if (!iseval)
|
|
842
|
+
await AgentInstance.maybeEvaluateResponse(
|
|
843
|
+
this,
|
|
844
|
+
message,
|
|
845
|
+
msgsContent,
|
|
846
|
+
response.content,
|
|
847
|
+
env
|
|
848
|
+
);
|
|
573
849
|
msgs.push(assistantMessage(response.content));
|
|
574
850
|
if (isplnr) {
|
|
575
851
|
msgs[0] = sysMsg;
|
|
@@ -606,7 +882,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
606
882
|
validationEventName: string
|
|
607
883
|
): Promise<Instance> {
|
|
608
884
|
let isstr = true;
|
|
609
|
-
const content =
|
|
885
|
+
const content = normalizeGeneratedCode(response.content);
|
|
610
886
|
try {
|
|
611
887
|
const c = JSON.parse(content);
|
|
612
888
|
isstr = isString(c);
|
|
@@ -703,34 +979,92 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
703
979
|
|
|
704
980
|
private async maybeAddRelevantDocuments(message: string, env: Environment): Promise<string> {
|
|
705
981
|
if (this.documents && this.documents.length > 0) {
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
const
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
const
|
|
713
|
-
`{${CoreAIModuleName}/Document {
|
|
982
|
+
try {
|
|
983
|
+
const docNames = this.documents.split(',').map(d => d.trim());
|
|
984
|
+
|
|
985
|
+
const searchQuery = message;
|
|
986
|
+
|
|
987
|
+
try {
|
|
988
|
+
const semanticResult: any[] = await parseHelper(
|
|
989
|
+
`{${CoreAIModuleName}/Document {content? "${searchQuery.replace(/"/g, '\\"')}"}}`,
|
|
714
990
|
env
|
|
715
991
|
);
|
|
716
|
-
|
|
717
|
-
|
|
992
|
+
|
|
993
|
+
if (semanticResult && semanticResult.length > 0) {
|
|
994
|
+
const docs: Instance[] = [];
|
|
995
|
+
for (const doc of semanticResult) {
|
|
996
|
+
const docTitle = doc.lookup ? doc.lookup('title') : doc.title;
|
|
997
|
+
if (AgentInstance.docTitlesMatch(docTitle, docNames)) {
|
|
998
|
+
docs.push(
|
|
999
|
+
doc instanceof Instance
|
|
1000
|
+
? doc
|
|
1001
|
+
: Instance.newWithAttributes(doc, new Map(Object.entries(doc)))
|
|
1002
|
+
);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
if (docs.length > 0) {
|
|
1007
|
+
return message.concat('\n\nRelevant context from documents:\n').concat(
|
|
1008
|
+
docs
|
|
1009
|
+
.map((v: Instance) => {
|
|
1010
|
+
return `Document: ${v.lookup('title')}\n${v.lookup('content') as string}`;
|
|
1011
|
+
})
|
|
1012
|
+
.join('\n\n---\n\n')
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
718
1015
|
}
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
docs
|
|
723
|
-
.map((v: Instance) => {
|
|
724
|
-
return v.lookup('content');
|
|
725
|
-
})
|
|
726
|
-
.join('\n')
|
|
1016
|
+
} catch (semanticErr) {
|
|
1017
|
+
logger.debug(
|
|
1018
|
+
`Semantic search is not available, falling back to title-based filtering: ${semanticErr}`
|
|
727
1019
|
);
|
|
728
1020
|
}
|
|
1021
|
+
|
|
1022
|
+
const result: any[] = await parseHelper(`{${CoreAIModuleName}/Document? {}}`, env);
|
|
1023
|
+
if (result && result.length > 0) {
|
|
1024
|
+
const docs: Instance[] = [];
|
|
1025
|
+
for (let i = 0; i < result.length; ++i) {
|
|
1026
|
+
const v: any = result[i];
|
|
1027
|
+
const docTitle: string | undefined = AgentInstance.getDocumentTitle(v);
|
|
1028
|
+
|
|
1029
|
+
if (docTitle && docNames.includes(docTitle)) {
|
|
1030
|
+
if (v instanceof Instance) {
|
|
1031
|
+
docs.push(v);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
if (docs.length > 0) {
|
|
1037
|
+
return message.concat('\n\nRelevant context from documents:\n').concat(
|
|
1038
|
+
docs
|
|
1039
|
+
.map((v: Instance) => {
|
|
1040
|
+
return v.lookup('content') as string;
|
|
1041
|
+
})
|
|
1042
|
+
.join('\n\n')
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
} catch (err) {
|
|
1047
|
+
logger.debug(`Error retrieving documents: ${err}`);
|
|
729
1048
|
}
|
|
730
1049
|
}
|
|
731
1050
|
return message;
|
|
732
1051
|
}
|
|
733
1052
|
|
|
1053
|
+
private static docTitlesMatch(title: string | undefined, docNames: string[]): boolean {
|
|
1054
|
+
return title !== undefined && docNames.includes(title);
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
private static getDocumentTitle(doc: any): string | undefined {
|
|
1058
|
+
if (typeof doc.lookup === 'function') {
|
|
1059
|
+
return doc.lookup('title') as string | undefined;
|
|
1060
|
+
} else if (doc.attributes) {
|
|
1061
|
+
return doc.attributes.get('title') as string | undefined;
|
|
1062
|
+
} else if (doc.title) {
|
|
1063
|
+
return doc.title;
|
|
1064
|
+
}
|
|
1065
|
+
return undefined;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
734
1068
|
private static ToolsCache = new Map<string, string>();
|
|
735
1069
|
|
|
736
1070
|
private toolsAsString(): string {
|
|
@@ -920,7 +1254,7 @@ function processScenarioResponse(resp: string): string {
|
|
|
920
1254
|
return resp;
|
|
921
1255
|
}
|
|
922
1256
|
|
|
923
|
-
export function
|
|
1257
|
+
export function normalizeGeneratedCode(code: string | undefined): string {
|
|
924
1258
|
if (code !== undefined) {
|
|
925
1259
|
let s = code.trim();
|
|
926
1260
|
if (s.startsWith('```')) {
|
|
@@ -935,3 +1269,98 @@ export function trimGeneratedCode(code: string | undefined): string {
|
|
|
935
1269
|
return '';
|
|
936
1270
|
}
|
|
937
1271
|
}
|
|
1272
|
+
|
|
1273
|
+
async function parseAndInternAgentLearning(
|
|
1274
|
+
moduleName: string,
|
|
1275
|
+
agentName: string,
|
|
1276
|
+
learning: string,
|
|
1277
|
+
env: Environment
|
|
1278
|
+
) {
|
|
1279
|
+
const obj = JSON.parse(normalizeGeneratedCode(learning));
|
|
1280
|
+
const fqName = makeFqName(moduleName, agentName);
|
|
1281
|
+
if (obj.decisions) {
|
|
1282
|
+
for (let j = 0; j < obj.decisions.length; ++j) {
|
|
1283
|
+
const conds: any[] = obj.decisions[j].conditions;
|
|
1284
|
+
if (conds && conds.length > 0) {
|
|
1285
|
+
AgentInstance.ResetCache(fqName, AgentCacheType.DIRECTIVE);
|
|
1286
|
+
for (let i = 0; i < conds.length; ++i) {
|
|
1287
|
+
const entry: any = conds[i];
|
|
1288
|
+
const cond: string = entry.if;
|
|
1289
|
+
const conseq: string = entry.then;
|
|
1290
|
+
if (cond && conseq) {
|
|
1291
|
+
await parseAndEvaluateStatement(
|
|
1292
|
+
`{${CoreAIModuleName}/Directive {
|
|
1293
|
+
agentFqName "${fqName}",
|
|
1294
|
+
condition "${escapeSpecialChars(cond)}",
|
|
1295
|
+
consequent "${escapeSpecialChars(conseq)}"}}`,
|
|
1296
|
+
env.getActiveUser(),
|
|
1297
|
+
env
|
|
1298
|
+
);
|
|
1299
|
+
} else {
|
|
1300
|
+
throw new Error(`Invalid directive generated - missing 'if' or 'then' in ${learning}`);
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
if (obj.glossary) {
|
|
1307
|
+
AgentInstance.ResetCache(fqName, AgentCacheType.GLOSSARY);
|
|
1308
|
+
for (let i = 0; i < obj.glossary.length; ++i) {
|
|
1309
|
+
const word = obj.glossary[i].word;
|
|
1310
|
+
const meaning = obj.glossary[i].meaning;
|
|
1311
|
+
if (word && meaning) {
|
|
1312
|
+
await parseAndEvaluateStatement(
|
|
1313
|
+
`{${CoreAIModuleName}/GlossaryEntry {
|
|
1314
|
+
agentFqName "${fqName}",
|
|
1315
|
+
name "${word}",
|
|
1316
|
+
meaning "${escapeSpecialChars(meaning)}"}}`,
|
|
1317
|
+
env.getActiveUser(),
|
|
1318
|
+
env
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
if (obj.scenarios) {
|
|
1324
|
+
AgentInstance.ResetCache(fqName, AgentCacheType.SCENARIO);
|
|
1325
|
+
for (let i = 0; i < obj.scenarios.length; ++i) {
|
|
1326
|
+
const user = obj.scenarios[i].user;
|
|
1327
|
+
const ai = obj.scenarios[i].ai;
|
|
1328
|
+
if (user && ai) {
|
|
1329
|
+
await parseAndEvaluateStatement(
|
|
1330
|
+
`{${CoreAIModuleName}/Scenario {
|
|
1331
|
+
agentFqName "${fqName}",
|
|
1332
|
+
user "${escapeSpecialChars(user)}",
|
|
1333
|
+
ai "${escapeSpecialChars(ai)}"}}`,
|
|
1334
|
+
env.getActiveUser(),
|
|
1335
|
+
env
|
|
1336
|
+
);
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
AgentInstance.ResetCache(fqName, AgentCacheType.SUMMARY);
|
|
1341
|
+
const summary = obj.summary;
|
|
1342
|
+
delete obj.summary;
|
|
1343
|
+
await parseAndEvaluateStatement(
|
|
1344
|
+
`{${CoreAIModuleName}/AgentLearningResult {
|
|
1345
|
+
agentFqName "${fqName}",
|
|
1346
|
+
data "${escapeSpecialChars(JSON.stringify(obj))}",
|
|
1347
|
+
summary "${escapeSpecialChars(summary) || ''}"}}`,
|
|
1348
|
+
env.getActiveUser(),
|
|
1349
|
+
env
|
|
1350
|
+
);
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
export async function processAgentLearning(
|
|
1354
|
+
moduleName: string,
|
|
1355
|
+
agentName: string,
|
|
1356
|
+
instruction: string,
|
|
1357
|
+
env: Environment
|
|
1358
|
+
): Promise<any> {
|
|
1359
|
+
const learning = await parseAndEvaluateStatement(
|
|
1360
|
+
`{${moduleName}/${agentName}_${AgentLearnerType} {message \`${instruction}\`}}`,
|
|
1361
|
+
env.getActiveUser(),
|
|
1362
|
+
env
|
|
1363
|
+
);
|
|
1364
|
+
await parseAndInternAgentLearning(moduleName, agentName, learning, env);
|
|
1365
|
+
return { agentLearning: { result: learning } };
|
|
1366
|
+
}
|