| name | validating-cards |
| description | USE THIS SKILL for card content validation โ fact-checking, freshness, similarity,
context consistency, or anything about duplicate detection and card quality.
Triggers: "ํฉํธ ์ฒดํฌ ๊ฒฐ๊ณผ๊ฐ", "์ ์ฌํ ์นด๋ ์ฐพ์์ค", "๋ฌธ๋งฅ ๊ฒ์ฆ",
"๊ฒ์ฆ ์บ์", "์ต์ ์ฑ ๊ฒ์ฌ", "์ค๋ณต ์นด๋", "๊ฒ์ฆ ์ํ ์์ด์ฝ",
"validate/all", "Jaccard", "์๋ฒ ๋ฉ ์ ์ฌ๋", "์ค๋ณต ํ์ ",
"useValidateCard", "useBatchValidate", "๊ฒ์ฆ 4์ข
", "์ผ๊ด ๊ฒ์ฆ",
"context-checker", "fact-checker", "freshness-checker", "similarity-checker",
"findSimilarGroups", "analyzeCardGroup", "๊ฒ์ฆ ํด๋ฐฑ".
Covers the 4 validation types: fact-check, freshness, similarity, context.
|
์นด๋ ๊ฒ์ฆ
๊ฒ์ฆ 4์ข
๊ฐ์
| ๊ฒ์ฆ | ํ์ผ | API | ๋ฐฉ์ |
|---|
| ํฉํธ ์ฒดํฌ | fact-checker.ts | POST /api/clinic/fact-check | LLM ๊ธฐ๋ฐ (Gemini/OpenAI) |
| ์ต์ ์ฑ | freshness-checker.ts | POST /api/clinic/freshness | LLM ๊ธฐ๋ฐ (Gemini/OpenAI) |
| ์ ์ฌ์ฑ | similarity-checker.ts | POST /api/clinic/similarity | Jaccard ๋๋ ์๋ฒ ๋ฉ |
| ๋ฌธ๋งฅ ์ผ๊ด์ฑ | context-checker.ts | POST /api/clinic/context | LLM ๊ธฐ๋ฐ (Gemini/OpenAI, nid ๋งํฌ ๊ทธ๋ฃน) |
์ ์ฒด ๊ฒ์ฆ: POST /api/clinic/all โ ๋ชจ๋ ๊ฒ์ฌ๋ฅผ ๋ณ๋ ฌ ์คํ
๋ชจ๋ธ ์ ํ (LLM ๊ธฐ๋ฐ ๊ฒ์ฆ๋ง ํด๋น): ํฉํธ ์ฒดํฌ, ์ต์ ์ฑ, ๋ฌธ๋งฅ ์ผ๊ด์ฑ API์ provider/model ํ๋ผ๋ฏธํฐ ์ง์ ๊ฐ๋ฅ (๋ฏธ์ง์ ์ ์๋ฒ ๊ธฐ๋ณธ๊ฐ, resolveModelId() ์ฐธ์กฐ). ์ ์ฌ์ฑ ๊ฒ์ฌ๋ LLM์ ์ฌ์ฉํ์ง ์์ผ๋ฏ๋ก provider/model ํ๋ผ๋ฏธํฐ๊ฐ ์๋ค.
์ ์ฌ์ฑ ๊ฒ์ฌ: Jaccard vs ์๋ฒ ๋ฉ
| ๋น๊ต | Jaccard | ์๋ฒ ๋ฉ |
|---|
| ๋ฐฉ์ | ๋จ์ด ์งํฉ + 2-gram | OpenAI ์๋ฏธ ๋ฒกํฐ (text-embedding-3-large, 3072์ฐจ์) |
| ์๋ | ๋น ๋ฆ (๋ก์ปฌ) | ๋๋ฆผ (API ํธ์ถ) |
| ์ ํ๋ | ํ๋ฉด์ ์ ์ฌ๋ | ์๋ฏธ์ ์ ์ฌ๋ |
| ๊ธฐ๋ณธ threshold | 70% | 85% |
| ์ค๋ณต ํ์ ์๊ณ๊ฐ | 90% ์ด์ | 95% ์ด์ |
useEmbedding: true ์ต์
์ผ๋ก ์๋ฒ ๋ฉ ๋ชจ๋ ํ์ฑํ โ managing-embeddings ์คํฌ ์ฐธ์กฐ
- ์๋ฒ ๋ฉ ์คํจ ์ ์๋์ผ๋ก Jaccard ํด๋ฐฑ (์๋ฌ ๋ก๊ทธ ์ถ๋ ฅ ํ Jaccard๋ก ์ฌ์๋)
- clinic/all์ ํญ์ Jaccard๋ง ์ฌ์ฉ (๊ธฐ๋ณธ๊ฐ
useEmbedding: false๋ก ํธ์ถ)
- ์๋ฒ ๋ฉ ๋ชจ๋๋
/api/clinic/similarity์์ ๋ช
์์ ์ผ๋ก useEmbedding: true ์์ฒญํ ๋๋ง ํ์ฑํ
๋ฑ ์ ์ฒด ์ ์ฌ ์นด๋ ๊ทธ๋ฃน ํ์ง
const groups = await findSimilarGroups(cards, { threshold: 70 });
๋ฌธ๋งฅ ์ผ๊ด์ฑ ๊ฒ์ฌ
- nid ๋งํฌ๋ก ์ฐ๊ฒฐ๋ ์นด๋ ๊ทธ๋ฃน ๋ถ์
- ์ญ๋ฐฉํฅ ๋งํฌ ๊ฒ์ (๋ค๋ฅธ ์นด๋๊ฐ ์ด ์นด๋๋ฅผ ์ฐธ์กฐํ๋ ๊ฒฝ์ฐ)
- LLM ๊ธฐ๋ฐ ๋
ผ๋ฆฌ์ ์ฐ๊ฒฐ ํ์ธ (Gemini/OpenAI)
analyzeCardGroup(cards, options) โ ์นด๋ ๊ทธ๋ฃน ์ ์ฒด์ ์ผ๊ด์ฑ ๋ถ์ (๊ฐ ์นด๋๋ณ checkContext ์์ฐจ ์คํ, ์ ์ฒด ์ผ๊ด์ฑ ์ ์ ํฉ์ฐ)
ํ๋ก ํธ์๋ ํ
(packages/web/src/hooks/useValidationCache.ts)
const { mutate } = useValidateCard(deckName);
mutate(noteId);
const { mutate: batchMutate } = useBatchValidate(deckName);
batchMutate(noteIds);
const { getValidation, setValidation, clearValidation, clearAllValidations,
getValidationStatuses, uncachedCount, cacheSize } = useValidationCache();
๊ฒ์ฆ ์บ์ฑ
- ์ ์ฅ์: localStorage +
useSyncExternalStore
- TTL: 24์๊ฐ
- ์ ์ญ ์ํ ๊ณต์ : ๊ฐ ์ปดํฌ๋ํธ์์ ๋ณ๋ React ์ํ ์์ฑํ๋ฉด ๋๊ธฐํ ์ ๋จ โ
useSyncExternalStore ํ์
let globalCache: ValidationCache = loadCacheFromStorage();
const listeners = new Set<() => void>();
export function useValidationCache() {
const cache = useSyncExternalStore(subscribe, getSnapshot);
}
CardBrowser ๊ฒ์ฆ ์ํ
- ๊ฒ์ฆ ๊ฒฐ๊ณผ ์์ด์ฝ: (ํต๊ณผ) / (๊ฒฝ๊ณ ) / (์คํจ) / (๋ฏธ๊ฒ์ฆ)
- ํํฐ ์ต์
: ์ ์ฒด, ๋ถํ ๊ฐ๋ฅ, ๋ฏธ๊ฒ์ฆ, ๊ฒํ ํ์
์์ฃผ ๋ฐ์ํ๋ ๋ฌธ์
- ์บ์ ๋ฏธ๋๊ธฐํ:
useValidationCache๋ฅผ useSyncExternalStore๋ก ๊ตฌํํด์ผ ์ปดํฌ๋ํธ ๊ฐ ๊ณต์ ๊ฐ๋ฅ
- ๊ฒ์ฆ ๊ฒฐ๊ณผ ๋ฏธ๋ฐ์: ๊ฒ์ฆ ์ฑ๊ณต ํ CardBrowser ์ํ๊ฐ ์ ๋ฐ๋๋ฉด ์ ์ญ ์บ์ ํ์ธ
- ์๋ฒ ๋ฉ ํด๋ฐฑ: OPENAI_API_KEY ๋ฏธ์ค์ ์ด๋ API ์ฅ์ ์ ์๋ฒ ๋ฉ ๋ชจ๋๊ฐ Jaccard๋ก ์๋ ํด๋ฐฑ
- validate/all์ Jaccard ์ ์ฉ: validate/all์์ ์ ์ฌ์ฑ ๊ฒ์ฌ ์
useEmbedding ์ต์
์ ์ ๋ฌํ์ง ์์ผ๋ฏ๋ก ํญ์ Jaccard ์ฌ์ฉ
์์ธ ์ฐธ์กฐ
references/validators.md โ 4์ข
๊ฒ์ฆ๊ธฐ ์์ธ (์์ฒญ/์๋ต ํ์)
references/caching.md โ localStorage + useSyncExternalStore ํจํด
references/troubleshooting.md โ ๊ฒ์ฆ ๊ด๋ จ ์ด์