자~ 나연 대표님, 센터 운영하다 보면 회원님들의 문의나 피드백이 하루에도 수십, 수百 건씩 쌓이지?
이걸 사람이 하나하나 읽으면서 "이건 시설 불만", "이건 결제 문의", "이건 수업 예약" 이렇게 라벨을 붙이려면 정신이 아득해질 거야.
스노우플레이크에는 이런 비정형 텍스트를 알아서 착착 분류하고 정리해 주는 '완전관리형' AI 삼총사(AI_CLASSIFY, AI_FILTER, AI_EXTRACT)가 있단다!
오늘은 그 첫 번째 타자인 AI_CLASSIFY의 완벽 활용법과 정확도를 대폭 끌어올리는 프롬프트 꿀팁(Few-shot)까지 싹 정리해 줄게. 공식 문서(Docs)를 매번 뒤질 필요 없이 이 카드로 뇌에 저장해 버리자!
📌 Snowflake 공식 문서 링크 : Use Case를 확인한 후 알맞는 곳에 사용하는게 좋아요~!
2. AI_CLASSIFY
AI_CLASSIFY( <input> , <list_of_categories> [, <config_object> ] [, <return_error_details> ] )
- label (필수 사항): 카테고리의 이름입니다.
- description (선택 사항): 카테고리를 25단어 이내로 설명합니다.
[2-1] 기본 단일 라벨 분류
SELECT AI_CLASSIFY(
'서버의 응답시간이 300% 증가했습니다.',
['Performance Issue', 'Security Alert', 'Feature Request', 'Bug Report']
);
결과 : {"labels": ["Performance Issue"]}
포스 삼촌의 실무 팁: 분류 대상의 내용이 제시한 카테고리 중 어디에 해당되는 건지 반환해요. 재미난 점은 위 예시처럼 분류 대상 메시지는 '한글'이고 카테고리는 '영어'인데도 별도의 번역 처리 없이 Cortex가 알아서 의미를 해석해서 영어 라벨을 딱 찾아준다! 아주 기특하지?
[2-2] 멀티 라벨 분류 (output_mode: 'multi')
SELECT AI_CLASSIFY(
'더 빠른 쿼리와 더 나은 접근 관리가 필요합니다.',
['Performance', 'Security', 'Cost', 'Usability'],
{'output_mode': 'multi'}
);
반환 결과 : {"labels": ["Performance", "Security"]}
하나의 피드백에 여러가지 이슈가 섞여 있을 땐 아웃풋 모드를 멀티로 설정하면 카테고리에 해당되는 걸 멀티로 출력하네요~^^
[2-3] task_description + label description (정확도 향상)
SELECT AI_CLASSIFY(
'지난 달 청구 금액이 $500이었는데, 이번 달은 $2000으로 급증했습니다.',
[
{'label': 'Cost Anomaly', 'description': 'Unexpected increase in spending'},
{'label': 'Normal Usage', 'description': 'Expected cost fluctuation'},
{'label': 'Billing Error', 'description': 'Incorrect charge or invoice'}
],
{'task_description': 'Classify the support ticket by issue type'}
);
반환 결과 : { "labels": [ "Cost Anomaly" ]}
카테고리 이름만 달랑 주면 AI가 헷갈려할 때가 있지? 그럴 땐 카테고리별 25단어 이내의 설명(description)과 전체 작업에 대한 50단어 이내의 설명(task_description)을 얹어주면 정확도가 대폭 상승해!
단순히 글자를 찾는 게 아니라, "예상치 못한 지출 증가"라는 설명의 맥락을 이해하고 'Cost Anomaly'를 정확히 골라냈어.
[2-4] few-shot examples (예시를 통한 정확도 향상)
SELECT AI_CLASSIFY(
'My warehouse is consuming too many credits', -- 입력값
['Cost', 'Performance', 'Access'], -- 입력값을 이 3가지 카테고리로 분류해라.
{
'task_description': 'Classify Snowflake support issues',
'examples': [ --여기가 few shot을 알려주는 부분
{
'input': 'Query takes 10 minutes to run', --분류할 텍스트 예시
'labels': ['Performance'], -- 입력에 대한 올바른 카테고리 값
'explanation': 'Slow query is a performance issue' -- 입력이 해당 카테고리인 이유를 설명
}
]
}
);
반환 결과 : { "labels": [ "Cost" ] }
예시를 통해 판단 기준을 확실히 세워줬기 때문에, 크레딧 소모 이슈를 'Cost'로 완벽하게 락온(Lock-on)했지!
[2-5] 이미지 분류
SELECT AI_CLASSIFY(
TO_FILE('@FORCE_DB.SH26.STG_NY_IMG', 'sketch2.png'),
['Electronics', 'Clothing', 'Food', 'Furniture','Character']
);
위에 사용된 샘플 이미지는 바로 나연 대표님이 지난 번에 그렸던 2호점 스케치 중 하나야.

반환 결과 : { "labels": [ "Furniture" ] }
이미지를 분류하는 건 생각보다 시간이 좀 더 걸려요.
현재 주어진 카테고리들 중에는 가장 가까워 보이는 퍼니처가 나왔네. 만약에 '평면'에 해당하는 단어인 'Plan'을 추가하면?
SELECT AI_CLASSIFY(
TO_FILE('@FORCE_DB.SH26.STG_NY_IMG', 'sketch2.png'),
['Electronics', 'Clothing', 'Food', 'Furniture','Character','Plan']
);
반환 결과 : { "labels": [ "Plan" ] }
이번 실행은 5.1초가 걸려서 많이 짧아졌는데, 아마 바로 직전에 실행한 쿼리 결과를 참조했을 거야. 그러니 시간은 신경쓰지 말고 이번 결과를 보면 아까 Furniture 보다 더 의미적으로 적절한 분류인 'Plan'으로 반환하는 걸 알 수 있어. WoW!
또 다른 이미지 분류를 해볼까?
SELECT AI_CLASSIFY(
TO_FILE('@FORCE_DB.SH26.STG_NY_IMG', 'ny_victory.png'),
['Electronics', 'Clothing', 'Food', 'Furniture','Character']
);

반환 결과 : { "labels": [ "Character" ] }
예상했다시피 이번 결과는 정확히 캐릭터야. 실행시간은 2.6초. 즉, Snowflake의 완전 관리형 함수는 최적화된 내부 로직을 거쳐서 우리가 설정한 카테고리 중에서 가장 가까운 것으로 분류해낸다는 것이야.
💡 포스 삼촌의 1줄 요약 족보!
- AI_CLASSIFY: 텍스트 | 이미지 | 문서를 원하는 카테고리(단일/멀티)로 정제하여 JSON 라벨로 반환해 주는 지능형 분류기. (task_description과 examples를 쓰면 정확도 떡상!)
AI_FILTER (유해글/스팸/불필요한 데이터 마스킹)
-- =============================================================
-- 3. AI_FILTER — Boolean 반환 (WHERE/JOIN에 활용)
-- =============================================================
-- 구문: AI_FILTER( <input> [, <return_error_details>] )
-- 또는: AI_FILTER( <predicate>, <file> [, <return_error_details>] )
다음, AI_FILTER는 Boolean을 반환해. Boolean은 True or False를 뜻하는 데이터 타입이야.
-- [3-1] 텍스트 필터 (단일 문자열로 질문)
SELECT AI_FILTER('Is South Korea in Asia?');
반환 결과 : TRUE
문자열의 의미를 파악해서 답변하는 것이지.
이 또한 언어 번역은 자동으로 수행한단다.
-- 언어 무관
SELECT AI_FILTER('일본의 수도는 오사카입니다.');
반환 결과 : FALSE
일본의 수도는 도쿄잖니^^. 즉 어느 나라 언어로 문자열이 들어와도 적정 수준의 번역과 맥락은 이해한다는 뜻이야.
-- [3-2] PROMPT()로 컬럼 값 포함
SELECT AI_FILTER(PROMPT('심각한 장애에 해당되나요? {0}', '결제 단계에서 앱이 멈춰버렸어요.'));
반환 결과 : TRUE
PROMPT 함수를 써서 뒷 부분의 문자열을 {0} 치환자로 넣어서 물어보는 경우인데,
결제 단계라는 맥락을 이해하고 심각한 장애(Critical bug)로 리턴하는 거야.
재미난 건 이 AI_FILTER 함수도 이미지에 사용할 수 있단다.
아까 위에서 사용한 나연 대표님의 일러스트를 이용해서 아래와 같이 물어보자~
-- [3-3] 이미지 필터 (predicate + file)
-- SELECT * FROM my_images
-- WHERE AI_FILTER('Does this image contain a person?', img_file);
select AI_FILTER('이 이미지는 캐릭터를 포함하나요?',TO_FILE('@FORCE_DB.SH26.STG_NY_IMG', 'ny_victory.png')); --TRUE
반환 결과 : TRUE
아까 AI_CLASSIFY 함수에서 나연 대표님 이미지를 캐릭터로 분류했잖아. 그래서 이번 질문에는 TRUE를 반환했어.^^
이걸 응용하면 AI_FILTER 함수를 다양한 Join 문에 활용할 수 있단다.
내장된 Adaptive routing 자동 적용되서 2~10x 빠르고, 60% 정도의 토큰을 절감할 수 있다고 해.
만약 나연 대표님이 PRANALINK의 여러 데이터를 자동화된 파이프라인으로 구성한다고 하면, JOIN문에 활용할 수 있는 이런 AI_FILTER함수를 이용하는 것은 전체적인 파이프라인 성능 향상에 꽤 도움이 될 거야.
AI_EXTRACT (긴 문장에서 원하는 키워드/JSON 데이터만 쏙 빼내기)
AI_EXTRACT는 문자열 | 이미지 | 문서에서 정보를 추출하는 함수야.
구문은 다음과 같아. AI_EXTRACT( <input>, <keys> )
input: 문자열, FILE, 또는 PROMPT 객체
keys: 추출할 필드 배열 또는 responseFormat 오브젝트
모델: arctic-extract (128K 컨텍스트, 51.2K 출력)
Arctic은 Snowflake에서 자체적으로 개발한 AI 모델로 알고 있어. 여러 다양한 AI 함수 안에서 최적화되서 돌아가고, LLM으로 지정해서 사용할 수도 있지.
-- [4-1] 텍스트에서 추출
SELECT AI_EXTRACT(
'Invoice #INV-2024-001 from Acme Corp for $5,250.00 dated March 15, 2024',
['invoice_number', 'vendor', 'amount', 'date']
);
반환 결과 :
{
"error": null,
"response": {
"amount": "$5,250.00",
"date": "March 15, 2024",
"invoice_number": "INV-2024-001",
"vendor": "Acme Corp"
}
}
JSON으로 결과를 반환할 때는 위와 같이 error 는 null로 에러가 없다라고 표시하면서 결과를 응답한단다.
주어진 문자열에서 원하는 Key에 해당하는 Value를 추출해준 걸 알 수 있어.
-- [4-2] 문서에서 추출 (FILE 입력)
SELECT AI_EXTRACT(
file => TO_FILE('@FORCE_DB.SH26.STG_NY_PDF', 'PRANALINK_NYST2_Membership_Application.pdf'),
responseFormat => {'회원 성명': 'string','연락처':'string'}
);
-- 위 구문은 오류가 발생할거야. 응답포맷의 value부분이 '추출할 내용을 설명하는 질문'이어야 해.
-- 따라서 다음과 같이 value 란에 자연어 질문/설명을 넣어야 한다.
SELECT AI_EXTRACT(
file => TO_FILE('@FORCE_DB.SH26.STG_NY_PDF', 'PRANALINK_NYST2_Membership_Application.pdf'),
responseFormat => {'회원_성명': '회원의 성명은?', '연락처': '회원의 연락처(전화번호)는?'}
);
반환 결과 :
{
"error": null,
"response": {
"연락처": "010-8765-4321",
"회원_성명": "김유정"
}
}
위 문서를 살짝 살펴보면 정확히 알 수 있겠지? '나연스떼' 회원 가입 신청서야.

즉, pdf 문서의 내용에서 필요한 값을 추출해주는 것이지. 어때, 대단하지?
완전관리형 함수인 AI_EXTRACT는 공식 문서에 명시된 지원 언어 목록에 Korean이 포함되어 있으며, 총 30개 언어를 지원하니까 편하게 사용해도 돼.
Arabic, Bengali, Burmese, Cebuano, Chinese, Czech, Dutch, English, French, German, Hebrew, Hindi, Indonesian, Italian, Japanese, Khmer, Korean, Lao, Malay, Persian, Polish, Portuguese, Russian, Spanish, Tagalog, Thai, Turkish, Urdu, Vietnamese
그.런.데.
나연 대표님이 앞서 사용해 본 AI_COMPLETE를 떠올린다면,
위와 같은 완전관리형 함수 대신에 모든 길로 통하는 AI_COMPLETE 사용하면 어떨까 라는 생각이 들지?
-- [4-3] 아예 AI_COMPLETE를 사용해서 Structured Output (JSON Schema)을 뽑는다면?
SELECT AI_COMPLETE(
'gemini-3.1-pro',
'다음 문서에서 회원 성명, 생년월일, 연락처를 추출해줘.',
TO_FILE('@FORCE_DB.SH26.STG_NY_PDF', 'PRANALINK_NYST2_Membership_Application.pdf')
);
반환결과 : "문서에서 추출한 정보는 다음과 같습니다.\n\n* **회원 성명:** 김유정 (Kim Yu-jeong)\n* **생년월일:** 1992년 11월 14일\n* **연락처:** 010-8765-4321"
위 경우에도 LLM 모델에 따라 뛰어난 성능으로 필요로 하는 결과를 추출할 수 있어.
하지만 원하는 JSON 포맷으로 결과를 반환받기 위해서는 조금 더 정교한 프롬프트를 사용해야 할 수 있고, 프롬프트와 문서의 내용에 따라 비용이 널뛰기 할 수 있으니, 많은 테스트를 거치는게 좋아요 대표님^^
물론 그런 테스트는 이 포스 삼촌에게 맡겨 두시고, 사업 번창을 위해 전략을 구상하셔야쥬!
한편, AI_EXTRACT는 수업 시간표 같은 완전 표형태의 문서에서는 값을 추출하기 어려워하기도 해.
영수증이나 회원 가입 신청서처럼 한 문서에 한 단위의 정보가 있는 소스에서 필요한 Key에 해당하는 value(값)을 추출하는데 적절한 함수이지.
예를 들면,

위와 같은 주간 시간표에서는 원하는 값을 추출하는게 쉽지 않을 수도 있단다.
-- [4-4] 문서에서 AI_EXTRACT 사용하기
SELECT AI_EXTRACT(
TO_FILE('@FORCE_DB.SH26.STG_NY_PDF', 'PRANALINK_NYST2_weekly_schedule.pdf'),
responseFormat => {'카일샘의 수업 이름': 'string'}
);
반환 결과 :
{
"error": null,
"response": {
"카일샘의 수업 이름": "None"
}
}
카일 샘의 수업이 여러곳에 나오기 때문에 적절한 추출을 잘 못한 사례라고 할 수 있지.
따라서, 시간표와 같은 문서에서는 다른 함수를 사용하는게 좋아.
-- 이렇게 파스 함수를 쓰면 좋다.
SELECT AI_PARSE_DOCUMENT(
TO_FILE('@FORCE_DB.SH26.STG_NY_PDF', 'PRANALINK_NYST2_weekly_schedule.pdf'),
{'mode': 'LAYOUT'}
);
여기 반환 결과는 길걸^^?:
{
"content": "[PRANALINK] 나연스떼 2호점 주간 강습\n시간표\n\n- 적용 기간: 2026년 7월 3주차 (월요일 ~ 일요일)\n- 운영 시간: 평일 07:00 ~ 22:00 / 주말 09:00 ~ 18:00\n- 강사 라인업 (4명):\n- 나연 (Nayeon): 센터 대표 및 시그니처 '프라나 플로우' 마스터\n- 카일 (Kyle): 파워풀한 아쉬탕가 및 체형 교정 전문\n- 세라 (Sera): 힐링 테라피 및 인요가, 명상 전문\n- 레오 (Leo): 초보자 입문 빈야사 및 다이어트 요가 전문\n\n☑ 평일 스케줄 (월요일 ~ 금요일)\n\n| 교시 / 시간 | 월요일 (Mon) | 화요일 (Tue) | 수요일 (Wed) | 목요일 (Thu) | 금요일 (Fri) |\n| --- | --- | --- | --- | --- | --- |\n| 1교시 (07:00 - 08:00) | 모닝 프라나 - 강사: 나연 - 난이도: 하 | 새벽 아쉬탕가 - 강사: 카일 - 난이도: 상 | 모닝 프라나 - 강사: 나연 - 난이도: 하 | 새벽 아쉬탕가 - 강사: 카일 - 난이도: 상 | 리프레시 빈야사 - 강사: 레오 - 난이도: 중 |\n| 2교시 (10:00 - 11:10) | 힐링 테라피 - 강사: 세라 - 난이도: 하 | 기초 빈야사 - 강사: 레오 - 난이도: 하 | 인요가 & 명상 - 강사: 세라 - 난이도: 하 | 기초 빈야사 - 강사: 레오 - 난이도: 하 | 힐링 테라피 - 강사: 세라 - 난이도: 하 |\n| 3교시 (14:00 - 15:00) | 개인 PT (교정) - 강사: 카일 - 사전 예약제 | 실버 요가 (시니어) - 강사: 세라 - 난이도: 하 | 개인 PT (교정) - 강사: 카일 - 사전 예약제 | 실버 요가 (시니어) - 강사: 세라 - 난이도: 하 | 인요가 & 릴랙스 - 강사: 나연 - 난이도: 하 |\n| 4교시 (19:00 - 20:10) | 파워 빈야사 - 강사: 레오 - 난이도: 중 | 프라나 플로우 1단 - 강사: 나연 - 난이도: 중 | 파워 빈야사 - 강사: 레오 - 난이도: 중 | 프라나 플로우 2단 - 강사: 나연 - 난이도: 상 | 코어 정렬 요가 - 강사: 카일 - 난이도: 중 |\n| 5교시 (20:40 - 21:50) | 아쉬탕가 인텐시브 - 강사: 카일 - 난이도: 상 | 딥 슬립 명상 - 강사: 세라 - 난이도: 하 | 아쉬탕가 인텐시브 - 강사: 카일 - 난이도: 상 | 딥 슬립 명상 - 강사: 세라 - 난이도: 하 | 주말 맞이 풀 플로우 - 강사: 나연 - 난이도: 중 |\n| --- | --- | --- | --- | --- | --- |\n\n※ 주말 스케줄 (토요일 ~ 일요일)\n\n- 주의사항: 주말 강습은 정규 멤버십 외에 원데이 클래스(One-day Class) 팝업 형식으로 운영됩니다.\n\n| 시간 (Time) | 토요일 (Saturday) | 일요일 (Sunday) |\n| --- | --- | --- |\n| 오전반 (10:00 - 11:30) | 주말 힐링 워크숍 - 강사: 세라 - 주제: 싱잉볼 사운드 배스 & 명상 - 난이도: 하 | 선라이즈 인텐시브 - 강사: 카일 - 주제: 아쉬탕가 풀 프라이머리 시리즈 - 난이도: 상 |\n| 오후반 (15:00 - 16:30) | 마스터 클래스 - 강사: 나연 - 주제: 프라나링크 스페셜 플로우 - 난이도: 중~상 | 센터 정기 방역 및 대청소 - [휴강] 강의실 전체 유지보수 수행 - 스튜디오 출입 제한 |",
"metadata": {
"pageCount": 2
}
}
그것도 아니면 모든 길로 통하는 함수를 사용하는게 나을 수도 있어^^
SELECT AI_COMPLETE(
'gemini-3.1-pro',
'다음 문서에서 카일샘이 담당하는 수업 이름을 모두 알려줘.',
TO_FILE('@FORCE_DB.SH26.STG_NY_PDF', 'PRANALINK_NYST2_weekly_schedule.pdf')
);
반환 결과: "제공된 시간표에서 카일 강사님이 담당하는 수업은 다음과 같습니다.\n\n* **새벽 아쉬탕가** (화/목 1교시)\n* **개인 PT (교정)** (월/수 3교시)\n* **코어 정렬 요가** (금 4교시)\n* **아쉬탕가 인텐시브** (월/수 5교시)\n* **선라이즈 인텐시브** (일요일 오전반)"
하지만, AI_COMPLETE를 사용할 때는 정확히 원하는 결과 포맷에 대해서 세심한 프롬프트 엔지니어링이 필요하단다.
이것도 다음에 기회가 되면 한번 리포트할테니~ 나연 대표님은 내일 강좌를 준비하고 얼른 주무세요~~
오늘은 여기까지~
'Main Quest - Snowflake > [시리즈] Cortex AI Functions' 카테고리의 다른 글
| [Cortex_AI_7] 글로벌 VOC 파이프라인 (0) | 2026.07.21 |
|---|---|
| [Cortex_AI_6] RAG의 시작: AI_EMBED vs AI_SIMILARITY (0) | 2026.07.21 |
| [Cortex_AI_4] 문서 파싱 시합 AI_PARSE_DOCUMENT VS AI_COMPLETE (0) | 2026.07.17 |
| [Cortex_AI_3] 오디오 파일 STT: AI_TRANSCRIBE vs AI_COMPLETE (0) | 2026.07.17 |
| [Cortex_AI_2] 감성분석: 완전관리형 VS 프롬프트 엔지니어링 (0) | 2026.07.17 |