symposium 0.12.8 → 0.12.10

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/README.md ADDED
@@ -0,0 +1,150 @@
1
+ # Symposium
2
+
3
+ Symposium is an npm library designed to simplify the deployment and management of AI agents. Its modular and flexible architecture makes it easy to create agents that can interact with users, execute functions through integrated tools, and manage complex conversation threads—all while supporting multiple language models from various providers.
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ - [Overview](#overview)
10
+ - [Features](#features)
11
+ - [Installation](#installation)
12
+ - [Usage](#usage)
13
+ - [Architecture](#architecture)
14
+ - [Supported Models](#supported-models)
15
+ - [Extending Symposium](#extending-symposium)
16
+ - [Examples](#examples)
17
+ - [Contributing](#contributing)
18
+ - [License](#license)
19
+
20
+ ---
21
+
22
+ ## Overview
23
+
24
+ Symposium provides a robust framework for deploying AI agents with ease. It handles message threading, state management, logging, and even conversation summarization to keep interactions within token limits. With built-in support for multiple AI models and a plugin-like system for tools, Symposium enables developers to quickly build sophisticated agent-based applications.
25
+
26
+ ---
27
+
28
+ ## Features
29
+
30
+ - **Agent Management**: Create and manage agents that process user messages and execute actions.
31
+ - **Tool Integration**: Extend your agents’ capabilities by integrating custom tools with defined functions.
32
+ - **Thread & Memory Handling**: Manage conversation state and threads seamlessly, with automatic summarization support.
33
+ - **Multi-Agent Coordination**: Support for multi-agent systems to allow agents to collaborate and share tasks.
34
+ - **Flexible Model Support**: Out-of-the-box compatibility with various models including OpenAI, Anthropic, Groq, and DeepSeek.
35
+ - **Structured Function Calls**: Enable agents to call functions using structured output, ensuring clarity and consistency.
36
+
37
+ ---
38
+
39
+ ## Installation
40
+
41
+ Install Symposium via npm:
42
+
43
+ ```bash
44
+ npm install symposium
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Usage
50
+
51
+ Below is a basic example of how to create a custom agent using Symposium:
52
+
53
+ ```js
54
+ import { Symposium, Agent } from 'symposium';
55
+
56
+ class MyAgent extends Agent {
57
+ constructor(options = {}) {
58
+ super(options);
59
+ this.name = 'MyAgent';
60
+ }
61
+
62
+ async doInitThread(thread) {
63
+ await thread.addMessage('system', 'Welcome! How can I assist you today?');
64
+ }
65
+ }
66
+
67
+ (async () => {
68
+ const myAgent = new MyAgent();
69
+ await myAgent.init();
70
+
71
+ const thread = await myAgent.getThread('example-thread');
72
+ await myAgent.message(thread, 'default', 'Hello, agent!');
73
+ })();
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Architecture
79
+
80
+ Symposium is built around several core components:
81
+
82
+ - **Agent**: The base class for creating agents. Agents process messages, manage threads, and interact with tools.
83
+ - **Tool**: Extend functionality by integrating custom functions. Tools define their own functions and provide implementations through the `callFunction` method.
84
+ - **Thread**: Represents a conversation, handling message storage, state management, and persistence.
85
+ - **Logger & MemoryHandler**: Utilities for logging events and managing conversation memory, respectively.
86
+ - **Summarizer**: A specialized memory handler that summarizes conversation threads to maintain context within token limits.
87
+ - **Interface**: Abstracts output and error handling, enabling custom integrations with external systems.
88
+
89
+ ---
90
+
91
+ ## Supported Models
92
+
93
+ Symposium supports a variety of AI models, allowing you to switch between them based on your needs:
94
+
95
+ - **OpenAI Models**:
96
+ - GPT-3.5-turbo
97
+ - GPT-4, GPT-4Turbo, GPT-4o
98
+ - GPT-o1, GPT-o1 mini
99
+ - **Anthropic Models**:
100
+ - Claude3 variants (Haiku, Sonnet, Opus, and 3.5 Sonnet)
101
+ - **Groq Models**:
102
+ - Llama3, Mixtral8
103
+ - **DeepSeek Models**:
104
+ - DeepSeekChat, DeepSeekReasoner
105
+ - **Other Models**:
106
+ - Whisper (for speech-to-text)
107
+
108
+ These models are encapsulated in their own modules, and you can easily switch the active model by updating the conversation thread state.
109
+
110
+ ---
111
+
112
+ ## Extending Symposium
113
+
114
+ Symposium is designed to be extended and customized:
115
+
116
+ - **Creating Custom Agents**: Inherit from the `Agent` class and override methods like `doInitThread` and `message` to implement custom behavior.
117
+ - **Implementing Tools**: Build your own tools by extending the `Tool` class. Define the functions your tool exposes and provide implementations via `callFunction`.
118
+ - **Custom Memory Handlers & Loggers**: Implement your own memory or logging strategies by creating classes that adhere to the respective interfaces.
119
+ - **Defining Interfaces**: Customize output and error handling by implementing your own `Interface` classes.
120
+
121
+ ---
122
+
123
+ ## Examples
124
+
125
+ The repository includes an `examples` folder with sample implementations demonstrating:
126
+
127
+ - **ChatAgent**: A basic conversational agent.
128
+ - **MultiAgent**: An agent that coordinates with other agents via internal interfaces.
129
+ - **TitlerAgent**: An agent that generates concise titles for conversations.
130
+ - **Tools**: Examples like `GenericTool` and `MultiAgentTool` show how to integrate custom functionality.
131
+
132
+ > **Important:** The content in the `examples` folder is provided solely for demo purposes and will not be part of the exported npm package. You can use these examples as a guide for building your own implementations.
133
+
134
+ ---
135
+
136
+ ## Contributing
137
+
138
+ Contributions to Symposium are welcome! If you have ideas, improvements, or bug fixes, please fork the repository and submit a pull request.
139
+
140
+ ---
141
+
142
+ ## License
143
+
144
+ Symposium is released under the ISC License.
145
+
146
+ ---
147
+
148
+ Developed by **Domenico Giambra**
149
+
150
+ For more details or to report issues, please refer to the repository's issue tracker. Enjoy building your AI-driven applications with Symposium!
@@ -0,0 +1,21 @@
1
+ import {Agent, Symposium} from "symposium";
2
+ import GenericTool from "./Tools/GenericTool.js";
3
+
4
+ export default class ChatAgent extends Agent {
5
+ default_model = 'gpt-4o';
6
+
7
+ constructor(options = {}) {
8
+ super(options);
9
+
10
+ this.name = 'ChatAgent';
11
+
12
+ this.addTool(new GenericTool());
13
+ }
14
+
15
+ async doInitThread(thread) {
16
+ await thread.addMessage('system',
17
+ `You are a helpful assistant, assist the user using the tools you are provided with.
18
+ Current time is: ${(new Date()).toLocaleDateString()}`
19
+ );
20
+ }
21
+ }
@@ -0,0 +1,115 @@
1
+ import {Agent, Symposium} from "symposium";
2
+ import MultiAgentTool from "./Tools/MultiAgentTool.js";
3
+
4
+ export default class MultiAgent extends Agent {
5
+ default_model = 'gpt-4o';
6
+
7
+ constructor(options = {}) {
8
+ options = {
9
+ agents: [],
10
+ ...options,
11
+ };
12
+
13
+ super(options);
14
+ this.name = 'Multi Agent';
15
+
16
+ this.internalInterface = {
17
+ name: 'agent-vs-agent',
18
+ promises: [],
19
+ init: async () => {
20
+ },
21
+ message: async (thread, msg) => {
22
+ },
23
+ output: async (thread, msg) => {
24
+ },
25
+ error: async (thread, error) => {
26
+ },
27
+ };
28
+
29
+ this.addTool(new MultiAgentTool(this.options.agents));
30
+ }
31
+
32
+ async init() {
33
+ await super.init();
34
+
35
+ for (let agent of this.options.agents) {
36
+ agent.options.interfaces = [this.internalInterface];
37
+ await agent.init();
38
+ }
39
+ }
40
+
41
+ async reset(thread) {
42
+ await super.reset(thread);
43
+
44
+ for (let agent of this.options.agents) {
45
+ const sub_thread = await agent.getThread(thread.id, 'agent-vs-agent');
46
+ await agent.reset(sub_thread);
47
+ }
48
+ }
49
+
50
+ async doInitThread(thread) {
51
+ const memory = await this.tools.get('Memory').get();
52
+
53
+ await thread.addMessage('system',
54
+ `You are a helpful assistant, assist the user using the tools you are provided with.
55
+ In order to do so, you have a series of agents at your service, with which you can communicate behind the scenes to provide the user with what they asked for. You can communicate with them through their respective tools that you have.
56
+ You can talk to the agents in natural language, and also respond to them multiple times if necessary. Try to use clear and direct language with precise instructions when talking to an agent.
57
+
58
+ At the end of each task, when the agent has completed its function, remember to reset the conversation with the agent to save memory. You can do this using the "reset" function.
59
+
60
+ Interrogate them only if the user asks to perform tasks that concern them, otherwise you can rely on your knowledge to respond directly.
61
+
62
+ Current time is: ${(new Date()).toLocaleDateString()}`,
63
+ );
64
+
65
+ for (let agent of this.options.agents) {
66
+ const sub_thread = await agent.getThread(thread.id, 'agent-vs-agent');
67
+ if (sub_thread) {
68
+ await sub_thread.flush();
69
+ await agent.initThread(sub_thread);
70
+ }
71
+ }
72
+ }
73
+
74
+ async beforeExecute(thread) {
75
+ if (this.options.reasoning) {
76
+ let reasoning = await this.generateCompletion(thread, {
77
+ functions: [
78
+ {
79
+ name: 'ragionamento',
80
+ description: 'Before responding to the user, ask yourself what needs to be done and if you need to ask for more info.',
81
+ parameters: {
82
+ type: 'object',
83
+ properties: {
84
+ ragionamento: {
85
+ type: 'string',
86
+ description: 'Reflect on the request just made. What do you need to do to fulfill the user\'s request? These are your thoughts and the user cannot see them.',
87
+ }
88
+ },
89
+ required: ['ragionamento'],
90
+ }
91
+ },
92
+ ...(await this.getFunctions()),
93
+ ],
94
+ force_function: 'ragionamento',
95
+ });
96
+
97
+ if (reasoning) {
98
+ reasoning = Symposium.extractFunctionsFromResponse(reasoning)[0];
99
+ await this.log('reasoning', reasoning);
100
+ thread.addMessage('assistant', "[Thinking] " + reasoning.ragionamento + "\n");
101
+ }
102
+ }
103
+
104
+ return thread;
105
+ }
106
+
107
+ async getPromptWordsForTranscription(thread) {
108
+ let words = [this.name];
109
+ for (let agent of this.options.agents) {
110
+ const sub_thread = await agent.getThread(thread.id, 'agent-vs-agent');
111
+ words = [...words, ...(await agent.getPromptWordsForTranscription(sub_thread))];
112
+ }
113
+ return words;
114
+ }
115
+ }
@@ -0,0 +1,25 @@
1
+ import {Agent} from "symposium";
2
+
3
+ export default class TitlerAgent extends Agent {
4
+ default_model = 'gpt-4o';
5
+
6
+ constructor(options) {
7
+ super(options);
8
+ this.name = 'Titler';
9
+ }
10
+
11
+ async init() {
12
+ await super.init();
13
+
14
+ this.utility = {
15
+ type: 'text',
16
+ };
17
+ }
18
+
19
+ async doInitThread(thread) {
20
+ await thread.addMessage('system',
21
+ `Your task is to observe the following message, which represents the beginning of a conversation from the user, and give a title of a few words (maximum 30 characters) that describes it as accurately as possible. Even a single word is fine, if necessary.
22
+ Do not write anything else in your message, but only and exclusively the title.`
23
+ );
24
+ }
25
+ }
@@ -0,0 +1,42 @@
1
+ import {Tool} from "symposium";
2
+
3
+ export default class GenericTool extends Tool {
4
+ name = 'GenericTool';
5
+
6
+ async getFunctions() {
7
+ return [
8
+ {
9
+ name: `create_todo`,
10
+ description: `Create a new TODO`,
11
+ parameters: {
12
+ type: 'object',
13
+ properties: {
14
+ title: {
15
+ type: 'string',
16
+ description: 'Title of the TODO',
17
+ },
18
+ description: {
19
+ type: 'string',
20
+ description: 'Description of the TODO',
21
+ },
22
+ due_date: {
23
+ type: 'string',
24
+ description: 'Due date of the TODO',
25
+ },
26
+ },
27
+ required: ['title', 'description', 'due_date'],
28
+ },
29
+ }
30
+ ];
31
+ }
32
+
33
+ async callFunction(thread, name, payload) {
34
+ try {
35
+ // Implement your function here
36
+
37
+ throw new Error(`Unknown function: ${name}`);
38
+ } catch (error) {
39
+ return {error: error.response?.body || error};
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,77 @@
1
+ import {Tool} from "symposium";
2
+
3
+ export default class MultiAgentTool extends Tool {
4
+ name = 'MultiAgentTool';
5
+ agents;
6
+
7
+ constructor(agents) {
8
+ super();
9
+ this.agents = agents;
10
+ }
11
+
12
+ async getFunctions() {
13
+ return [
14
+ ...this.agents.map(a => ({
15
+ name: a.name,
16
+ description: a.description,
17
+ parameters: {
18
+ type: 'object',
19
+ properties: {
20
+ message: {
21
+ type: 'string',
22
+ description: 'The message to send to the agent'
23
+ }
24
+ }
25
+ }
26
+ })),
27
+ {
28
+ name: 'reset',
29
+ description: 'Reset an agent\'s memory to start the conversation again',
30
+ parameters: {
31
+ type: 'object',
32
+ properties: {
33
+ agent: {
34
+ type: 'string',
35
+ description: 'The name of the agent to reset'
36
+ }
37
+ }
38
+ }
39
+ }
40
+ ];
41
+ }
42
+
43
+ async callFunction(thread, name, payload) {
44
+ try {
45
+ if (name === 'reset') {
46
+ const agent = this.agents.find(a => a.name === payload.agent);
47
+ if (!agent)
48
+ throw new Error('No agent named "' + payload.agent + '"');
49
+
50
+ const sub_thread = await agent.getThread(thread.id, 'agent-vs-agent');
51
+
52
+ await agent.reset(sub_thread);
53
+
54
+ return {success: true};
55
+ } else {
56
+ const agent = this.agents.find(a => a.name === name);
57
+ if (!agent)
58
+ throw new Error('No agent named "' + name + '"');
59
+
60
+ return await (new Promise(async (resolve, reject) => {
61
+ try {
62
+ const sub_thread = await agent.getThread(thread.id, 'agent-vs-agent');
63
+
64
+ await agent.message(sub_thread, 'agent-vs-agent', payload.message, msg => {
65
+ resolve({reply: msg});
66
+ });
67
+ } catch (e) {
68
+ console.error(JSON.stringify(e));
69
+ reject(e);
70
+ }
71
+ }));
72
+ }
73
+ } catch (error) {
74
+ return {error};
75
+ }
76
+ }
77
+ }
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "symposium",
4
- "version": "0.12.8",
4
+ "version": "0.12.10",
5
5
  "description": "Agents",
6
6
  "main": "index.js",
7
7
  "author": "Domenico Giambra",
8
8
  "license": "ISC",
9
9
  "dependencies": {
10
10
  "@anthropic-ai/sdk": "^0.36.0",
11
- "groq-sdk": "^0.13.0",
11
+ "groq-sdk": "^0.15.0",
12
12
  "openai": "^4.12.1",
13
13
  "tiktoken": "^1.0.10"
14
14
  }