@drax/ai-back 3.54.0 → 3.55.0

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.
Files changed (35) hide show
  1. package/dist/config/AiConfig.js +6 -0
  2. package/dist/factory/ai/AiProviderFactory.js +6 -1
  3. package/dist/index.js +2 -1
  4. package/dist/providers/ai/AbstractAiProvider.js +53 -0
  5. package/dist/providers/ai/DeepSeekAiProvider.js +209 -3
  6. package/dist/providers/ai/GoogleAiProvider.js +4 -20
  7. package/dist/providers/ai/OllamaAiProvider.js +4 -43
  8. package/dist/providers/ai/OpenAiProvider.js +4 -40
  9. package/package.json +3 -3
  10. package/src/config/AiConfig.ts +10 -0
  11. package/src/factory/ai/AiProviderFactory.ts +6 -1
  12. package/src/index.ts +2 -0
  13. package/src/providers/ai/AbstractAiProvider.ts +69 -0
  14. package/src/providers/ai/DeepSeekAiProvider.ts +263 -5
  15. package/src/providers/ai/GoogleAiProvider.ts +4 -26
  16. package/src/providers/ai/OllamaAiProvider.ts +4 -53
  17. package/src/providers/ai/OpenAiProvider.ts +4 -50
  18. package/test/DeepSeekProvider.test.ts +94 -0
  19. package/test/GoogleAiProvider.test.ts +17 -1
  20. package/tsconfig.tsbuildinfo +1 -1
  21. package/types/config/AiConfig.d.ts +6 -0
  22. package/types/config/AiConfig.d.ts.map +1 -0
  23. package/types/controllers/AICrudController.d.ts +1 -1
  24. package/types/factory/ai/AiProviderFactory.d.ts.map +1 -1
  25. package/types/index.d.ts +2 -1
  26. package/types/index.d.ts.map +1 -1
  27. package/types/providers/ai/AbstractAiProvider.d.ts +11 -1
  28. package/types/providers/ai/AbstractAiProvider.d.ts.map +1 -1
  29. package/types/providers/ai/DeepSeekAiProvider.d.ts +65 -2
  30. package/types/providers/ai/DeepSeekAiProvider.d.ts.map +1 -1
  31. package/types/providers/ai/GoogleAiProvider.d.ts.map +1 -1
  32. package/types/providers/ai/OllamaAiProvider.d.ts +0 -2
  33. package/types/providers/ai/OllamaAiProvider.d.ts.map +1 -1
  34. package/types/providers/ai/OpenAiProvider.d.ts +0 -2
  35. package/types/providers/ai/OpenAiProvider.d.ts.map +1 -1
@@ -0,0 +1,6 @@
1
+ var AiConfig;
2
+ (function (AiConfig) {
3
+ AiConfig["AiProvider"] = "AI_PROVIDER";
4
+ })(AiConfig || (AiConfig = {}));
5
+ export default AiConfig;
6
+ export { AiConfig };
@@ -1,20 +1,25 @@
1
+ import { DraxConfig } from "@drax/common-back";
2
+ import AiConfig from "../../config/AiConfig.js";
1
3
  import OpenAiProviderFactory from "./OpenAiProviderFactory.js";
2
4
  import GoogleAiProviderFactory from "./GoogleAiProviderFactory.js";
3
5
  import OllamaAiProviderFactory from "./OllamaAiProviderFactory.js";
4
6
  import DeepSeekAiProviderFactory from "./DeepSeekAiProviderFactory.js";
5
7
  class AiProviderFactory {
6
- static instance(provider = 'OpenAi') {
8
+ static instance(provider = DraxConfig.getOrLoad(AiConfig.AiProvider, "string", "OpenAi")) {
7
9
  if (!AiProviderFactory.singletons[provider]) {
8
10
  switch (provider) {
9
11
  case 'OpenAi':
10
12
  AiProviderFactory.singletons[provider] = OpenAiProviderFactory.instance();
11
13
  break;
12
14
  case 'GoogleAi':
15
+ case 'Google':
13
16
  AiProviderFactory.singletons[provider] = GoogleAiProviderFactory.instance();
14
17
  break;
15
18
  case 'OllamaAi':
19
+ case 'Ollama':
16
20
  AiProviderFactory.singletons[provider] = OllamaAiProviderFactory.instance();
17
21
  break;
22
+ case 'DeepSeekAi':
18
23
  case 'DeepSeek':
19
24
  AiProviderFactory.singletons[provider] = DeepSeekAiProviderFactory.instance();
20
25
  break;
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { AiConfig } from "./config/AiConfig.js";
1
2
  import { OpenAiConfig } from "./config/OpenAiConfig.js";
2
3
  import { GoogleAiConfig } from "./config/GoogleAiConfig.js";
3
4
  import { OllamaAiConfig } from "./config/OllamaAiConfig.js";
@@ -54,7 +55,7 @@ import DraxAgentRoutes from "./routes/DraxAgentRoutes.js";
54
55
  import AgentSessionRoutes from "./routes/AgentSessionRoutes.js";
55
56
  import { DraxAgent } from "./agents/DraxAgent.js";
56
57
  import { BuildContextTool } from "./tools/BuildContextTool.js";
57
- export { OpenAiConfig, GoogleAiConfig, OllamaAiConfig, DeepSeekConfig, ElevenLabsTTSConfig, AILogSchema, AILogBaseSchema, TTSVoiceSchema, TTSVoiceBaseSchema, TTSVoiceProviderSchema, TTSRequestSchema, TTSVoiceSettingsSchema, AILogModel, TTSVoiceModel, AILogMongoRepository, AILogSqliteRepository, TTSVoiceMongoRepository, TTSVoiceSqliteRepository, OpenAiProviderFactory, GoogleAiProviderFactory, OllamaAiProviderFactory, DeepSeekAiProviderFactory, AiProviderFactory, ElevenLabsTTSProviderFactory, TTSProviderFactory, DraxAgentFactory, AILogServiceFactory, TTSVoiceServiceFactory, OpenAiProvider, GoogleAiProvider, OllamaAiProvider, DeepSeekAiProvider, ElevenLabsTTSProvider, BuilderTool, BuildContextTool,
58
+ export { AiConfig, OpenAiConfig, GoogleAiConfig, OllamaAiConfig, DeepSeekConfig, ElevenLabsTTSConfig, AILogSchema, AILogBaseSchema, TTSVoiceSchema, TTSVoiceBaseSchema, TTSVoiceProviderSchema, TTSRequestSchema, TTSVoiceSettingsSchema, AILogModel, TTSVoiceModel, AILogMongoRepository, AILogSqliteRepository, TTSVoiceMongoRepository, TTSVoiceSqliteRepository, OpenAiProviderFactory, GoogleAiProviderFactory, OllamaAiProviderFactory, DeepSeekAiProviderFactory, AiProviderFactory, ElevenLabsTTSProviderFactory, TTSProviderFactory, DraxAgentFactory, AILogServiceFactory, TTSVoiceServiceFactory, OpenAiProvider, GoogleAiProvider, OllamaAiProvider, DeepSeekAiProvider, ElevenLabsTTSProvider, BuilderTool, BuildContextTool,
58
59
  //Service
59
60
  KnowledgeService, AILogService, TTSVoiceService, TTSGenericService, PromptAudioService,
60
61
  //Permissions
@@ -3,6 +3,59 @@ class AbstractAiProvider {
3
3
  this.providerName = providerName;
4
4
  this._aiLogService = aiLogService;
5
5
  }
6
+ buildSystemPrompt(input) {
7
+ if (!input.systemPrompt) {
8
+ throw new Error("systemPrompt required");
9
+ }
10
+ let systemPrompt = input.systemPrompt;
11
+ if (input.memory && input.memory.length > 0) {
12
+ systemPrompt += `\n\n ${input.memoryHeader ?? '[MEMORIA]'}\n ${input.memory.map(m => `${m.key}: ${m.value}`).join('\n')}`;
13
+ }
14
+ if (input.knowledgeBase && input.knowledgeBase.length > 0) {
15
+ systemPrompt += `\n\n${input.knowledgeBaseHeader ?? '[BASE DE CONOCIMIENTO]'}\n ${input.knowledgeBase.join('\n')}`;
16
+ }
17
+ return systemPrompt;
18
+ }
19
+ resolvePromptModel(input, model, visionModel) {
20
+ return input.model ?? (this.hasImageInput(input) ? visionModel ?? model : model);
21
+ }
22
+ getDefaultToolParameters() {
23
+ return {
24
+ type: "object",
25
+ properties: {},
26
+ additionalProperties: false,
27
+ };
28
+ }
29
+ findToolOrThrow(toolName, tools = []) {
30
+ const tool = tools.find(t => t.name === toolName);
31
+ if (!tool) {
32
+ throw new Error(`Tool not found: ${toolName}`);
33
+ }
34
+ return tool;
35
+ }
36
+ parseToolArguments(args) {
37
+ if (!args) {
38
+ return {};
39
+ }
40
+ if (typeof args === "object") {
41
+ return args;
42
+ }
43
+ try {
44
+ return JSON.parse(args);
45
+ }
46
+ catch (e) {
47
+ throw new Error(`Invalid tool arguments: ${args}`);
48
+ }
49
+ }
50
+ serializeToolOutput(output) {
51
+ if (typeof output === "string") {
52
+ return output;
53
+ }
54
+ if (output === undefined) {
55
+ return "";
56
+ }
57
+ return JSON.stringify(output);
58
+ }
6
59
  hasImageInput(input) {
7
60
  if (input.userImages && input.userImages.length > 0) {
8
61
  return true;
@@ -1,6 +1,8 @@
1
1
  import OpenAI from "openai";
2
- import OpenAiProvider from "./OpenAiProvider.js";
3
- class DeepSeekAiProvider extends OpenAiProvider {
2
+ import { toJSONSchema } from "zod";
3
+ import PromptAudioService from "../../services/PromptAudioService.js";
4
+ import AbstractAiProvider from "./AbstractAiProvider.js";
5
+ class DeepSeekAiProvider extends AbstractAiProvider {
4
6
  constructor(apiKey, model, baseUrl = "https://api.deepseek.com", visionModel, aiLogService) {
5
7
  if (!apiKey) {
6
8
  throw new Error("DeepSeek apiKey required");
@@ -8,11 +10,20 @@ class DeepSeekAiProvider extends OpenAiProvider {
8
10
  if (!model) {
9
11
  throw new Error("DeepSeek model required");
10
12
  }
11
- super(apiKey, model, visionModel, aiLogService, "deepseek");
12
13
  if (!baseUrl) {
13
14
  throw new Error("DeepSeek baseUrl required");
14
15
  }
16
+ super("deepseek", aiLogService);
17
+ this._apiKey = apiKey;
18
+ this._model = model;
15
19
  this._baseUrl = baseUrl;
20
+ this._visionModel = visionModel;
21
+ }
22
+ get model() {
23
+ if (!this._model) {
24
+ throw new Error("DeepSeek model not found");
25
+ }
26
+ return this._model;
16
27
  }
17
28
  get client() {
18
29
  if (!this._client) {
@@ -23,6 +34,201 @@ class DeepSeekAiProvider extends OpenAiProvider {
23
34
  }
24
35
  return this._client;
25
36
  }
37
+ get visionModel() {
38
+ return this._visionModel;
39
+ }
40
+ buildUserContent(input) {
41
+ if (input.userContent && input.userContent.length > 0) {
42
+ return this.mapContentParts(input.userContent);
43
+ }
44
+ if (input.userImages && input.userImages.length > 0) {
45
+ const content = [];
46
+ if (input.userInput) {
47
+ content.push({ type: 'text', text: input.userInput });
48
+ }
49
+ content.push(...input.userImages.map(image => ({
50
+ type: 'image_url',
51
+ image_url: {
52
+ url: image.url,
53
+ ...(image.detail ? { detail: image.detail } : {}),
54
+ }
55
+ })));
56
+ return content;
57
+ }
58
+ return input.userInput ?? "";
59
+ }
60
+ mapContentParts(content) {
61
+ return content.map(part => {
62
+ if (part.type === 'text') {
63
+ return {
64
+ type: 'text',
65
+ text: part.text
66
+ };
67
+ }
68
+ return {
69
+ type: 'image_url',
70
+ image_url: {
71
+ url: part.imageUrl,
72
+ ...(part.detail ? { detail: part.detail } : {}),
73
+ }
74
+ };
75
+ });
76
+ }
77
+ mapHistory(history = []) {
78
+ return history.map(message => ({
79
+ role: message.role,
80
+ content: typeof message.content === 'string'
81
+ ? message.content
82
+ : this.mapContentParts(message.content)
83
+ }));
84
+ }
85
+ async generateEmbedding({ text, model = "text-embedding-ada-002" }) {
86
+ const response = await this.client.embeddings.create({
87
+ model: model,
88
+ input: text,
89
+ });
90
+ return response.data[0].embedding;
91
+ }
92
+ mapTools(tools = []) {
93
+ return tools.map(tool => ({
94
+ type: "function",
95
+ function: {
96
+ name: tool.name,
97
+ description: tool.description,
98
+ parameters: tool.parameters ?? this.getDefaultToolParameters(),
99
+ },
100
+ }));
101
+ }
102
+ normalizeJsonSchema(input) {
103
+ if (input.zodSchema) {
104
+ return toJSONSchema(input.zodSchema, {
105
+ target: "draft-7",
106
+ });
107
+ }
108
+ if (!input.jsonSchema) {
109
+ return undefined;
110
+ }
111
+ const jsonSchema = input.jsonSchema;
112
+ if (jsonSchema.type === "json_schema" && jsonSchema.json_schema?.schema) {
113
+ return jsonSchema.json_schema.schema;
114
+ }
115
+ if (jsonSchema.type === "json_object") {
116
+ return undefined;
117
+ }
118
+ return jsonSchema;
119
+ }
120
+ normalizeResponseFormat(input) {
121
+ if (input.zodSchema || input.jsonSchema) {
122
+ return { type: "json_object" };
123
+ }
124
+ return undefined;
125
+ }
126
+ buildDeepSeekSystemPrompt(input) {
127
+ const systemPrompt = this.buildSystemPrompt(input);
128
+ const jsonSchema = this.normalizeJsonSchema(input);
129
+ if (!jsonSchema) {
130
+ return systemPrompt;
131
+ }
132
+ return `${systemPrompt}
133
+
134
+ Respond only with valid JSON matching this JSON Schema. Do not wrap the response in markdown or include any extra text.
135
+
136
+ JSON Schema:
137
+ ${JSON.stringify(jsonSchema, null, 2)}`;
138
+ }
139
+ async buildToolMessages(toolCalls = [], tools = []) {
140
+ const toolMessages = [];
141
+ for (const toolCall of toolCalls) {
142
+ const toolName = toolCall.function?.name;
143
+ const tool = this.findToolOrThrow(toolName, tools);
144
+ const args = this.parseToolArguments(toolCall.function?.arguments);
145
+ const output = await tool.execute(args);
146
+ toolMessages.push({
147
+ role: "tool",
148
+ tool_call_id: toolCall.id,
149
+ content: this.serializeToolOutput(output),
150
+ });
151
+ }
152
+ return toolMessages;
153
+ }
154
+ async prompt(input) {
155
+ const systemPrompt = this.buildDeepSeekSystemPrompt(input);
156
+ const userInput = this.buildUserContent(input);
157
+ const model = this.resolvePromptModel(input, this.model, this.visionModel);
158
+ const startedAt = new Date();
159
+ const startTime = performance.now();
160
+ let tokens = 0;
161
+ let inputTokens = 0;
162
+ let outputTokens = 0;
163
+ try {
164
+ const messages = [
165
+ { role: 'system', content: systemPrompt },
166
+ ...this.mapHistory(input.history),
167
+ { role: 'user', content: userInput },
168
+ ];
169
+ const tools = input.tools ?? [];
170
+ const maxIterations = input.toolMaxIterations ?? 5;
171
+ const responseFormat = this.normalizeResponseFormat(input);
172
+ let output;
173
+ for (let iteration = 0; iteration < maxIterations; iteration++) {
174
+ const chatCompletion = await this.client.chat.completions.create({
175
+ messages,
176
+ ...(responseFormat ? { response_format: responseFormat } : {}),
177
+ ...(tools.length > 0 ? { tools: this.mapTools(tools) } : {}),
178
+ model: model,
179
+ });
180
+ tokens += chatCompletion.usage?.total_tokens ?? 0;
181
+ inputTokens += chatCompletion.usage?.prompt_tokens ?? 0;
182
+ outputTokens += chatCompletion.usage?.completion_tokens ?? 0;
183
+ const message = chatCompletion.choices[0].message;
184
+ const toolCalls = message.tool_calls ?? [];
185
+ if (toolCalls.length === 0) {
186
+ output = message.content;
187
+ break;
188
+ }
189
+ messages.push(message);
190
+ messages.push(...await this.buildToolMessages(toolCalls, tools));
191
+ }
192
+ if (output === undefined) {
193
+ throw new Error(`Tool max iterations reached: ${maxIterations}`);
194
+ }
195
+ const endTime = performance.now();
196
+ const time = endTime - startTime;
197
+ const endedAt = new Date();
198
+ const audio = await PromptAudioService.build(input, output);
199
+ await this.registerPromptLog(input, {
200
+ model,
201
+ systemPrompt,
202
+ startedAt,
203
+ endedAt,
204
+ inputTokens,
205
+ outputTokens,
206
+ tokens,
207
+ output,
208
+ success: true,
209
+ });
210
+ return {
211
+ output,
212
+ tokens,
213
+ inputTokens,
214
+ outputTokens,
215
+ time,
216
+ ...(audio ? { audio } : {}),
217
+ };
218
+ }
219
+ catch (e) {
220
+ const endedAt = new Date();
221
+ await this.registerPromptLog(input, {
222
+ model,
223
+ systemPrompt,
224
+ startedAt,
225
+ endedAt,
226
+ success: false,
227
+ errorMessage: e?.message,
228
+ });
229
+ throw e;
230
+ }
231
+ }
26
232
  }
27
233
  export default DeepSeekAiProvider;
28
234
  export { DeepSeekAiProvider };
@@ -136,11 +136,7 @@ class GoogleAiProvider extends AbstractAiProvider {
136
136
  functionDeclarations: tools.map(tool => ({
137
137
  name: tool.name,
138
138
  description: tool.description,
139
- parametersJsonSchema: tool.parameters ?? {
140
- type: "object",
141
- properties: {},
142
- additionalProperties: false,
143
- },
139
+ parametersJsonSchema: tool.parameters ?? this.getDefaultToolParameters(),
144
140
  }))
145
141
  }];
146
142
  }
@@ -177,10 +173,7 @@ class GoogleAiProvider extends AbstractAiProvider {
177
173
  const parts = [];
178
174
  for (const functionCall of functionCalls) {
179
175
  const toolName = functionCall.name;
180
- const tool = tools.find(t => t.name === toolName);
181
- if (!tool) {
182
- throw new Error(`Tool not found: ${toolName}`);
183
- }
176
+ const tool = this.findToolOrThrow(toolName, tools);
184
177
  const output = await tool.execute(functionCall.args ?? {});
185
178
  parts.push({
186
179
  functionResponse: {
@@ -203,18 +196,9 @@ class GoogleAiProvider extends AbstractAiProvider {
203
196
  };
204
197
  }
205
198
  async prompt(input) {
206
- if (!input.systemPrompt) {
207
- throw new Error("systemPrompt required");
208
- }
209
- let systemPrompt = input.systemPrompt;
210
- if (input.memory && input.memory.length > 0) {
211
- systemPrompt += `\n\n ${input.memoryHeader ?? '[MEMORIA]'}\n ${input.memory.map(m => `${m.key}: ${m.value}`).join('\n')}`;
212
- }
213
- if (input.knowledgeBase && input.knowledgeBase.length > 0) {
214
- systemPrompt += `\n\n${input.knowledgeBaseHeader ?? '[BASE DE CONOCIMIENTO]'}\n ${input.knowledgeBase.join('\n')}`;
215
- }
199
+ const systemPrompt = this.buildSystemPrompt(input);
216
200
  const userInput = this.buildUserContent(input);
217
- const model = input.model ?? (this.hasImageInput(input) ? this.visionModel ?? this.model : this.model);
201
+ const model = this.resolvePromptModel(input, this.model, this.visionModel);
218
202
  const startedAt = new Date();
219
203
  const startTime = performance.now();
220
204
  let tokens = 0;
@@ -112,11 +112,7 @@ class OllamaAiProvider extends AbstractAiProvider {
112
112
  function: {
113
113
  name: tool.name,
114
114
  description: tool.description,
115
- parameters: tool.parameters ?? {
116
- type: "object",
117
- properties: {},
118
- additionalProperties: false,
119
- },
115
+ parameters: tool.parameters ?? this.getDefaultToolParameters(),
120
116
  },
121
117
  }));
122
118
  }
@@ -135,37 +131,11 @@ class OllamaAiProvider extends AbstractAiProvider {
135
131
  }
136
132
  return jsonSchema;
137
133
  }
138
- parseToolArguments(args) {
139
- if (!args) {
140
- return {};
141
- }
142
- if (typeof args === "object") {
143
- return args;
144
- }
145
- try {
146
- return JSON.parse(args);
147
- }
148
- catch (e) {
149
- throw new Error(`Invalid tool arguments: ${args}`);
150
- }
151
- }
152
- serializeToolOutput(output) {
153
- if (typeof output === "string") {
154
- return output;
155
- }
156
- if (output === undefined) {
157
- return "";
158
- }
159
- return JSON.stringify(output);
160
- }
161
134
  async buildToolMessages(toolCalls = [], tools = []) {
162
135
  const toolMessages = [];
163
136
  for (const toolCall of toolCalls) {
164
137
  const toolName = toolCall.function?.name;
165
- const tool = tools.find(t => t.name === toolName);
166
- if (!tool) {
167
- throw new Error(`Tool not found: ${toolName}`);
168
- }
138
+ const tool = this.findToolOrThrow(toolName, tools);
169
139
  const args = this.parseToolArguments(toolCall.function?.arguments);
170
140
  const output = await tool.execute(args);
171
141
  toolMessages.push({
@@ -177,17 +147,8 @@ class OllamaAiProvider extends AbstractAiProvider {
177
147
  return toolMessages;
178
148
  }
179
149
  async prompt(input) {
180
- if (!input.systemPrompt) {
181
- throw new Error("systemPrompt required");
182
- }
183
- let systemPrompt = input.systemPrompt;
184
- if (input.memory && input.memory.length > 0) {
185
- systemPrompt += `\n\n ${input.memoryHeader ?? '[MEMORIA]'}\n ${input.memory.map(m => `${m.key}: ${m.value}`).join('\n')}`;
186
- }
187
- if (input.knowledgeBase && input.knowledgeBase.length > 0) {
188
- systemPrompt += `\n\n${input.knowledgeBaseHeader ?? '[BASE DE CONOCIMIENTO]'}\n ${input.knowledgeBase.join('\n')}`;
189
- }
190
- const model = input.model ?? (this.hasImageInput(input) ? this.visionModel ?? this.model : this.model);
150
+ const systemPrompt = this.buildSystemPrompt(input);
151
+ const model = this.resolvePromptModel(input, this.model, this.visionModel);
191
152
  const startedAt = new Date();
192
153
  const startTime = performance.now();
193
154
  let tokens = 0;
@@ -90,42 +90,15 @@ class OpenAiProvider extends AbstractAiProvider {
90
90
  function: {
91
91
  name: tool.name,
92
92
  description: tool.description,
93
- parameters: tool.parameters ?? {
94
- type: "object",
95
- properties: {},
96
- additionalProperties: false,
97
- },
93
+ parameters: tool.parameters ?? this.getDefaultToolParameters(),
98
94
  },
99
95
  }));
100
96
  }
101
- parseToolArguments(args) {
102
- if (!args) {
103
- return {};
104
- }
105
- try {
106
- return JSON.parse(args);
107
- }
108
- catch (e) {
109
- throw new Error(`Invalid tool arguments: ${args}`);
110
- }
111
- }
112
- serializeToolOutput(output) {
113
- if (typeof output === "string") {
114
- return output;
115
- }
116
- if (output === undefined) {
117
- return "";
118
- }
119
- return JSON.stringify(output);
120
- }
121
97
  async buildToolMessages(toolCalls = [], tools = []) {
122
98
  const toolMessages = [];
123
99
  for (const toolCall of toolCalls) {
124
100
  const toolName = toolCall.function?.name;
125
- const tool = tools.find(t => t.name === toolName);
126
- if (!tool) {
127
- throw new Error(`Tool not found: ${toolName}`);
128
- }
101
+ const tool = this.findToolOrThrow(toolName, tools);
129
102
  const args = this.parseToolArguments(toolCall.function?.arguments);
130
103
  const output = await tool.execute(args);
131
104
  toolMessages.push({
@@ -137,18 +110,9 @@ class OpenAiProvider extends AbstractAiProvider {
137
110
  return toolMessages;
138
111
  }
139
112
  async prompt(input) {
140
- if (!input.systemPrompt) {
141
- throw new Error("systemPrompt required");
142
- }
143
- let systemPrompt = input.systemPrompt;
144
- if (input.memory && input.memory.length > 0) {
145
- systemPrompt += `\n\n ${input.memoryHeader ?? '[MEMORIA]'}\n ${input.memory.map(m => `${m.key}: ${m.value}`).join('\n')}`;
146
- }
147
- if (input.knowledgeBase && input.knowledgeBase.length > 0) {
148
- systemPrompt += `\n\n${input.knowledgeBaseHeader ?? '[BASE DE CONOCIMIENTO]'}\n ${input.knowledgeBase.join('\n')}`;
149
- }
113
+ const systemPrompt = this.buildSystemPrompt(input);
150
114
  const userInput = this.buildUserContent(input);
151
- const model = input.model ?? (this.hasImageInput(input) ? this.visionModel ?? this.model : this.model);
115
+ const model = this.resolvePromptModel(input, this.model, this.visionModel);
152
116
  const startedAt = new Date();
153
117
  const startTime = performance.now();
154
118
  let tokens = 0;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "3.54.0",
6
+ "version": "3.55.0",
7
7
  "description": "Ai utils",
8
8
  "main": "dist/index.js",
9
9
  "types": "types/index.d.ts",
@@ -19,7 +19,7 @@
19
19
  "license": "ISC",
20
20
  "dependencies": {
21
21
  "@drax/ai-share": "^3.52.0",
22
- "@drax/crud-back": "^3.54.0",
22
+ "@drax/crud-back": "^3.54.1",
23
23
  "mongoose": "^8.23.0",
24
24
  "mongoose-paginate-v2": "^1.8.3"
25
25
  },
@@ -46,5 +46,5 @@
46
46
  "typescript": "^5.9.3",
47
47
  "vitest": "^3.0.8"
48
48
  },
49
- "gitHead": "e7b0f29f3f68e352e8accb9d70c66b6f745a3278"
49
+ "gitHead": "4b9f6eb08041ce382b5244984f6c6e07e2b3c52c"
50
50
  }
@@ -0,0 +1,10 @@
1
+ enum AiConfig {
2
+
3
+ AiProvider = "AI_PROVIDER",
4
+
5
+ }
6
+
7
+
8
+ export default AiConfig;
9
+
10
+ export {AiConfig}
@@ -1,4 +1,6 @@
1
1
  import type {IAIProvider} from "../../interfaces/IAIProvider.js"
2
+ import {DraxConfig} from "@drax/common-back";
3
+ import AiConfig from "../../config/AiConfig.js";
2
4
  import OpenAiProviderFactory from "./OpenAiProviderFactory.js";
3
5
  import GoogleAiProviderFactory from "./GoogleAiProviderFactory.js";
4
6
  import OllamaAiProviderFactory from "./OllamaAiProviderFactory.js";
@@ -7,18 +9,21 @@ import DeepSeekAiProviderFactory from "./DeepSeekAiProviderFactory.js";
7
9
  class AiProviderFactory {
8
10
  private static singletons: Record<string, IAIProvider> = {};
9
11
 
10
- public static instance(provider: string = 'OpenAi'): IAIProvider {
12
+ public static instance(provider: string = DraxConfig.getOrLoad(AiConfig.AiProvider, "string", "OpenAi")): IAIProvider {
11
13
  if (!AiProviderFactory.singletons[provider]) {
12
14
  switch (provider) {
13
15
  case 'OpenAi':
14
16
  AiProviderFactory.singletons[provider] = OpenAiProviderFactory.instance()
15
17
  break;
16
18
  case 'GoogleAi':
19
+ case 'Google':
17
20
  AiProviderFactory.singletons[provider] = GoogleAiProviderFactory.instance()
18
21
  break;
19
22
  case 'OllamaAi':
23
+ case 'Ollama':
20
24
  AiProviderFactory.singletons[provider] = OllamaAiProviderFactory.instance()
21
25
  break;
26
+ case 'DeepSeekAi':
22
27
  case 'DeepSeek':
23
28
  AiProviderFactory.singletons[provider] = DeepSeekAiProviderFactory.instance()
24
29
  break;
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import {AiConfig} from "./config/AiConfig.js";
1
2
  import {OpenAiConfig} from "./config/OpenAiConfig.js";
2
3
  import {GoogleAiConfig} from "./config/GoogleAiConfig.js";
3
4
  import {OllamaAiConfig} from "./config/OllamaAiConfig.js";
@@ -160,6 +161,7 @@ export type {
160
161
  }
161
162
 
162
163
  export {
164
+ AiConfig,
163
165
  OpenAiConfig,
164
166
  GoogleAiConfig,
165
167
  OllamaAiConfig,