symposium 1.1.0 → 1.2.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/Agent.js CHANGED
@@ -6,6 +6,8 @@ import Symposium from "./Symposium.js";
6
6
  import Thread from "./Thread.js";
7
7
  import Tool from "./Tool.js";
8
8
  import Context from "./Context.js";
9
+ import Text from "./Contexts/Text.js";
10
+ import GetContextTool from "./GetContextTool.js";
9
11
 
10
12
  export default class Agent {
11
13
  name = 'Agent';
@@ -72,28 +74,56 @@ export default class Agent {
72
74
  this.tools.set(tool.name, tool);
73
75
  }
74
76
 
75
- addContext(context) {
77
+ async addContext(context, options = {}) {
78
+ if (typeof context === 'string')
79
+ context = new Text(context);
76
80
  if (!(context instanceof Context))
77
81
  throw new Error('Context must be an instance of Context class');
78
82
 
79
- // TODO: on-request contexts
83
+ options = {
84
+ type: 'always', // always, on_request
85
+ description: null,
86
+ ...options,
87
+ };
88
+
80
89
  // TODO: summarization based on tokens
81
90
  // TODO: RAG
82
91
 
83
- this.context.push(context);
92
+ const title = await context.getTitle();
93
+ this.context.push({title, context, options});
84
94
  }
85
95
 
86
96
  async initThread(thread) {
87
97
  await this.doInitThread(thread);
88
98
 
89
- const context_texts = [];
90
- for (let context of this.context) {
91
- const text = await context.getText();
92
- if (text)
93
- context_texts.push('<context>' + text + '</context>');
99
+ let context_texts = [], is_there_on_request = false;
100
+ for (let {title, context, options} of this.context) {
101
+ switch (options.type) {
102
+ case 'always':
103
+ const text = await context.getText();
104
+ if (text)
105
+ context_texts.push('<context>' + text + '</context>');
106
+ break;
107
+
108
+ case 'on_request':
109
+ is_there_on_request = true;
110
+ context_texts.push('<context_on_request><name>' + title + '</name><description>' + options.description + '</description></context_on_request>');
111
+ break;
112
+
113
+ default:
114
+ throw new Error('Bad context option type ' + options.type);
115
+ }
94
116
  }
95
117
 
96
118
  if (context_texts.length) {
119
+ let context_string = context_texts.join('\n');
120
+ if (is_there_on_request) {
121
+ context_string = '<important>Some of the context is available to you immediately here, while longer texts may be available only on request; you are provided with a title and a description. If you think it may be useful for your current task, you can request the text via the get_context tool</important>';
122
+ if (!this.tools.has('get_context'))
123
+ this.addTool(new GetContextTool(this));
124
+ }
125
+ context_string = '\n<context_info>' + context_string + '</context_info>';
126
+
97
127
  let system_message_found = null;
98
128
  for (let messages of thread.messages) {
99
129
  if (messages.role === 'system')
@@ -101,9 +131,9 @@ export default class Agent {
101
131
  }
102
132
 
103
133
  if (system_message_found)
104
- system_message_found.content[0].content += '<context_info>' + context_texts.join('\n') + '</context_info>';
134
+ system_message_found.content[0].content += context_string;
105
135
  else
106
- thread.addMessage('system', '<context_info>' + context_texts.join('\n') + '</context_info>');
136
+ thread.addMessage('system', context_string);
107
137
  }
108
138
 
109
139
  await thread.storeState();
package/Context.js CHANGED
@@ -1,4 +1,11 @@
1
1
  export default class Context {
2
+ /**
3
+ * @returns {Promise<string|null>}
4
+ */
5
+ async getTitle() {
6
+ return null;
7
+ }
8
+
2
9
  /**
3
10
  * @returns {Promise<string|null>}
4
11
  */
package/Contexts/File.js CHANGED
@@ -7,6 +7,13 @@ export default class File extends Context {
7
7
  this.file = file;
8
8
  }
9
9
 
10
+ async getTitle() {
11
+ if (this.file.startsWith('http://') || this.file.startsWith('https://'))
12
+ return this.file;
13
+ else
14
+ return this.file.split('/').pop();
15
+ }
16
+
10
17
  async getText() {
11
18
  if (this.file.startsWith('http://') || this.file.startsWith('https://')) {
12
19
  return fetch(this.file);
@@ -0,0 +1,17 @@
1
+ import Context from "../Context.js";
2
+
3
+ export default class Text extends Context {
4
+ constructor(text, title = null) {
5
+ super();
6
+ this.text = text;
7
+ this.title = title;
8
+ }
9
+
10
+ async getTitle() {
11
+ return this.title;
12
+ }
13
+
14
+ async getText() {
15
+ return this.text;
16
+ }
17
+ }
@@ -0,0 +1,42 @@
1
+ import Tool from "./Tool.js";
2
+
3
+ export default class GetContextTool extends Tool {
4
+ name = 'get_context';
5
+
6
+ constructor(agent) {
7
+ super();
8
+ this.agent = agent;
9
+ }
10
+
11
+ async getFunctions() {
12
+ return [
13
+ {
14
+ name: 'get_context',
15
+ description: 'Get the text from a specific context snippet',
16
+ parameters: {
17
+ type: 'object',
18
+ properties: {
19
+ title: {
20
+ type: 'string',
21
+ },
22
+ },
23
+ required: ['title'],
24
+ },
25
+ }
26
+ ];
27
+ }
28
+
29
+ async callFunction(thread, name, payload) {
30
+ if (name !== 'get_context')
31
+ return {error: `Function ${name} not found`};
32
+
33
+ const title = payload.title;
34
+ const context = this.agent.context.find(c => c.title === title && c.options.type === 'on_request');
35
+ if (!context)
36
+ return {error: `Context with title ${title} not found`};
37
+
38
+ return {
39
+ context: await context.context.getText(),
40
+ };
41
+ }
42
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "symposium",
4
- "version": "1.1.0",
4
+ "version": "1.2.0",
5
5
  "description": "Agents",
6
6
  "main": "index.js",
7
7
  "author": "Domenico Giambra",