@aigne/core 1.0.8 → 1.0.10
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.d.ts +10 -0
- package/lib/cjs/agent.js +11 -0
- package/lib/cjs/llm-decision-agent.d.ts +12 -29
- package/lib/cjs/llm-decision-agent.js +28 -11
- package/lib/cjs/llm-models/openai-llm-model.d.ts +4 -1
- package/lib/cjs/llm-models/openai-llm-model.js +14 -14
- package/lib/cjs/utils/runnable-type.d.ts +20 -0
- package/lib/dts/agent.d.ts +10 -0
- package/lib/dts/llm-decision-agent.d.ts +12 -29
- package/lib/dts/llm-models/openai-llm-model.d.ts +4 -1
- package/lib/dts/utils/runnable-type.d.ts +20 -0
- package/lib/esm/agent.d.ts +10 -0
- package/lib/esm/agent.js +11 -0
- package/lib/esm/llm-decision-agent.d.ts +12 -29
- package/lib/esm/llm-decision-agent.js +28 -11
- package/lib/esm/llm-models/openai-llm-model.d.ts +4 -1
- package/lib/esm/llm-models/openai-llm-model.js +14 -14
- package/lib/esm/utils/runnable-type.d.ts +20 -0
- package/package.json +4 -4
package/lib/cjs/agent.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Context, ContextState } from "./context";
|
|
2
2
|
import type { MemoryItemWithScore, MemoryMessage } from "./memorable";
|
|
3
3
|
import { type RunOptions, Runnable, type RunnableResponse, type RunnableResponseChunk, type RunnableResponseStream } from "./runnable";
|
|
4
|
+
import type { BindAgentInputs, BoundAgent } from "./utils/runnable-type";
|
|
4
5
|
export interface AgentProcessOptions<Memories extends {
|
|
5
6
|
[name: string]: MemoryItemWithScore[];
|
|
6
7
|
}> {
|
|
@@ -38,4 +39,13 @@ export declare abstract class Agent<I extends {
|
|
|
38
39
|
*/
|
|
39
40
|
protected onResult(_result: O): Promise<void>;
|
|
40
41
|
abstract process(input: I, options: AgentProcessOptions<Memories>): Promise<RunnableResponse<O> | AsyncGenerator<RunnableResponseChunk<O>, void>> | AsyncGenerator<RunnableResponseChunk<O>, void>;
|
|
42
|
+
/**
|
|
43
|
+
* Bind some inputs to the agent, used for process of `PipelineAgent` or case of `LLMDecisionAgent`.
|
|
44
|
+
* @param options The bind options.
|
|
45
|
+
* @returns The bound agent.
|
|
46
|
+
*/
|
|
47
|
+
bind<Input extends BindAgentInputs<typeof this>>(options: {
|
|
48
|
+
description?: string;
|
|
49
|
+
input?: Input;
|
|
50
|
+
}): BoundAgent<typeof this, Readonly<Input>>;
|
|
41
51
|
}
|
package/lib/cjs/agent.js
CHANGED
|
@@ -100,5 +100,16 @@ class Agent extends runnable_1.Runnable {
|
|
|
100
100
|
async onResult(_result) {
|
|
101
101
|
// Override this method to perform additional operations before the result is returned
|
|
102
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Bind some inputs to the agent, used for process of `PipelineAgent` or case of `LLMDecisionAgent`.
|
|
105
|
+
* @param options The bind options.
|
|
106
|
+
* @returns The bound agent.
|
|
107
|
+
*/
|
|
108
|
+
bind(options) {
|
|
109
|
+
return {
|
|
110
|
+
...options,
|
|
111
|
+
runnable: this,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
103
114
|
}
|
|
104
115
|
exports.Agent = Agent;
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { Agent, type AgentProcessOptions } from "./agent";
|
|
2
2
|
import type { Context, ContextState } from "./context";
|
|
3
|
-
import type { DataTypeSchema } from "./definitions/data-type-schema";
|
|
4
3
|
import { type CreateRunnableMemory } from "./definitions/memory";
|
|
5
4
|
import type { CreateLLMAgentOptions, LLMAgentDefinition } from "./llm-agent";
|
|
6
5
|
import type { LLMModel } from "./llm-model";
|
|
7
6
|
import type { MemorableSearchOutput, MemoryItemWithScore } from "./memorable";
|
|
8
|
-
import type {
|
|
7
|
+
import type { RunnableDefinition } from "./runnable";
|
|
9
8
|
import { OrderedRecord } from "./utils";
|
|
10
|
-
import type {
|
|
11
|
-
import type { UnionToIntersection } from "./utils/union";
|
|
9
|
+
import type { BindAgentInput, BoundAgent, ExtractRunnableInputTypeIntersection, ExtractRunnableOutputType, OmitBoundAgentInput } from "./utils/runnable-type";
|
|
12
10
|
export declare class LLMDecisionAgent<I extends {
|
|
13
11
|
[name: string]: any;
|
|
14
12
|
} = {}, O extends {
|
|
@@ -22,30 +20,7 @@ export declare class LLMDecisionAgent<I extends {
|
|
|
22
20
|
constructor(definition: LLMDecisionAgentDefinition, context?: Context<State>, model?: LLMModel | undefined);
|
|
23
21
|
process(input: I, options: AgentProcessOptions<Memories>): Promise<import("./runnable").RunnableResponse<O>>;
|
|
24
22
|
}
|
|
25
|
-
|
|
26
|
-
description?: string;
|
|
27
|
-
runnable: R;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Options to create LLMDecisionAgent.
|
|
31
|
-
*/
|
|
32
|
-
export interface CreateLLMDecisionAgentOptions<Case extends DecisionAgentCaseParameter, I extends UnionToIntersection<ExtractRunnableInputType<Case["runnable"]>, {
|
|
33
|
-
[name: string]: DataTypeSchema;
|
|
34
|
-
}>, O extends UnionToIntersection<ExtractRunnableOutputType<Case["runnable"]>, {
|
|
35
|
-
[name: string]: DataTypeSchema;
|
|
36
|
-
}>, Memories extends {
|
|
37
|
-
[name: string]: CreateRunnableMemory<I>;
|
|
38
|
-
}, State extends ContextState> extends Pick<CreateLLMAgentOptions<I, O, Memories, State>, "name" | "memories" | "messages" | "modelOptions"> {
|
|
39
|
-
context: Context<State>;
|
|
40
|
-
cases: {
|
|
41
|
-
[name: string]: Case;
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
declare function create<Case extends DecisionAgentCaseParameter, I extends UnionToIntersection<ExtractRunnableInputType<Case["runnable"]>, {
|
|
45
|
-
[name: string]: DataTypeSchema;
|
|
46
|
-
}>, O extends UnionToIntersection<ExtractRunnableOutputType<Case["runnable"]>, {
|
|
47
|
-
[name: string]: DataTypeSchema;
|
|
48
|
-
}>, Memories extends {
|
|
23
|
+
declare function create<Case extends BoundAgent, I extends ExtractRunnableInputTypeIntersection<Case["runnable"]>, O extends ExtractRunnableOutputType<Case["runnable"]>, Memories extends {
|
|
49
24
|
[name: string]: CreateRunnableMemory<I> & {
|
|
50
25
|
/**
|
|
51
26
|
* Whether this memory is primary? Primary memory will be passed as messages to LLM chat model,
|
|
@@ -55,7 +30,12 @@ declare function create<Case extends DecisionAgentCaseParameter, I extends Union
|
|
|
55
30
|
*/
|
|
56
31
|
primary?: boolean;
|
|
57
32
|
};
|
|
58
|
-
}, State extends ContextState>({ context, ...options }:
|
|
33
|
+
}, State extends ContextState>({ context, ...options }: Pick<CreateLLMAgentOptions<I, O, Memories, State>, "name" | "memories" | "messages" | "modelOptions"> & {
|
|
34
|
+
context: Context<State>;
|
|
35
|
+
cases: {
|
|
36
|
+
[name: string]: Case;
|
|
37
|
+
};
|
|
38
|
+
}): LLMDecisionAgent<OmitBoundAgentInput<Case, "ai">, ExtractRunnableOutputType<Case["runnable"]>, {
|
|
59
39
|
[name in keyof Memories]: MemorableSearchOutput<Memories[name]["memory"]>;
|
|
60
40
|
}, State>;
|
|
61
41
|
export interface LLMDecisionAgentDefinition extends RunnableDefinition, Pick<LLMAgentDefinition, "modelOptions" | "messages" | "primaryMemoryId"> {
|
|
@@ -69,5 +49,8 @@ export interface LLMDecisionCase {
|
|
|
69
49
|
runnable?: {
|
|
70
50
|
id?: string;
|
|
71
51
|
};
|
|
52
|
+
input?: {
|
|
53
|
+
[inputId: string]: BindAgentInput;
|
|
54
|
+
};
|
|
72
55
|
}
|
|
73
56
|
export {};
|
|
@@ -20,6 +20,7 @@ const constants_1 = require("./constants");
|
|
|
20
20
|
const memory_1 = require("./definitions/memory");
|
|
21
21
|
const utils_1 = require("./utils");
|
|
22
22
|
const message_utils_1 = require("./utils/message-utils");
|
|
23
|
+
const structured_output_schema_1 = require("./utils/structured-output-schema");
|
|
23
24
|
let LLMDecisionAgent = class LLMDecisionAgent extends agent_1.Agent {
|
|
24
25
|
definition;
|
|
25
26
|
model;
|
|
@@ -45,19 +46,23 @@ let LLMDecisionAgent = class LLMDecisionAgent extends agent_1.Agent {
|
|
|
45
46
|
const name = t.name || runnable.name;
|
|
46
47
|
if (!name)
|
|
47
48
|
throw new Error("Case name is required");
|
|
48
|
-
return {
|
|
49
|
+
return { ...t, name, runnable };
|
|
49
50
|
}));
|
|
50
51
|
const llmInputs = {
|
|
51
52
|
messages: messagesWithMemory,
|
|
52
53
|
modelOptions: definition.modelOptions,
|
|
53
54
|
tools: cases.map((t) => {
|
|
54
|
-
//
|
|
55
|
+
// Filter inputs that are bound from AI
|
|
56
|
+
const inputsFromAI = utils_1.OrderedRecord.fromArray(utils_1.OrderedRecord.filter(t.runnable.definition.inputs, (i) => t.input?.[i.id]?.from === "ai"));
|
|
57
|
+
const parameters = inputsFromAI.$indexes.length > 0
|
|
58
|
+
? (0, structured_output_schema_1.outputsToJsonSchema)(inputsFromAI)
|
|
59
|
+
: {};
|
|
55
60
|
return {
|
|
56
61
|
type: "function",
|
|
57
62
|
function: {
|
|
58
63
|
name: t.name,
|
|
59
64
|
description: t.description,
|
|
60
|
-
parameters
|
|
65
|
+
parameters,
|
|
61
66
|
},
|
|
62
67
|
};
|
|
63
68
|
}),
|
|
@@ -65,14 +70,16 @@ let LLMDecisionAgent = class LLMDecisionAgent extends agent_1.Agent {
|
|
|
65
70
|
};
|
|
66
71
|
const { toolCalls } = await model.run(llmInputs);
|
|
67
72
|
// TODO: support run multiple calls
|
|
68
|
-
const functionNameToCall = toolCalls?.[0]?.function
|
|
73
|
+
const { name: functionNameToCall, arguments: args } = toolCalls?.[0]?.function ?? {};
|
|
69
74
|
if (!functionNameToCall)
|
|
70
75
|
throw new Error("No any runnable called");
|
|
71
76
|
const caseToCall = cases.find((i) => i.name === functionNameToCall);
|
|
72
77
|
if (!caseToCall)
|
|
73
78
|
throw new Error("Case not found");
|
|
79
|
+
// Prepare arguments generated by LLM model
|
|
80
|
+
const llmArgs = args ? JSON.parse(args) : {};
|
|
74
81
|
// TODO: check result structure and omit undefined values
|
|
75
|
-
const output = await caseToCall.runnable.run(input, { stream: true });
|
|
82
|
+
const output = await caseToCall.runnable.run({ ...input, ...llmArgs }, { stream: true });
|
|
76
83
|
return (0, utils_1.extractOutputsFromRunnableOutput)(output, ({ $text, ...json }) => this.updateMemories([
|
|
77
84
|
...originalMessages,
|
|
78
85
|
{
|
|
@@ -92,12 +99,22 @@ exports.LLMDecisionAgent = LLMDecisionAgent = __decorate([
|
|
|
92
99
|
], LLMDecisionAgent);
|
|
93
100
|
function create({ context, ...options }) {
|
|
94
101
|
const agentId = options.name || (0, nanoid_1.nanoid)();
|
|
95
|
-
const cases = utils_1.OrderedRecord.fromArray(Object.entries(options.cases).map(([name, c]) =>
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
102
|
+
const cases = utils_1.OrderedRecord.fromArray(Object.entries(options.cases).map(([name, c]) => {
|
|
103
|
+
const bindInputs = Object.entries(c.input ?? {});
|
|
104
|
+
return {
|
|
105
|
+
id: (0, nanoid_1.nanoid)(),
|
|
106
|
+
name: name || c.runnable.name,
|
|
107
|
+
description: c.description,
|
|
108
|
+
runnable: { id: c.runnable.id },
|
|
109
|
+
input: Object.fromEntries(bindInputs.map(([inputName, v]) => {
|
|
110
|
+
const input = c.runnable.definition.inputs[inputName] ||
|
|
111
|
+
utils_1.OrderedRecord.find(c.runnable.definition.inputs, (i) => i.name === inputName);
|
|
112
|
+
if (!input)
|
|
113
|
+
throw new Error(`Input ${inputName} not found`);
|
|
114
|
+
return [input.id, v];
|
|
115
|
+
})),
|
|
116
|
+
};
|
|
117
|
+
}));
|
|
101
118
|
const inputs = utils_1.OrderedRecord.merge(...Object.values(options.cases).map((i) => i.runnable.definition.inputs));
|
|
102
119
|
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 })));
|
|
103
120
|
const memories = (0, memory_1.toRunnableMemories)(agentId, inputs, options.memories ?? {});
|
|
@@ -8,7 +8,9 @@ export declare class OpenaiLLMModel extends LLMModel {
|
|
|
8
8
|
private client;
|
|
9
9
|
setApiKey(apiKey: string): void;
|
|
10
10
|
process(input: LLMModelInputs): AsyncGenerator<{
|
|
11
|
-
$text: string
|
|
11
|
+
$text: string;
|
|
12
|
+
delta?: undefined;
|
|
13
|
+
} | {
|
|
12
14
|
delta: {
|
|
13
15
|
toolCalls: {
|
|
14
16
|
id?: string;
|
|
@@ -19,5 +21,6 @@ export declare class OpenaiLLMModel extends LLMModel {
|
|
|
19
21
|
};
|
|
20
22
|
}[];
|
|
21
23
|
};
|
|
24
|
+
$text?: undefined;
|
|
22
25
|
}, void, unknown>;
|
|
23
26
|
}
|
|
@@ -43,22 +43,22 @@ class OpenaiLLMModel extends llm_model_1.LLMModel {
|
|
|
43
43
|
const toolCalls = [];
|
|
44
44
|
for await (const chunk of res) {
|
|
45
45
|
const choice = chunk.choices?.[0];
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
if (choice?.delta.tool_calls?.length) {
|
|
47
|
+
for (const call of choice.delta.tool_calls) {
|
|
48
|
+
const tool = toolCalls[call.index] ?? { id: call.id || (0, nanoid_1.nanoid)() };
|
|
49
|
+
toolCalls[call.index] = tool;
|
|
50
|
+
if (call.type)
|
|
51
|
+
tool.type = call.type;
|
|
52
|
+
tool.function ??= {};
|
|
53
|
+
tool.function.name =
|
|
54
|
+
(tool.function.name || "") + (call.function?.name || "");
|
|
55
|
+
tool.function.arguments = (tool.function.arguments || "").concat(call.function?.arguments || "");
|
|
56
|
+
}
|
|
56
57
|
}
|
|
57
|
-
|
|
58
|
-
$text: choice
|
|
59
|
-
delta: { toolCalls },
|
|
60
|
-
};
|
|
58
|
+
if (choice?.delta.content)
|
|
59
|
+
yield { $text: choice.delta.content };
|
|
61
60
|
}
|
|
61
|
+
yield { delta: { toolCalls } };
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
exports.OpenaiLLMModel = OpenaiLLMModel;
|
|
@@ -1,3 +1,23 @@
|
|
|
1
1
|
import type { Runnable, RunnableResponseStream } from "../runnable";
|
|
2
|
+
import type { UnionToIntersection } from "./union";
|
|
2
3
|
export type ExtractRunnableInputType<T> = T extends Runnable<infer I, any> ? I : never;
|
|
3
4
|
export type ExtractRunnableOutputType<T> = T extends Runnable<any, infer O> ? Exclude<O, RunnableResponseStream<any>> : never;
|
|
5
|
+
export type ExtractRunnableInputTypeIntersection<T> = UnionToIntersection<ExtractRunnableInputType<T>, {}>;
|
|
6
|
+
export type ExtractRunnableOutputTypeIntersection<T> = UnionToIntersection<ExtractRunnableOutputType<T>, {}>;
|
|
7
|
+
export type BindAgentInput = {
|
|
8
|
+
from: "ai";
|
|
9
|
+
};
|
|
10
|
+
export type PickInputFrom<I, From extends BindAgentInput["from"]> = {
|
|
11
|
+
[key in keyof I as I[key] extends {
|
|
12
|
+
from: From;
|
|
13
|
+
} ? key : never]: I[key];
|
|
14
|
+
};
|
|
15
|
+
export type OmitBoundAgentInput<Case extends BoundAgent, From extends BindAgentInput["from"]> = Omit<UnionToIntersection<ExtractRunnableInputType<Case["runnable"]>, {}>, keyof PickInputFrom<Required<UnionToIntersection<NonNullable<Case["input"]>, {}>>, From>>;
|
|
16
|
+
export type BindAgentInputs<R extends Runnable> = {
|
|
17
|
+
[key in keyof ExtractRunnableInputType<R>]?: BindAgentInput;
|
|
18
|
+
};
|
|
19
|
+
export interface BoundAgent<R extends Runnable = Runnable, I extends BindAgentInputs<R> = BindAgentInputs<R>> {
|
|
20
|
+
description?: string;
|
|
21
|
+
runnable: R;
|
|
22
|
+
input?: I;
|
|
23
|
+
}
|
package/lib/dts/agent.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Context, ContextState } from "./context";
|
|
2
2
|
import type { MemoryItemWithScore, MemoryMessage } from "./memorable";
|
|
3
3
|
import { type RunOptions, Runnable, type RunnableResponse, type RunnableResponseChunk, type RunnableResponseStream } from "./runnable";
|
|
4
|
+
import type { BindAgentInputs, BoundAgent } from "./utils/runnable-type";
|
|
4
5
|
export interface AgentProcessOptions<Memories extends {
|
|
5
6
|
[name: string]: MemoryItemWithScore[];
|
|
6
7
|
}> {
|
|
@@ -38,4 +39,13 @@ export declare abstract class Agent<I extends {
|
|
|
38
39
|
*/
|
|
39
40
|
protected onResult(_result: O): Promise<void>;
|
|
40
41
|
abstract process(input: I, options: AgentProcessOptions<Memories>): Promise<RunnableResponse<O> | AsyncGenerator<RunnableResponseChunk<O>, void>> | AsyncGenerator<RunnableResponseChunk<O>, void>;
|
|
42
|
+
/**
|
|
43
|
+
* Bind some inputs to the agent, used for process of `PipelineAgent` or case of `LLMDecisionAgent`.
|
|
44
|
+
* @param options The bind options.
|
|
45
|
+
* @returns The bound agent.
|
|
46
|
+
*/
|
|
47
|
+
bind<Input extends BindAgentInputs<typeof this>>(options: {
|
|
48
|
+
description?: string;
|
|
49
|
+
input?: Input;
|
|
50
|
+
}): BoundAgent<typeof this, Readonly<Input>>;
|
|
41
51
|
}
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { Agent, type AgentProcessOptions } from "./agent";
|
|
2
2
|
import type { Context, ContextState } from "./context";
|
|
3
|
-
import type { DataTypeSchema } from "./definitions/data-type-schema";
|
|
4
3
|
import { type CreateRunnableMemory } from "./definitions/memory";
|
|
5
4
|
import type { CreateLLMAgentOptions, LLMAgentDefinition } from "./llm-agent";
|
|
6
5
|
import type { LLMModel } from "./llm-model";
|
|
7
6
|
import type { MemorableSearchOutput, MemoryItemWithScore } from "./memorable";
|
|
8
|
-
import type {
|
|
7
|
+
import type { RunnableDefinition } from "./runnable";
|
|
9
8
|
import { OrderedRecord } from "./utils";
|
|
10
|
-
import type {
|
|
11
|
-
import type { UnionToIntersection } from "./utils/union";
|
|
9
|
+
import type { BindAgentInput, BoundAgent, ExtractRunnableInputTypeIntersection, ExtractRunnableOutputType, OmitBoundAgentInput } from "./utils/runnable-type";
|
|
12
10
|
export declare class LLMDecisionAgent<I extends {
|
|
13
11
|
[name: string]: any;
|
|
14
12
|
} = {}, O extends {
|
|
@@ -22,30 +20,7 @@ export declare class LLMDecisionAgent<I extends {
|
|
|
22
20
|
constructor(definition: LLMDecisionAgentDefinition, context?: Context<State>, model?: LLMModel | undefined);
|
|
23
21
|
process(input: I, options: AgentProcessOptions<Memories>): Promise<import("./runnable").RunnableResponse<O>>;
|
|
24
22
|
}
|
|
25
|
-
|
|
26
|
-
description?: string;
|
|
27
|
-
runnable: R;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Options to create LLMDecisionAgent.
|
|
31
|
-
*/
|
|
32
|
-
export interface CreateLLMDecisionAgentOptions<Case extends DecisionAgentCaseParameter, I extends UnionToIntersection<ExtractRunnableInputType<Case["runnable"]>, {
|
|
33
|
-
[name: string]: DataTypeSchema;
|
|
34
|
-
}>, O extends UnionToIntersection<ExtractRunnableOutputType<Case["runnable"]>, {
|
|
35
|
-
[name: string]: DataTypeSchema;
|
|
36
|
-
}>, Memories extends {
|
|
37
|
-
[name: string]: CreateRunnableMemory<I>;
|
|
38
|
-
}, State extends ContextState> extends Pick<CreateLLMAgentOptions<I, O, Memories, State>, "name" | "memories" | "messages" | "modelOptions"> {
|
|
39
|
-
context: Context<State>;
|
|
40
|
-
cases: {
|
|
41
|
-
[name: string]: Case;
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
declare function create<Case extends DecisionAgentCaseParameter, I extends UnionToIntersection<ExtractRunnableInputType<Case["runnable"]>, {
|
|
45
|
-
[name: string]: DataTypeSchema;
|
|
46
|
-
}>, O extends UnionToIntersection<ExtractRunnableOutputType<Case["runnable"]>, {
|
|
47
|
-
[name: string]: DataTypeSchema;
|
|
48
|
-
}>, Memories extends {
|
|
23
|
+
declare function create<Case extends BoundAgent, I extends ExtractRunnableInputTypeIntersection<Case["runnable"]>, O extends ExtractRunnableOutputType<Case["runnable"]>, Memories extends {
|
|
49
24
|
[name: string]: CreateRunnableMemory<I> & {
|
|
50
25
|
/**
|
|
51
26
|
* Whether this memory is primary? Primary memory will be passed as messages to LLM chat model,
|
|
@@ -55,7 +30,12 @@ declare function create<Case extends DecisionAgentCaseParameter, I extends Union
|
|
|
55
30
|
*/
|
|
56
31
|
primary?: boolean;
|
|
57
32
|
};
|
|
58
|
-
}, State extends ContextState>({ context, ...options }:
|
|
33
|
+
}, State extends ContextState>({ context, ...options }: Pick<CreateLLMAgentOptions<I, O, Memories, State>, "name" | "memories" | "messages" | "modelOptions"> & {
|
|
34
|
+
context: Context<State>;
|
|
35
|
+
cases: {
|
|
36
|
+
[name: string]: Case;
|
|
37
|
+
};
|
|
38
|
+
}): LLMDecisionAgent<OmitBoundAgentInput<Case, "ai">, ExtractRunnableOutputType<Case["runnable"]>, {
|
|
59
39
|
[name in keyof Memories]: MemorableSearchOutput<Memories[name]["memory"]>;
|
|
60
40
|
}, State>;
|
|
61
41
|
export interface LLMDecisionAgentDefinition extends RunnableDefinition, Pick<LLMAgentDefinition, "modelOptions" | "messages" | "primaryMemoryId"> {
|
|
@@ -69,5 +49,8 @@ export interface LLMDecisionCase {
|
|
|
69
49
|
runnable?: {
|
|
70
50
|
id?: string;
|
|
71
51
|
};
|
|
52
|
+
input?: {
|
|
53
|
+
[inputId: string]: BindAgentInput;
|
|
54
|
+
};
|
|
72
55
|
}
|
|
73
56
|
export {};
|
|
@@ -8,7 +8,9 @@ export declare class OpenaiLLMModel extends LLMModel {
|
|
|
8
8
|
private client;
|
|
9
9
|
setApiKey(apiKey: string): void;
|
|
10
10
|
process(input: LLMModelInputs): AsyncGenerator<{
|
|
11
|
-
$text: string
|
|
11
|
+
$text: string;
|
|
12
|
+
delta?: undefined;
|
|
13
|
+
} | {
|
|
12
14
|
delta: {
|
|
13
15
|
toolCalls: {
|
|
14
16
|
id?: string;
|
|
@@ -19,5 +21,6 @@ export declare class OpenaiLLMModel extends LLMModel {
|
|
|
19
21
|
};
|
|
20
22
|
}[];
|
|
21
23
|
};
|
|
24
|
+
$text?: undefined;
|
|
22
25
|
}, void, unknown>;
|
|
23
26
|
}
|
|
@@ -1,3 +1,23 @@
|
|
|
1
1
|
import type { Runnable, RunnableResponseStream } from "../runnable";
|
|
2
|
+
import type { UnionToIntersection } from "./union";
|
|
2
3
|
export type ExtractRunnableInputType<T> = T extends Runnable<infer I, any> ? I : never;
|
|
3
4
|
export type ExtractRunnableOutputType<T> = T extends Runnable<any, infer O> ? Exclude<O, RunnableResponseStream<any>> : never;
|
|
5
|
+
export type ExtractRunnableInputTypeIntersection<T> = UnionToIntersection<ExtractRunnableInputType<T>, {}>;
|
|
6
|
+
export type ExtractRunnableOutputTypeIntersection<T> = UnionToIntersection<ExtractRunnableOutputType<T>, {}>;
|
|
7
|
+
export type BindAgentInput = {
|
|
8
|
+
from: "ai";
|
|
9
|
+
};
|
|
10
|
+
export type PickInputFrom<I, From extends BindAgentInput["from"]> = {
|
|
11
|
+
[key in keyof I as I[key] extends {
|
|
12
|
+
from: From;
|
|
13
|
+
} ? key : never]: I[key];
|
|
14
|
+
};
|
|
15
|
+
export type OmitBoundAgentInput<Case extends BoundAgent, From extends BindAgentInput["from"]> = Omit<UnionToIntersection<ExtractRunnableInputType<Case["runnable"]>, {}>, keyof PickInputFrom<Required<UnionToIntersection<NonNullable<Case["input"]>, {}>>, From>>;
|
|
16
|
+
export type BindAgentInputs<R extends Runnable> = {
|
|
17
|
+
[key in keyof ExtractRunnableInputType<R>]?: BindAgentInput;
|
|
18
|
+
};
|
|
19
|
+
export interface BoundAgent<R extends Runnable = Runnable, I extends BindAgentInputs<R> = BindAgentInputs<R>> {
|
|
20
|
+
description?: string;
|
|
21
|
+
runnable: R;
|
|
22
|
+
input?: I;
|
|
23
|
+
}
|
package/lib/esm/agent.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Context, ContextState } from "./context";
|
|
2
2
|
import type { MemoryItemWithScore, MemoryMessage } from "./memorable";
|
|
3
3
|
import { type RunOptions, Runnable, type RunnableResponse, type RunnableResponseChunk, type RunnableResponseStream } from "./runnable";
|
|
4
|
+
import type { BindAgentInputs, BoundAgent } from "./utils/runnable-type";
|
|
4
5
|
export interface AgentProcessOptions<Memories extends {
|
|
5
6
|
[name: string]: MemoryItemWithScore[];
|
|
6
7
|
}> {
|
|
@@ -38,4 +39,13 @@ export declare abstract class Agent<I extends {
|
|
|
38
39
|
*/
|
|
39
40
|
protected onResult(_result: O): Promise<void>;
|
|
40
41
|
abstract process(input: I, options: AgentProcessOptions<Memories>): Promise<RunnableResponse<O> | AsyncGenerator<RunnableResponseChunk<O>, void>> | AsyncGenerator<RunnableResponseChunk<O>, void>;
|
|
42
|
+
/**
|
|
43
|
+
* Bind some inputs to the agent, used for process of `PipelineAgent` or case of `LLMDecisionAgent`.
|
|
44
|
+
* @param options The bind options.
|
|
45
|
+
* @returns The bound agent.
|
|
46
|
+
*/
|
|
47
|
+
bind<Input extends BindAgentInputs<typeof this>>(options: {
|
|
48
|
+
description?: string;
|
|
49
|
+
input?: Input;
|
|
50
|
+
}): BoundAgent<typeof this, Readonly<Input>>;
|
|
41
51
|
}
|
package/lib/esm/agent.js
CHANGED
|
@@ -94,4 +94,15 @@ export class Agent extends Runnable {
|
|
|
94
94
|
async onResult(_result) {
|
|
95
95
|
// Override this method to perform additional operations before the result is returned
|
|
96
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Bind some inputs to the agent, used for process of `PipelineAgent` or case of `LLMDecisionAgent`.
|
|
99
|
+
* @param options The bind options.
|
|
100
|
+
* @returns The bound agent.
|
|
101
|
+
*/
|
|
102
|
+
bind(options) {
|
|
103
|
+
return {
|
|
104
|
+
...options,
|
|
105
|
+
runnable: this,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
97
108
|
}
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { Agent, type AgentProcessOptions } from "./agent";
|
|
2
2
|
import type { Context, ContextState } from "./context";
|
|
3
|
-
import type { DataTypeSchema } from "./definitions/data-type-schema";
|
|
4
3
|
import { type CreateRunnableMemory } from "./definitions/memory";
|
|
5
4
|
import type { CreateLLMAgentOptions, LLMAgentDefinition } from "./llm-agent";
|
|
6
5
|
import type { LLMModel } from "./llm-model";
|
|
7
6
|
import type { MemorableSearchOutput, MemoryItemWithScore } from "./memorable";
|
|
8
|
-
import type {
|
|
7
|
+
import type { RunnableDefinition } from "./runnable";
|
|
9
8
|
import { OrderedRecord } from "./utils";
|
|
10
|
-
import type {
|
|
11
|
-
import type { UnionToIntersection } from "./utils/union";
|
|
9
|
+
import type { BindAgentInput, BoundAgent, ExtractRunnableInputTypeIntersection, ExtractRunnableOutputType, OmitBoundAgentInput } from "./utils/runnable-type";
|
|
12
10
|
export declare class LLMDecisionAgent<I extends {
|
|
13
11
|
[name: string]: any;
|
|
14
12
|
} = {}, O extends {
|
|
@@ -22,30 +20,7 @@ export declare class LLMDecisionAgent<I extends {
|
|
|
22
20
|
constructor(definition: LLMDecisionAgentDefinition, context?: Context<State>, model?: LLMModel | undefined);
|
|
23
21
|
process(input: I, options: AgentProcessOptions<Memories>): Promise<import("./runnable").RunnableResponse<O>>;
|
|
24
22
|
}
|
|
25
|
-
|
|
26
|
-
description?: string;
|
|
27
|
-
runnable: R;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Options to create LLMDecisionAgent.
|
|
31
|
-
*/
|
|
32
|
-
export interface CreateLLMDecisionAgentOptions<Case extends DecisionAgentCaseParameter, I extends UnionToIntersection<ExtractRunnableInputType<Case["runnable"]>, {
|
|
33
|
-
[name: string]: DataTypeSchema;
|
|
34
|
-
}>, O extends UnionToIntersection<ExtractRunnableOutputType<Case["runnable"]>, {
|
|
35
|
-
[name: string]: DataTypeSchema;
|
|
36
|
-
}>, Memories extends {
|
|
37
|
-
[name: string]: CreateRunnableMemory<I>;
|
|
38
|
-
}, State extends ContextState> extends Pick<CreateLLMAgentOptions<I, O, Memories, State>, "name" | "memories" | "messages" | "modelOptions"> {
|
|
39
|
-
context: Context<State>;
|
|
40
|
-
cases: {
|
|
41
|
-
[name: string]: Case;
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
declare function create<Case extends DecisionAgentCaseParameter, I extends UnionToIntersection<ExtractRunnableInputType<Case["runnable"]>, {
|
|
45
|
-
[name: string]: DataTypeSchema;
|
|
46
|
-
}>, O extends UnionToIntersection<ExtractRunnableOutputType<Case["runnable"]>, {
|
|
47
|
-
[name: string]: DataTypeSchema;
|
|
48
|
-
}>, Memories extends {
|
|
23
|
+
declare function create<Case extends BoundAgent, I extends ExtractRunnableInputTypeIntersection<Case["runnable"]>, O extends ExtractRunnableOutputType<Case["runnable"]>, Memories extends {
|
|
49
24
|
[name: string]: CreateRunnableMemory<I> & {
|
|
50
25
|
/**
|
|
51
26
|
* Whether this memory is primary? Primary memory will be passed as messages to LLM chat model,
|
|
@@ -55,7 +30,12 @@ declare function create<Case extends DecisionAgentCaseParameter, I extends Union
|
|
|
55
30
|
*/
|
|
56
31
|
primary?: boolean;
|
|
57
32
|
};
|
|
58
|
-
}, State extends ContextState>({ context, ...options }:
|
|
33
|
+
}, State extends ContextState>({ context, ...options }: Pick<CreateLLMAgentOptions<I, O, Memories, State>, "name" | "memories" | "messages" | "modelOptions"> & {
|
|
34
|
+
context: Context<State>;
|
|
35
|
+
cases: {
|
|
36
|
+
[name: string]: Case;
|
|
37
|
+
};
|
|
38
|
+
}): LLMDecisionAgent<OmitBoundAgentInput<Case, "ai">, ExtractRunnableOutputType<Case["runnable"]>, {
|
|
59
39
|
[name in keyof Memories]: MemorableSearchOutput<Memories[name]["memory"]>;
|
|
60
40
|
}, State>;
|
|
61
41
|
export interface LLMDecisionAgentDefinition extends RunnableDefinition, Pick<LLMAgentDefinition, "modelOptions" | "messages" | "primaryMemoryId"> {
|
|
@@ -69,5 +49,8 @@ export interface LLMDecisionCase {
|
|
|
69
49
|
runnable?: {
|
|
70
50
|
id?: string;
|
|
71
51
|
};
|
|
52
|
+
input?: {
|
|
53
|
+
[inputId: string]: BindAgentInput;
|
|
54
|
+
};
|
|
72
55
|
}
|
|
73
56
|
export {};
|
|
@@ -17,6 +17,7 @@ import { TYPES } from "./constants";
|
|
|
17
17
|
import { toRunnableMemories, } from "./definitions/memory";
|
|
18
18
|
import { OrderedRecord, extractOutputsFromRunnableOutput, renderMessage, } from "./utils";
|
|
19
19
|
import { prepareMessages } from "./utils/message-utils";
|
|
20
|
+
import { outputsToJsonSchema } from "./utils/structured-output-schema";
|
|
20
21
|
let LLMDecisionAgent = class LLMDecisionAgent extends Agent {
|
|
21
22
|
definition;
|
|
22
23
|
model;
|
|
@@ -42,19 +43,23 @@ let LLMDecisionAgent = class LLMDecisionAgent extends Agent {
|
|
|
42
43
|
const name = t.name || runnable.name;
|
|
43
44
|
if (!name)
|
|
44
45
|
throw new Error("Case name is required");
|
|
45
|
-
return {
|
|
46
|
+
return { ...t, name, runnable };
|
|
46
47
|
}));
|
|
47
48
|
const llmInputs = {
|
|
48
49
|
messages: messagesWithMemory,
|
|
49
50
|
modelOptions: definition.modelOptions,
|
|
50
51
|
tools: cases.map((t) => {
|
|
51
|
-
//
|
|
52
|
+
// Filter inputs that are bound from AI
|
|
53
|
+
const inputsFromAI = OrderedRecord.fromArray(OrderedRecord.filter(t.runnable.definition.inputs, (i) => t.input?.[i.id]?.from === "ai"));
|
|
54
|
+
const parameters = inputsFromAI.$indexes.length > 0
|
|
55
|
+
? outputsToJsonSchema(inputsFromAI)
|
|
56
|
+
: {};
|
|
52
57
|
return {
|
|
53
58
|
type: "function",
|
|
54
59
|
function: {
|
|
55
60
|
name: t.name,
|
|
56
61
|
description: t.description,
|
|
57
|
-
parameters
|
|
62
|
+
parameters,
|
|
58
63
|
},
|
|
59
64
|
};
|
|
60
65
|
}),
|
|
@@ -62,14 +67,16 @@ let LLMDecisionAgent = class LLMDecisionAgent extends Agent {
|
|
|
62
67
|
};
|
|
63
68
|
const { toolCalls } = await model.run(llmInputs);
|
|
64
69
|
// TODO: support run multiple calls
|
|
65
|
-
const functionNameToCall = toolCalls?.[0]?.function
|
|
70
|
+
const { name: functionNameToCall, arguments: args } = toolCalls?.[0]?.function ?? {};
|
|
66
71
|
if (!functionNameToCall)
|
|
67
72
|
throw new Error("No any runnable called");
|
|
68
73
|
const caseToCall = cases.find((i) => i.name === functionNameToCall);
|
|
69
74
|
if (!caseToCall)
|
|
70
75
|
throw new Error("Case not found");
|
|
76
|
+
// Prepare arguments generated by LLM model
|
|
77
|
+
const llmArgs = args ? JSON.parse(args) : {};
|
|
71
78
|
// TODO: check result structure and omit undefined values
|
|
72
|
-
const output = await caseToCall.runnable.run(input, { stream: true });
|
|
79
|
+
const output = await caseToCall.runnable.run({ ...input, ...llmArgs }, { stream: true });
|
|
73
80
|
return extractOutputsFromRunnableOutput(output, ({ $text, ...json }) => this.updateMemories([
|
|
74
81
|
...originalMessages,
|
|
75
82
|
{
|
|
@@ -89,12 +96,22 @@ LLMDecisionAgent = __decorate([
|
|
|
89
96
|
export { LLMDecisionAgent };
|
|
90
97
|
function create({ context, ...options }) {
|
|
91
98
|
const agentId = options.name || nanoid();
|
|
92
|
-
const cases = OrderedRecord.fromArray(Object.entries(options.cases).map(([name, c]) =>
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
const cases = OrderedRecord.fromArray(Object.entries(options.cases).map(([name, c]) => {
|
|
100
|
+
const bindInputs = Object.entries(c.input ?? {});
|
|
101
|
+
return {
|
|
102
|
+
id: nanoid(),
|
|
103
|
+
name: name || c.runnable.name,
|
|
104
|
+
description: c.description,
|
|
105
|
+
runnable: { id: c.runnable.id },
|
|
106
|
+
input: Object.fromEntries(bindInputs.map(([inputName, v]) => {
|
|
107
|
+
const input = c.runnable.definition.inputs[inputName] ||
|
|
108
|
+
OrderedRecord.find(c.runnable.definition.inputs, (i) => i.name === inputName);
|
|
109
|
+
if (!input)
|
|
110
|
+
throw new Error(`Input ${inputName} not found`);
|
|
111
|
+
return [input.id, v];
|
|
112
|
+
})),
|
|
113
|
+
};
|
|
114
|
+
}));
|
|
98
115
|
const inputs = OrderedRecord.merge(...Object.values(options.cases).map((i) => i.runnable.definition.inputs));
|
|
99
116
|
const outputs = OrderedRecord.fromArray(OrderedRecord.map(OrderedRecord.merge(...Object.values(options.cases).map((i) => i.runnable.definition.outputs)), (o) => ({ ...o, required: false })));
|
|
100
117
|
const memories = toRunnableMemories(agentId, inputs, options.memories ?? {});
|
|
@@ -8,7 +8,9 @@ export declare class OpenaiLLMModel extends LLMModel {
|
|
|
8
8
|
private client;
|
|
9
9
|
setApiKey(apiKey: string): void;
|
|
10
10
|
process(input: LLMModelInputs): AsyncGenerator<{
|
|
11
|
-
$text: string
|
|
11
|
+
$text: string;
|
|
12
|
+
delta?: undefined;
|
|
13
|
+
} | {
|
|
12
14
|
delta: {
|
|
13
15
|
toolCalls: {
|
|
14
16
|
id?: string;
|
|
@@ -19,5 +21,6 @@ export declare class OpenaiLLMModel extends LLMModel {
|
|
|
19
21
|
};
|
|
20
22
|
}[];
|
|
21
23
|
};
|
|
24
|
+
$text?: undefined;
|
|
22
25
|
}, void, unknown>;
|
|
23
26
|
}
|
|
@@ -37,22 +37,22 @@ export class OpenaiLLMModel extends LLMModel {
|
|
|
37
37
|
const toolCalls = [];
|
|
38
38
|
for await (const chunk of res) {
|
|
39
39
|
const choice = chunk.choices?.[0];
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
if (choice?.delta.tool_calls?.length) {
|
|
41
|
+
for (const call of choice.delta.tool_calls) {
|
|
42
|
+
const tool = toolCalls[call.index] ?? { id: call.id || nanoid() };
|
|
43
|
+
toolCalls[call.index] = tool;
|
|
44
|
+
if (call.type)
|
|
45
|
+
tool.type = call.type;
|
|
46
|
+
tool.function ??= {};
|
|
47
|
+
tool.function.name =
|
|
48
|
+
(tool.function.name || "") + (call.function?.name || "");
|
|
49
|
+
tool.function.arguments = (tool.function.arguments || "").concat(call.function?.arguments || "");
|
|
50
|
+
}
|
|
50
51
|
}
|
|
51
|
-
|
|
52
|
-
$text: choice
|
|
53
|
-
delta: { toolCalls },
|
|
54
|
-
};
|
|
52
|
+
if (choice?.delta.content)
|
|
53
|
+
yield { $text: choice.delta.content };
|
|
55
54
|
}
|
|
55
|
+
yield { delta: { toolCalls } };
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
async function contentsFromInputMessages(messages) {
|
|
@@ -1,3 +1,23 @@
|
|
|
1
1
|
import type { Runnable, RunnableResponseStream } from "../runnable";
|
|
2
|
+
import type { UnionToIntersection } from "./union";
|
|
2
3
|
export type ExtractRunnableInputType<T> = T extends Runnable<infer I, any> ? I : never;
|
|
3
4
|
export type ExtractRunnableOutputType<T> = T extends Runnable<any, infer O> ? Exclude<O, RunnableResponseStream<any>> : never;
|
|
5
|
+
export type ExtractRunnableInputTypeIntersection<T> = UnionToIntersection<ExtractRunnableInputType<T>, {}>;
|
|
6
|
+
export type ExtractRunnableOutputTypeIntersection<T> = UnionToIntersection<ExtractRunnableOutputType<T>, {}>;
|
|
7
|
+
export type BindAgentInput = {
|
|
8
|
+
from: "ai";
|
|
9
|
+
};
|
|
10
|
+
export type PickInputFrom<I, From extends BindAgentInput["from"]> = {
|
|
11
|
+
[key in keyof I as I[key] extends {
|
|
12
|
+
from: From;
|
|
13
|
+
} ? key : never]: I[key];
|
|
14
|
+
};
|
|
15
|
+
export type OmitBoundAgentInput<Case extends BoundAgent, From extends BindAgentInput["from"]> = Omit<UnionToIntersection<ExtractRunnableInputType<Case["runnable"]>, {}>, keyof PickInputFrom<Required<UnionToIntersection<NonNullable<Case["input"]>, {}>>, From>>;
|
|
16
|
+
export type BindAgentInputs<R extends Runnable> = {
|
|
17
|
+
[key in keyof ExtractRunnableInputType<R>]?: BindAgentInput;
|
|
18
|
+
};
|
|
19
|
+
export interface BoundAgent<R extends Runnable = Runnable, I extends BindAgentInputs<R> = BindAgentInputs<R>> {
|
|
20
|
+
description?: string;
|
|
21
|
+
runnable: R;
|
|
22
|
+
input?: I;
|
|
23
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"description": "AIGNE core library",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -24,14 +24,14 @@
|
|
|
24
24
|
"url": "git+https://github.com/blocklet/ai-studio.git"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
+
"@google/generative-ai": "^0.21.0",
|
|
27
28
|
"@types/mustache": "^4.2.5",
|
|
28
29
|
"lodash": "^4.17.21",
|
|
29
30
|
"mustache": "^4.2.0",
|
|
30
31
|
"nanoid": "^5.0.9",
|
|
31
|
-
"tsyringe": "^4.8.0",
|
|
32
|
-
"ufo": "^1.5.4",
|
|
33
32
|
"openai": "^4.79.1",
|
|
34
|
-
"
|
|
33
|
+
"tsyringe": "^4.8.0",
|
|
34
|
+
"ufo": "^1.5.4"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@google/generative-ai": "^0.21.0",
|