Repository navigation
Expand file tree
/
Copy pathchatWithOpenAI.js
More file actions
77 lines (69 loc) · 2.78 KB
/
Copy pathchatWithOpenAI.js
File metadata and controls
77 lines (69 loc) · 2.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import dotenv from 'dotenv';
import { fileURLToPath } from 'node:url';
import OpenAI from 'openai';
import {
ProviderControlError,
ProviderRequestControls,
readProviderNumber
} from '../../library/javascript/commonHelpers/providerRequestControls.js';
dotenv.config({ path: fileURLToPath(new URL('.env', import.meta.url)), quiet: true });
const SYSTEM_INSTRUCTIONS = 'You are a helpful assistant. Analyze or respond based on the provided meeting transcript.';
export const openAIConfig = Object.freeze({
model: process.env.OPENAI_MODEL || 'gpt-4.1-mini',
timeoutMs: readProviderNumber('OPENAI_TIMEOUT_MS', 20_000, { integer: true, minimum: 1 }),
maxRetries: readProviderNumber('OPENAI_MAX_RETRIES', 2, { integer: true }),
maxOutputTokens: readProviderNumber('OPENAI_MAX_OUTPUT_TOKENS', 512, { integer: true, minimum: 1 }),
maxInputCharacters: readProviderNumber('OPENAI_MAX_INPUT_CHARACTERS', 12_000, { integer: true, minimum: 1 }),
maxRequestsPerMinute: readProviderNumber('OPENAI_MAX_REQUESTS_PER_MINUTE', 30, { integer: true }),
maxRequestsPerStream: readProviderNumber('OPENAI_MAX_REQUESTS_PER_STREAM', 300, { integer: true }),
maxSpendUsdPerStream: readProviderNumber('OPENAI_MAX_SPEND_USD_PER_STREAM', 1),
inputCostPerMillionTokens: readProviderNumber('OPENAI_INPUT_COST_PER_MILLION_TOKENS', 0.4),
outputCostPerMillionTokens: readProviderNumber('OPENAI_OUTPUT_COST_PER_MILLION_TOKENS', 1.6)
});
const controls = new ProviderRequestControls({ provider: 'OpenAI', ...openAIConfig });
let openai;
function getClient() {
if (!openai) {
openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
timeout: openAIConfig.timeoutMs,
maxRetries: openAIConfig.maxRetries
});
}
return openai;
}
export async function chatWithTranscript(transcriptText, streamId) {
const transcript = String(transcriptText || '').trim();
if (!transcript) {
throw new ProviderControlError(
'empty_input',
'OpenAI request has no transcript text.',
'Wait for a non-empty RTMS transcript event before calling the provider.'
);
}
const input = `Transcript:\n\n${transcript}`;
const reservation = controls.reserve(
streamId,
`${SYSTEM_INSTRUCTIONS}\n${input}`,
openAIConfig.maxOutputTokens
);
try {
const response = await getClient().responses.create({
model: openAIConfig.model,
instructions: SYSTEM_INSTRUCTIONS,
input,
max_output_tokens: openAIConfig.maxOutputTokens
});
controls.complete(reservation, {
inputTokens: response.usage?.input_tokens,
outputTokens: response.usage?.output_tokens
});
return response.output_text || '(no text response)';
} catch (error) {
controls.fail(reservation);
throw error;
}
}
export function clearOpenAIStream(streamId) {
controls.clearStream(streamId);
}