@xuda.io/ai_module 1.1.5616 → 1.1.5618

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.
@@ -0,0 +1,423 @@
1
+ // const add_data_to_table_tool = tool({
2
+ // name: 'Add data to table tool',
3
+ // description: 'Add data to a table by receiving a table_id and a data object containing key–value pairs representing the fields and their values.',
4
+ // parameters: z.object({
5
+ // table_id: z.string(),
6
+ // }),
7
+ // async execute(e, RunContext) {
8
+ // const { table_id } = e;
9
+ // const { app_id, uid } = RunContext.context;
10
+
11
+ // if (!table_id) throw new Error('got null in the table_id parameter');
12
+
13
+ // try {
14
+ // const project_db = await get_project_db(app_id);
15
+
16
+ // let response = '';
17
+
18
+ // try {
19
+ // response = await project_db.get(table_id);
20
+ // } catch (error) {
21
+ // throw new Error(`table doc ${table_id} not found`);
22
+ // }
23
+
24
+ // if (_.isEmpty(response)) {
25
+ // throw new Error(`table with table_id ${table_id} not found`);
26
+ // }
27
+
28
+ // return response;
29
+ // } catch (err) {
30
+ // return err.message;
31
+ // }
32
+ // },
33
+ // });
34
+
35
+ // let table_tools = {};
36
+ // const build_studio_table_tools = async function (app_id) {
37
+ // try {
38
+ // if (!table_tools[app_id]) {
39
+ // table_tools[app_id] = {};
40
+ // }
41
+
42
+ // const project_db = await get_project_db(app_id);
43
+ // let tables = await project_db.view('xuda', 'studio_docs_by_type', { key: 'table' });
44
+
45
+ // for (const table_header_doc of tables.rows) {
46
+ // try {
47
+ // const doc = await project_db.get(table_header_doc.id);
48
+
49
+ // let data_parameters = {};
50
+
51
+ // for (const field of doc.tableFields || []) {
52
+ // const fieldId = field.data.field_id;
53
+ // const fieldType = field.props.fieldType;
54
+ // const mandatory = field.props.mandatory;
55
+ // const comment = field.props.fieldComment;
56
+
57
+ // let zodType;
58
+ // switch (fieldType) {
59
+ // case 'string':
60
+ // zodType = z.string();
61
+ // break;
62
+ // case 'number':
63
+ // zodType = z.number();
64
+ // break;
65
+ // case 'array':
66
+ // zodType = z.array(z.any());
67
+ // break;
68
+ // case 'object':
69
+ // zodType = z.object({});
70
+ // break;
71
+ // default:
72
+ // zodType = z.any();
73
+ // }
74
+
75
+ // // Add description if comment exists
76
+ // if (comment) {
77
+ // zodType = zodType.describe(comment);
78
+ // }
79
+
80
+ // // Make optional if not mandatory
81
+ // if (!mandatory) {
82
+ // zodType = zodType.optional();
83
+ // }
84
+
85
+ // data_parameters[fieldId] = zodType;
86
+ // }
87
+
88
+ // const _tool = {
89
+ // name: `add data to table tool`,
90
+ // description: `Add data to ${doc.properties.menuName} table by receiving key–value pairs representing the fields and their values.`,
91
+ // parameters: z.object(data_parameters),
92
+ // // parameters: z.object({ ...{ table_id: z.string() }, ...data_parameters }),
93
+ // // parameters: z.object({
94
+ // // table_id: z.string(),
95
+ // // data: z.object(data_parameters),
96
+ // // }),
97
+ // async execute(e, RunContext) {
98
+ // debugger;
99
+ // const {} = e;
100
+ // const { app_id, uid, table_id } = RunContext.context;
101
+ // let response = '';
102
+ // try {
103
+ // if (!table_id) throw new Error('got null in the table_id parameter');
104
+
105
+ // const FlexibleDatabaseSchema = z.object({
106
+ // _id: z.string(),
107
+ // _rev: z.string(),
108
+ // docType: z.literal('database'),
109
+ // stat: z.number(),
110
+ // udfData: z.object({
111
+ // udffileid: z.string(),
112
+ // data: z.record(z.union([z.string(), z.number()])), // Any key-value pairs
113
+ // error: z.object({}).optional(),
114
+ // }),
115
+ // ts: z.number(),
116
+ // date: z.number(),
117
+ // udfIndex: z.array(
118
+ // z.object({
119
+ // fileId: z.string(),
120
+ // indexId: z.string(),
121
+ // keySegments: z.array(z.any()),
122
+ // keyValue: z.array(z.any()),
123
+ // }),
124
+ // ),
125
+ // });
126
+
127
+ // // for (const [key, val] of Object.entities(data || {})) {
128
+ // // }
129
+
130
+ // let udfIndex = [];
131
+
132
+ // for (const [key, val] of Object.entities(doc.tableIndexes || [])) {
133
+ // let keyValue = [];
134
+ // for (const key_val of val?.data?.keys || []) {
135
+ // keyValue.push(data[key_val]);
136
+ // }
137
+
138
+ // udfIndex.push({
139
+ // fileId: table_id,
140
+ // indexId: val.id,
141
+ // keySegments: val?.data?.keys || [],
142
+ // keyValue,
143
+ // });
144
+ // }
145
+ // const t = Date.now();
146
+ // let table_obj = {
147
+ // _id: 'dbs-' + crypto.randomUUID(),
148
+
149
+ // docType: 'database',
150
+ // stat: 3,
151
+ // udfData: {
152
+ // udffileid: table_id,
153
+ // data: e,
154
+ // error: {},
155
+ // },
156
+ // ts: t,
157
+ // date: t,
158
+ // udfIndex,
159
+ // };
160
+
161
+ // return response;
162
+ // } catch (err) {
163
+ // return err.message;
164
+ // }
165
+ // },
166
+ // };
167
+
168
+ // // const jsonSchema = zodToJsonSchema(_tool.parameters, 'UserSchema');
169
+
170
+ // // console.log(JSON.stringify(jsonSchema, null, 2));
171
+
172
+ // table_tools[app_id][doc._id] = tool(_tool);
173
+ // } catch (error) {
174
+ // throw new Error(`table doc ${doc.id} not found`);
175
+ // }
176
+ // }
177
+ // // console.log(studio_units);
178
+ // } catch (err) {
179
+ // console.error(err);
180
+ // }
181
+
182
+ // return table_tools[app_id];
183
+ // };
184
+
185
+ const get_mock_data_generator_agent = function (app_id, table_id) {
186
+ return new Agent({
187
+ name: `Mock Data Generator Agent`,
188
+ instructions: `You are a Mock Data Generator Assistant for table id ${table_id}. Help the user populate data for table id ${table_id} with sample data. First, retrieve the table field definitions using get_studio_table_info_by_table_id_tool. Then generate five realistic mock data samples based on the table structure and insert each one individually using add data to table tool.`,
189
+ // instructions: `You are a Mock Data Generator Assistant.
190
+ // 1. First, get table info using the get_studio_table_info_by_table_id tool with table_id: ${table_id}
191
+ // 2. Analyze the table structure and field types
192
+ // 3. Generate 5 realistic mock data samples based on the fields
193
+ // 4. Return the generated data in a structured format`,
194
+ model,
195
+ tools: [get_studio_table_info_by_table_id_tool, table_tools[app_id][table_id]], //, table_tools[app_id][table_id]
196
+ // modelSettings: { toolChoice: 'required' },
197
+ });
198
+ };
199
+
200
+ // const get_add_data_to_table_agent = function (app_id, table_id) {
201
+ // return new Agent({
202
+ // name: `Add Data to Table Agent`,
203
+ // instructions: `You are an Add Data Assistant for table ID ${table_id}. Your job is to help the user provide valid data for this table. First, retrieve the table field definitions using get_studio_table_info_by_table_id_tool. Then prepare the data as key–value pairs (e.g., { first_name: "John", last_name: "Smith" }) and submit it using the add_data_to_table_tool. Generate UUID values for required unique fields when necessary. Ignore extra fields from the user prompt, and skip optional fields if not provided.`,
204
+ // model,
205
+ // tools: [get_studio_table_info_by_table_id_tool, table_tools[app_id][table_id]],
206
+ // modelSettings: { toolChoice: 'required' },
207
+ // });
208
+ // };
209
+
210
+ // const add_data_to_table = tool({
211
+ // name: 'Create table agent',
212
+ // description: 'crete agent that handles table tools by providing table_id',
213
+ // parameters: z.object({
214
+ // table_id: z.string(),
215
+ // }),
216
+ // async execute(e, RunContext) {
217
+ // const { table_id } = e;
218
+ // const { app_id, uid } = RunContext.context;
219
+ // let response = '';
220
+ // try {
221
+ // if (!table_id) throw new Error('got null in the table_id parameter');
222
+ // let table_doc = {};
223
+ // const project_db = await get_project_db(app_id);
224
+ // try {
225
+ // table_doc = await project_db.get(table_id);
226
+ // } catch (error) {
227
+ // throw new Error(`table doc ${table_id} not found`);
228
+ // }
229
+
230
+ // const agent_name = `${table_doc.properties.menuName} table AI Agent`;
231
+
232
+ // try {
233
+ // const ai_agents_ret = await get_ai_agents({ uid });
234
+ // for (const doc of ai_agents_ret?.data?.docs || []) {
235
+ // if (doc.properties.menuName === table_doc.properties.menuName) {
236
+ // throw new Error(`ai agent for ${table_id} already exist with name ${agent_name}`);
237
+ // }
238
+ // }
239
+ // } catch (err) {
240
+ // debugger;
241
+ // console.error(err);
242
+ // // throw new Error(err.message);
243
+ // }
244
+
245
+ // const agentConfig = {
246
+ // agent_name,
247
+ // agent_tools: [
248
+ // {
249
+ // type: 'table',
250
+ // prog_id: table_id,
251
+ // },
252
+ // ],
253
+ // agent_instructions: 'You are a Table Data Assistant. Your role is to query, analyze, and modify data within tables as requested. You can retrieve specific information, perform calculations, filter or sort records, and apply updates or structural changes to the data when necessary.',
254
+ // };
255
+
256
+ // response = await create_ai_agent({
257
+ // uid,
258
+ // agentConfig,
259
+ // });
260
+
261
+ // return { response, agentConfig };
262
+ // } catch (err) {
263
+ // return err.message;
264
+ // }
265
+ // },
266
+ // });
267
+
268
+ // const get_studio_tables = tool({
269
+ // name: 'Get studio tables',
270
+ // description: 'fetch all studio tables',
271
+ // parameters: z.object({
272
+ // app_id: z.string(),
273
+ // }),
274
+ // async execute(e, RunContext) {
275
+ // const { app_id } = e;
276
+ // try {
277
+ // const project_db = await get_project_db(app_id);
278
+ // let tables = await project_db.view('xuda', 'studio_docs_by_type', { key: 'table', include_docs: true });
279
+
280
+ // return tables;
281
+ // } catch (err) {
282
+ // return 'unknown';
283
+ // }
284
+ // },
285
+ // });
286
+
287
+ const get_plugins = tool({
288
+ name: 'Get plugins',
289
+ description: 'I am responsible to return all available plugins',
290
+ parameters: z.object({}),
291
+ async execute(e, RunContext) {
292
+ try {
293
+ const db = get_xuda_couch('xuda_plugins');
294
+ const plugins_res = await db.view('xuda', 'all-active-plugins', {});
295
+ let data = [];
296
+ if (!_.isEmpty(plugins_res.rows)) {
297
+ for (val of plugins_res.rows) {
298
+ if (!['library', 'widget', 'ui'].includes(val.plugin_type)) continue;
299
+ var plugin = _.clone(val.value);
300
+ delete plugin.account_id;
301
+ delete plugin.manifest;
302
+ delete plugin.plugin_name;
303
+ delete plugin.setup;
304
+ delete plugin.stat;
305
+ delete plugin.updated_date;
306
+ plugin._id = plugin._id.replace('@xuda.io/', '');
307
+
308
+ data.push(plugin);
309
+ }
310
+ }
311
+
312
+ console.log('get_plugins >>>> ', data);
313
+ return data;
314
+ } catch (err) {
315
+ console.error(err);
316
+ return err.message;
317
+ }
318
+ },
319
+ });
320
+
321
+ const update_app_doc_tool = tool({
322
+ name: 'update app doc tool',
323
+ description: 'update any app doc query by _id and _rev and save to the app db',
324
+ parameters: z.object({
325
+ app_id: z.string(),
326
+ doc: z.object({ _id: z.string(), _rev: z.string() }),
327
+ }),
328
+ async execute(e, RunContext) {
329
+ console.log(`SAVED ${e.app_id}`);
330
+ return `OK`;
331
+ },
332
+ });
333
+
334
+ const get_app_doc_tool = tool({
335
+ name: 'get app doc tool',
336
+ description: 'get any doc by id from the app db',
337
+ parameters: z.object({
338
+ app_id: z.string(),
339
+ _id: z.string(),
340
+ }),
341
+ async execute(e, RunContext) {
342
+ try {
343
+ const project_db = await get_project_db(e.app_id);
344
+
345
+ const result = await project_db.get(_id);
346
+ console.log('get_app_doc_tool >>>> ', result);
347
+ return result;
348
+ } catch (err) {
349
+ console.error(err);
350
+ return err.message;
351
+ }
352
+ },
353
+ });
354
+
355
+ const get_additional_information_tool = tool({
356
+ name: 'get additional information tool',
357
+ description: 'get additional information for object unit tool',
358
+ parameters: z.object({
359
+ object_unit: z.enum(['table']),
360
+ }),
361
+ async execute(e, RunContext) {
362
+ let obj = { table: ['studio_table'] };
363
+ const db = get_xuda_couch('xuda_website');
364
+ try {
365
+ if (!obj[e.object_unit]) throw new Error(`${e.object_unit} not found`);
366
+ const doc = await db.get(obj[e.object_unit]);
367
+ // console.log(`INFO ${doc}`);
368
+ return doc.md || doc;
369
+ } catch (err) {
370
+ console.error(err);
371
+ return err.message;
372
+ }
373
+ },
374
+ });
375
+
376
+ async function fineTuneWithMultipleFiles(datasetPaths, baseModel = 'gpt-4o-mini') {
377
+ try {
378
+ console.log('📤 Uploading datasets...');
379
+
380
+ // Step 1. Upload all JSONL files in parallel
381
+ const uploadedFiles = await Promise.all(
382
+ datasetPaths.map(async (filePath) => {
383
+ const file = await openai.files.create({
384
+ file: fs.createReadStream(path.resolve(filePath)),
385
+ purpose: 'fine-tune',
386
+ });
387
+ console.log(`✅ Uploaded: ${file.filename} → ID: ${file.id}`);
388
+ return file.id;
389
+ }),
390
+ );
391
+
392
+ // Step 2. Create fine-tuning job with multiple training files
393
+ console.log(`🚀 Creating fine-tuning job for ${baseModel}...`);
394
+ const fineTuneJob = await openai.fineTuning.jobs.create({
395
+ training_files: uploadedFiles.map((id) => ({ file_id: id })), // <-- multiple files here
396
+ model: baseModel,
397
+ });
398
+
399
+ console.log(`📌 Fine-tuning job created: ${fineTuneJob.id}`);
400
+
401
+ // Step 3. Poll job status until training completes
402
+ let status = fineTuneJob.status;
403
+ while (status === 'pending' || status === 'running') {
404
+ console.log(`⏳ Job status: ${status}...`);
405
+ await new Promise((resolve) => setTimeout(resolve, 10000));
406
+
407
+ const updatedJob = await openai.fineTuning.jobs.retrieve(fineTuneJob.id);
408
+ status = updatedJob.status;
409
+ }
410
+
411
+ // Step 4. Check final status
412
+ if (status === 'succeeded') {
413
+ console.log('🎉 Fine-tuning completed successfully!');
414
+ console.log(`🆕 Fine-tuned model: ${fineTuneJob.fine_tuned_model}`);
415
+ return fineTuneJob.fine_tuned_model;
416
+ } else {
417
+ throw new Error(`❌ Fine-tuning failed: ${status}`);
418
+ }
419
+ } catch (error) {
420
+ console.error('⚠️ Fine-tuning error:', error);
421
+ throw error;
422
+ }
423
+ }