This commit is contained in:
juanmaldini7 committed 2026-09-30 23:03:14 -03:00
1 parent 89fc33d954
commit 41a4303244
3 files changed
+10 -20

No files matched your search

-3
View File
@@ -1,5 +1,2 @@
DISCORD_TOKEN= DISCORD_TOKEN=
GEMINI_API_KEY= GEMINI_API_KEY=
GEMINI_MODEL=
# Opcional: se usa si GEMINI_MODEL sigue saturado después de los reintentos
GEMINI_FALLBACK_MODEL=
+7 -14
View File
@@ -11,8 +11,7 @@ import type { AudioTrack } from './recorder.js';
import { buildPrompt } from './prompt.js'; import { buildPrompt } from './prompt.js';
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY }); const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
export const MODEL = process.env.GEMINI_MODEL!; export const MODEL = 'gemini-3.5-flash-lite';
export const FALLBACK_MODEL = process.env.GEMINI_FALLBACK_MODEL;
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
@@ -26,29 +25,23 @@ async function upload(track: AudioTrack): Promise<File> {
return file; return file;
} }
// 429/500/503 suelen ser picos de demanda: reintenta y, si hay GEMINI_FALLBACK_MODEL, prueba con ese // Los errores temporales de Gemini pueden resolverse con reintentos del mismo modelo.
const RETRY_DELAYS = [5_000, 15_000, 30_000]; const RETRY_DELAYS = [2_000, 4_000, 8_000, 16_000, 32_000];
async function generateWithRetry(contents: Content) { async function generateWithRetry(contents: Content) {
const models = [MODEL, FALLBACK_MODEL].filter((m): m is string => !!m); for (let attempt = 0; ; attempt++) {
let lastErr: unknown;
for (const model of models) {
for (let attempt = 0; attempt <= RETRY_DELAYS.length; attempt++) {
try { try {
return await ai.models.generateContent({ model, contents }); return await ai.models.generateContent({ model: MODEL, contents });
} catch (err) { } catch (err) {
lastErr = err;
const status = err instanceof ApiError ? err.status : 0; const status = err instanceof ApiError ? err.status : 0;
if (![429, 500, 503].includes(status)) throw err; if (![429, 500, 503].includes(status)) throw err;
const delay = RETRY_DELAYS[attempt]; const delay = RETRY_DELAYS[attempt];
if (delay === undefined) break; if (delay === undefined) throw err;
console.warn(`${model} respondió ${status}, reintento en ${delay / 1000}s`); console.warn(`${MODEL} respondió ${status}; reintento ${attempt + 1}/${RETRY_DELAYS.length} en ${delay / 1000}s`);
await sleep(delay); await sleep(delay);
} }
} }
} }
throw lastErr;
}
export async function generateNotes(tracks: AudioTrack[], startedAt: Date): Promise<string> { export async function generateNotes(tracks: AudioTrack[], startedAt: Date): Promise<string> {
const files: File[] = []; const files: File[] = [];
+3 -3
View File
@@ -9,9 +9,9 @@ import {
} from 'discord.js'; } from 'discord.js';
import { VoiceConnectionStatus, entersState } from '@discordjs/voice'; import { VoiceConnectionStatus, entersState } from '@discordjs/voice';
import { Recording } from './recorder.js'; import { Recording } from './recorder.js';
import { FALLBACK_MODEL, MODEL, generateNotes } from './gemini.js'; import { MODEL, generateNotes } from './gemini.js';
for (const key of ['DISCORD_TOKEN', 'GEMINI_API_KEY', 'GEMINI_MODEL']) { for (const key of ['DISCORD_TOKEN', 'GEMINI_API_KEY']) {
if (!process.env[key]) throw new Error(`Falta la variable de entorno ${key}`); if (!process.env[key]) throw new Error(`Falta la variable de entorno ${key}`);
} }
@@ -62,7 +62,7 @@ async function autoFinish(guildId: string, reason: string) {
client.once(Events.ClientReady, async (c) => { client.once(Events.ClientReady, async (c) => {
await c.application.commands.set(commands.map((cmd) => cmd.toJSON())); await c.application.commands.set(commands.map((cmd) => cmd.toJSON()));
console.log(`ready as ${c.user.tag} | modelo: ${MODEL} | respaldo: ${FALLBACK_MODEL ?? '(ninguno)'}`); console.log(`ready as ${c.user.tag} | modelo único: ${MODEL} | reintentos activos`);
}); });
client.on(Events.InteractionCreate, async (interaction) => { client.on(Events.InteractionCreate, async (interaction) => {