54 lines
1.8 KiB
TypeScript
54 lines
1.8 KiB
TypeScript
/**
|
|
* 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<NotifVerdict> => {
|
|
if (!alertText?.trim()) return SAFE_DEFAULT
|
|
const prompt =
|
|
`다음 ITSM 알림이 즉시 대응이 필요한 긴급 알림인지 판단하세요: "${alertText}". ` +
|
|
`JSON으로만 출력: {"urgent": true 또는 false, "reason": "한국어 한 줄 사유"}`
|
|
return generateJSON<NotifVerdict>(DEFAULT_TEXT_MODEL, prompt, SAFE_DEFAULT)
|
|
}, [])
|
|
|
|
/**
|
|
* 알림 배열을 긴급한 것만 남기도록 필터링.
|
|
* getText: 알림 객체에서 판단용 텍스트 추출.
|
|
*/
|
|
const filter = useCallback(
|
|
async <T>(notifs: T[], getText: (n: T) => string): Promise<T[]> => {
|
|
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<boolean> => {
|
|
const v = await judge(alertText)
|
|
return v.urgent
|
|
},
|
|
[judge],
|
|
)
|
|
|
|
return { judge, filter, shouldShow }
|
|
}
|
|
|
|
export default useSmartNotif
|