/** * useSmartNotif (#28) — AI 스마트 알림 필터링 훅 * * 알림 수신 시 Ollama로 긴급도 판단 → urgent=false면 묵음 처리. * 반환된 filter() 함수로 알림 큐를 필터링/표시 제어. * * 보안: 온프레미스 Ollama만 사용. 알림 본문에 자격증명 미포함 가정. */ import { useCallback } from 'react' import { generateJSON, DEFAULT_TEXT_MODEL } from '../lib/ollama' interface NotifVerdict { urgent: boolean reason: string } const SAFE_DEFAULT: NotifVerdict = { urgent: true, reason: 'AI 판단 불가 — 기본 표시' } export function useSmartNotif() { /** 단일 알림 긴급도 판단. Ollama 미가동 시 안전하게 urgent=true. */ const judge = useCallback(async (alertText: string): Promise => { if (!alertText?.trim()) return SAFE_DEFAULT const prompt = `다음 ITSM 알림이 즉시 대응이 필요한 긴급 알림인지 판단하세요: "${alertText}". ` + `JSON으로만 출력: {"urgent": true 또는 false, "reason": "한국어 한 줄 사유"}` return generateJSON(DEFAULT_TEXT_MODEL, prompt, SAFE_DEFAULT) }, []) /** * 알림 배열을 긴급한 것만 남기도록 필터링. * getText: 알림 객체에서 판단용 텍스트 추출. */ const filter = useCallback( async (notifs: T[], getText: (n: T) => string): Promise => { const verdicts = await Promise.all(notifs.map(n => judge(getText(n)))) return notifs.filter((_, i) => verdicts[i].urgent) }, [judge], ) /** 단일 알림 표시 여부 (urgent=false면 묵음). */ const shouldShow = useCallback( async (alertText: string): Promise => { const v = await judge(alertText) return v.urgent }, [judge], ) return { judge, filter, shouldShow } } export default useSmartNotif