Skip to content

Commit 273ea57

Browse files
committed
Memory Allocation optimization for agents with very large contexts.
1 parent f01e341 commit 273ea57

File tree

4 files changed

+44
-47
lines changed

4 files changed

+44
-47
lines changed

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@smythos/sre",
3-
"version": "1.5.55",
3+
"version": "1.5.56",
44
"description": "Smyth Runtime Environment",
55
"author": "Alaa-eddine KADDOURI",
66
"license": "MIT",

packages/core/src/subsystems/AgentManager/AgentRuntime.class.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
import fs from 'fs';
2-
import path from 'path';
3-
import { Agent } from './Agent.class';
41
import { Component } from '@sre/Components/Component.class';
2+
import { Agent } from './Agent.class';
53

64
import { Logger } from '@sre/helpers/Log.helper';
7-
import { uid } from '@sre/utils';
8-
import { RuntimeContext } from '@sre/MemoryManager/RuntimeContext';
95
import { LLMCache } from '@sre/MemoryManager/LLMCache';
6+
import { RuntimeContext } from '@sre/MemoryManager/RuntimeContext';
107
import { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';
8+
import { uid } from '@sre/utils';
119

1210
const console = Logger('AgentRuntime');
1311
const AgentRuntimeUnavailable = new Proxy(
@@ -201,7 +199,7 @@ export class AgentRuntime {
201199
delete AgentRuntime.tagsData[this.reqTag];
202200
}
203201

204-
this.agentContext.sync();
202+
this.agentContext.enqueueSync();
205203
}
206204
public getWaitingComponents() {
207205
const ctxData = this.agentContext;

packages/core/src/subsystems/MemoryManager/RuntimeContext.ts

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type TComponentContext = {
2121
input?: { [key: string]: any };
2222
output?: { [key: string]: any };
2323
};
24+
2425
export class RuntimeContext extends EventEmitter {
2526
public circularLimitReached: string | boolean = false;
2627
public step: number = 0;
@@ -120,10 +121,12 @@ export class RuntimeContext extends EventEmitter {
120121
cpt.ctx.active = true;
121122
}
122123
}
123-
//fs.writeFileSync(this.ctxFile, JSON.stringify(ctxData, null, 2));
124-
await this._cacheConnector
125-
.requester(AccessCandidate.agent(this.runtime.agent.id))
126-
.set(this.ctxFile, JSON.stringify(ctxData, null, 2), null, null, 6 * 60 * 60); //expires in 6 hours max
124+
125+
if (this.runtime.debug) {
126+
await this._cacheConnector
127+
.requester(AccessCandidate.agent(this.runtime.agent.id))
128+
.set(this.ctxFile, JSON.stringify(ctxData), null, null, 1 * 60 * 60); //expires in 1 hour
129+
}
127130
} else {
128131
ctxData = JSON.parse(data);
129132
if (!ctxData.step) ctxData.step = 0;
@@ -133,42 +136,15 @@ export class RuntimeContext extends EventEmitter {
133136
this._runtimeFileReady = true;
134137
this.emit('ready');
135138
});
136-
137-
// if (!fs.existsSync(this.ctxFile)) {
138-
// ctxData = JSON.parse(JSON.stringify({ components: agent.components, connections: agent.connections, timestamp: Date.now() }));
139-
// if (!ctxData.step) ctxData.step = 0;
140-
// for (let cptId in ctxData.components) {
141-
// ctxData.components[cptId] = {
142-
// id: cptId,
143-
// name: ctxData.components[cptId].name,
144-
// //dbg: { active: false, name: ctxData.components[cptId].name },
145-
// ctx: { active: false, name: ctxData.components[cptId].name },
146-
// };
147-
148-
// const cpt = ctxData.components[cptId];
149-
// //if this debug session was initiated from an endpoint, we mark the endpoint component as active
150-
// if (endpoint && endpoint.id != undefined && cpt.id == endpoint.id && endpointDBGCall) {
151-
// //cpt.dbg.active = true;
152-
// cpt.ctx.active = true;
153-
// }
154-
// }
155-
// fs.writeFileSync(this.ctxFile, JSON.stringify(ctxData, null, 2));
156-
// } else {
157-
// ctxData = JSON.parse(fs.readFileSync(this.ctxFile, 'utf8'));
158-
// if (!ctxData.step) ctxData.step = 0;
159-
// }
160-
161-
// this.deserialize(ctxData);
162-
// this._runtimeFileReady = true;
163-
// this.emit('ready');
164139
}
165140

166141
public async ready() {
167142
if (this._runtimeFileReady) return true;
168143
return this._readyPromise;
169144
}
170-
public async sync() {
171-
if (!this.ctxFile) return;
145+
private async sync() {
146+
if (!this.ctxFile || this.runtime.debug) return;
147+
172148
this.emit('syncing');
173149

174150
const deleteSession = this.runtime.sessionClosed;
@@ -183,23 +159,36 @@ export class RuntimeContext extends EventEmitter {
183159
else this._cacheConnector.requester(AccessCandidate.agent(this.runtime.agent.id)).delete(this.ctxFile);
184160
//if (this.runtime.debug && fs.existsSync(this.ctxFile)) await delay(1000 * 60); //if we're in debug mode, we keep the file for a while to allow final state read
185161
//if (fs.existsSync(this.ctxFile)) fs.unlinkSync(this.ctxFile);
162+
this.ctxFile = null;
186163
}
187164
} else {
188165
const data = this.serialize();
189166
//if (data) fs.writeFileSync(this.ctxFile, JSON.stringify(data, null, 2));
190167
if (data) {
191-
const serializedData = JSON.stringify(data, null, 2);
168+
let serializedData = JSON.stringify(data);
192169
console.debug('Agent Context Size', this.ctxFile, serializedData.length, AccessCandidate.agent(this.runtime.agent.id));
193170
await this._cacheConnector
194171
.requester(AccessCandidate.agent(this.runtime.agent.id))
195172
.set(this.ctxFile, serializedData, null, null, 3 * 60 * 60); //expires in 3 hours max
173+
174+
const mb = serializedData.length / 1024 / 1024;
175+
const cooldown = (mb / 10) * 1000;
176+
serializedData = null;
177+
178+
await delay(cooldown);
196179
}
197180
}
198181
}
182+
private _syncQueue = Promise.resolve();
199183

184+
public enqueueSync() {
185+
if (!this.ctxFile) return;
186+
console.log('ENQUEUE SYNC');
187+
this._syncQueue = this._syncQueue.then(() => this.sync()).catch(() => {}); // avoid unhandled rejections
188+
}
200189
public incStep() {
201190
this.step++;
202-
this.sync();
191+
//this.sync();
203192
}
204193

205194
public updateComponent(componentId: string, data: any) {
@@ -217,11 +206,16 @@ export class RuntimeContext extends EventEmitter {
217206
console.debug('>>> ctxFile', this.ctxFile, AccessCandidate.agent(this.runtime.agent.id));
218207
console.debug('>>> ctxData', ctxData, AccessCandidate.agent(this.runtime.agent.id));
219208
}
220-
component.ctx = { ...component.ctx, ...data, step: this.step };
209+
//component.ctx = { ...component.ctx, ...data, step: this.step };
210+
// minimal allocations
211+
212+
if (!component.ctx) component.ctx = { active: false, name: '', step: 0 };
213+
Object.assign(component.ctx, data);
214+
component.ctx.step = this.step;
221215

222216
//if (this.debug) component.dbg = { ...component.dbg, ...data };
223217

224-
this.sync();
218+
this.enqueueSync();
225219
}
226220
public resetComponent(componentId: string) {
227221
const ctxData = this;
@@ -240,8 +234,13 @@ export class RuntimeContext extends EventEmitter {
240234
//component.dbg.runtimeData = {};
241235
component.ctx.runtimeData = {};
242236
component.ctx.active = false;
237+
if (!this.runtime.debug) {
238+
//console.debug('NOT in debug mode, clearing context input/output');
239+
component.ctx.input = undefined;
240+
component.ctx.output = undefined;
241+
}
243242

244-
this.sync();
243+
this.enqueueSync();
245244
}
246245

247246
public getComponentData(componentId: string) {

packages/sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@smythos/sdk",
3-
"version": "1.0.49",
3+
"version": "1.0.50",
44
"description": "SRE SDK",
55
"keywords": [
66
"smythos",

0 commit comments

Comments
 (0)