Skip to content

Commit 5fc762c

Browse files
committed
add sliding window logic + add timestamp field
1 parent 36955f5 commit 5fc762c

File tree

10 files changed

+93
-26
lines changed

10 files changed

+93
-26
lines changed

src/modules/llms/api/athropic.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ export const anthropicCompletion = async (
4949
completion: {
5050
content: completion[0].text,
5151
role: 'assistant',
52-
model
52+
model,
53+
timestamp: Date.now()
5354
},
5455
usage: totalOutputTokens + totalInputTokens,
5556
price: 0,
@@ -92,7 +93,8 @@ export const xaiCompletion = async (
9293
completion: {
9394
content: completion[0].text,
9495
role: 'assistant',
95-
model
96+
model,
97+
timestamp: Date.now()
9698
},
9799
usage: totalOutputTokens + totalInputTokens,
98100
price: 0,
@@ -202,7 +204,8 @@ export const anthropicStreamCompletion = async (
202204
completion: {
203205
content: completion,
204206
role: 'assistant',
205-
model
207+
model,
208+
timestamp: Date.now()
206209
},
207210
usage: parseInt(totalOutputTokens, 10) + parseInt(totalInputTokens, 10),
208211
price: 0,
@@ -252,7 +255,8 @@ export const toolsChatCompletion = async (
252255
completion: {
253256
content: completion[0].text,
254257
role: 'assistant',
255-
model
258+
model,
259+
timestamp: Date.now()
256260
},
257261
usage: totalOutputTokens + totalInputTokens,
258262
price: 0,
@@ -264,7 +268,8 @@ export const toolsChatCompletion = async (
264268
completion: {
265269
content: 'Timeout error',
266270
role: 'assistant',
267-
model
271+
model,
272+
timestamp: Date.now()
268273
},
269274
usage: 0,
270275
price: 0

src/modules/llms/api/llmApi.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import axios from 'axios'
22
import config from '../../../config'
3-
import { type ChatConversation } from '../../types'
3+
import { type ChatConversationWithoutTimestamp, type ChatConversation } from '../../types'
44
import pino from 'pino'
55
import { type ChatModel } from '../utils/types'
66
import { headers } from './helper'
@@ -36,7 +36,7 @@ interface LlmAddUrlDocument {
3636
interface QueryUrlDocument {
3737
collectioName: string
3838
prompt: string
39-
conversation?: ChatConversation[]
39+
conversation?: ChatConversationWithoutTimestamp[]
4040
}
4141

4242
export const getChatModel = (modelName: string): ChatModel | undefined => {
@@ -130,7 +130,8 @@ export const llmCompletion = async (
130130
completion: {
131131
content: completion[0].message?.content,
132132
role: 'system',
133-
model
133+
model,
134+
timestamp: Date.now()
134135
},
135136
usage: totalOutputTokens + totalInputTokens,
136137
price: 0

src/modules/llms/api/openai.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ export async function alterGeneratedImg (
7979
}
8080
}
8181

82-
const prepareConversation = (conversation: ChatConversation[], model: string): ChatConversation[] => {
82+
type ConversationOutput = Omit<ChatConversation, 'timestamp' | 'model' | 'id' | 'author' | 'numSubAgents'>
83+
84+
const prepareConversation = (conversation: ChatConversation[], model: string): ConversationOutput[] => {
8385
const messages = conversation.filter(c => c.model === model).map(m => { return { content: m.content, role: m.role } })
8486
if (messages.length !== 1 || model === LlmModelsEnum.O1) {
8587
return messages
@@ -125,7 +127,8 @@ export async function chatCompletion (
125127
return {
126128
completion: {
127129
content: response.choices[0].message?.content ?? 'Error - no completion available',
128-
role: 'assistant'
130+
role: 'assistant',
131+
timestamp: Date.now()
129132
},
130133
usage: response.usage?.total_tokens, // 2010
131134
price: price * config.openAi.chatGpt.priceAdjustment,
@@ -215,7 +218,8 @@ export const streamChatCompletion = async (
215218
return {
216219
completion: {
217220
content: completion,
218-
role: 'assistant'
221+
role: 'assistant',
222+
timestamp: Date.now()
219223
},
220224
usage: outputTokens + inputTokens,
221225
price: 0,
@@ -308,7 +312,8 @@ export const streamChatVisionCompletion = async (
308312
return {
309313
completion: {
310314
content: completion,
311-
role: 'assistant'
315+
role: 'assistant',
316+
timestamp: Date.now()
312317
},
313318
usage: outputTokens + inputTokens,
314319
price: 0,
@@ -319,7 +324,7 @@ export const streamChatVisionCompletion = async (
319324

320325
export async function improvePrompt (promptText: string, model: string): Promise<string> {
321326
const prompt = `Improve this picture description using max 100 words and don't add additional text to the image: ${promptText} `
322-
const conversation = [{ role: 'user', content: prompt }]
327+
const conversation = [{ role: 'user', content: prompt, timestamp: Date.now() }]
323328
const response = await chatCompletion(conversation, model)
324329
return response.completion?.content as string ?? ''
325330
}

src/modules/llms/api/pdfHandler.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ export const handlePdf = async (prompt: string): Promise<PdfCompletion> => {
1919
return {
2020
completion: {
2121
content: response.data.response,
22-
role: 'system'
22+
role: 'system',
23+
timestamp: Date.now()
2324
},
2425
prompt,
2526
price: response.data.cost

src/modules/llms/api/vertex.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import axios, { type AxiosResponse } from 'axios'
22
import config from '../../../config'
3-
import { type OnMessageContext, type ChatConversation, type OnCallBackQueryData } from '../../types'
3+
import { type OnMessageContext, type ChatConversation, type OnCallBackQueryData, type ChatConversationWithoutTimestamp } from '../../types'
44
import { type LlmCompletion } from './llmApi'
55
import { type Readable } from 'stream'
66
import { GrammyError } from 'grammy'
@@ -29,7 +29,7 @@ export const vertexCompletion = async (
2929
stream: false,
3030
messages: conversation.filter(c => c.model === model)
3131
.map((msg) => {
32-
const msgFiltered: ChatConversation = { content: msg.content, model: msg.model }
32+
const msgFiltered: ChatConversationWithoutTimestamp = { content: msg.content, model: msg.model }
3333
if (model === LlmModelsEnum.CHAT_BISON) {
3434
msgFiltered.author = msg.role
3535
} else {
@@ -48,7 +48,8 @@ export const vertexCompletion = async (
4848
completion: {
4949
content: response.data._prediction_response[0][0].candidates[0].content,
5050
role: 'bot', // role replace to author attribute will be done later
51-
model
51+
model,
52+
timestamp: Date.now()
5253
},
5354
usage: totalOutputTokens + totalInputTokens,
5455
price: 0
@@ -145,7 +146,8 @@ export const vertexStreamCompletion = async (
145146
completion: {
146147
content: completion,
147148
role: 'assistant',
148-
model
149+
model,
150+
timestamp: Date.now()
149151
},
150152
usage: parseInt(totalOutputTokens, 10) + parseInt(totalInputTokens, 10),
151153
price: 0,

src/modules/llms/llmsBase.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
type LLMModelsManager,
3838
type ModelVersion
3939
} from './utils/llmModelsManager'
40+
import { conversationManager } from './utils/conversationManager'
4041

4142
export abstract class LlmsBase implements PayableBot {
4243
public module: string
@@ -205,7 +206,8 @@ export abstract class LlmsBase implements PayableBot {
205206
id: ctx.message?.message_id,
206207
model,
207208
content: await preparePrompt(ctx, prompt as string),
208-
numSubAgents: 0
209+
numSubAgents: 0,
210+
timestamp: Date.now()
209211
})
210212
if (!session.isProcessingQueue) {
211213
session.isProcessingQueue = true
@@ -218,7 +220,8 @@ export abstract class LlmsBase implements PayableBot {
218220
id: ctx.message?.message_id ?? ctx.message?.message_thread_id ?? 0,
219221
model,
220222
content: prompt as string ?? '', // await preparePrompt(ctx, prompt as string),
221-
numSubAgents: supportedAgents
223+
numSubAgents: supportedAgents,
224+
timestamp: Date.now()
222225
}
223226
await this.runSubagents(ctx, msg, stream, usesTools) // prompt as string)
224227
}
@@ -230,6 +233,8 @@ export abstract class LlmsBase implements PayableBot {
230233

231234
async onChatRequestHandler (ctx: OnMessageContext | OnCallBackQueryData, stream: boolean, usesTools: boolean): Promise<void> {
232235
const session = this.getSession(ctx)
236+
session.chatConversation = conversationManager.manageConversationWindow(session.chatConversation)
237+
233238
while (session.requestQueue.length > 0) {
234239
try {
235240
const msg = session.requestQueue.shift()
@@ -272,7 +277,8 @@ export abstract class LlmsBase implements PayableBot {
272277
const chat: ChatConversation = {
273278
content: enhancedPrompt || prompt,
274279
role: 'user',
275-
model: modelVersion
280+
model: modelVersion,
281+
timestamp: Date.now()
276282
}
277283
chatConversation.push(chat)
278284
const payload = {
@@ -358,7 +364,8 @@ export abstract class LlmsBase implements PayableBot {
358364
conversation.push({
359365
role: 'assistant',
360366
content: completion.completion?.content ?? '',
361-
model
367+
model,
368+
timestamp: Date.now()
362369
})
363370
return {
364371
price: price.price,
@@ -371,7 +378,8 @@ export abstract class LlmsBase implements PayableBot {
371378
conversation.push({
372379
role: 'assistant',
373380
content: response.completion?.content ?? '',
374-
model
381+
model,
382+
timestamp: Date.now()
375383
})
376384
return {
377385
price: response.price,
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { type VisionContent, type ChatConversation } from '../../types'
2+
3+
const MINUTE_IN_MS = 60000 // 1 minute in milliseconds
4+
const INACTIVE_THRESHOLD = 5 * MINUTE_IN_MS // 5 minutes
5+
const IDLE_THRESHOLD = MINUTE_IN_MS // 1 minute
6+
const IDLE_MESSAGE_LIMIT = 5
7+
8+
// const HOUR_IN_MS = 3600000 // 1 hour in milliseconds
9+
// const INACTIVE_THRESHOLD = 12 * HOUR_IN_MS // 12 hours
10+
// const IDLE_THRESHOLD = HOUR_IN_MS // 1 hour
11+
// const IDLE_MESSAGE_LIMIT = 5
12+
13+
// Utility functions
14+
export const conversationManager = {
15+
manageConversationWindow (conversation: ChatConversation[]): ChatConversation[] {
16+
console.log('fco::::::: here', conversation.length)
17+
if (conversation.length === 0) return conversation
18+
const now = Date.now()
19+
const lastMessageTime = conversation[conversation.length - 1].timestamp
20+
const timeDifference = now - lastMessageTime
21+
// Case 1: Inactive conversation (>12 hours) - Reset
22+
if (timeDifference > INACTIVE_THRESHOLD) {
23+
return []
24+
}
25+
26+
// Case 2: Idle conversation (>1 hour) - Keep last 5 messages
27+
if (timeDifference > IDLE_THRESHOLD) {
28+
return conversation.slice(-IDLE_MESSAGE_LIMIT)
29+
}
30+
31+
// Case 3: Active conversation (<1 hour) - Keep full history
32+
return conversation
33+
},
34+
35+
addMessageWithTimestamp (message: Omit<ChatConversation, 'timestamp'> | Partial<Omit<ChatConversation, 'content' | 'timestamp'>> & { content: string | VisionContent[] }): ChatConversation {
36+
return {
37+
...message,
38+
timestamp: Date.now()
39+
}
40+
}
41+
}

src/modules/subagents/llamaSubagent.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
type Collection, type OnCallBackQueryData,
1212
type OnMessageContext,
1313
type SubagentResult,
14-
SubagentStatus
14+
SubagentStatus,
15+
type ChatConversationWithoutTimestamp
1516
} from '../types'
1617
import config from '../../config'
1718
import { appText } from '../../utils/text'
@@ -305,7 +306,7 @@ export class LlamaAgent extends SubagentBase {
305306
const session = this.getSession(ctx)
306307
const collection = ctx.session.collections.activeCollections.find(c => c.url === url)
307308
if (collection) {
308-
const conversation = this.getCollectionConversation(ctx, collection)
309+
const conversation = this.getCollectionConversation(ctx, collection) as unknown as ChatConversationWithoutTimestamp[]
309310
if (conversation.length === 0) {
310311
conversation.push({
311312
role: 'system',

src/modules/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,11 @@ export interface ChatConversation {
5858
content: string | VisionContent[]
5959
model?: string
6060
numSubAgents?: number
61+
timestamp: number
6162
}
6263

64+
export type ChatConversationWithoutTimestamp = Omit<ChatConversation, 'timestamp'>
65+
6366
export interface ImageRequest {
6467
command?: 'dalle' | 'alter' | 'vision'
6568
prompt?: string

src/modules/voice-to-voice-gpt/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export class VoiceToVoiceGPTBot implements PayableBot {
6363
const resultText = await speechToText(fs.createReadStream(filename))
6464
fs.rmSync(filename)
6565

66-
const conversation = [{ role: 'user', content: resultText }]
66+
const conversation = [{ role: 'user', content: resultText, timestamp: Date.now() }]
6767
const response = await chatCompletion(conversation, LlmModelsEnum.GPT_35_TURBO)
6868

6969
const voiceResult = await generateVoiceFromText(response.completion?.content as string)

0 commit comments

Comments
 (0)