@aigne/core 0.4.204 → 0.4.205-1
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/lib/cjs/agent.js +60 -0
- package/lib/cjs/definitions/data-type-schema.js +46 -0
- package/lib/cjs/definitions/memory.js +21 -0
- package/lib/cjs/function-agent.js +1 -1
- package/lib/cjs/function-runner.js +2 -2
- package/lib/cjs/index.js +2 -2
- package/lib/cjs/llm-agent.js +93 -87
- package/lib/cjs/llm-decision-agent.js +40 -33
- package/lib/cjs/llm-model.js +2 -2
- package/lib/cjs/local-function-agent.js +11 -9
- package/lib/cjs/memorable.js +32 -0
- package/lib/cjs/pipeline-agent.js +2 -4
- package/lib/cjs/runnable.js +3 -1
- package/lib/cjs/tsconfig.tsbuildinfo +1 -1
- package/lib/cjs/utils/message-utils.js +72 -0
- package/lib/cjs/utils/nullable.js +2 -0
- package/lib/cjs/utils/ordered-map.js +25 -0
- package/lib/cjs/utils/stream-utils.js +43 -5
- package/lib/cjs/utils/structured-output-schema.js +39 -0
- package/lib/esm/agent.js +53 -0
- package/lib/esm/definitions/data-type-schema.js +43 -0
- package/lib/esm/definitions/memory.js +18 -0
- package/lib/esm/function-agent.js +1 -1
- package/lib/esm/function-runner.js +2 -2
- package/lib/esm/index.js +2 -2
- package/lib/esm/llm-agent.js +94 -88
- package/lib/esm/llm-decision-agent.js +41 -34
- package/lib/esm/llm-model.js +2 -2
- package/lib/esm/local-function-agent.js +11 -9
- package/lib/esm/memorable.js +27 -0
- package/lib/esm/pipeline-agent.js +2 -4
- package/lib/esm/runnable.js +3 -1
- package/lib/esm/tsconfig.tsbuildinfo +1 -1
- package/lib/esm/utils/message-utils.js +64 -0
- package/lib/esm/utils/nullable.js +1 -0
- package/lib/esm/utils/ordered-map.js +25 -0
- package/lib/esm/utils/stream-utils.js +42 -5
- package/lib/esm/utils/structured-output-schema.js +33 -0
- package/lib/types/agent.d.ts +42 -0
- package/lib/types/context.d.ts +5 -1
- package/lib/types/definitions/data-type-schema.d.ts +40 -0
- package/lib/types/definitions/memory.d.ts +40 -0
- package/lib/types/function-agent.d.ts +1 -1
- package/lib/types/function-runner.d.ts +2 -1
- package/lib/types/index.d.ts +2 -2
- package/lib/types/llm-agent.d.ts +74 -19
- package/lib/types/llm-decision-agent.d.ts +54 -30
- package/lib/types/llm-model.d.ts +2 -1
- package/lib/types/local-function-agent.d.ts +51 -20
- package/lib/types/memorable.d.ts +183 -0
- package/lib/types/pipeline-agent.d.ts +2 -3
- package/lib/types/runnable.d.ts +23 -2
- package/lib/types/tsconfig.tsbuildinfo +1 -1
- package/lib/types/utils/message-utils.d.ts +20 -0
- package/lib/types/utils/nullable.d.ts +7 -0
- package/lib/types/utils/ordered-map.d.ts +6 -0
- package/lib/types/utils/stream-utils.d.ts +12 -1
- package/lib/types/utils/structured-output-schema.d.ts +3 -0
- package/lib/types/utils/union.d.ts +1 -1
- package/package.json +1 -1
package/lib/cjs/agent.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Agent = void 0;
|
|
7
|
+
const logger_1 = __importDefault(require("./logger"));
|
|
8
|
+
const runnable_1 = require("./runnable");
|
|
9
|
+
const utils_1 = require("./utils");
|
|
10
|
+
class Agent extends runnable_1.Runnable {
|
|
11
|
+
async getMemoryQuery(input, query) {
|
|
12
|
+
if (query?.from === 'variable') {
|
|
13
|
+
const i = utils_1.OrderedRecord.find(this.definition.inputs, (i) => i.id === query.fromVariableId);
|
|
14
|
+
if (!i)
|
|
15
|
+
throw new Error(`Input variable ${query.fromVariableId} not found`);
|
|
16
|
+
const value = input[i.name];
|
|
17
|
+
return (0, utils_1.renderMessage)('{{value}}', { value });
|
|
18
|
+
}
|
|
19
|
+
return Object.entries(input)
|
|
20
|
+
.map(([key, value]) => `${key} ${value}`)
|
|
21
|
+
.join('\n');
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Load memories that are defined in the agent definition.
|
|
25
|
+
* @param input The agent input.
|
|
26
|
+
* @param context The AIGNE context.
|
|
27
|
+
* @returns A dictionary of memories, where the key is the memory name and the value is an array of memory items.
|
|
28
|
+
*/
|
|
29
|
+
async loadMemories(input, context) {
|
|
30
|
+
const { memories } = this.definition;
|
|
31
|
+
const { userId, sessionId } = context?.state ?? {};
|
|
32
|
+
return Object.fromEntries((await Promise.all(utils_1.OrderedRecord.map(memories, async ({ name, memory, query, options }) => {
|
|
33
|
+
if (!name || !memory)
|
|
34
|
+
return null;
|
|
35
|
+
const q = await this.getMemoryQuery(input, query);
|
|
36
|
+
const { results: memories } = await memory.search(q, { ...options, userId, sessionId });
|
|
37
|
+
return [name, memories];
|
|
38
|
+
}))).filter(utils_1.isNonNullable));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Update memories by user messages and assistant responses.
|
|
42
|
+
* @param messages Messages to be added to memories.
|
|
43
|
+
*/
|
|
44
|
+
async updateMemories(messages) {
|
|
45
|
+
const { memories } = this.definition;
|
|
46
|
+
const { userId, sessionId } = this.context?.state ?? {};
|
|
47
|
+
await Promise.all(utils_1.OrderedRecord.map(memories, async ({ memory }) => {
|
|
48
|
+
if (!memory) {
|
|
49
|
+
logger_1.default.warn(`Memory is not defined in agent ${this.name || this.id}`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
return await memory.add(messages, { userId, sessionId });
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
async run(input, options) {
|
|
56
|
+
const memories = await this.loadMemories(input, this.context);
|
|
57
|
+
return this.process(input, { ...options, memories });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.Agent = Agent;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.schemaToDataType = schemaToDataType;
|
|
4
|
+
const nanoid_1 = require("nanoid");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
function schemaToDataType(dataType) {
|
|
7
|
+
return utils_1.OrderedRecord.fromArray(Object.entries(dataType).map(([name, schema]) => {
|
|
8
|
+
const base = {
|
|
9
|
+
...schema,
|
|
10
|
+
id: (0, nanoid_1.nanoid)(),
|
|
11
|
+
name,
|
|
12
|
+
};
|
|
13
|
+
switch (schema.type) {
|
|
14
|
+
case 'string':
|
|
15
|
+
return {
|
|
16
|
+
...base,
|
|
17
|
+
type: 'string',
|
|
18
|
+
};
|
|
19
|
+
case 'number':
|
|
20
|
+
return {
|
|
21
|
+
...base,
|
|
22
|
+
type: 'number',
|
|
23
|
+
};
|
|
24
|
+
case 'boolean':
|
|
25
|
+
return {
|
|
26
|
+
...base,
|
|
27
|
+
type: 'boolean',
|
|
28
|
+
};
|
|
29
|
+
case 'object':
|
|
30
|
+
return {
|
|
31
|
+
...base,
|
|
32
|
+
type: 'object',
|
|
33
|
+
properties: schemaToDataType(schema.properties),
|
|
34
|
+
};
|
|
35
|
+
case 'array':
|
|
36
|
+
return {
|
|
37
|
+
...base,
|
|
38
|
+
type: 'array',
|
|
39
|
+
items: utils_1.OrderedRecord.find(schemaToDataType({ items: schema.items }), (i) => i.name === 'items'),
|
|
40
|
+
};
|
|
41
|
+
default: {
|
|
42
|
+
throw new Error(`Unknown data type: ${schema.type}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toRunnableMemories = toRunnableMemories;
|
|
4
|
+
const nanoid_1 = require("nanoid");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
function toRunnableMemories(agentName, inputs, memories) {
|
|
7
|
+
return utils_1.OrderedRecord.fromArray(Object.entries(memories).map(([name, { memory, query, options }]) => {
|
|
8
|
+
const queryFromVariable = query?.fromVariable
|
|
9
|
+
? utils_1.OrderedRecord.find(inputs, (j) => j.name === query.fromVariable)
|
|
10
|
+
: null;
|
|
11
|
+
if (query?.fromVariable && !queryFromVariable)
|
|
12
|
+
throw new Error(`LLMAgent ${agentName} -> Memory ${name} -> Query variable ${query.fromVariable.toString()} not found`);
|
|
13
|
+
return {
|
|
14
|
+
id: name || (0, nanoid_1.nanoid)(),
|
|
15
|
+
name: name,
|
|
16
|
+
memory: memory,
|
|
17
|
+
query: queryFromVariable ? { from: 'variable', fromVariableId: queryFromVariable.id } : undefined,
|
|
18
|
+
options,
|
|
19
|
+
};
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
@@ -18,7 +18,7 @@ exports.createFunctionAgentDefinition = createFunctionAgentDefinition;
|
|
|
18
18
|
const nanoid_1 = require("nanoid");
|
|
19
19
|
const tsyringe_1 = require("tsyringe");
|
|
20
20
|
const constants_1 = require("./constants");
|
|
21
|
-
const data_type_schema_1 = require("./data-type-schema");
|
|
21
|
+
const data_type_schema_1 = require("./definitions/data-type-schema");
|
|
22
22
|
const function_runner_1 = require("./function-runner");
|
|
23
23
|
const runnable_1 = require("./runnable");
|
|
24
24
|
const utils_1 = require("./utils");
|
|
@@ -4,7 +4,7 @@ exports.FunctionRunner = void 0;
|
|
|
4
4
|
const runnable_1 = require("./runnable");
|
|
5
5
|
const utils_1 = require("./utils");
|
|
6
6
|
class FunctionRunner extends runnable_1.Runnable {
|
|
7
|
-
constructor() {
|
|
7
|
+
constructor(context) {
|
|
8
8
|
super({
|
|
9
9
|
id: 'function_runner',
|
|
10
10
|
type: 'function_runner',
|
|
@@ -23,7 +23,7 @@ class FunctionRunner extends runnable_1.Runnable {
|
|
|
23
23
|
type: 'object',
|
|
24
24
|
},
|
|
25
25
|
]),
|
|
26
|
-
});
|
|
26
|
+
}, context);
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
exports.FunctionRunner = FunctionRunner;
|
package/lib/cjs/index.js
CHANGED
|
@@ -17,7 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./utils"), exports);
|
|
18
18
|
__exportStar(require("./constants"), exports);
|
|
19
19
|
__exportStar(require("./data-type"), exports);
|
|
20
|
-
__exportStar(require("./data-type-schema"), exports);
|
|
20
|
+
__exportStar(require("./definitions/data-type-schema"), exports);
|
|
21
21
|
__exportStar(require("./context"), exports);
|
|
22
22
|
__exportStar(require("./runnable"), exports);
|
|
23
23
|
__exportStar(require("./pipeline-agent"), exports);
|
|
@@ -27,4 +27,4 @@ __exportStar(require("./function-agent"), exports);
|
|
|
27
27
|
__exportStar(require("./function-runner"), exports);
|
|
28
28
|
__exportStar(require("./llm-decision-agent"), exports);
|
|
29
29
|
__exportStar(require("./local-function-agent"), exports);
|
|
30
|
-
__exportStar(require("./
|
|
30
|
+
__exportStar(require("./memorable"), exports);
|
package/lib/cjs/llm-agent.js
CHANGED
|
@@ -15,79 +15,63 @@ var LLMAgent_1;
|
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.LLMAgent = void 0;
|
|
17
17
|
exports.createLLMAgentDefinition = createLLMAgentDefinition;
|
|
18
|
-
const lodash_1 = require("lodash");
|
|
19
18
|
const nanoid_1 = require("nanoid");
|
|
20
19
|
const tsyringe_1 = require("tsyringe");
|
|
20
|
+
const agent_1 = require("./agent");
|
|
21
21
|
const constants_1 = require("./constants");
|
|
22
|
-
const data_type_schema_1 = require("./data-type-schema");
|
|
22
|
+
const data_type_schema_1 = require("./definitions/data-type-schema");
|
|
23
|
+
const memory_1 = require("./definitions/memory");
|
|
23
24
|
const llm_model_1 = require("./llm-model");
|
|
24
|
-
const runnable_1 = require("./runnable");
|
|
25
25
|
const utils_1 = require("./utils");
|
|
26
|
+
const message_utils_1 = require("./utils/message-utils");
|
|
26
27
|
const mustache_utils_1 = require("./utils/mustache-utils");
|
|
27
28
|
const ordered_map_1 = require("./utils/ordered-map");
|
|
28
|
-
|
|
29
|
+
const structured_output_schema_1 = require("./utils/structured-output-schema");
|
|
30
|
+
let LLMAgent = LLMAgent_1 = class LLMAgent extends agent_1.Agent {
|
|
29
31
|
definition;
|
|
30
32
|
model;
|
|
31
33
|
static create(options) {
|
|
32
34
|
const definition = createLLMAgentDefinition(options);
|
|
33
35
|
return new LLMAgent_1(definition);
|
|
34
36
|
}
|
|
35
|
-
constructor(definition, model) {
|
|
36
|
-
super(definition);
|
|
37
|
+
constructor(definition, context, model) {
|
|
38
|
+
super(definition, context);
|
|
37
39
|
this.definition = definition;
|
|
38
40
|
this.model = model;
|
|
39
41
|
}
|
|
40
|
-
async
|
|
42
|
+
async process(input, options) {
|
|
41
43
|
const { definition, model } = this;
|
|
42
44
|
if (!model)
|
|
43
45
|
throw new Error('LLM model is required');
|
|
44
|
-
const
|
|
45
|
-
if (!messages.length)
|
|
46
|
-
throw new Error('Messages are required');
|
|
47
|
-
// TODO: support comment/image for messages
|
|
46
|
+
const { originalMessages, messagesWithMemory } = (0, message_utils_1.prepareMessages)(definition, input, options.memories);
|
|
48
47
|
const llmInputs = {
|
|
49
|
-
messages:
|
|
50
|
-
role,
|
|
51
|
-
content: (0, mustache_utils_1.renderMessage)(content, input),
|
|
52
|
-
})),
|
|
48
|
+
messages: messagesWithMemory,
|
|
53
49
|
modelOptions: definition.modelOptions,
|
|
54
50
|
};
|
|
55
|
-
const
|
|
56
|
-
const textOutput =
|
|
57
|
-
|
|
58
|
-
const outputJsonSchema = jsonOutputs.length ? outputsToJsonSchema(ordered_map_1.OrderedRecord.fromArray(jsonOutputs)) : undefined;
|
|
59
|
-
const jsonOutput = outputJsonSchema
|
|
60
|
-
? model
|
|
61
|
-
.run({
|
|
62
|
-
...llmInputs,
|
|
63
|
-
responseFormat: outputJsonSchema && {
|
|
64
|
-
type: 'json_schema',
|
|
65
|
-
jsonSchema: {
|
|
66
|
-
name: 'output',
|
|
67
|
-
schema: outputJsonSchema,
|
|
68
|
-
strict: true,
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
})
|
|
72
|
-
.then(async (response) => {
|
|
73
|
-
if (!response.$text)
|
|
74
|
-
throw new Error('No text in JSON mode response');
|
|
75
|
-
const json = JSON.parse(response.$text);
|
|
76
|
-
// TODO: validate json with outputJsonSchema
|
|
77
|
-
return json;
|
|
78
|
-
})
|
|
51
|
+
const jsonOutput = this.runWithStructuredOutput(llmInputs);
|
|
52
|
+
const textOutput = ordered_map_1.OrderedRecord.find(definition.outputs, (i) => i.name === constants_1.StreamTextOutputName)
|
|
53
|
+
? await this.runWithTextOutput(llmInputs)
|
|
79
54
|
: undefined;
|
|
55
|
+
const updateMemories = (text, json) => {
|
|
56
|
+
return this.updateMemories([
|
|
57
|
+
...originalMessages,
|
|
58
|
+
{ role: 'assistant', content: (0, mustache_utils_1.renderMessage)('{{text}}\n{{json}}', { text, json }).trim() },
|
|
59
|
+
]);
|
|
60
|
+
};
|
|
80
61
|
if (options?.stream) {
|
|
62
|
+
let $text = '';
|
|
81
63
|
return new ReadableStream({
|
|
82
64
|
start: async (controller) => {
|
|
83
65
|
try {
|
|
84
66
|
if (textOutput) {
|
|
85
|
-
|
|
86
|
-
|
|
67
|
+
for await (const chunk of textOutput) {
|
|
68
|
+
$text += chunk.$text || '';
|
|
87
69
|
controller.enqueue({ $text: chunk.$text });
|
|
88
70
|
}
|
|
89
71
|
}
|
|
90
|
-
|
|
72
|
+
const json = await jsonOutput;
|
|
73
|
+
controller.enqueue({ delta: json });
|
|
74
|
+
await updateMemories($text || undefined, json);
|
|
91
75
|
}
|
|
92
76
|
catch (error) {
|
|
93
77
|
controller.error(error);
|
|
@@ -98,62 +82,84 @@ let LLMAgent = LLMAgent_1 = class LLMAgent extends runnable_1.Runnable {
|
|
|
98
82
|
},
|
|
99
83
|
});
|
|
100
84
|
}
|
|
101
|
-
const text =
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
85
|
+
const [$text, json] = await Promise.all([
|
|
86
|
+
textOutput ? (0, utils_1.runnableResponseStreamToObject)(textOutput).then((res) => res.$text || undefined) : undefined,
|
|
87
|
+
jsonOutput,
|
|
88
|
+
]);
|
|
89
|
+
await updateMemories($text, json);
|
|
90
|
+
return { $text, ...json };
|
|
91
|
+
}
|
|
92
|
+
async runWithStructuredOutput(llmInputs) {
|
|
93
|
+
const jsonOutputs = ordered_map_1.OrderedRecord.filter(this.definition.outputs, (i) => i.name !== constants_1.StreamTextOutputName // ignore `$text` output
|
|
94
|
+
);
|
|
95
|
+
if (!jsonOutputs.length)
|
|
96
|
+
return null;
|
|
97
|
+
const schema = (0, structured_output_schema_1.outputsToJsonSchema)(ordered_map_1.OrderedRecord.fromArray(jsonOutputs));
|
|
98
|
+
const { model } = this;
|
|
99
|
+
if (!model)
|
|
100
|
+
throw new Error('LLM model is required');
|
|
101
|
+
const response = await model.run({
|
|
102
|
+
...llmInputs,
|
|
103
|
+
responseFormat: {
|
|
104
|
+
type: 'json_schema',
|
|
105
|
+
jsonSchema: {
|
|
106
|
+
name: 'output',
|
|
107
|
+
schema: schema,
|
|
108
|
+
strict: true,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
if (!response.$text)
|
|
113
|
+
throw new Error('No text in JSON mode response');
|
|
114
|
+
const json = JSON.parse(response.$text);
|
|
115
|
+
// TODO: validate json with outputJsonSchema
|
|
116
|
+
return json;
|
|
117
|
+
}
|
|
118
|
+
async runWithTextOutput(llmInputs) {
|
|
119
|
+
const { model } = this;
|
|
120
|
+
if (!model)
|
|
121
|
+
throw new Error('LLM model is required');
|
|
122
|
+
return model.run(llmInputs, { stream: true });
|
|
106
123
|
}
|
|
107
124
|
};
|
|
108
125
|
exports.LLMAgent = LLMAgent;
|
|
109
126
|
exports.LLMAgent = LLMAgent = LLMAgent_1 = __decorate([
|
|
110
127
|
(0, tsyringe_1.injectable)(),
|
|
111
128
|
__param(0, (0, tsyringe_1.inject)(constants_1.TYPES.definition)),
|
|
112
|
-
__param(1, (0, tsyringe_1.inject)(constants_1.TYPES.
|
|
113
|
-
|
|
129
|
+
__param(1, (0, tsyringe_1.inject)(constants_1.TYPES.context)),
|
|
130
|
+
__param(2, (0, tsyringe_1.inject)(constants_1.TYPES.llmModel)),
|
|
131
|
+
__metadata("design:paramtypes", [Object, Object, llm_model_1.LLMModel])
|
|
114
132
|
], LLMAgent);
|
|
133
|
+
/**
|
|
134
|
+
* Create LLMAgent definition.
|
|
135
|
+
* @param options Options to create LLMAgent.
|
|
136
|
+
* @returns LLMAgent definition.
|
|
137
|
+
*/
|
|
115
138
|
function createLLMAgentDefinition(options) {
|
|
139
|
+
const agentId = options.name || (0, nanoid_1.nanoid)();
|
|
140
|
+
const inputs = (0, data_type_schema_1.schemaToDataType)(options.inputs);
|
|
141
|
+
const outputs = (0, data_type_schema_1.schemaToDataType)(options.outputs);
|
|
142
|
+
const memories = (0, memory_1.toRunnableMemories)(agentId, inputs, options.memories ?? {});
|
|
143
|
+
const primaryMemoryNames = Object.entries(options.memories ?? {})
|
|
144
|
+
.filter(([, i]) => i.primary)
|
|
145
|
+
.map(([name]) => name);
|
|
146
|
+
if (primaryMemoryNames && primaryMemoryNames.length > 1) {
|
|
147
|
+
throw new Error('Only one primary memory is allowed');
|
|
148
|
+
}
|
|
149
|
+
const messages = ordered_map_1.OrderedRecord.fromArray(options.messages?.map((i) => ({
|
|
150
|
+
id: (0, nanoid_1.nanoid)(),
|
|
151
|
+
role: i.role,
|
|
152
|
+
content: i.content,
|
|
153
|
+
})));
|
|
116
154
|
return {
|
|
117
|
-
id:
|
|
155
|
+
id: agentId,
|
|
118
156
|
name: options.name,
|
|
119
157
|
type: 'llm_agent',
|
|
120
|
-
inputs
|
|
121
|
-
outputs
|
|
158
|
+
inputs,
|
|
159
|
+
outputs,
|
|
160
|
+
primaryMemoryId: primaryMemoryNames?.at(0),
|
|
161
|
+
memories,
|
|
122
162
|
modelOptions: options.modelOptions,
|
|
123
|
-
messages
|
|
124
|
-
id: (0, nanoid_1.nanoid)(),
|
|
125
|
-
role: i.role,
|
|
126
|
-
content: i.content,
|
|
127
|
-
}))),
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
function outputsToJsonSchema(outputs) {
|
|
131
|
-
const outputToSchema = (output) => {
|
|
132
|
-
const properties = output.type === 'object' && output.properties?.$indexes.length
|
|
133
|
-
? ordered_map_1.OrderedRecord.map(output.properties, (property) => {
|
|
134
|
-
if (!property.name)
|
|
135
|
-
return null;
|
|
136
|
-
const schema = outputToSchema(property);
|
|
137
|
-
if (!schema)
|
|
138
|
-
return null;
|
|
139
|
-
return { schema, property };
|
|
140
|
-
}).filter(utils_1.isNonNullable)
|
|
141
|
-
: undefined;
|
|
142
|
-
return (0, lodash_1.omitBy)({
|
|
143
|
-
type: output.type,
|
|
144
|
-
description: output.description,
|
|
145
|
-
properties: properties?.length
|
|
146
|
-
? Object.fromEntries(properties.map((p) => [p.property.name, p.schema]))
|
|
147
|
-
: undefined,
|
|
148
|
-
items: output.type === 'array' && output.items ? outputToSchema(output.items) : undefined,
|
|
149
|
-
additionalProperties: output.type === 'object' ? false : undefined,
|
|
150
|
-
required: properties?.length
|
|
151
|
-
? properties.filter((i) => i.property.required).map((i) => i.property.name)
|
|
152
|
-
: undefined,
|
|
153
|
-
}, (v) => v === undefined);
|
|
163
|
+
messages,
|
|
154
164
|
};
|
|
155
|
-
return outputToSchema({
|
|
156
|
-
type: 'object',
|
|
157
|
-
properties: outputs,
|
|
158
|
-
});
|
|
159
165
|
}
|
|
@@ -17,33 +17,31 @@ exports.LLMDecisionAgent = void 0;
|
|
|
17
17
|
exports.createLLMDecisionAgentDefinition = createLLMDecisionAgentDefinition;
|
|
18
18
|
const nanoid_1 = require("nanoid");
|
|
19
19
|
const tsyringe_1 = require("tsyringe");
|
|
20
|
+
const agent_1 = require("./agent");
|
|
20
21
|
const constants_1 = require("./constants");
|
|
22
|
+
const memory_1 = require("./definitions/memory");
|
|
21
23
|
const llm_model_1 = require("./llm-model");
|
|
22
|
-
const runnable_1 = require("./runnable");
|
|
23
24
|
const utils_1 = require("./utils");
|
|
24
|
-
|
|
25
|
+
const message_utils_1 = require("./utils/message-utils");
|
|
26
|
+
let LLMDecisionAgent = LLMDecisionAgent_1 = class LLMDecisionAgent extends agent_1.Agent {
|
|
25
27
|
definition;
|
|
26
28
|
model;
|
|
27
|
-
context;
|
|
28
29
|
static create(options) {
|
|
29
30
|
const definition = createLLMDecisionAgentDefinition(options);
|
|
30
31
|
return new LLMDecisionAgent_1(definition);
|
|
31
32
|
}
|
|
32
|
-
constructor(definition,
|
|
33
|
-
super(definition);
|
|
33
|
+
constructor(definition, context, model) {
|
|
34
|
+
super(definition, context);
|
|
34
35
|
this.definition = definition;
|
|
35
36
|
this.model = model;
|
|
36
|
-
this.context = context;
|
|
37
37
|
}
|
|
38
|
-
async
|
|
38
|
+
async process(input, options) {
|
|
39
39
|
const { definition, context, model } = this;
|
|
40
40
|
if (!model)
|
|
41
41
|
throw new Error('LLM model is required');
|
|
42
42
|
if (!context)
|
|
43
43
|
throw new Error('Context is required');
|
|
44
|
-
const
|
|
45
|
-
if (!messages.length)
|
|
46
|
-
throw new Error('Messages are required');
|
|
44
|
+
const { originalMessages, messagesWithMemory } = (0, message_utils_1.prepareMessages)(definition, input, options.memories);
|
|
47
45
|
const cases = await Promise.all(utils_1.OrderedRecord.map(definition.cases, async (t) => {
|
|
48
46
|
if (!t.runnable?.id)
|
|
49
47
|
throw new Error('Runnable is required');
|
|
@@ -52,13 +50,10 @@ let LLMDecisionAgent = LLMDecisionAgent_1 = class LLMDecisionAgent extends runna
|
|
|
52
50
|
const name = t.name || runnable.name;
|
|
53
51
|
if (!name)
|
|
54
52
|
throw new Error('Case name is required');
|
|
55
|
-
return { name, description: t.description, runnable
|
|
53
|
+
return { name, description: t.description, runnable };
|
|
56
54
|
}));
|
|
57
55
|
const llmInputs = {
|
|
58
|
-
messages:
|
|
59
|
-
role,
|
|
60
|
-
content: typeof content === 'string' ? (0, utils_1.renderMessage)(content, input) : content,
|
|
61
|
-
})),
|
|
56
|
+
messages: messagesWithMemory,
|
|
62
57
|
modelOptions: definition.modelOptions,
|
|
63
58
|
tools: cases.map((t) => {
|
|
64
59
|
// TODO: auto generate parameters by llm model if needed
|
|
@@ -82,40 +77,52 @@ let LLMDecisionAgent = LLMDecisionAgent_1 = class LLMDecisionAgent extends runna
|
|
|
82
77
|
if (!caseToCall)
|
|
83
78
|
throw new Error('Case not found');
|
|
84
79
|
// TODO: check result structure and omit undefined values
|
|
85
|
-
|
|
80
|
+
const output = (await caseToCall.runnable.run(input, options));
|
|
81
|
+
return (0, utils_1.extractOutputsFromRunnableOutput)(output, ({ $text, ...json }) => this.updateMemories([
|
|
82
|
+
...originalMessages,
|
|
83
|
+
{ role: 'assistant', content: (0, utils_1.renderMessage)('{{$text}}\n{{json}}', { $text, json }).trim() },
|
|
84
|
+
]));
|
|
86
85
|
}
|
|
87
86
|
};
|
|
88
87
|
exports.LLMDecisionAgent = LLMDecisionAgent;
|
|
89
88
|
exports.LLMDecisionAgent = LLMDecisionAgent = LLMDecisionAgent_1 = __decorate([
|
|
90
89
|
(0, tsyringe_1.injectable)(),
|
|
91
90
|
__param(0, (0, tsyringe_1.inject)(constants_1.TYPES.definition)),
|
|
92
|
-
__param(1, (0, tsyringe_1.inject)(constants_1.TYPES.
|
|
93
|
-
__param(2, (0, tsyringe_1.inject)(constants_1.TYPES.
|
|
94
|
-
__metadata("design:paramtypes", [Object, llm_model_1.LLMModel
|
|
91
|
+
__param(1, (0, tsyringe_1.inject)(constants_1.TYPES.context)),
|
|
92
|
+
__param(2, (0, tsyringe_1.inject)(constants_1.TYPES.llmModel)),
|
|
93
|
+
__metadata("design:paramtypes", [Object, Object, llm_model_1.LLMModel])
|
|
95
94
|
], LLMDecisionAgent);
|
|
96
95
|
function createLLMDecisionAgentDefinition(options) {
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
id: (0, nanoid_1.nanoid)(),
|
|
100
|
-
role: 'system',
|
|
101
|
-
content: options.messages,
|
|
102
|
-
},
|
|
103
|
-
]);
|
|
104
|
-
const cases = utils_1.OrderedRecord.fromArray(options.cases.map((c) => ({
|
|
96
|
+
const agentId = options.name || (0, nanoid_1.nanoid)();
|
|
97
|
+
const cases = utils_1.OrderedRecord.fromArray(Object.entries(options.cases).map(([name, c]) => ({
|
|
105
98
|
id: (0, nanoid_1.nanoid)(),
|
|
106
|
-
name:
|
|
99
|
+
name: name || c.runnable.name,
|
|
107
100
|
description: c.description,
|
|
108
101
|
runnable: { id: c.runnable.id },
|
|
109
102
|
})));
|
|
103
|
+
const inputs = utils_1.OrderedRecord.merge(...Object.values(options.cases).map((i) => i.runnable.definition.inputs));
|
|
104
|
+
const outputs = utils_1.OrderedRecord.fromArray(utils_1.OrderedRecord.map(utils_1.OrderedRecord.merge(...Object.values(options.cases).map((i) => i.runnable.definition.outputs)), (o) => ({ ...o, required: false })));
|
|
105
|
+
const memories = (0, memory_1.toRunnableMemories)(agentId, inputs, options.memories ?? {});
|
|
106
|
+
const primaryMemoryNames = Object.entries(options.memories ?? {})
|
|
107
|
+
.filter(([, i]) => i.primary)
|
|
108
|
+
.map(([name]) => name);
|
|
109
|
+
if (primaryMemoryNames && primaryMemoryNames.length > 1) {
|
|
110
|
+
throw new Error('Only one primary memory is allowed');
|
|
111
|
+
}
|
|
112
|
+
const messages = utils_1.OrderedRecord.fromArray(options.messages?.map((i) => ({
|
|
113
|
+
id: (0, nanoid_1.nanoid)(),
|
|
114
|
+
role: i.role,
|
|
115
|
+
content: i.content,
|
|
116
|
+
})));
|
|
110
117
|
return {
|
|
111
|
-
id:
|
|
118
|
+
id: agentId,
|
|
112
119
|
name: options.name,
|
|
113
120
|
type: 'llm_decision_agent',
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
// TODO: decision agent outputs should be the union of all case outputs
|
|
117
|
-
outputs: utils_1.OrderedRecord.fromArray([]),
|
|
121
|
+
inputs,
|
|
122
|
+
outputs,
|
|
118
123
|
messages,
|
|
124
|
+
primaryMemoryId: primaryMemoryNames?.at(0),
|
|
125
|
+
memories,
|
|
119
126
|
modelOptions: options.modelOptions,
|
|
120
127
|
cases,
|
|
121
128
|
};
|
package/lib/cjs/llm-model.js
CHANGED
|
@@ -4,7 +4,7 @@ exports.LLMModel = void 0;
|
|
|
4
4
|
const runnable_1 = require("./runnable");
|
|
5
5
|
const utils_1 = require("./utils");
|
|
6
6
|
class LLMModel extends runnable_1.Runnable {
|
|
7
|
-
constructor() {
|
|
7
|
+
constructor(context) {
|
|
8
8
|
super({
|
|
9
9
|
id: 'llm_model',
|
|
10
10
|
type: 'llm_model',
|
|
@@ -21,7 +21,7 @@ class LLMModel extends runnable_1.Runnable {
|
|
|
21
21
|
{ id: '$text', name: '$text', type: 'string' },
|
|
22
22
|
{ id: 'toolCalls', name: 'toolCalls', type: 'object' },
|
|
23
23
|
]),
|
|
24
|
-
});
|
|
24
|
+
}, context);
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
exports.LLMModel = LLMModel;
|
|
@@ -17,29 +17,28 @@ exports.LocalFunctionAgent = void 0;
|
|
|
17
17
|
exports.createLocalFunctionAgentDefinition = createLocalFunctionAgentDefinition;
|
|
18
18
|
const nanoid_1 = require("nanoid");
|
|
19
19
|
const tsyringe_1 = require("tsyringe");
|
|
20
|
+
const agent_1 = require("./agent");
|
|
20
21
|
const constants_1 = require("./constants");
|
|
21
|
-
const data_type_schema_1 = require("./data-type-schema");
|
|
22
|
-
const
|
|
22
|
+
const data_type_schema_1 = require("./definitions/data-type-schema");
|
|
23
|
+
const memory_1 = require("./definitions/memory");
|
|
23
24
|
const utils_1 = require("./utils");
|
|
24
|
-
let LocalFunctionAgent = LocalFunctionAgent_1 = class LocalFunctionAgent extends
|
|
25
|
+
let LocalFunctionAgent = LocalFunctionAgent_1 = class LocalFunctionAgent extends agent_1.Agent {
|
|
25
26
|
definition;
|
|
26
|
-
context;
|
|
27
27
|
static create(options) {
|
|
28
28
|
const definition = createLocalFunctionAgentDefinition(options);
|
|
29
29
|
return new LocalFunctionAgent_1(definition);
|
|
30
30
|
}
|
|
31
31
|
constructor(definition, context) {
|
|
32
|
-
super(definition);
|
|
32
|
+
super(definition, context);
|
|
33
33
|
this.definition = definition;
|
|
34
|
-
this.context = context;
|
|
35
34
|
}
|
|
36
|
-
async
|
|
35
|
+
async process(input, options) {
|
|
37
36
|
const { definition: { function: func }, context, } = this;
|
|
38
37
|
if (!func)
|
|
39
38
|
throw new Error('Function is required');
|
|
40
39
|
if (!context)
|
|
41
40
|
throw new Error('Context is required');
|
|
42
|
-
const result =
|
|
41
|
+
const result = await func(input, { context, memories: options.memories });
|
|
43
42
|
// TODO: validate the result against the definition.outputs
|
|
44
43
|
return options?.stream
|
|
45
44
|
? result instanceof ReadableStream
|
|
@@ -58,14 +57,17 @@ exports.LocalFunctionAgent = LocalFunctionAgent = LocalFunctionAgent_1 = __decor
|
|
|
58
57
|
__metadata("design:paramtypes", [Object, Object])
|
|
59
58
|
], LocalFunctionAgent);
|
|
60
59
|
function createLocalFunctionAgentDefinition(options) {
|
|
60
|
+
const agentId = options.name || (0, nanoid_1.nanoid)();
|
|
61
61
|
const inputs = (0, data_type_schema_1.schemaToDataType)(options.inputs);
|
|
62
62
|
const outputs = (0, data_type_schema_1.schemaToDataType)(options.outputs);
|
|
63
|
+
const memories = (0, memory_1.toRunnableMemories)(agentId, inputs, options.memories || {});
|
|
63
64
|
return {
|
|
64
|
-
id:
|
|
65
|
+
id: agentId,
|
|
65
66
|
name: options.name,
|
|
66
67
|
type: 'local_function_agent',
|
|
67
68
|
inputs,
|
|
68
69
|
outputs,
|
|
70
|
+
memories,
|
|
69
71
|
function: options.function,
|
|
70
72
|
};
|
|
71
73
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MemoryRunner = exports.Memorable = void 0;
|
|
4
|
+
const lodash_1 = require("lodash");
|
|
5
|
+
const runnable_1 = require("./runnable");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
class Memorable extends runnable_1.Runnable {
|
|
8
|
+
constructor() {
|
|
9
|
+
super({
|
|
10
|
+
id: 'memory',
|
|
11
|
+
type: 'memory',
|
|
12
|
+
name: 'Memory',
|
|
13
|
+
inputs: utils_1.OrderedRecord.fromArray([]),
|
|
14
|
+
outputs: utils_1.OrderedRecord.fromArray([]),
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.Memorable = Memorable;
|
|
19
|
+
class MemoryRunner extends runnable_1.Runnable {
|
|
20
|
+
constructor(name) {
|
|
21
|
+
const id = `${(0, lodash_1.camelCase)(name)}_runner`;
|
|
22
|
+
super({
|
|
23
|
+
id,
|
|
24
|
+
type: id,
|
|
25
|
+
name: `${(0, lodash_1.startCase)(name)} Runner`,
|
|
26
|
+
description: `${(0, lodash_1.startCase)(name)} Runner`,
|
|
27
|
+
inputs: utils_1.OrderedRecord.fromArray([]),
|
|
28
|
+
outputs: utils_1.OrderedRecord.fromArray([]),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.MemoryRunner = MemoryRunner;
|