@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.
- package/dist/config/AiConfig.js +6 -0
- package/dist/factory/ai/AiProviderFactory.js +6 -1
- package/dist/index.js +2 -1
- package/dist/providers/ai/AbstractAiProvider.js +53 -0
- package/dist/providers/ai/DeepSeekAiProvider.js +209 -3
- package/dist/providers/ai/GoogleAiProvider.js +4 -20
- package/dist/providers/ai/OllamaAiProvider.js +4 -43
- package/dist/providers/ai/OpenAiProvider.js +4 -40
- package/package.json +3 -3
- package/src/config/AiConfig.ts +10 -0
- package/src/factory/ai/AiProviderFactory.ts +6 -1
- package/src/index.ts +2 -0
- package/src/providers/ai/AbstractAiProvider.ts +69 -0
- package/src/providers/ai/DeepSeekAiProvider.ts +263 -5
- package/src/providers/ai/GoogleAiProvider.ts +4 -26
- package/src/providers/ai/OllamaAiProvider.ts +4 -53
- package/src/providers/ai/OpenAiProvider.ts +4 -50
- package/test/DeepSeekProvider.test.ts +94 -0
- package/test/GoogleAiProvider.test.ts +17 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/types/config/AiConfig.d.ts +6 -0
- package/types/config/AiConfig.d.ts.map +1 -0
- package/types/controllers/AICrudController.d.ts +1 -1
- package/types/factory/ai/AiProviderFactory.d.ts.map +1 -1
- package/types/index.d.ts +2 -1
- package/types/index.d.ts.map +1 -1
- package/types/providers/ai/AbstractAiProvider.d.ts +11 -1
- package/types/providers/ai/AbstractAiProvider.d.ts.map +1 -1
- package/types/providers/ai/DeepSeekAiProvider.d.ts +65 -2
- package/types/providers/ai/DeepSeekAiProvider.d.ts.map +1 -1
- package/types/providers/ai/GoogleAiProvider.d.ts.map +1 -1
- package/types/providers/ai/OllamaAiProvider.d.ts +0 -2
- package/types/providers/ai/OllamaAiProvider.d.ts.map +1 -1
- package/types/providers/ai/OpenAiProvider.d.ts +0 -2
- package/types/providers/ai/OpenAiProvider.d.ts.map +1 -1
|
@@ -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 =
|
|
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
|
|
3
|
-
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
181
|
-
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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.
|
|
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.
|
|
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": "
|
|
49
|
+
"gitHead": "4b9f6eb08041ce382b5244984f6c6e07e2b3c52c"
|
|
50
50
|
}
|
|
@@ -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 =
|
|
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,
|