mailbox/backend/services/geminiService.js

140 lines
3.6 KiB
JavaScript
Raw Normal View History

2025-12-16 08:18:15 +09:00
/**
* Gemini 번역 서비스
* @google/genai SDK를 사용한 이메일 번역
*/
const SystemConfig = require("../models/SystemConfig");
const GeminiModel = require("../models/GeminiModel");
/**
* DB에서 활성화된 Gemini 모델 목록 조회
*/
const listModels = async () => {
try {
const models = await GeminiModel.findAll({
where: { isActive: true },
order: [["sortOrder", "ASC"]],
attributes: ["modelId", "name", "description"],
});
return models.map((m) => ({
id: m.modelId,
name: m.name,
description: m.description || "",
}));
} catch (error) {
console.error("Gemini 모델 목록 조회 오류:", error);
// 폴백: 기본 모델 반환
return [
{ id: "gemini-2.5-flash", name: "Gemini 2.5 Flash", description: "" },
];
}
};
/**
* Gemini API로 텍스트 번역
* @param {string} text - 번역할 텍스트
* @param {string} targetLang - 대상 언어 (ko, en, ja, zh )
* @param {string} apiKey - Gemini API
* @param {string} model - 사용할 모델 ID
*/
const translateText = async (text, targetLang, apiKey, model) => {
if (!apiKey) {
throw new Error("Gemini API 키가 설정되지 않았습니다.");
}
const langNames = {
ko: "한국어",
en: "영어",
ja: "일본어",
zh: "중국어",
es: "스페인어",
fr: "프랑스어",
de: "독일어",
ru: "러시아어",
pt: "포르투갈어",
it: "이탈리아어",
};
const targetLangName = langNames[targetLang] || targetLang;
const selectedModel = model || "gemini-2.5-flash";
// ES Module 동적 import
const { GoogleGenAI } = await import("@google/genai");
// Google GenAI SDK 초기화
const ai = new GoogleGenAI({ apiKey });
// HTML 태그 보존하면서 번역하도록 프롬프트 작성
const prompt = `다음 이메일 내용을 ${targetLangName}로 번역해주세요. HTML 태그가 있다면 그대로 유지하고 텍스트만 번역해주세요. 번역만 출력하고 다른 설명은 하지 마세요.
${text}`;
try {
const response = await ai.models.generateContent({
model: selectedModel,
contents: prompt,
});
const translatedText = response.text;
if (!translatedText) {
throw new Error("번역 결과를 가져올 수 없습니다.");
}
return translatedText;
} catch (error) {
console.error("Gemini 번역 오류:", error);
throw new Error(error.message || "번역 중 오류가 발생했습니다.");
}
};
/**
* Gemini 설정 조회 (DB에서 모델 목록 가져오기)
*/
const getGeminiConfig = async () => {
const apiKeyRecord = await SystemConfig.findOne({
where: { key: "gemini_api_key" },
});
const modelRecord = await SystemConfig.findOne({
where: { key: "gemini_model" },
});
// DB에서 모델 목록 조회
const models = await listModels();
return {
gemini_api_key: apiKeyRecord?.value || "",
gemini_model: modelRecord?.value || "gemini-2.5-flash",
models,
};
};
/**
* Gemini 설정 저장
*/
const saveGeminiConfig = async (config) => {
// API 키가 마스킹된 값이 아닐 때만 저장 (********로 시작하지 않을 때)
if (
config.gemini_api_key !== undefined &&
!config.gemini_api_key.includes("*")
) {
await SystemConfig.upsert({
key: "gemini_api_key",
value: config.gemini_api_key,
});
}
if (config.gemini_model !== undefined) {
await SystemConfig.upsert({
key: "gemini_model",
value: config.gemini_model,
});
}
};
module.exports = {
translateText,
getGeminiConfig,
saveGeminiConfig,
listModels,
};