symposium 0.5.2 → 0.5.4
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/Model.js +28 -15
- package/Summarizer.js +11 -14
- package/Symposium.js +10 -0
- package/models/AnthropicModel.js +1 -1
- package/models/OpenAIModel.js +17 -0
- package/package.json +1 -1
package/Model.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import Message from "./Message.js";
|
|
2
|
-
|
|
3
1
|
export default class Model {
|
|
4
2
|
type = 'llm';
|
|
5
3
|
name;
|
|
6
|
-
name_for_tiktoken;
|
|
7
4
|
label;
|
|
8
5
|
tokens;
|
|
9
6
|
supports_functions = false;
|
|
@@ -11,27 +8,40 @@ export default class Model {
|
|
|
11
8
|
constructor() {
|
|
12
9
|
if (!this.label)
|
|
13
10
|
this.label = this.name;
|
|
14
|
-
if (!this.name_for_tiktoken)
|
|
15
|
-
this.name_for_tiktoken = this.name;
|
|
16
11
|
}
|
|
17
12
|
|
|
18
13
|
async generate(thread, payload = {}, functions = []) {
|
|
19
14
|
return null;
|
|
20
15
|
}
|
|
21
16
|
|
|
22
|
-
|
|
17
|
+
async countTokens(thread) {
|
|
18
|
+
throw new Error('countTokens not implemented in this model');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
promptFromFunctions(payload, functions) {
|
|
22
|
+
if (payload.function_call)
|
|
23
|
+
functions = functions.filter(f => f.name !== payload.function_call);
|
|
24
|
+
|
|
23
25
|
if (!functions.length)
|
|
24
26
|
return '';
|
|
25
27
|
|
|
26
|
-
let message
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
let message;
|
|
29
|
+
if (payload.function_call) {
|
|
30
|
+
message = "Nella prossima risposta, rispondi UNICAMENTE seguendo le seguenti istruzioni:\n";
|
|
31
|
+
message += functions[0].description + "\n";
|
|
32
|
+
delete functions[0].description;
|
|
33
|
+
message += "Rispondi con un messaggio che inizia con le parole:\nCALL " + payload.function_call + "\nE poi a capo un oggetto JSON che segue queste direttive OpenAPI:\n";
|
|
34
|
+
} else {
|
|
35
|
+
message = "Hai a disposizione alcune funzioni che puoi chiamare per ottenere risposte o compiere azioni. Ricorda che devi attendere la risposta dalla funzione per sapere se ha avuto successo. Per chiamare una funzione scrivi un messaggio che inizia con CALL nome_funzione e a capo inserisci il JSON con gli argomenti; delimitando il tutto da 3 caratteri ``` - ad esempio:\n" +
|
|
36
|
+
"```\n" +
|
|
37
|
+
"CALL create_user\n" +
|
|
38
|
+
'{"name":"test"}' + "\n" +
|
|
39
|
+
"```\n\n" +
|
|
40
|
+
"Lista delle funzioni che hai a disposizione:\n";
|
|
41
|
+
|
|
42
|
+
for (let f of functions)
|
|
43
|
+
message += '- ' + f.name + "\n " + f.description + "\n";
|
|
44
|
+
}
|
|
35
45
|
|
|
36
46
|
message += "\nOpenAPI specs:\n\n";
|
|
37
47
|
for (let f of functions) {
|
|
@@ -40,6 +50,9 @@ export default class Model {
|
|
|
40
50
|
message += '=== ' + f.name + " ===\n" + JSON.stringify(f.parameters.properties) + "\n\n";
|
|
41
51
|
}
|
|
42
52
|
|
|
53
|
+
if (payload.function_call)
|
|
54
|
+
message += "\nNella risposta non deve esserci NIENTE ALTRO se non queste due cose, non saranno prese in considerazione dal sistema altro genere di risposte.";
|
|
55
|
+
|
|
43
56
|
return message;
|
|
44
57
|
}
|
|
45
58
|
}
|
package/Summarizer.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import Symposium from "./Symposium.js";
|
|
2
2
|
import MemoryHandler from "./MemoryHandler.js";
|
|
3
|
-
import {encoding_for_model} from "tiktoken";
|
|
4
3
|
|
|
5
4
|
export default class Summarizer extends MemoryHandler {
|
|
6
5
|
constructor(threshold = 0.7, summary_length = 0.5) {
|
|
@@ -14,19 +13,14 @@ export default class Summarizer extends MemoryHandler {
|
|
|
14
13
|
if (!model)
|
|
15
14
|
return thread;
|
|
16
15
|
|
|
17
|
-
const
|
|
18
|
-
const tokens = this.countTokens(encoder, thread);
|
|
16
|
+
const tokens = await model.countTokens(thread);
|
|
19
17
|
if (tokens >= model.tokens * this.threshold)
|
|
20
|
-
return await this.summarize(
|
|
18
|
+
return await this.summarize(model, thread, model.tokens * this.summary_length);
|
|
21
19
|
else
|
|
22
20
|
return thread;
|
|
23
21
|
}
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
return encoder.encode(thread.messages.map(m => m.text).join('')).length;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async summarize(encoder, thread, maxLength) {
|
|
23
|
+
async summarize(model, thread, maxLength) {
|
|
30
24
|
let summaryThread = thread.clone(false);
|
|
31
25
|
|
|
32
26
|
let currentStep = 'system';
|
|
@@ -37,7 +31,7 @@ export default class Summarizer extends MemoryHandler {
|
|
|
37
31
|
currentStep = 'summary';
|
|
38
32
|
break;
|
|
39
33
|
case 'summary':
|
|
40
|
-
if (message.role === 'user' && this.hasPassedLimit(
|
|
34
|
+
if (message.role === 'user' && (await this.hasPassedLimit(model, summaryThread, maxLength))) {
|
|
41
35
|
summaryThread = await this.doSummarize(summaryThread, maxLength);
|
|
42
36
|
currentStep = 'retain';
|
|
43
37
|
}
|
|
@@ -50,8 +44,8 @@ export default class Summarizer extends MemoryHandler {
|
|
|
50
44
|
return summaryThread;
|
|
51
45
|
}
|
|
52
46
|
|
|
53
|
-
hasPassedLimit(
|
|
54
|
-
|
|
47
|
+
async hasPassedLimit(model, thread, maxLength) {
|
|
48
|
+
const length = await model.countTokens(thread);
|
|
55
49
|
return length > maxLength;
|
|
56
50
|
}
|
|
57
51
|
|
|
@@ -79,13 +73,16 @@ export default class Summarizer extends MemoryHandler {
|
|
|
79
73
|
if (!summary)
|
|
80
74
|
return false;
|
|
81
75
|
|
|
82
|
-
// TODO: sistemare con nuova interfaccia
|
|
83
76
|
let summarizedThread = thread.clone(false);
|
|
84
77
|
for (let message of thread.messages) {
|
|
85
78
|
if (message.role === 'system' && !message.tags.includes('summary')) {
|
|
86
79
|
summarizedThread.messages.push(message);
|
|
87
80
|
} else {
|
|
88
|
-
|
|
81
|
+
const functionResponse = Symposium.extractFunctionFromResponse(summary);
|
|
82
|
+
if (functionResponse)
|
|
83
|
+
throw new Error('Errore durante la generazione di un riassunto interno');
|
|
84
|
+
|
|
85
|
+
summarizedThread.addMessage('system', "This is what happened until now:\n" + functionResponse.summary, undefined, ['summary']);
|
|
89
86
|
break;
|
|
90
87
|
}
|
|
91
88
|
}
|
package/Symposium.js
CHANGED
|
@@ -36,4 +36,14 @@ export default class Symposium {
|
|
|
36
36
|
static getModelByLabel(label) {
|
|
37
37
|
return Array.from(this.models.values()).find(model => model.label === label);
|
|
38
38
|
}
|
|
39
|
+
|
|
40
|
+
static extractFunctionFromResponse(messages) {
|
|
41
|
+
for (let message of messages) {
|
|
42
|
+
const functionResponse = message.content.filter(c => c.type === 'function');
|
|
43
|
+
if (functionResponse.length)
|
|
44
|
+
return functionResponse[0].arguments;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
39
49
|
}
|
package/models/AnthropicModel.js
CHANGED
|
@@ -18,7 +18,7 @@ export default class AnthropicModel extends Model {
|
|
|
18
18
|
|
|
19
19
|
if (functions.length && !this.supports_functions) {
|
|
20
20
|
// Se il modello non supporta nativamente le funzioni, aggiungo il prompt al messaggio di sistema
|
|
21
|
-
const functions_prompt = this.promptFromFunctions(functions);
|
|
21
|
+
const functions_prompt = this.promptFromFunctions(payload, functions);
|
|
22
22
|
system += "\n\n" + functions_prompt;
|
|
23
23
|
functions = [];
|
|
24
24
|
}
|
package/models/OpenAIModel.js
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import Model from "../Model.js";
|
|
2
2
|
import OpenAI from "openai";
|
|
3
3
|
import Message from "../Message.js";
|
|
4
|
+
import {encoding_for_model} from "tiktoken";
|
|
4
5
|
|
|
5
6
|
export default class OpenAIModel extends Model {
|
|
6
7
|
openai;
|
|
8
|
+
name_for_tiktoken;
|
|
7
9
|
supports_functions = true;
|
|
8
10
|
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
if (!this.name_for_tiktoken)
|
|
14
|
+
this.name_for_tiktoken = this.name;
|
|
15
|
+
}
|
|
16
|
+
|
|
9
17
|
getOpenAi() {
|
|
10
18
|
if (!this.openai)
|
|
11
19
|
this.openai = new OpenAI({apiKey: process.env.OPENAI_API_KEY});
|
|
@@ -74,6 +82,15 @@ export default class OpenAIModel extends Model {
|
|
|
74
82
|
];
|
|
75
83
|
}
|
|
76
84
|
|
|
85
|
+
async countTokens(thread) {
|
|
86
|
+
const encoder = encoding_for_model(this.name_for_tiktoken);
|
|
87
|
+
|
|
88
|
+
const texts = [];
|
|
89
|
+
for (let message of thread.messages)
|
|
90
|
+
texts.push(message.content.map(m => typeof m.content === 'string' ? m.content : JSON.stringify(m.content)).join(''));
|
|
91
|
+
return encoder.encode(texts.join('')).length;
|
|
92
|
+
}
|
|
93
|
+
|
|
77
94
|
convertMessage(message) {
|
|
78
95
|
const messages = [];
|
|
79
96
|
for (let c of message.content) {
|