symposium 0.15.3 → 0.15.5

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 (3) hide show
  1. package/Agent.js +88 -90
  2. package/README.md +2 -8
  3. package/package.json +1 -1
package/Agent.js CHANGED
@@ -123,88 +123,88 @@ export default class Agent {
123
123
  async execute(thread, counter = 0, existing_emitter = null) {
124
124
  const emitter = existing_emitter || new BufferedEventEmitter();
125
125
 
126
- if (counter === 0)
127
- thread = await this.beforeExecute(thread, emitter);
128
-
129
- const model = Symposium.getModelByName(thread.state.model);
126
+ const execution = new Promise(async (resolve, reject) => {
127
+ try {
128
+ if (counter === 0)
129
+ thread = await this.beforeExecute(thread, emitter);
130
+
131
+ const model = Symposium.getModelByName(thread.state.model);
132
+
133
+ const completion_options = {};
134
+ if (this.type === 'utility') {
135
+ if (['function', 'json'].includes(this.utility.type)) {
136
+ if (!this.utility.function || !this.utility.function.name || !this.utility.function.parameters)
137
+ throw new Error('Bad function definition');
138
+
139
+ let response_format = null;
140
+ if (this.utility.type === 'json' && model.supports_structured_output)
141
+ response_format = this.convertFunctionToResponseFormat(this.utility.function.parameters);
142
+
143
+ if (response_format && response_format.count <= 100) { // OpenAI does not support structured output if there are more than 100 parameters
144
+ completion_options.response_format = {
145
+ type: 'json_schema',
146
+ json_schema: {
147
+ name: this.utility.function.name,
148
+ schema: response_format.obj,
149
+ strict: true,
150
+ },
151
+ };
152
+ } else {
153
+ completion_options.functions = [
154
+ this.utility.function,
155
+ ];
156
+ completion_options.force_function = this.utility.function.name;
157
+ }
158
+ }
159
+ }
130
160
 
131
- const completion_options = {};
132
- if (this.type === 'utility') {
133
- if (['function', 'json'].includes(this.utility.type)) {
134
- if (!this.utility.function || !this.utility.function.name || !this.utility.function.parameters)
135
- throw new Error('Bad function definition');
136
-
137
- let response_format = null;
138
- if (this.utility.type === 'json' && model.supports_structured_output)
139
- response_format = this.convertFunctionToResponseFormat(this.utility.function.parameters);
140
-
141
- if (response_format && response_format.count <= 100) { // OpenAI does not support structured output if there are more than 100 parameters
142
- completion_options.response_format = {
143
- type: 'json_schema',
144
- json_schema: {
145
- name: this.utility.function.name,
146
- schema: response_format.obj,
147
- strict: true,
148
- },
149
- };
150
- } else {
151
- completion_options.functions = [
152
- this.utility.function,
153
- ];
154
- completion_options.force_function = this.utility.function.name;
161
+ let completion;
162
+ try {
163
+ completion = await this.generateCompletion(thread, completion_options);
164
+ } catch (e) {
165
+ console.error(e.message);
166
+ switch (this.type) {
167
+ case 'chat':
168
+ emitter.emit('error', e.message);
169
+ return resolve(e);
170
+
171
+ case 'utility':
172
+ throw e;
173
+
174
+ default:
175
+ throw new Error('Bad agent type');
176
+ }
155
177
  }
156
- }
157
- }
158
178
 
159
- let completion;
160
- try {
161
- completion = await this.generateCompletion(thread, completion_options);
162
- } catch (e) {
163
- console.error(e.message);
164
- switch (this.type) {
165
- case 'chat':
166
- emitter.emit('error', e.message);
167
- if (!existing_emitter)
168
- emitter.emit('end');
169
- return emitter;
170
-
171
- case 'utility':
172
- throw e;
173
-
174
- default:
175
- throw new Error('Bad agent type');
176
- }
177
- }
179
+ try {
180
+ thread = await this.afterExecute(thread, completion, emitter);
181
+ const response = await this.handleCompletion(thread, completion, emitter);
178
182
 
179
- try {
180
- thread = await this.afterExecute(thread, completion);
181
- const response = await this.handleCompletion(thread, completion, emitter);
182
-
183
- switch (this.type) {
184
- case 'utility':
185
- if (!existing_emitter)
186
- emitter.emit('end');
187
- return response;
188
-
189
- case 'chat':
190
- if (!existing_emitter) {
191
- emitter.on('data', data => {
192
- if (data.type === 'response' && data.content.type === 'continue')
193
- this.execute(thread, 0, emitter);
194
- }, false);
195
- }
183
+ switch (this.type) {
184
+ case 'utility':
185
+ return resolve(response);
186
+
187
+ case 'chat':
188
+ if (response.type === 'continue')
189
+ return this.execute(thread, 0, emitter);
190
+
191
+ return resolve(null);
196
192
 
197
- return emitter;
193
+ default:
194
+ throw new Error('Bad agent type');
195
+ }
196
+ } catch (e) {
197
+ console.error(e);
198
198
 
199
- default:
200
- throw new Error('Bad agent type');
199
+ if (counter < this.max_retries)
200
+ await this.execute(thread, counter + 1, emitter);
201
+ }
202
+ } catch (e) {
203
+ reject(e);
201
204
  }
202
- } catch (e) {
203
- console.error(e);
205
+ });
204
206
 
205
- if (counter < this.max_retries)
206
- await this.execute(thread, counter + 1, emitter);
207
- }
207
+ return this.type === 'chat' ? emitter : execution;
208
208
  }
209
209
 
210
210
  convertFunctionToResponseFormat(obj) {
@@ -246,7 +246,7 @@ export default class Agent {
246
246
  };
247
247
  }
248
248
 
249
- async afterExecute(thread, completion) {
249
+ async afterExecute(thread, completion, emitter) {
250
250
  return thread;
251
251
  }
252
252
 
@@ -315,12 +315,12 @@ export default class Agent {
315
315
  case 'text':
316
316
  if (this.type === 'utility') {
317
317
  if (this.utility.type === 'text')
318
- return this.afterHandle(thread, completion, 'return', m.content);
318
+ return this.afterHandle(thread, completion, m.content);
319
319
  if (this.utility.type === 'json' && model.supports_structured_output)
320
- return this.afterHandle(thread, completion, 'return', JSON.parse(m.content));
320
+ return this.afterHandle(thread, completion, JSON.parse(m.content));
321
321
  }
322
322
 
323
- emitter.emit('data', {type: 'output', content: m.content});
323
+ emitter.emit('output', m.content);
324
324
  break;
325
325
 
326
326
  case 'function':
@@ -334,7 +334,7 @@ export default class Agent {
334
334
  if (functions.length) {
335
335
  for (let f of functions) {
336
336
  if (this.utility && ['function', 'json'].includes(this.utility.type))
337
- return this.afterHandle(thread, completion, 'return', f.arguments);
337
+ return this.afterHandle(thread, completion, f.arguments);
338
338
 
339
339
  const function_response = await this.callFunction(thread, f, emitter);
340
340
 
@@ -348,18 +348,15 @@ export default class Agent {
348
348
  await this.log('function_response', function_response);
349
349
  }
350
350
 
351
- return this.afterHandle(thread, completion, 'continue');
351
+ return this.afterHandle(thread, completion);
352
352
  } else {
353
353
  await thread.storeState();
354
- return this.afterHandle(thread, completion, 'void');
354
+ return this.afterHandle(thread, completion);
355
355
  }
356
356
  }
357
357
 
358
- async afterHandle(thread, completion, type, value = null) {
359
- return {
360
- type,
361
- value,
362
- };
358
+ async afterHandle(thread, completion, value = null) {
359
+ return value;
363
360
  }
364
361
 
365
362
  async getFunctions(parsed = true) {
@@ -392,16 +389,16 @@ export default class Agent {
392
389
 
393
390
  const func = functions.get(function_call.name);
394
391
  const partialOutput = func.partialOutput ? ((typeof func.partialOutput) === 'text' ? func.partialOutput : func.partialOutput.call(this, function_call.arguments)) : 'Uso lo strumento ' + function_call.name + '...';
395
- emitter.emit('data', {type: 'partial', content: partialOutput});
392
+ emitter.emit('partial', partialOutput);
396
393
 
397
394
  await this.log('function_call', function_call);
398
395
 
399
396
  try {
400
397
  const response = await func.tool.callFunction(thread, function_call.name, function_call.arguments);
401
- emitter.emit('data', {type: 'partial', content: 'Risposta ricevuta da ' + func.tool.name});
398
+ emitter.emit('partial', 'Risposta ricevuta da ' + func.tool.name);
402
399
  return response;
403
400
  } catch (error) {
404
- emitter.emit('data', {type: 'partial', content: 'Ricevuto errore da ' + func.tool.name});
401
+ emitter.emit('partial', 'Ricevuto errore da ' + func.tool.name);
405
402
  return {error};
406
403
  }
407
404
  }
@@ -423,6 +420,7 @@ export default class Agent {
423
420
  return [this.name];
424
421
  }
425
422
 
423
+ // Currently specific for OpenAI Realtime API
426
424
  async createRealtimeSession(thread_id = null, options = {}) {
427
425
  options = {
428
426
  include_thread: true,
@@ -430,7 +428,7 @@ export default class Agent {
430
428
  ...options,
431
429
  };
432
430
 
433
- // Se viene passato un thread esistente, lo si usa, altrimenti si crea un nuovo thread temporaneo
431
+ // If a thread is passed, it is used, otherwise a temporary thread is created
434
432
  const thread = await this.getThread(thread_id || uuid());
435
433
 
436
434
  const system_message = [], conversation = [];
package/README.md CHANGED
@@ -82,14 +82,8 @@ async function main() {
82
82
 
83
83
  const emitter = await agent.message('Hello, who are you?');
84
84
 
85
- emitter.on('data', (data) => {
86
- if (data.type === 'output') {
87
- process.stdout.write(data.content);
88
- }
89
- });
90
-
91
- emitter.on('end', () => {
92
- console.log('\nConversation ended.');
85
+ emitter.on('output', (content) => {
86
+ process.stdout.write(content);
93
87
  });
94
88
  }
95
89
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "symposium",
4
- "version": "0.15.3",
4
+ "version": "0.15.5",
5
5
  "description": "Agents",
6
6
  "main": "index.js",
7
7
  "author": "Domenico Giambra",