clinicpal / src /app /api /translate /route.ts
Vrda's picture
Deploy ClinIcPal frontend
9bc2f29 verified
import { NextResponse } from 'next/server';
const MEDGEMMA_BACKEND_URL =
process.env.MEDGEMMA_BACKEND_URL || 'http://localhost:8100';
const MEDGEMMA_API_KEY = process.env.MEDGEMMA_API_KEY || '';
function backendHeaders(): Record<string, string> {
const h: Record<string, string> = { 'Content-Type': 'application/json' };
if (MEDGEMMA_API_KEY) h['x-api-key'] = MEDGEMMA_API_KEY;
return h;
}
interface TranslateRequest {
text: string;
source_lang?: string;
target_lang?: string;
provider?: string; // 'local' | 'vastai'
model_id?: string;
quantize?: string | null;
}
// POST /api/translate — Proxy to the MedGemma backend /api/v1/translate
export async function POST(request: Request) {
try {
const body: TranslateRequest = await request.json();
if (!body.text || body.text.trim().length === 0) {
return NextResponse.json(
{ success: false, error: 'Text to translate is required' },
{ status: 400 }
);
}
const backendResponse = await fetch(
`${MEDGEMMA_BACKEND_URL}/api/v1/translate`,
{
method: 'POST',
headers: backendHeaders(),
body: JSON.stringify({
text: body.text,
source_lang: body.source_lang ?? 'hr',
target_lang: body.target_lang ?? 'en',
provider: body.provider ?? 'local',
model_id: body.model_id ?? 'google/translategemma-12b-it',
quantize: body.quantize ?? null,
}),
// Translation can take a few minutes for long reports
signal: AbortSignal.timeout(600_000), // 10 min
}
);
if (!backendResponse.ok) {
const errorData = await backendResponse.json().catch(() => null);
const errorMessage =
errorData?.detail || `Backend returned ${backendResponse.status}`;
return NextResponse.json(
{ success: false, error: errorMessage },
{ status: backendResponse.status }
);
}
const data = await backendResponse.json();
return NextResponse.json({
success: true,
translated_text: data.translated_text,
source_lang: data.source_lang,
target_lang: data.target_lang,
chunks_count: data.chunks_count,
elapsed_ms: data.elapsed_ms,
model_id: data.model_id,
provider: data.provider,
});
} catch (error) {
const message =
error instanceof Error ? error.message : 'Translation failed';
if (message.includes('timeout') || message.includes('Timeout')) {
return NextResponse.json(
{
success: false,
error:
'Translation timed out. The model may still be loading or the text is very long.',
},
{ status: 504 }
);
}
if (
message.includes('ECONNREFUSED') ||
message.includes('fetch failed') ||
message.includes('connect')
) {
return NextResponse.json(
{
success: false,
error:
'Cannot connect to translation backend. Make sure the MedGemma backend is running on port 8100.',
},
{ status: 503 }
);
}
return NextResponse.json(
{ success: false, error: message },
{ status: 500 }
);
}
}