Skip to content

Commit 766d4d1

Browse files
authored
Merge pull request #19 from AmbireTech/feat/llm-max-timeout
Add max timeout for LLM responses
2 parents 66f3872 + 11bb199 commit 766d4d1

File tree

5 files changed

+44
-15
lines changed

5 files changed

+44
-15
lines changed

lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ export * from './utils/llm/structures'
77
export * from './utils/prompts'
88
export * from './utils/strategies'
99
export * from './utils/errors'
10+
export * from './utils/timing'

lib/types/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ export type LlmProcessProps = {
4747
prompt: string
4848
model?: string
4949
llmOptionsOverride?: { [x: string]: any }
50+
timeout?: number
51+
timeoutMsg?: string
5052
}
5153

5254
export type LlmProcessOutput = {

lib/utils/llm/gemini.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { GoogleGenerativeAI } from '@google/generative-ai'
22
import { LlmProcessOutput, LlmProcessProps, Strategy } from '../../types'
33
import { stringifyError } from '../errors'
44
import { StrategiesGoogleSchema } from './structures/google'
5+
import { timeoutPromise } from '../timing'
56

67
export const GEMINI_MODELS = {
78
gemini20flashExp: 'gemini-2.0-flash-exp',
@@ -26,7 +27,11 @@ export async function callGemini(llmInput: LlmProcessProps): Promise<LlmProcessO
2627
},
2728
...llmInput.llmOptionsOverride
2829
})
29-
const result = await aiModel.generateContent(llmInput.prompt)
30+
const result = await timeoutPromise(
31+
aiModel.generateContent(llmInput.prompt),
32+
llmInput.timeout || 60,
33+
llmInput.timeoutMsg
34+
)
3035
// console.log(JSON.stringify(result))
3136

3237
const content = result.response.text()

lib/utils/llm/grok.ts

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { zodResponseFormat } from 'openai/helpers/zod'
33
import { LlmProcessOutput, LlmProcessProps, Strategy } from '../../types'
44
import { StrategiesZodSchema } from './structures/zod'
55
import { stringifyError } from '../errors'
6+
import { timeoutPromise } from '../timing'
67

78
export const XAI_MODELS = {
89
grok2latest: 'grok-2-latest',
@@ -22,20 +23,24 @@ export async function callGrok(llmInput: LlmProcessProps): Promise<LlmProcessOut
2223
let outputTokens: number | undefined
2324

2425
try {
25-
const completion = await apiClient.chat.completions.create({
26-
model,
27-
store: true,
28-
messages: [
29-
{
30-
role: 'system',
31-
content:
32-
'You are an expert in cryptocurrencies, DeFi applications and their use cases. Return output in JSON format.'
33-
},
34-
{ role: 'user', content: llmInput.prompt }
35-
],
36-
response_format: zodResponseFormat(StrategiesZodSchema, 'strategies'),
37-
...llmInput.llmOptionsOverride
38-
})
26+
const completion = await timeoutPromise(
27+
apiClient.chat.completions.create({
28+
model,
29+
store: true,
30+
messages: [
31+
{
32+
role: 'system',
33+
content:
34+
'You are an expert in cryptocurrencies, DeFi applications and their use cases. Return output in JSON format.'
35+
},
36+
{ role: 'user', content: llmInput.prompt }
37+
],
38+
response_format: zodResponseFormat(StrategiesZodSchema, 'strategies'),
39+
...llmInput.llmOptionsOverride
40+
}),
41+
llmInput.timeout || 60,
42+
llmInput.timeoutMsg
43+
)
3944

4045
const outputContent = completion.choices[0].message.content || '{}'
4146
inputTokens = completion.usage?.prompt_tokens || 0

lib/utils/timing.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export function timeoutPromise(
2+
promise: Promise<any>,
3+
timeoutSeconds: number,
4+
errorMsg?: string
5+
): Promise<any> {
6+
let timer: NodeJS.Timeout
7+
const timeout = new Promise(
8+
(_, reject) =>
9+
(timer = setTimeout(
10+
() => reject(new Error(errorMsg || 'Request timeout')),
11+
timeoutSeconds * 1000
12+
))
13+
)
14+
15+
return Promise.race([promise.finally(() => clearTimeout(timer)), timeout])
16+
}

0 commit comments

Comments
 (0)