Skip to content

Commit c5c29c4

Browse files
committed
feat: add rate limiter and reduce unnecessary AI calls for free tier
1 parent 9b0ba6f commit c5c29c4

2 files changed

Lines changed: 37 additions & 2 deletions

File tree

src/echo-ai/aiModel.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,33 @@ import { generateText } from 'ai'
22
import { aiConfig } from '#configs/ai.config.js'
33
import { promptService } from '#ai/services/prompt.service.js'
44

5+
// Simple rate limiter for OpenAI requests
6+
class RateLimiter {
7+
constructor(maxRequests = 3, windowMs = 60000) {
8+
this.maxRequests = maxRequests
9+
this.windowMs = windowMs
10+
this.requests = []
11+
}
12+
13+
async waitForSlot() {
14+
const now = Date.now()
15+
// Remove old requests outside the window
16+
this.requests = this.requests.filter(time => now - time < this.windowMs)
17+
18+
if (this.requests.length >= this.maxRequests) {
19+
const oldestRequest = this.requests[0]
20+
const waitTime = this.windowMs - (now - oldestRequest) + 100 // Add 100ms buffer
21+
console.log(`Rate limit: waiting ${waitTime}ms before next request`)
22+
await new Promise(resolve => setTimeout(resolve, waitTime))
23+
return this.waitForSlot() // Recursive call after waiting
24+
}
25+
26+
this.requests.push(now)
27+
}
28+
}
29+
30+
const rateLimiter = new RateLimiter(3, 60000) // 3 requests per minute
31+
532
/**
633
* AI Model wrapper that provides a consistent interface for agents
734
*/
@@ -72,6 +99,9 @@ export class AIModel {
7299
// Set a reasonable default max tokens based on prompt length
73100
const dynamicMaxTokens = this._calculateOptimalTokens(optimizedPrompt)
74101

102+
// Wait for rate limit slot before making request
103+
await rateLimiter.waitForSlot()
104+
75105
// Create a proper system message that won't be overridden
76106
const result = await generateText({
77107
model: this.provider(options.model || aiConfig.model),

src/echo-ai/services/ai.service.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ class AIService {
633633
* @private
634634
*/
635635
_classifyMessageIntent = async message => {
636-
// Quick checks for obvious patterns
636+
// Quick checks for obvious patterns (no AI call needed)
637637
const msg = message.toLowerCase()
638638

639639
// Add research pattern check
@@ -690,7 +690,12 @@ class AIService {
690690
return 'knowledge'
691691
}
692692

693-
// Use AI for more nuanced classification with improved prompt
693+
// For simple/short messages, default to conversation without AI call
694+
if (message.length < 50 || msg.match(/^(hi|hello|hey|thanks|ok|yes|no|sure)\b/)) {
695+
return 'conversation'
696+
}
697+
698+
// Only use AI for complex/ambiguous cases - this reduces API calls significantly
694699
try {
695700
const classification = await this.aiModel.getResponse(`Classify this message into one of these categories:
696701
Message: "${message}"

0 commit comments

Comments
 (0)