symposium 1.0.4 → 1.1.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 +44 -1
- package/Context.js +8 -0
- package/{MemoryHandler.js → ContextHandler.js} +1 -1
- package/Contexts/File.js +20 -0
- package/README.md +37 -5
- package/Summarizer.js +2 -2
- package/Symposium.js +17 -0
- package/index.js +2 -2
- package/package.json +4 -4
package/Agent.js
CHANGED
|
@@ -4,6 +4,8 @@ import BufferedEventEmitter from "./BufferedEventEmitter.js";
|
|
|
4
4
|
|
|
5
5
|
import Symposium from "./Symposium.js";
|
|
6
6
|
import Thread from "./Thread.js";
|
|
7
|
+
import Tool from "./Tool.js";
|
|
8
|
+
import Context from "./Context.js";
|
|
7
9
|
|
|
8
10
|
export default class Agent {
|
|
9
11
|
name = 'Agent';
|
|
@@ -12,6 +14,7 @@ export default class Agent {
|
|
|
12
14
|
threads;
|
|
13
15
|
functions = null;
|
|
14
16
|
tools = new Map();
|
|
17
|
+
context = [];
|
|
15
18
|
default_model = 'gpt-4o';
|
|
16
19
|
max_retries = 5;
|
|
17
20
|
type = 'chat'; // chat, utility
|
|
@@ -61,18 +64,58 @@ export default class Agent {
|
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
addTool(tool) {
|
|
67
|
+
if (!(tool instanceof Tool) || !tool.name)
|
|
68
|
+
throw new Error('Tool must be an instance of Tool class');
|
|
69
|
+
if (this.tools.has(tool.name))
|
|
70
|
+
throw new Error('Tool with name ' + tool.name + ' already exists in agent');
|
|
71
|
+
|
|
64
72
|
this.tools.set(tool.name, tool);
|
|
65
73
|
}
|
|
66
74
|
|
|
75
|
+
addContext(context) {
|
|
76
|
+
if (!(context instanceof Context))
|
|
77
|
+
throw new Error('Context must be an instance of Context class');
|
|
78
|
+
|
|
79
|
+
// TODO: on-request contexts
|
|
80
|
+
// TODO: summarization based on tokens
|
|
81
|
+
// TODO: RAG
|
|
82
|
+
|
|
83
|
+
this.context.push(context);
|
|
84
|
+
}
|
|
85
|
+
|
|
67
86
|
async initThread(thread) {
|
|
68
87
|
await this.doInitThread(thread);
|
|
88
|
+
|
|
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>');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (context_texts.length) {
|
|
97
|
+
let system_message_found = null;
|
|
98
|
+
for (let messages of thread.messages) {
|
|
99
|
+
if (messages.role === 'system')
|
|
100
|
+
system_message_found = messages;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (system_message_found)
|
|
104
|
+
system_message_found.content[0].content += '<context_info>' + context_texts.join('\n') + '</context_info>';
|
|
105
|
+
else
|
|
106
|
+
thread.addMessage('system', '<context_info>' + context_texts.join('\n') + '</context_info>');
|
|
107
|
+
}
|
|
108
|
+
|
|
69
109
|
await thread.storeState();
|
|
70
110
|
}
|
|
71
111
|
|
|
72
112
|
async doInitThread(thread) {
|
|
73
113
|
}
|
|
74
114
|
|
|
75
|
-
async getThread(id) {
|
|
115
|
+
async getThread(id = null) {
|
|
116
|
+
if (id === null)
|
|
117
|
+
id = uuid();
|
|
118
|
+
|
|
76
119
|
let thread = this.threads.get(id);
|
|
77
120
|
if (!thread) {
|
|
78
121
|
thread = new Thread(id, this);
|
package/Context.js
ADDED
package/Contexts/File.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import Context from "../Context.js";
|
|
3
|
+
|
|
4
|
+
export default class File extends Context {
|
|
5
|
+
constructor(file) {
|
|
6
|
+
super();
|
|
7
|
+
this.file = file;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async getText() {
|
|
11
|
+
if (this.file.startsWith('http://') || this.file.startsWith('https://')) {
|
|
12
|
+
return fetch(this.file);
|
|
13
|
+
} else {
|
|
14
|
+
if (fs.existsSync(this.file))
|
|
15
|
+
return fs.promises.readFile(this.file, "utf8");
|
|
16
|
+
else
|
|
17
|
+
throw new Error(`File not found: ${this.file}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ The framework is built around a few core components:
|
|
|
38
38
|
- **`Thread`**: Represents a single conversation with an agent. It maintains the message history and the agent's state for that conversation. Each thread has a unique ID.
|
|
39
39
|
- **`Tool`**: A base class for creating tools that an `Agent` can use. Tools expose functions that the LLM can call to interact with external APIs or data.
|
|
40
40
|
- **`Message`**: A wrapper for messages within a `Thread`, containing the role (`user`, `assistant`, `system`, `tool`), content, and other metadata.
|
|
41
|
-
- **`
|
|
41
|
+
- **`ContextHandler`**: A class for managing an agent's long contexts. It can be extended to create custom memory strategies.
|
|
42
42
|
- **`Summarizer`**: A utility agent for summarizing text or conversations.
|
|
43
43
|
- **`Logger`**: A simple logging utility that can be passed to an agent to log its activity.
|
|
44
44
|
|
|
@@ -62,9 +62,41 @@ async function main() {
|
|
|
62
62
|
main();
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
### 2.
|
|
65
|
+
### 2. One shot prompts
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
You can also use the static `Symposium.prompt()` method for one-off prompts without creating an agent.
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
import { Symposium } from 'symposium';
|
|
71
|
+
await Symposium.init();
|
|
72
|
+
|
|
73
|
+
const response = await Symposium.prompt('Translate the text from English to French.', 'Hello, how are you?');
|
|
74
|
+
console.log(response); // "Bonjour, comment ça va?"
|
|
75
|
+
|
|
76
|
+
const structured_response = await Symposium.prompt('Extract name and emails from the following email', email_text, {
|
|
77
|
+
response: {
|
|
78
|
+
type: 'json',
|
|
79
|
+
function: {
|
|
80
|
+
name: 'extract_data',
|
|
81
|
+
parameters: {
|
|
82
|
+
type: 'array',
|
|
83
|
+
items: {
|
|
84
|
+
type: 'object',
|
|
85
|
+
properties: {
|
|
86
|
+
name: {type: 'string'},
|
|
87
|
+
email: {type: 'string'},
|
|
88
|
+
},
|
|
89
|
+
required: ['name', 'email'],
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 3. Create your Agent
|
|
98
|
+
|
|
99
|
+
For more structured and/or reusable tasks, create a new class that extends `Agent`. At a minimum, you'll want to define a name and a system prompt.
|
|
68
100
|
|
|
69
101
|
```javascript
|
|
70
102
|
// MyChatAgent.js
|
|
@@ -80,7 +112,7 @@ export default class MyChatAgent extends Agent {
|
|
|
80
112
|
}
|
|
81
113
|
```
|
|
82
114
|
|
|
83
|
-
###
|
|
115
|
+
### 4. Start a Conversation
|
|
84
116
|
|
|
85
117
|
Now you can instantiate your agent and start a conversation.
|
|
86
118
|
|
|
@@ -338,7 +370,7 @@ This is a high-level overview. For details, please refer to the source code.
|
|
|
338
370
|
|
|
339
371
|
### Other Classes
|
|
340
372
|
|
|
341
|
-
- **`
|
|
373
|
+
- **`ContextHandler`**: Provides a base for managing long-term context. Can be extended for custom memory strategies.
|
|
342
374
|
- **`Summarizer`**: A utility agent for text summarization.
|
|
343
375
|
- **`Logger`**: A simple logger for agent activity.
|
|
344
376
|
|
package/Summarizer.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Symposium from "./Symposium.js";
|
|
2
|
-
import
|
|
2
|
+
import ContextHandler from "./ContextHandler.js";
|
|
3
3
|
|
|
4
|
-
export default class Summarizer extends
|
|
4
|
+
export default class Summarizer extends ContextHandler {
|
|
5
5
|
constructor(threshold = 0.7, summary_length = 0.5) {
|
|
6
6
|
super();
|
|
7
7
|
this.threshold = threshold;
|
package/Symposium.js
CHANGED
|
@@ -2,6 +2,8 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import {fileURLToPath} from 'url';
|
|
4
4
|
|
|
5
|
+
import Agent from "./Agent.js";
|
|
6
|
+
|
|
5
7
|
export default class Symposium {
|
|
6
8
|
static models = new Map();
|
|
7
9
|
static storage = null;
|
|
@@ -113,4 +115,19 @@ export default class Symposium {
|
|
|
113
115
|
|
|
114
116
|
return mimeToExt[mime] || null;
|
|
115
117
|
}
|
|
118
|
+
|
|
119
|
+
static async prompt(system, prompt, options = {}) {
|
|
120
|
+
const agent = new Agent(options.agent || {});
|
|
121
|
+
agent.type = 'utility';
|
|
122
|
+
agent.utility = options.response || {
|
|
123
|
+
type: 'text',
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
agent.doInitThread = async thread => {
|
|
127
|
+
await thread.addMessage('system', system);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const thread = await agent.getThread();
|
|
131
|
+
return agent.message(prompt, thread);
|
|
132
|
+
}
|
|
116
133
|
}
|
package/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import Agent from "./Agent.js";
|
|
|
5
5
|
import Thread from "./Thread.js";
|
|
6
6
|
import Tool from "./Tool.js";
|
|
7
7
|
import Logger from "./Logger.js";
|
|
8
|
-
import
|
|
8
|
+
import ContextHandler from "./ContextHandler.js";
|
|
9
9
|
import Summarizer from "./Summarizer.js";
|
|
10
10
|
|
|
11
11
|
export {
|
|
@@ -14,6 +14,6 @@ export {
|
|
|
14
14
|
Thread,
|
|
15
15
|
Tool,
|
|
16
16
|
Logger,
|
|
17
|
-
|
|
17
|
+
ContextHandler,
|
|
18
18
|
Summarizer,
|
|
19
19
|
};
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "symposium",
|
|
4
|
-
"version": "1.0
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"description": "Agents",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"author": "Domenico Giambra",
|
|
8
8
|
"license": "ISC",
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@anthropic-ai/sdk": "^0.
|
|
11
|
-
"groq-sdk": "^0.
|
|
10
|
+
"@anthropic-ai/sdk": "^0.64.0",
|
|
11
|
+
"groq-sdk": "^0.32.0",
|
|
12
12
|
"openai": "^5.0.0",
|
|
13
13
|
"tiktoken": "^1.0.10",
|
|
14
|
-
"uuid": "^
|
|
14
|
+
"uuid": "^13.0.0"
|
|
15
15
|
}
|
|
16
16
|
}
|