agentlang 0.9.4 → 0.9.6
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/api/http.js +8 -2
- package/out/api/http.js.map +1 -1
- package/out/extension/main.cjs +253 -253
- package/out/extension/main.cjs.map +2 -2
- package/out/language/generated/ast.d.ts +1997 -151
- package/out/language/generated/ast.d.ts.map +1 -1
- package/out/language/generated/ast.js +2113 -1263
- package/out/language/generated/ast.js.map +1 -1
- package/out/language/generated/grammar.d.ts +1 -1
- package/out/language/generated/grammar.d.ts.map +1 -1
- package/out/language/generated/grammar.js +649 -762
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/generated/module.d.ts +1 -1
- package/out/language/generated/module.js +1 -1
- package/out/language/main.cjs +6401 -4072
- package/out/language/main.cjs.map +4 -4
- 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/auth/defs.d.ts +1 -1
- package/out/runtime/auth/defs.js +1 -1
- package/out/runtime/defs.d.ts +1 -1
- package/out/runtime/defs.js +1 -1
- 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 +20 -4
- package/out/runtime/interpreter.js.map +1 -1
- package/out/runtime/loader.d.ts.map +1 -1
- package/out/runtime/loader.js +43 -6
- package/out/runtime/loader.js.map +1 -1
- package/out/runtime/module.d.ts +18 -3
- package/out/runtime/module.d.ts.map +1 -1
- package/out/runtime/module.js +62 -4
- package/out/runtime/module.js.map +1 -1
- package/out/runtime/modules/ai.d.ts +18 -2
- package/out/runtime/modules/ai.d.ts.map +1 -1
- package/out/runtime/modules/ai.js +271 -21
- 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 -0
- package/out/runtime/resolvers/sqldb/database.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/database.js +19 -10
- package/out/runtime/resolvers/sqldb/database.js.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts +1 -1
- package/out/runtime/resolvers/sqldb/impl.d.ts.map +1 -1
- package/out/runtime/resolvers/sqldb/impl.js +2 -2
- package/out/runtime/resolvers/sqldb/impl.js.map +1 -1
- package/out/runtime/state.d.ts +37 -367
- 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/setupClassic.d.ts +98 -0
- package/out/setupClassic.d.ts.map +1 -0
- package/out/setupClassic.js +38 -0
- package/out/setupClassic.js.map +1 -0
- package/out/setupCommon.d.ts +2 -0
- package/out/setupCommon.d.ts.map +1 -0
- package/out/setupCommon.js +33 -0
- package/out/setupCommon.js.map +1 -0
- package/out/setupExtended.d.ts +40 -0
- package/out/setupExtended.d.ts.map +1 -0
- package/out/setupExtended.js +67 -0
- package/out/setupExtended.js.map +1 -0
- package/out/syntaxes/agentlang.monarch.js +4 -4
- package/out/syntaxes/agentlang.monarch.js.map +1 -1
- package/out/utils/runtime.d.ts +7 -6
- package/out/utils/runtime.d.ts.map +1 -1
- package/package.json +185 -187
- package/src/api/http.ts +8 -2
- package/src/language/agentlang.langium +8 -2
- package/src/language/generated/ast.ts +2204 -1322
- package/src/language/generated/grammar.ts +649 -762
- package/src/language/generated/module.ts +1 -1
- 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/auth/defs.ts +1 -1
- package/src/runtime/defs.ts +1 -1
- package/src/runtime/exec-graph.ts +4 -0
- package/src/runtime/interpreter.ts +23 -4
- package/src/runtime/loader.ts +43 -4
- package/src/runtime/module.ts +80 -3
- package/src/runtime/modules/ai.ts +391 -19
- package/src/runtime/modules/auth.ts +11 -5
- package/src/runtime/resolvers/interface.ts +1 -1
- package/src/runtime/resolvers/sqldb/database.ts +20 -11
- package/src/runtime/resolvers/sqldb/impl.ts +3 -3
- package/src/runtime/state.ts +4 -0
- package/src/syntaxes/agentlang.monarch.ts +4 -4
|
@@ -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,18 +40,21 @@ 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,
|
|
@@ -65,9 +70,14 @@ import { isMonitoringEnabled, TtlCache } from '../state.js';
|
|
|
65
70
|
export const CoreAIModuleName = makeCoreModuleName('ai');
|
|
66
71
|
export const AgentEntityName = 'Agent';
|
|
67
72
|
export const LlmEntityName = 'LLM';
|
|
73
|
+
export const AgentLearnerType = 'learner';
|
|
74
|
+
|
|
75
|
+
const AgentEvalType = 'eval';
|
|
68
76
|
|
|
69
77
|
export default `module ${CoreAIModuleName}
|
|
70
78
|
|
|
79
|
+
import "./modules/ai.js" @as ai
|
|
80
|
+
|
|
71
81
|
entity ${LlmEntityName} {
|
|
72
82
|
name String @id,
|
|
73
83
|
service String @default("openai"),
|
|
@@ -77,7 +87,7 @@ entity ${LlmEntityName} {
|
|
|
77
87
|
entity ${AgentEntityName} {
|
|
78
88
|
name String @id,
|
|
79
89
|
moduleName String @default("${CoreAIModuleName}"),
|
|
80
|
-
type @enum("chat", "planner", "flow-exec") @default("chat"),
|
|
90
|
+
type @enum("chat", "planner", "flow-exec", "${AgentEvalType}", "${AgentLearnerType}") @default("chat"),
|
|
81
91
|
runWorkflows Boolean @default(true),
|
|
82
92
|
instruction String @optional,
|
|
83
93
|
tools String @optional, // comma-separated list of tool names
|
|
@@ -136,8 +146,122 @@ entity GlossaryEntry {
|
|
|
136
146
|
meaning String,
|
|
137
147
|
synonyms String @optional
|
|
138
148
|
}
|
|
149
|
+
|
|
150
|
+
entity EvaluationResult {
|
|
151
|
+
id UUID @id @default(uuid()),
|
|
152
|
+
agentFqName String @indexed,
|
|
153
|
+
userRequest String,
|
|
154
|
+
score Int,
|
|
155
|
+
summary String
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
entity AgentLearningResult {
|
|
159
|
+
id UUID @id @default(uuid()),
|
|
160
|
+
agentFqName String @indexed,
|
|
161
|
+
data String,
|
|
162
|
+
summary String
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@public event agentLearning{
|
|
166
|
+
agentName String,
|
|
167
|
+
agentModuleName String,
|
|
168
|
+
instruction String
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
workflow agentLearning {
|
|
172
|
+
await ai.processAgentLearning(agentLearning.agentModuleName, agentLearning.agentName, agentLearning.instruction)
|
|
173
|
+
}
|
|
139
174
|
`;
|
|
140
175
|
|
|
176
|
+
enum AgentCacheType {
|
|
177
|
+
DIRECTIVE,
|
|
178
|
+
GLOSSARY,
|
|
179
|
+
SCENARIO,
|
|
180
|
+
SUMMARY,
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
type AgentInstructionActivator = {
|
|
184
|
+
provider: AgentServiceProvider;
|
|
185
|
+
userMessage: string;
|
|
186
|
+
agentInstruction: string;
|
|
187
|
+
agentRole: string | undefined;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const MAX_USER_DEFINED_GLOSSARY = 20;
|
|
191
|
+
const MAX_USER_DEFINED_DIRECTIVES = 20;
|
|
192
|
+
const MAX_USER_DEFINED_SCENARIOS = 5;
|
|
193
|
+
const MAX_USER_DEFINED_SUMMARIES = 5;
|
|
194
|
+
|
|
195
|
+
async function activatedUserDefinedAgentLearnings<T>(
|
|
196
|
+
objLabel: string,
|
|
197
|
+
learningObjects: T[],
|
|
198
|
+
activator: AgentInstructionActivator,
|
|
199
|
+
maxResults: number
|
|
200
|
+
): Promise<T[]> {
|
|
201
|
+
const msg = `Consider the following ${objLabel} (in JSON format):
|
|
202
|
+
${JSON.stringify(learningObjects)}
|
|
203
|
+
|
|
204
|
+
Return the indices of the ${objLabel} relevant for the following text:
|
|
205
|
+
|
|
206
|
+
${activator.userMessage}
|
|
207
|
+
|
|
208
|
+
Return the relevant indices and a JSON array of integers with the index starting at zero (0). Do not return any additional comments
|
|
209
|
+
or text.
|
|
210
|
+
`;
|
|
211
|
+
const msgs = new Array<BaseMessage>();
|
|
212
|
+
msgs.push(
|
|
213
|
+
new SystemMessage(
|
|
214
|
+
'You are an agent that filters a JSON array and return relevant indices as a JSON array of integers.'
|
|
215
|
+
)
|
|
216
|
+
);
|
|
217
|
+
msgs.push(new HumanMessage(msg));
|
|
218
|
+
const response: AIResponse = await activator.provider.invoke(msgs, undefined);
|
|
219
|
+
const indices: number[] = JSON.parse(normalizeGeneratedCode(response.content));
|
|
220
|
+
if (indices.length == 0 || indices.length == learningObjects.length) return learningObjects;
|
|
221
|
+
const result = new Array<T>();
|
|
222
|
+
for (let i = 0; i < indices.length; ++i) {
|
|
223
|
+
if (i >= maxResults) break;
|
|
224
|
+
result.push(learningObjects[indices[i]]);
|
|
225
|
+
}
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async function activatedUserDefinedAgentGlossary(
|
|
230
|
+
gls: AgentGlossaryEntry[],
|
|
231
|
+
activator: AgentInstructionActivator
|
|
232
|
+
): Promise<AgentGlossaryEntry[]> {
|
|
233
|
+
return await activatedUserDefinedAgentLearnings<AgentGlossaryEntry>(
|
|
234
|
+
'glossary entries',
|
|
235
|
+
gls,
|
|
236
|
+
activator,
|
|
237
|
+
MAX_USER_DEFINED_GLOSSARY
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async function activatedUserDefinedAgentScenarios(
|
|
242
|
+
scns: AgentScenario[],
|
|
243
|
+
activator: AgentInstructionActivator
|
|
244
|
+
): Promise<AgentScenario[]> {
|
|
245
|
+
return await activatedUserDefinedAgentLearnings<AgentScenario>(
|
|
246
|
+
'scenarios',
|
|
247
|
+
scns,
|
|
248
|
+
activator,
|
|
249
|
+
MAX_USER_DEFINED_SCENARIOS
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async function activatedUserDefinedAgentDirectives(
|
|
254
|
+
dirs: AgentCondition[],
|
|
255
|
+
activator: AgentInstructionActivator
|
|
256
|
+
): Promise<AgentCondition[]> {
|
|
257
|
+
return await activatedUserDefinedAgentLearnings<AgentCondition>(
|
|
258
|
+
'directives or conditions',
|
|
259
|
+
dirs,
|
|
260
|
+
activator,
|
|
261
|
+
MAX_USER_DEFINED_DIRECTIVES
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
141
265
|
export const AgentFqName = makeFqName(CoreAIModuleName, AgentEntityName);
|
|
142
266
|
|
|
143
267
|
const ProviderDb = new Map<string, AgentServiceProvider>();
|
|
@@ -276,10 +400,18 @@ export class AgentInstance {
|
|
|
276
400
|
return this.hasModuleTools || this.type == 'planner';
|
|
277
401
|
}
|
|
278
402
|
|
|
403
|
+
isLearner(): boolean {
|
|
404
|
+
return this.type === 'learner';
|
|
405
|
+
}
|
|
406
|
+
|
|
279
407
|
isFlowExecutor(): boolean {
|
|
280
408
|
return this.type == 'flow-exec';
|
|
281
409
|
}
|
|
282
410
|
|
|
411
|
+
isEvaluator(): boolean {
|
|
412
|
+
return this.type == AgentEvalType;
|
|
413
|
+
}
|
|
414
|
+
|
|
283
415
|
markAsDecisionExecutor(): AgentInstance {
|
|
284
416
|
this.decisionExecutor = true;
|
|
285
417
|
return this;
|
|
@@ -301,14 +433,22 @@ export class AgentInstance {
|
|
|
301
433
|
let r: AgentCondition[] = [];
|
|
302
434
|
if (result && result.length > 0) {
|
|
303
435
|
r = result.map((inst: Instance) => {
|
|
304
|
-
return newAgentDirective(
|
|
436
|
+
return newAgentDirective(
|
|
437
|
+
restoreSpecialChars(inst.lookup('condition')),
|
|
438
|
+
restoreSpecialChars(inst.lookup('consequent'))
|
|
439
|
+
);
|
|
305
440
|
});
|
|
306
441
|
}
|
|
307
442
|
return AgentInstance.DirectivesCache.set(fqName, r);
|
|
308
443
|
}
|
|
309
444
|
|
|
310
|
-
private async directivesAsString(
|
|
311
|
-
|
|
445
|
+
private async directivesAsString(
|
|
446
|
+
fqName: string,
|
|
447
|
+
activator: AgentInstructionActivator
|
|
448
|
+
): Promise<string> {
|
|
449
|
+
let userDirs = await this.getUserDefinedAgentDirectives(fqName);
|
|
450
|
+
if (userDirs.length > MAX_USER_DEFINED_DIRECTIVES)
|
|
451
|
+
userDirs = await activatedUserDefinedAgentDirectives(userDirs, activator);
|
|
312
452
|
const dirs = getAgentDirectives(fqName) || [];
|
|
313
453
|
const conds = dirs.concat(userDirs);
|
|
314
454
|
if (conds.length > 0) {
|
|
@@ -341,7 +481,7 @@ export class AgentInstance {
|
|
|
341
481
|
r = result.map((inst: Instance) => {
|
|
342
482
|
return newAgentGlossaryEntry(
|
|
343
483
|
inst.lookup('name'),
|
|
344
|
-
inst.lookup('meaning'),
|
|
484
|
+
restoreSpecialChars(inst.lookup('meaning')),
|
|
345
485
|
inst.lookup('synonyms')
|
|
346
486
|
);
|
|
347
487
|
});
|
|
@@ -349,6 +489,23 @@ export class AgentInstance {
|
|
|
349
489
|
return AgentInstance.GlossaryCache.set(fqName, r);
|
|
350
490
|
}
|
|
351
491
|
|
|
492
|
+
private static SummariesCache = new TtlCache<AgentLearningResult[]>(AgentInstance.CACHE_TTL_MS);
|
|
493
|
+
|
|
494
|
+
private async getUserDefinedAgentLearningResults(fqName: string): Promise<AgentLearningResult[]> {
|
|
495
|
+
const cached = AgentInstance.SummariesCache.get(fqName);
|
|
496
|
+
if (cached !== undefined) return cached;
|
|
497
|
+
const result: Instance[] = await parseAndEvaluateStatement(
|
|
498
|
+
`{${CoreAIModuleName}/AgentLearningResult {agentFqName? "${fqName}"}}`
|
|
499
|
+
);
|
|
500
|
+
let r: AgentLearningResult[] = [];
|
|
501
|
+
if (result && result.length > 0) {
|
|
502
|
+
r = result.map((inst: Instance) => {
|
|
503
|
+
return { data: inst.lookup('data'), summary: inst.lookup('summary') };
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
return AgentInstance.SummariesCache.set(fqName, r);
|
|
507
|
+
}
|
|
508
|
+
|
|
352
509
|
private static ScenariosCache = new TtlCache<AgentScenario[]>(AgentInstance.CACHE_TTL_MS);
|
|
353
510
|
|
|
354
511
|
private async getUserDefinedAgentScenarios(fqName: string): Promise<AgentScenario[]> {
|
|
@@ -366,12 +523,34 @@ export class AgentInstance {
|
|
|
366
523
|
return AgentInstance.ScenariosCache.set(fqName, r);
|
|
367
524
|
}
|
|
368
525
|
|
|
369
|
-
|
|
526
|
+
public static ResetCache(fqName: string, type: AgentCacheType) {
|
|
527
|
+
switch (type) {
|
|
528
|
+
case AgentCacheType.DIRECTIVE:
|
|
529
|
+
AgentInstance.DirectivesCache.delete(fqName);
|
|
530
|
+
break;
|
|
531
|
+
case AgentCacheType.GLOSSARY:
|
|
532
|
+
AgentInstance.GlossaryCache.delete(fqName);
|
|
533
|
+
break;
|
|
534
|
+
case AgentCacheType.SCENARIO:
|
|
535
|
+
AgentInstance.ScenariosCache.delete(fqName);
|
|
536
|
+
break;
|
|
537
|
+
case AgentCacheType.SUMMARY:
|
|
538
|
+
AgentInstance.SummariesCache.delete(fqName);
|
|
539
|
+
break;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
private async getFullInstructions(
|
|
544
|
+
env: Environment,
|
|
545
|
+
activator: AgentInstructionActivator
|
|
546
|
+
): Promise<string> {
|
|
370
547
|
const fqName = this.getFqName();
|
|
371
548
|
const ins = this.role ? `${this.role}\n${this.instruction || ''}` : this.instruction || '';
|
|
372
|
-
let finalInstruction = `${ins} ${await this.directivesAsString(fqName)}`;
|
|
549
|
+
let finalInstruction = `${ins} ${await this.directivesAsString(fqName, activator)}`;
|
|
373
550
|
const staticGls = getAgentGlossary(fqName) || [];
|
|
374
|
-
|
|
551
|
+
let userGls = await this.getUserDefinedAgentGlossary(fqName);
|
|
552
|
+
if (userGls.length > MAX_USER_DEFINED_GLOSSARY)
|
|
553
|
+
userGls = await activatedUserDefinedAgentGlossary(userGls, activator);
|
|
375
554
|
const gls = staticGls.concat(userGls);
|
|
376
555
|
if (gls.length > 0) {
|
|
377
556
|
const glss = new Array<string>();
|
|
@@ -384,7 +563,9 @@ export class AgentInstance {
|
|
|
384
563
|
${glss.join('\n')}\n`;
|
|
385
564
|
}
|
|
386
565
|
const staticScns = getAgentScenarios(fqName) || [];
|
|
387
|
-
|
|
566
|
+
let userScns = await this.getUserDefinedAgentScenarios(fqName);
|
|
567
|
+
if (userScns.length > MAX_USER_DEFINED_SCENARIOS)
|
|
568
|
+
userScns = await activatedUserDefinedAgentScenarios(userScns, activator);
|
|
388
569
|
const scenarios = staticScns.concat(userScns);
|
|
389
570
|
if (scenarios.length > 0) {
|
|
390
571
|
const scs = new Array<string>();
|
|
@@ -398,6 +579,20 @@ export class AgentInstance {
|
|
|
398
579
|
});
|
|
399
580
|
finalInstruction = `${finalInstruction}\nHere are some example user requests and the corresponding responses you are supposed to produce:\n${scs.join('\n')}`;
|
|
400
581
|
}
|
|
582
|
+
const summaries = await this.getUserDefinedAgentLearningResults(fqName);
|
|
583
|
+
if (summaries.length > 0) {
|
|
584
|
+
let s: string[] = summaries.map((sa: AgentLearningResult) => {
|
|
585
|
+
return restoreSpecialChars(sa.summary);
|
|
586
|
+
});
|
|
587
|
+
if (s.length > MAX_USER_DEFINED_SUMMARIES)
|
|
588
|
+
s = await activatedUserDefinedAgentLearnings<string>(
|
|
589
|
+
'summaries',
|
|
590
|
+
s,
|
|
591
|
+
activator,
|
|
592
|
+
MAX_USER_DEFINED_SUMMARIES
|
|
593
|
+
);
|
|
594
|
+
finalInstruction = `${finalInstruction}\nAlso keep in mind the following points:\n\n${s.join('\n')}\n\n`;
|
|
595
|
+
}
|
|
401
596
|
const responseSchema = getAgentResponseSchema(fqName);
|
|
402
597
|
if (responseSchema) {
|
|
403
598
|
finalInstruction = `${finalInstruction}\nReturn your response in the following JSON schema:\n${asJSONSchema(responseSchema)}
|
|
@@ -430,7 +625,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
430
625
|
if (response) {
|
|
431
626
|
const responseSchema = getAgentResponseSchema(this.getFqName());
|
|
432
627
|
if (responseSchema) {
|
|
433
|
-
const attrs = JSON.parse(
|
|
628
|
+
const attrs = JSON.parse(normalizeGeneratedCode(response));
|
|
434
629
|
const parts = nameToPath(responseSchema);
|
|
435
630
|
const moduleName = parts.getModuleName();
|
|
436
631
|
const entryName = parts.getEntryName();
|
|
@@ -495,16 +690,78 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
495
690
|
return this;
|
|
496
691
|
}
|
|
497
692
|
|
|
693
|
+
private static AgentEvaluators = new Map<string, AgentInstance>();
|
|
694
|
+
|
|
695
|
+
public static RegisterEvaluator(e: AgentEvaluator): AgentInstance {
|
|
696
|
+
const n = e.normalizedName();
|
|
697
|
+
const agentFqName = isFqName(n) ? n : makeFqName(e.moduleName, n);
|
|
698
|
+
const instruction = e.instruction;
|
|
699
|
+
let llm = e.llm;
|
|
700
|
+
const [agentModule, agentName] = splitFqName(agentFqName);
|
|
701
|
+
if (llm === undefined) llm = `${agentName}_llm`;
|
|
702
|
+
const inst = makeInstance(
|
|
703
|
+
CoreAIModuleName,
|
|
704
|
+
AgentEntityName,
|
|
705
|
+
newInstanceAttributes()
|
|
706
|
+
.set('llm', llm)
|
|
707
|
+
.set('name', agentName)
|
|
708
|
+
.set('moduleName', agentModule)
|
|
709
|
+
.set(
|
|
710
|
+
'instruction',
|
|
711
|
+
instruction || 'You are an agent that evaluates the performance of another agent.'
|
|
712
|
+
)
|
|
713
|
+
.set('type', AgentEvalType)
|
|
714
|
+
);
|
|
715
|
+
const einst = AgentInstance.FromInstance(inst).disableSession();
|
|
716
|
+
this.AgentEvaluators.set(agentFqName, einst);
|
|
717
|
+
return einst;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
private static async maybeEvaluateResponse(
|
|
721
|
+
agent: AgentInstance,
|
|
722
|
+
userRequest: string,
|
|
723
|
+
fullRequest: string,
|
|
724
|
+
response: string,
|
|
725
|
+
env: Environment
|
|
726
|
+
): Promise<void> {
|
|
727
|
+
const fqn = agent.getFqName();
|
|
728
|
+
const e: AgentInstance | undefined = AgentInstance.AgentEvaluators.get(fqn);
|
|
729
|
+
if (e !== undefined) {
|
|
730
|
+
await e.invoke(
|
|
731
|
+
JSON.stringify({ requestToAgent: fullRequest, responseFromAgent: response }),
|
|
732
|
+
env
|
|
733
|
+
);
|
|
734
|
+
try {
|
|
735
|
+
const r = JSON.parse(normalizeGeneratedCode(env.getLastResult()));
|
|
736
|
+
const score = r.score;
|
|
737
|
+
if (score === undefined || score === null) {
|
|
738
|
+
logger.warn(`Evaluation for agent ${fqn} failed to generate a valid score`);
|
|
739
|
+
} else {
|
|
740
|
+
await parseAndEvaluateStatement(`{${CoreAIModuleName}/EvaluationResult {
|
|
741
|
+
agentFqName "${fqn}",
|
|
742
|
+
userRequest "${escapeSpecialChars(userRequest)}",
|
|
743
|
+
score ${score},
|
|
744
|
+
summary "${escapeSpecialChars(r.summary)}"
|
|
745
|
+
}}`);
|
|
746
|
+
}
|
|
747
|
+
} catch (reason: any) {
|
|
748
|
+
logger.warn(`Failed to save evaluation for agent ${fqn} - ${reason}`);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
498
753
|
async invoke(message: string, env: Environment) {
|
|
499
754
|
const p = await findProviderForLLM(this.llm, env);
|
|
500
755
|
const agentName = this.name;
|
|
501
756
|
const chatId = env.getAgentChatId() || agentName;
|
|
502
757
|
let isplnr = this.isPlanner();
|
|
503
758
|
const isflow = !isplnr && this.isFlowExecutor();
|
|
504
|
-
|
|
759
|
+
const iseval = !isplnr && !isflow && this.isEvaluator();
|
|
760
|
+
const islearner = !isflow && !isplnr && !iseval && this.isLearner();
|
|
761
|
+
if ((isplnr || islearner || iseval) && this.withSession) {
|
|
505
762
|
this.withSession = false;
|
|
506
763
|
}
|
|
507
|
-
if (isflow) {
|
|
764
|
+
if (isflow || islearner) {
|
|
508
765
|
this.withSession = false;
|
|
509
766
|
}
|
|
510
767
|
if (this.withSession && env.getFlowContext()) {
|
|
@@ -520,19 +777,31 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
520
777
|
const sess: Instance | null = this.withSession ? await findAgentChatSession(chatId, env) : null;
|
|
521
778
|
let msgs: BaseMessage[] | undefined;
|
|
522
779
|
let cachedMsg: string | undefined = undefined;
|
|
780
|
+
const activator: AgentInstructionActivator = {
|
|
781
|
+
provider: p,
|
|
782
|
+
userMessage: message,
|
|
783
|
+
agentInstruction: this.instruction,
|
|
784
|
+
agentRole: this.role,
|
|
785
|
+
};
|
|
523
786
|
if (sess) {
|
|
524
787
|
msgs = sess.lookup('messages');
|
|
525
788
|
} else {
|
|
526
|
-
cachedMsg = await this.getFullInstructions(env);
|
|
789
|
+
cachedMsg = await this.getFullInstructions(env, activator);
|
|
527
790
|
msgs = [systemMessage(cachedMsg || '')];
|
|
528
791
|
}
|
|
529
792
|
if (msgs) {
|
|
530
793
|
try {
|
|
531
794
|
const sysMsg = msgs[0];
|
|
532
|
-
if (isplnr || isflow) {
|
|
533
|
-
const s = isplnr
|
|
795
|
+
if (isplnr || isflow || iseval || islearner) {
|
|
796
|
+
const s = isplnr
|
|
797
|
+
? PlannerInstructions
|
|
798
|
+
: isflow
|
|
799
|
+
? FlowExecInstructions
|
|
800
|
+
: iseval
|
|
801
|
+
? EvalInstructions
|
|
802
|
+
: LearnerAgentInstructions;
|
|
534
803
|
const ts = this.toolsAsString();
|
|
535
|
-
const msg = `${s}\n${ts}\n${cachedMsg || (await this.getFullInstructions(env))}`;
|
|
804
|
+
const msg = `${s}\n${ts}\n${cachedMsg || (await this.getFullInstructions(env, activator))}`;
|
|
536
805
|
const newSysMsg = systemMessage(msg);
|
|
537
806
|
msgs[0] = newSysMsg;
|
|
538
807
|
}
|
|
@@ -570,6 +839,14 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
570
839
|
if (v) {
|
|
571
840
|
response = await this.handleValidation(response, v, msgs, p);
|
|
572
841
|
}
|
|
842
|
+
if (!iseval)
|
|
843
|
+
await AgentInstance.maybeEvaluateResponse(
|
|
844
|
+
this,
|
|
845
|
+
message,
|
|
846
|
+
msgsContent,
|
|
847
|
+
response.content,
|
|
848
|
+
env
|
|
849
|
+
);
|
|
573
850
|
msgs.push(assistantMessage(response.content));
|
|
574
851
|
if (isplnr) {
|
|
575
852
|
msgs[0] = sysMsg;
|
|
@@ -606,7 +883,7 @@ Only return a pure JSON object with no extra text, annotations etc.`;
|
|
|
606
883
|
validationEventName: string
|
|
607
884
|
): Promise<Instance> {
|
|
608
885
|
let isstr = true;
|
|
609
|
-
const content =
|
|
886
|
+
const content = normalizeGeneratedCode(response.content);
|
|
610
887
|
try {
|
|
611
888
|
const c = JSON.parse(content);
|
|
612
889
|
isstr = isString(c);
|
|
@@ -920,7 +1197,7 @@ function processScenarioResponse(resp: string): string {
|
|
|
920
1197
|
return resp;
|
|
921
1198
|
}
|
|
922
1199
|
|
|
923
|
-
export function
|
|
1200
|
+
export function normalizeGeneratedCode(code: string | undefined): string {
|
|
924
1201
|
if (code !== undefined) {
|
|
925
1202
|
let s = code.trim();
|
|
926
1203
|
if (s.startsWith('```')) {
|
|
@@ -935,3 +1212,98 @@ export function trimGeneratedCode(code: string | undefined): string {
|
|
|
935
1212
|
return '';
|
|
936
1213
|
}
|
|
937
1214
|
}
|
|
1215
|
+
|
|
1216
|
+
async function parseAndInternAgentLearning(
|
|
1217
|
+
moduleName: string,
|
|
1218
|
+
agentName: string,
|
|
1219
|
+
learning: string,
|
|
1220
|
+
env: Environment
|
|
1221
|
+
) {
|
|
1222
|
+
const obj = JSON.parse(normalizeGeneratedCode(learning));
|
|
1223
|
+
const fqName = makeFqName(moduleName, agentName);
|
|
1224
|
+
if (obj.decisions) {
|
|
1225
|
+
for (let j = 0; j < obj.decisions.length; ++j) {
|
|
1226
|
+
const conds: any[] = obj.decisions[j].conditions;
|
|
1227
|
+
if (conds && conds.length > 0) {
|
|
1228
|
+
AgentInstance.ResetCache(fqName, AgentCacheType.DIRECTIVE);
|
|
1229
|
+
for (let i = 0; i < conds.length; ++i) {
|
|
1230
|
+
const entry: any = conds[i];
|
|
1231
|
+
const cond: string = entry.if;
|
|
1232
|
+
const conseq: string = entry.then;
|
|
1233
|
+
if (cond && conseq) {
|
|
1234
|
+
await parseAndEvaluateStatement(
|
|
1235
|
+
`{${CoreAIModuleName}/Directive {
|
|
1236
|
+
agentFqName "${fqName}",
|
|
1237
|
+
condition "${escapeSpecialChars(cond)}",
|
|
1238
|
+
consequent "${escapeSpecialChars(conseq)}"}}`,
|
|
1239
|
+
env.getActiveUser(),
|
|
1240
|
+
env
|
|
1241
|
+
);
|
|
1242
|
+
} else {
|
|
1243
|
+
throw new Error(`Invalid directive generated - missing 'if' or 'then' in ${learning}`);
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
if (obj.glossary) {
|
|
1250
|
+
AgentInstance.ResetCache(fqName, AgentCacheType.GLOSSARY);
|
|
1251
|
+
for (let i = 0; i < obj.glossary.length; ++i) {
|
|
1252
|
+
const word = obj.glossary[i].word;
|
|
1253
|
+
const meaning = obj.glossary[i].meaning;
|
|
1254
|
+
if (word && meaning) {
|
|
1255
|
+
await parseAndEvaluateStatement(
|
|
1256
|
+
`{${CoreAIModuleName}/GlossaryEntry {
|
|
1257
|
+
agentFqName "${fqName}",
|
|
1258
|
+
name "${word}",
|
|
1259
|
+
meaning "${escapeSpecialChars(meaning)}"}}`,
|
|
1260
|
+
env.getActiveUser(),
|
|
1261
|
+
env
|
|
1262
|
+
);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
if (obj.scenarios) {
|
|
1267
|
+
AgentInstance.ResetCache(fqName, AgentCacheType.SCENARIO);
|
|
1268
|
+
for (let i = 0; i < obj.scenarios.length; ++i) {
|
|
1269
|
+
const user = obj.scenarios[i].user;
|
|
1270
|
+
const ai = obj.scenarios[i].ai;
|
|
1271
|
+
if (user && ai) {
|
|
1272
|
+
await parseAndEvaluateStatement(
|
|
1273
|
+
`{${CoreAIModuleName}/Scenario {
|
|
1274
|
+
agentFqName "${fqName}",
|
|
1275
|
+
user "${escapeSpecialChars(user)}",
|
|
1276
|
+
ai "${escapeSpecialChars(ai)}"}}`,
|
|
1277
|
+
env.getActiveUser(),
|
|
1278
|
+
env
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
AgentInstance.ResetCache(fqName, AgentCacheType.SUMMARY);
|
|
1284
|
+
const summary = obj.summary;
|
|
1285
|
+
delete obj.summary;
|
|
1286
|
+
await parseAndEvaluateStatement(
|
|
1287
|
+
`{${CoreAIModuleName}/AgentLearningResult {
|
|
1288
|
+
agentFqName "${fqName}",
|
|
1289
|
+
data "${escapeSpecialChars(JSON.stringify(obj))}",
|
|
1290
|
+
summary "${escapeSpecialChars(summary) || ''}"}}`,
|
|
1291
|
+
env.getActiveUser(),
|
|
1292
|
+
env
|
|
1293
|
+
);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
export async function processAgentLearning(
|
|
1297
|
+
moduleName: string,
|
|
1298
|
+
agentName: string,
|
|
1299
|
+
instruction: string,
|
|
1300
|
+
env: Environment
|
|
1301
|
+
): Promise<any> {
|
|
1302
|
+
const learning = await parseAndEvaluateStatement(
|
|
1303
|
+
`{${moduleName}/${agentName}_${AgentLearnerType} {message \`${instruction}\`}}`,
|
|
1304
|
+
env.getActiveUser(),
|
|
1305
|
+
env
|
|
1306
|
+
);
|
|
1307
|
+
await parseAndInternAgentLearning(moduleName, agentName, learning, env);
|
|
1308
|
+
return { agentLearning: { result: learning } };
|
|
1309
|
+
}
|
|
@@ -959,9 +959,15 @@ export async function userHasPermissions(
|
|
|
959
959
|
}
|
|
960
960
|
UserRoleCache.set(userId, userRoles);
|
|
961
961
|
}
|
|
962
|
+
let tempRoles = userRoles;
|
|
963
|
+
const escalatedRole = env.getEscalatedRole();
|
|
964
|
+
if (escalatedRole) {
|
|
965
|
+
tempRoles = userRoles.slice();
|
|
966
|
+
tempRoles.push(escalatedRole);
|
|
967
|
+
}
|
|
962
968
|
if (
|
|
963
|
-
|
|
964
|
-
|
|
969
|
+
tempRoles &&
|
|
970
|
+
tempRoles.find((role: string) => {
|
|
965
971
|
return role === 'admin';
|
|
966
972
|
})
|
|
967
973
|
) {
|
|
@@ -973,9 +979,9 @@ export async function userHasPermissions(
|
|
|
973
979
|
perms.has(RbacPermissionFlag.UPDATE),
|
|
974
980
|
perms.has(RbacPermissionFlag.DELETE),
|
|
975
981
|
];
|
|
976
|
-
if (
|
|
977
|
-
for (let i = 0; i <
|
|
978
|
-
const permInsts: RbacPermission[] | undefined = RolePermissionsCache.get(
|
|
982
|
+
if (tempRoles !== null) {
|
|
983
|
+
for (let i = 0; i < tempRoles.length; ++i) {
|
|
984
|
+
const permInsts: RbacPermission[] | undefined = RolePermissionsCache.get(tempRoles[i]);
|
|
979
985
|
if (permInsts) {
|
|
980
986
|
if (
|
|
981
987
|
permInsts.find((p: RbacPermission) => {
|
|
@@ -174,7 +174,7 @@ export class Resolver {
|
|
|
174
174
|
entryName: string,
|
|
175
175
|
moduleName: string,
|
|
176
176
|
query: string,
|
|
177
|
-
options?:
|
|
177
|
+
options?: any
|
|
178
178
|
): Promise<any> {
|
|
179
179
|
return this.notImpl(`fullTextSearch(${entryName}, ${moduleName}, ${query}, ${options})`);
|
|
180
180
|
}
|