goblin-agents 2.5.0 → 3.0.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/llm/aiAgent.js +33 -112
- package/lib/llm/providers/opanAi.js +17 -2
- package/package.json +1 -1
package/lib/llm/aiAgent.js
CHANGED
|
@@ -150,6 +150,11 @@ class AiAgentShape {
|
|
|
150
150
|
role = string; //agent role
|
|
151
151
|
prompt = string; //default system prompt
|
|
152
152
|
contexts = record(string, string); //additionnal system prompt context
|
|
153
|
+
reasonings = record(
|
|
154
|
+
string,
|
|
155
|
+
enumeration(false, true, 'low', 'medium', 'high')
|
|
156
|
+
); //contextuals reasonings levels
|
|
157
|
+
models = record(string, string); //contextuals models
|
|
153
158
|
provider = enumeration('ollama', 'open-ai');
|
|
154
159
|
model = string;
|
|
155
160
|
otherModels = array(string);
|
|
@@ -161,7 +166,7 @@ class AiAgentShape {
|
|
|
161
166
|
tools = option(array(object));
|
|
162
167
|
toolServiceId = option(string);
|
|
163
168
|
usability = enumeration('disabled', 'experimental', 'stable', 'deprecated');
|
|
164
|
-
reasoning = option(
|
|
169
|
+
reasoning = option(enumeration(false, true, 'low', 'medium', 'high'));
|
|
165
170
|
vectorQuality = option(enumeration('f32', 'int8'));
|
|
166
171
|
meta = MetaShape;
|
|
167
172
|
}
|
|
@@ -201,6 +206,8 @@ class AiAgentLogic extends Elf.Archetype {
|
|
|
201
206
|
otherModels: defaultValues.otherModels,
|
|
202
207
|
messages: {},
|
|
203
208
|
contexts: {},
|
|
209
|
+
reasonings: {},
|
|
210
|
+
models: {},
|
|
204
211
|
options: defaultValues.options,
|
|
205
212
|
host: defaultValues.host,
|
|
206
213
|
headers: defaultValues.headers,
|
|
@@ -239,6 +246,12 @@ class AiAgentLogic extends Elf.Archetype {
|
|
|
239
246
|
if (state.contexts[contextId]) {
|
|
240
247
|
delete state.contexts[contextId];
|
|
241
248
|
}
|
|
249
|
+
if (state.models[contextId]) {
|
|
250
|
+
delete state.models[contextId];
|
|
251
|
+
}
|
|
252
|
+
if (state.reasonings[contextId]) {
|
|
253
|
+
delete state.reasonings[contextId];
|
|
254
|
+
}
|
|
242
255
|
}
|
|
243
256
|
|
|
244
257
|
set(contextId, messages) {
|
|
@@ -246,9 +259,11 @@ class AiAgentLogic extends Elf.Archetype {
|
|
|
246
259
|
state.messages[contextId] = messages;
|
|
247
260
|
}
|
|
248
261
|
|
|
249
|
-
setContext(contextId, context) {
|
|
262
|
+
setContext(contextId, context, model, reasoning) {
|
|
250
263
|
const {state} = this;
|
|
251
264
|
state.contexts[contextId] = context;
|
|
265
|
+
state.models[contextId] = model || this.state.model;
|
|
266
|
+
state.reasonings[contextId] = reasoning || this.state.reasoning;
|
|
252
267
|
}
|
|
253
268
|
|
|
254
269
|
chat(contextId, role, content) {
|
|
@@ -579,8 +594,15 @@ class AiAgent extends Elf {
|
|
|
579
594
|
this.logic.set(contextId, messages);
|
|
580
595
|
}
|
|
581
596
|
|
|
582
|
-
|
|
583
|
-
|
|
597
|
+
/**
|
|
598
|
+
* Set chat session context, model and level of reasoning
|
|
599
|
+
* @param {*} contextId
|
|
600
|
+
* @param {string} context
|
|
601
|
+
* @param {string} model
|
|
602
|
+
* @param {string} reasoning
|
|
603
|
+
*/
|
|
604
|
+
async setContext(contextId, context, model, reasoning) {
|
|
605
|
+
this.logic.setContext(contextId, context, model, reasoning);
|
|
584
606
|
}
|
|
585
607
|
|
|
586
608
|
async chat(contextId, question, userDesktopId) {
|
|
@@ -591,7 +613,9 @@ class AiAgent extends Elf {
|
|
|
591
613
|
|
|
592
614
|
await this._loadProvider();
|
|
593
615
|
const contextMessages = this.state.messages[contextId] || [];
|
|
594
|
-
const context = this.state.contexts[contextId];
|
|
616
|
+
const context = this.state.contexts[contextId] || null;
|
|
617
|
+
const reasoning = this.state.reasonings[contextId] || this.state.reasoning;
|
|
618
|
+
const model = this.state.models[contextId] || this.state.model;
|
|
595
619
|
|
|
596
620
|
let systemPrompt = this.state.prompt || '';
|
|
597
621
|
if (context) {
|
|
@@ -623,12 +647,12 @@ ${context}
|
|
|
623
647
|
this.log.dbg(`🐈 Chat session started : ${contextId}`);
|
|
624
648
|
|
|
625
649
|
const chatCompletionRequest = {
|
|
626
|
-
model
|
|
650
|
+
model,
|
|
651
|
+
reasoning,
|
|
627
652
|
messages,
|
|
628
653
|
options,
|
|
629
654
|
format: this.state.format?.toJS(),
|
|
630
655
|
tools: this.state.tools?.toJS(),
|
|
631
|
-
reasoning: this.state.reasoning,
|
|
632
656
|
};
|
|
633
657
|
|
|
634
658
|
const result = await this._provider.chat(chatCompletionRequest);
|
|
@@ -716,47 +740,6 @@ ${context}
|
|
|
716
740
|
this.logic.addToolMessage(contextId, toolId, toolName, answer);
|
|
717
741
|
}
|
|
718
742
|
|
|
719
|
-
async ask(contextId, question, questionId) {
|
|
720
|
-
if (this.state.provider !== 'ollama') {
|
|
721
|
-
throw new Error('Streaming API not impl.');
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
await this._mutex.lock(this.id);
|
|
725
|
-
this.quest.defer(() => this._mutex.unlock(this.id));
|
|
726
|
-
|
|
727
|
-
await this._loadProvider();
|
|
728
|
-
|
|
729
|
-
const contextMessages = this.state.messages[contextId] || [];
|
|
730
|
-
const messages = [
|
|
731
|
-
{role: 'system', content: this.state.prompt},
|
|
732
|
-
...Array.from(contextMessages).map((m) => m._state.toJS()), //history
|
|
733
|
-
];
|
|
734
|
-
//add new question
|
|
735
|
-
messages.push({role: 'user', content: question});
|
|
736
|
-
|
|
737
|
-
let options;
|
|
738
|
-
if (this.state.options) {
|
|
739
|
-
const pState = this.state._state.toJS();
|
|
740
|
-
options = pState?.options;
|
|
741
|
-
}
|
|
742
|
-
const response = await this._provider.chat({
|
|
743
|
-
model: this.state.model,
|
|
744
|
-
messages,
|
|
745
|
-
reasoning: this.state.reasoning,
|
|
746
|
-
options,
|
|
747
|
-
stream: true,
|
|
748
|
-
});
|
|
749
|
-
|
|
750
|
-
let agentResponse = '';
|
|
751
|
-
for await (const part of response) {
|
|
752
|
-
agentResponse += part.message.content;
|
|
753
|
-
this.quest.evt(`<${questionId}>`, {part: part.message.content});
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
//keep agent response
|
|
757
|
-
this.logic.ask(contextId, question, agentResponse);
|
|
758
|
-
}
|
|
759
|
-
|
|
760
743
|
async resumeExchange(resumePrompt, contextId) {
|
|
761
744
|
await this._mutex.lock(this.id);
|
|
762
745
|
this.quest.defer(() => this._mutex.unlock(this.id));
|
|
@@ -778,7 +761,7 @@ ${context}
|
|
|
778
761
|
model: this.state.model,
|
|
779
762
|
prompt,
|
|
780
763
|
system: resumePrompt,
|
|
781
|
-
reasoning:
|
|
764
|
+
reasoning: 'low',
|
|
782
765
|
options,
|
|
783
766
|
stream: false,
|
|
784
767
|
});
|
|
@@ -814,7 +797,7 @@ ${context}
|
|
|
814
797
|
model: this.state.model,
|
|
815
798
|
prompt,
|
|
816
799
|
system: CONVERSATION_TITLE_PROMPT,
|
|
817
|
-
reasoning:
|
|
800
|
+
reasoning: 'low',
|
|
818
801
|
options,
|
|
819
802
|
stream: false,
|
|
820
803
|
});
|
|
@@ -822,68 +805,6 @@ ${context}
|
|
|
822
805
|
return cleanText(title).trim();
|
|
823
806
|
}
|
|
824
807
|
|
|
825
|
-
async react(reactPrompt, contextId, question) {
|
|
826
|
-
await this._mutex.lock(this.id);
|
|
827
|
-
this.quest.defer(() => this._mutex.unlock(this.id));
|
|
828
|
-
|
|
829
|
-
await this._loadProvider();
|
|
830
|
-
const feedId = await this.newQuestFeed();
|
|
831
|
-
const contextMessages = this.state.messages[contextId] || [];
|
|
832
|
-
const messages = [
|
|
833
|
-
{role: 'system', content: reactPrompt},
|
|
834
|
-
...Array.from(contextMessages).map((m) => m._state.toJS()), //history
|
|
835
|
-
{role: 'user', content: question},
|
|
836
|
-
];
|
|
837
|
-
this.log.dbg('ReAct Question:', question);
|
|
838
|
-
|
|
839
|
-
let options;
|
|
840
|
-
if (this.state.options) {
|
|
841
|
-
options = this.state.options.toJS();
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
const answer = await this._provider.chat({
|
|
845
|
-
model: this.state.model,
|
|
846
|
-
messages,
|
|
847
|
-
options,
|
|
848
|
-
reasoning: this.state.reasoning,
|
|
849
|
-
format: {
|
|
850
|
-
type: 'object',
|
|
851
|
-
properties: {
|
|
852
|
-
observation: {type: 'string'},
|
|
853
|
-
thought: {type: 'string'},
|
|
854
|
-
action: {type: 'string'},
|
|
855
|
-
agentId: {type: 'string'},
|
|
856
|
-
result: {type: 'string'},
|
|
857
|
-
},
|
|
858
|
-
required: ['observation', 'thought', 'action', 'agentId', 'result'],
|
|
859
|
-
},
|
|
860
|
-
});
|
|
861
|
-
if (!answer.message.content) {
|
|
862
|
-
await this.addAssistantMessage(
|
|
863
|
-
contextId,
|
|
864
|
-
'Génération stoppée. Impossible de répondre.'
|
|
865
|
-
);
|
|
866
|
-
return;
|
|
867
|
-
}
|
|
868
|
-
const {agentId, action, result, observation} = answer.message.content;
|
|
869
|
-
this.log.dbg('ReAct Observation:', observation);
|
|
870
|
-
this.log.dbg('ReAct Action:', action);
|
|
871
|
-
// Ajoute l'observation
|
|
872
|
-
await this.addAssistantMessage(contextId, observation);
|
|
873
|
-
// Si un agent est nécessaire, appel de l'agent externe
|
|
874
|
-
if (agentId) {
|
|
875
|
-
const result = await this.callAgent(
|
|
876
|
-
contextId,
|
|
877
|
-
agentId,
|
|
878
|
-
`${observation} -> ${action}`,
|
|
879
|
-
feedId
|
|
880
|
-
);
|
|
881
|
-
return {agentId, action, result, observation};
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
return {agentId, action, result, observation};
|
|
885
|
-
}
|
|
886
|
-
|
|
887
808
|
async callAgent(contextId, agentId, action, feedId) {
|
|
888
809
|
this.log.dbg(`🥸 calling "${agentId}" with action: "${action}"`);
|
|
889
810
|
const exist = await this.cryo.isPersisted(AiAgentLogic.db, agentId);
|
|
@@ -13,7 +13,6 @@ class OpenAIProvider extends LLMProvider {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
async chat(chatRequest) {
|
|
16
|
-
delete chatRequest.reasoning; //not yet supported
|
|
17
16
|
if (chatRequest.options) {
|
|
18
17
|
chatRequest = {...chatRequest, ...chatRequest.options};
|
|
19
18
|
delete chatRequest.options;
|
|
@@ -24,6 +23,12 @@ class OpenAIProvider extends LLMProvider {
|
|
|
24
23
|
if (!chatRequest.format) {
|
|
25
24
|
delete chatRequest.format;
|
|
26
25
|
}
|
|
26
|
+
if (chatRequest.reasoning !== undefined) {
|
|
27
|
+
if (chatRequest.reasoning) {
|
|
28
|
+
chatRequest.reasoning_effort = chatRequest.reasoning;
|
|
29
|
+
}
|
|
30
|
+
delete chatRequest.reasoning;
|
|
31
|
+
}
|
|
27
32
|
const useFormat = chatRequest?.format !== undefined;
|
|
28
33
|
if (useFormat) {
|
|
29
34
|
chatRequest.response_format = {
|
|
@@ -69,7 +74,16 @@ class OpenAIProvider extends LLMProvider {
|
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
async gen(genRequest) {
|
|
72
|
-
const {
|
|
77
|
+
const {
|
|
78
|
+
model,
|
|
79
|
+
system,
|
|
80
|
+
prompt,
|
|
81
|
+
format,
|
|
82
|
+
tools,
|
|
83
|
+
options,
|
|
84
|
+
stream,
|
|
85
|
+
reasoning,
|
|
86
|
+
} = genRequest;
|
|
73
87
|
const chatRequest = {
|
|
74
88
|
model,
|
|
75
89
|
messages: [
|
|
@@ -80,6 +94,7 @@ class OpenAIProvider extends LLMProvider {
|
|
|
80
94
|
format,
|
|
81
95
|
tools,
|
|
82
96
|
stream,
|
|
97
|
+
reasoning,
|
|
83
98
|
};
|
|
84
99
|
const chat = await this.chat(chatRequest);
|
|
85
100
|
return chat.message.content;
|