Learning Quest - 공부공부

Vector Embeddings

포스 삼촌 2026. 7. 24. 23:28
-- =====================================================================
-- 10. Vector Embeddings & Semantic Search
-- =====================================================================
-- 시험 도메인: 벡터 임베딩 생성, 저장, 유사도 검색, Cortex Search 활용
-- RAG 파이프라인의 기반 기술 → Search/Agent와 연결되는 핵심
-- =====================================================================

-- =============================================================
-- 1. VECTOR 데이터 타입 ★DDL 암기★
-- =============================================================

-- 구문: VECTOR( <element_type>, <dimension> )
-- element_type: INT (8-bit signed integer) 또는 FLOAT (32-bit floating point)
-- dimension: 벡터 차원 수 (모델에 따라 다름)
    

-- [1-1] 테이블 생성
CREATE OR REPLACE TABLE FORCE_DB.SH26.my_schema.embeddings (
    id INT AUTOINCREMENT,
    text_content VARCHAR,
    embedding VECTOR(FLOAT, 768),       -- 768차원 float 벡터 . 반드시 타입 + 차원  개를 명시
    created_at TIMESTAMP_LTZ DEFAULT CURRENT_TIMESTAMP()
);

기본 DDL 구문이야. 벡터 컬럼은 일반 컬럼과 섞어 쓸 수 있어. 

 

-- [1-2] 다양한 차원의 벡터 컬럼
CREATE OR REPLACE TABLE FORCE_DB.SH26.multi_embeddings (
    id INT,
    text_content VARCHAR,
    embed_768  VECTOR(FLOAT, 768),      -- snowflake-arctic-embed-m
    embed_1024 VECTOR(FLOAT, 1024),     -- snowflake-arctic-embed-l-v2.0
    embed_int  VECTOR(INT, 768)         -- INT 타입 (양자화된 임베딩)
);

그리고 차원 수는 모델에 맞춰야 해.

 

만약에 컬럼은 768 차원으로 생성했는데, 모델이 1024 차원을 출력하므로 아래 명령은 오류가 나.

embedding VECTOR(FLOAT, 768)  -- 컬럼은 768
INSERT ... AI_EMBED('snowflake-arctic-embed-l-v2.0', text)  -- 모델은 1024 출력

 → 안 됨! 차원 불일치

 

-- ★ 핵심 규칙:
-- • 같은 테이블/연산에서 비교하는 벡터는 반드시 같은 차원이어야 함
-- • FLOAT와 INT 혼합 불가
-- • NULL 허용
-- • 인덱싱 가능 (ORDER BY, TOP-K 검색)

 

INT 벡터 = 양자화(Quantization)된 임베딩

일반적으로 임베딩은 FLOAT(32-bit)로 생성되지만, 저장/연산 효율을 위해 INT(8-bit)로 양자화할  있습니다.

FLOAT vs INT 비교:

FLOATINT
정밀도 32-bit 부동소수점 8-bit 정수 (-128~127)
저장 크기 768차원 = ~3KB 768차원 = ~768B (1/4)
정확도 높음 약간 손실
용도 일반적 (기본) 대규모 데이터, 비용 절감

시험 핵심 규칙 (60~64행):

  1. 같은 차원  VECTOR(FLOAT, 768) vs VECTOR(FLOAT, 1024) 비교  에러
  2. 같은 타입  VECTOR(FLOAT, 768) vs VECTOR(INT, 768) 비교  에러
  3. NULL 허용  임베딩이 아직 없는 행도 저장 가능
  4. ORDER BY 직접 불가  ORDER BY embedding  됨, 유사도 함수 결과로 정렬해야 

시험 함정:

text
Q: FLOAT 768차원과 INT 768차원 벡터의 코사인 유사도를 구하면?
A: 에러! 차원이 같아도 타입이 다르면 연산 불가

 

ORDER BY embedding  이렇게 벡터 컬럼을 직접 정렬하는   됩니다. 벡터는 다차원 데이터라 "크다/작다"의 기준이 없으니까요.

대신 유사도 함수 결과로 정렬하는  됩니다:

sql
ORDER BY VECTOR_COSINE_SIMILARITY(embedding, query_vec) DESC  -- 이건 OK
ORDER BY VECTOR_L2_DISTANCE(embedding, query_vec) ASC         -- 이것도 OK

유사도 함수가 반환하는  스칼라 값(FLOAT)이니까 정렬 가능한 겁니다.

시험 요약:

  • ORDER BY vector_column  불가
  • ORDER BY similarity_function(vector_column, ...)  가능 (Top-K 검색의 핵심 패턴)

 


-- =============================================================
-- 2. AI_EMBED — 텍스트/이미지 → 벡터 변환
-- =============================================================

-- 구문: AI_EMBED( <model>, <input> )   2개 인자
-- 반환: VECTOR 타입  (모델에 따라 768 또는 1024 차원)

 

 

-- [2-1] 텍스트 임베딩
SELECT AI_EMBED('snowflake-arctic-embed-m-v1.5', 'Snowflake data warehouse') AS vec;
[0.021374,0.032750,0.089970,0.030724,0.048971,0.058565,-0.014179,0.049781,0.006053,-0.018393,-0.030919,-0.003638,0.033803,0.055453,0.018571,0.014746,0.039119,0.020921,0.068838,-0.028310,0.031405,0.000520,0.081997,0.012162,0.012121,-0.023254,-0.010104,-0.060412,-0.049133,0.024469,-0.092174,0.022282,0.014398,0.038503,0.019624,0.096127,-0.088155,0.063880,-0.012551,-0.078172,-0.002394,-0.093924,-0.030319,0.085756,-0.023189,-0.057106,-0.257334,0.087182,0.002670,0.011773,-0.054448,0.092498,-0.033933,0.024648,0.026106,0.052050,-0.002323,-0.051305,-0.061319,-0.018149,0.042554,-0.001552,0.028018,-0.033706,0.064496,-0.047740,0.046865,0.026139,-0.040804,-0.015727,0.025588,-0.026139,-0.051175,0.002840,0.007308,-0.036882,-0.002627,0.007657,0.083682,0.086210,0.016010,0.033512,0.060801,0.059861,0.027970,-0.031632,0.049490,-0.077006,-0.014114,0.092887,-0.052342,-0.083034,0.067607,-0.008410,-0.052115,-0.059342,0.065695,0.058338,0.065079,0.022881,-0.056555,0.007754,0.035392,-0.001145,0.014690,-0.007045,-0.003389,-0.063588,-0.031454,-0.004473,-0.004173,0.012818,-0.008815,0.055875,-0.034290,0.069098,-0.014690,0.010468,0.014042,0.009950,0.049944,0.072792,0.019851,0.010136,0.029217,-0.025215,0.019413,0.016237,-0.063491,-0.041647,-0.010963,-0.007620,0.000488,0.000643,0.011060,-0.050138,-0.033998,0.012899,0.035197,-0.017858,-0.055615,0.079534,-0.009593,0.079339,0.035392,0.027905,-0.068190,-0.008273,-0.000916,0.061092,-0.033415,0.016407,-0.067088,-0.094896,-0.012113,0.072533,-0.009148,-0.047091,-0.085173,0.003571,-0.007398,0.055324,0.005741,-0.032102,0.072728,0.004209,0.014236,-0.008370,0.013410,-0.047578,-0.011538,-0.036558,0.030692,0.080441,-0.061481,0.039378,0.062486,0.076033,0.021909,0.020013,-0.030514,0.007159,-0.082645,0.016586,0.013004,-0.037336,0.034646,-0.042003,0.052407,0.031292,-0.056847,-0.108508,0.067153,-0.036623,0.012688,-0.038762,-0.022687,0.102480,0.025020,0.072663,0.000398,0.006198,0.046152,-0.016075,-0.001334,0.054740,0.064852,-0.011740,-0.006251,-0.018328,-0.030238,-0.119333,0.040383,-0.056620,0.002919,-0.036007,-0.047091,0.036850,0.028553,-0.041387,0.166068,0.030384,-0.007892,-0.003115,-0.036980,0.041711,0.101637,0.005809,0.045763,-0.062583,-0.014917,-0.008751,0.019657,0.043591,0.085432,-0.005656,-0.011886,0.022282,0.060412,-0.002338,0.019041,0.025101,0.043494,0.004768,-0.021812,-0.062681,0.049911,0.001040,-0.042424,-0.016999,-0.013677,0.011862,-0.031940,-0.023659,0.054060,0.019559,-0.012551,-0.017436,-0.025425,0.035521,0.025361,-0.002453,0.021925,-0.072663,0.038017,-0.009836,-0.008179,0.005692,-0.008824,0.028748,0.003966,-0.030546,0.016821,0.009715,-0.018490,-0.008256,0.051110,-0.025523,-0.032669,-0.031924,0.042360,-0.010355,0.025750,-0.003401,0.021601,-0.014746,0.017825,-0.016399,0.004910,0.023076,-0.003144,0.000901,-0.011465,-0.053379,0.057754,0.001851,-0.022509,0.035716,-0.006944,0.022201,-0.008499,0.004655,-0.033009,-0.027921,-0.043526,0.028666,-0.001833,0.002805,-0.139362,-0.046346,-0.001839,0.000840,-0.019106,-0.024939,0.031470,0.005352,-0.020726,0.012786,0.029606,-0.002027,0.029234,0.002094,0.008589,0.019851,0.011287,0.013053,0.015062,0.013215,-0.010574,0.044952,-0.030060,0.014941,-0.012697,0.013993,0.036299,0.038049,0.025523,-0.009520,-0.052828,0.021342,-0.026641,-0.002891,-0.005311,-0.008086,0.000202,-0.015743,0.024712,0.013628,0.022541,0.007685,0.032070,-0.008580,-0.012137,0.008232,-0.026706,0.001522,0.033090,-0.030222,-0.013296,-0.002980,0.006389,0.021585,-0.014641,0.003628,-0.042781,0.011416,0.032491,0.019268,-0.030174,-0.013029,0.044466,-0.016464,-0.067088,0.030125,-0.004477,0.018846,-0.021326,0.038859,0.007341,0.011052,-0.021698,0.021812,-0.018619,0.030789,-0.007037,0.001810,0.070135,0.019495,-0.024210,0.000290,0.023627,-0.031729,-0.005603,0.016610,0.021520,0.025685,-0.001287,0.027451,-0.013085,-0.040545,0.030319,0.015354,-0.024437,0.006259,0.026511,-0.025490,-0.026074,-0.011668,0.026025,-0.019122,-0.020677,-0.011141,-0.002358,-0.006413,-0.026868,-0.029655,-0.007337,0.009131,0.029282,-0.001477,0.037012,-0.055324,-0.011424,0.025620,-0.008556,-0.033577,-0.049814,0.042036,-0.056750,-0.004041,-0.037044,-0.015265,-0.035651,0.005623,-0.004286,0.013815,0.001940,0.004037,0.001664,-0.031600,0.027646,-0.007916,0.030255,-0.007248,-0.022784,0.048906,-0.002123,-0.062000,0.008856,0.024372,0.025296,-0.032199,0.021342,-0.001995,-0.047059,-0.006077,-0.010047,0.037595,0.013717,-0.036947,-0.012680,0.029963,0.048906,-0.016804,0.033706,-0.001259,-0.012291,0.039508,-0.019122,-0.064107,-0.021277,0.008905,0.010395,-0.008653,0.008645,-0.015694,0.032005,0.065792,0.001267,-0.010217,0.015338,0.003839,0.030579,0.051175,0.017566,-0.022590,0.018052,0.006267,-0.052277,0.036785,-0.021553,0.015395,-0.023530,0.028521,0.010047,0.044499,-0.012381,0.052698,-0.003136,-0.019041,-0.027597,-0.053638,-0.021666,0.000335,0.011441,-0.007393,-0.025863,-0.009569,0.017031,0.028083,0.020661,-0.022962,0.042198,0.035165,0.002182,-0.004841,0.023999,-0.037174,-0.000404,0.010590,-0.035910,0.014933,-0.001474,-0.068903,-0.022735,0.027937,-0.008905,0.020921,-0.011538,0.009853,0.003557,0.011959,0.027629,-0.036818,-0.037919,0.016359,-0.035942,0.062032,0.001659,-0.032734,-0.000458,0.026122,0.033285,0.013248,-0.052569,0.042878,0.032296,-0.001508,-0.041420,-0.012008,-0.004963,-0.032653,-0.033171,-0.001034,0.035618,-0.001076,0.023951,0.026414,-0.027289,-0.027694,0.044952,-0.016019,0.012462,-0.015840,0.021147,-0.025425,-0.007896,-0.025652,0.015913,-0.040123,0.020159,0.056490,-0.030708,0.041420,0.007045,-0.000925,0.016529,0.049328,0.020953,0.025069,-0.008265,-0.026268,-0.008597,-0.026868,0.042684,0.082126,-0.048031,0.059731,-0.027662,0.017809,0.011157,0.009618,-0.021941,0.033317,0.029639,0.007649,0.013410,0.036169,-0.004959,0.011773,-0.036267,-0.004100,-0.045633,-0.014981,0.030562,-0.023837,0.050365,-0.017696,0.040156,0.049198,-0.008978,0.008244,-0.020856,0.038568,-0.014560,-0.030643,0.042813,-0.002218,0.069811,0.049587,0.019284,-0.013904,0.013547,-0.058759,0.034678,-0.048161,-0.014325,-0.008370,0.011514,-0.035780,-0.012056,0.053379,-0.015946,-0.042036,0.030530,0.029849,-0.043818,-0.046994,0.006231,0.006502,0.002913,-0.031762,-0.011044,-0.000380,-0.004951,0.035035,-0.007442,-0.002785,-0.027824,0.002423,-0.024858,-0.004825,-0.006458,0.026997,-0.032102,-0.042198,-0.029947,0.040901,0.003735,0.028034,0.000956,0.012146,-0.028569,-0.025782,-0.017680,-0.015233,0.039734,-0.029234,0.012559,0.019527,-0.003334,-0.030076,-0.031178,-0.035586,-0.031729,0.001609,0.012113,-0.034549,-0.038762,-0.020159,-0.010023,0.007191,-0.030449,0.013418,0.013264,-0.008418,-0.010201,-0.021536,0.035100,0.006316,0.010647,-0.011554,0.038892,-0.006008,-0.036396,0.004424,0.002295,0.034257,-0.017307,-0.047642,0.001123,-0.060963,-0.009601,-0.023367,-0.053379,-0.015954,0.025490,0.001609,-0.014163,0.003926,0.052083,0.014860,0.035716,0.023967,0.009350,-0.007863,-0.007357,-0.005445,0.011108,0.021471,-0.014771,-0.013774,0.026868,-0.021471,0.004094,0.037855,0.025490,-0.000860,-0.045698,-0.022687,0.005793,-0.013515,0.032394,0.009723,-0.007657,-0.006603,0.003389,-0.032394,-0.031405,-0.010898,-0.005396,0.024113,0.009699,0.011368,-0.030498,-0.023513,0.004013,0.018490,-0.040447,-0.019851,0.016902,0.000962,-0.031421,-0.062778,0.009480,-0.022444,-0.045017,-0.014568,-0.006158,0.023303,-0.031438,0.036299,-0.002629,0.044823,0.028585,0.009277,0.025879,0.001520]

이런 모습으로 보이는 걸 알 수 있어요. 이 길~게 나오는 숫자 배열이 벡터란다.

 

 


-- [2-2] 이미지 임베딩 (멀티모달 모델)
-- SELECT AI_EMBED('snowflake-arctic-embed-m-v1.5', TO_FILE('@my_stage', 'photo.jpg'));

이미지일 경우 TO_FILE로 감싸서 AI_EMBED 함수로 벡터화할 수 있어요.

 

 

시험 핵심:

  1. 구문: AI_EMBED(모델명, 입력)   2개 인자
  2. 반환: VECTOR 타입 (모델에 따라 768 또는 1024 차원)
  3. 입력 종류:
    • 텍스트  문자열 그대로
    • 이미지  TO_FILE('@stage', 'file.jpg')  감싸야 
  4. 비용: 입력 토큰만 과금 (출력은 벡터라 토큰 아님)

 

-- [2-3] 테이블에 임베딩 저장
-- INSERT INTO FORCE_DB.SH26.TMP_embeddings (text_content, embedding)
-- SELECT
--     content,
--     AI_EMBED('snowflake-arctic-embed-m-v1.5', content)
-- FROM my_db.my_schema.raw_documents;

 

실전 패턴 (2-3, 2-4):

  • INSERT로 임베딩 저장  AI_EMBED() 결과를 VECTOR 컬럼에 넣기

 


-- [2-4] 배치 업데이트 (기존 테이블에 임베딩 컬럼 추가)
-- ALTER TABLE my_db.my_schema.documents ADD COLUMN embedding VECTOR(FLOAT, 768);
-- UPDATE my_db.my_schema.documents
-- SET embedding = AI_EMBED('snowflake-arctic-embed-m-v1.5', content)
-- WHERE embedding IS NULL;

 

실전 패턴 (2-3, 2-4):

  • ALTER TABLE + UPDATE  기존 테이블에 임베딩 컬럼 추가  채우기
  • WHERE embedding IS NULL  아직  만든 행만 처리 (증분 패턴)

 

시험 함정:

text
Q: AI_EMBED의 출력 차원을 지정할 수 있는가?
A: 없다! 모델이 결정한다. 모델 선택 = 차원 선택

 

 

-- =============================================================
-- 3. 임베딩 모델 비교 ★시험 암기★
-- =============================================================

-- ┌────────────────────────────────────┬──────┬──────────┬───────────────────────────┐
-- │ 모델                               │ 차원 │ 토큰 한도│ 특징                       │
-- ├────────────────────────────────────┼──────┼──────────┼───────────────────────────┤
-- │ e5-base-v2                         │ 768  │ 512      │ 영어 전용, 기본             │
-- │ snowflake-arctic-embed-m           │ 768  │ 512      │ MTEB 상위, 영어 특화       │
-- │ snowflake-arctic-embed-m-v1.5      │ 768  │ 512      │ 멀티모달 (텍스트+이미지)   │
-- │ snowflake-arctic-embed-l-v2.0      │ 1024 │ 512      │ 고품질, 대형              │
-- │ snowflake-arctic-embed-l-v2.0-8k   │ 1024 │ 8192     │ 긴 문서용 (8K 토큰!)      │
-- │ nv-embed-qa-4                      │ 1024 │ 512      │ Q&A 특화                  │
-- │ multilingual-e5-large              │ 1024 │ 512      │ 100+ 언어 지원            │
-- │ voyage-multilingual-2              │ 1024 │ 32000    │ 초장문, 다국어            │
-- └────────────────────────────────────┴──────┴──────────┴───────────────────────────┘

 

모델 선택 공식 (이것만 외우세요):

상황모델차원
한국어/다국어 multilingual-e5-large 1024
초장문 + 다국어 voyage-multilingual-2 1024 (32K 토큰!)
이미지+텍스트 멀티모달 snowflake-arctic-embed-m-v1.5 768
 문서 (영어) snowflake-arctic-embed-l-v2.0-8k 1024 (8K 토큰)
범용 기본 추천 snowflake-arctic-embed-m-v1.5 768
Q&A 특화 nv-embed-qa-4 1024

시험 핵심 구분법:

  • 768차원 = m (medium) 계열, -v1.5
  • 1024차원 = l (large) 계열, -v2.0
  • 토큰 한도 대부분 512  예외: 8k(8192), voyage(32000)

레거시 함수 (117~119행):

  • EMBED_TEXT_768(), EMBED_TEXT_1024()  폐기 예정
  • 시험에서 "권장되는 함수는?"  AI_EMBED


-- ★ 시험 포인트:
-- • 한국어 → multilingual-e5-large 또는 voyage-multilingual-2
-- • 이미지 → snowflake-arctic-embed-m-v1.5
-- • 긴 문서 → snowflake-arctic-embed-l-v2.0-8k (8K 토큰)
-- • 기본 추천 → snowflake-arctic-embed-m-v1.5 (범용, 멀티모달)

-- [레거시 함수]
-- EMBED_TEXT_768()  → 768차원 (폐기 예정 → AI_EMBED 사용)
-- EMBED_TEXT_1024() → 1024차원 (폐기 예정 → AI_EMBED 사용)

 

시험 함정:

text
Q: snowflake-arctic-embed-m-v1.5로 이미지 임베딩이 가능한가?
A: 가능! (유일한 멀티모달 모델)

Q: multilingual-e5-large로 이미지 처리가 가능한가?
A: 불가! (텍스트 전용)

다음 섹션 준비되면 말씀해주세요. 섹션 4(AI_MULTI_EMBED)는 Preview 기능이라 가볍게 넘기고, 섹션 5(유사도 함수)가 시험 비중 높습니다.

 

-- =============================================================
-- 4. AI_MULTI_EMBED — 멀티모달 벡터 생성 ★Preview★
-- =============================================================

-- 비디오/이미지에서 프레임별 임베딩 생성 (시맨틱 비디오 검색용)
-- SELECT AI_MULTI_EMBED(
--     'snowflake-arctic-embed-m-v1.5',
--     TO_FILE('@my_stage', 'video.mp4'),
--     {'mode': 'visual', 'frames_per_second': 1}
-- );
-- 반환: 벡터 배열 (프레임별 1개)

 

핵심은 비디오/이미지에서 프레임별로 여러 벡터를 한번에 생성한다는 점입니다.

AI_EMBED vs AI_MULTI_EMBED:

AI_EMBEDAI_MULTI_EMBED
입력 텍스트 1개 또는 이미지 1개 비디오/이미지
출력 벡터 1개 벡터 배열 (프레임별)
용도 일반 임베딩 시맨틱 비디오 검색

동작 방식:

  • 비디오를 초당 N프레임으로 잘라서   프레임마다 벡터 생성
  • frames_per_second: 1  1초에 1개 프레임 추출  10초 영상이면 벡터 10개

 


-- =============================================================
-- 5. 유사도 함수 ★시험 핵심 암기
-- =============================================================

-- ┌──────────────────────────────┬───────────────┬───────────────────────────────────┐
-- │ 함수                         │ 반환 범위     │ 용도                               │
-- ├──────────────────────────────┼───────────────┼───────────────────────────────────┤
-- │ VECTOR_COSINE_SIMILARITY     │ -1 ~ 1        │ 방향 유사성 (가장 범용)            │
-- │ VECTOR_INNER_PRODUCT         │ -∞ ~ +∞       │ 정규화된 벡터에서 속도 최적         │
-- │ VECTOR_L2_DISTANCE           │ 0 ~ +∞        │ 유클리드 거리 (작을수록 유사)      │
-- │ VECTOR_L1_DISTANCE           │ 0 ~ +∞        │ 맨해튼 거리 (작을수록 유사)        │
-- └──────────────────────────────┴───────────────┴───────────────────────────────────┘

-- ★ COSINE: 값이 클수록 유사 (1 = 동일 방향)
-- ★ L2/L1: 값이 작을수록 유사 (0 = 동일 벡터)
-- ★ INNER_PRODUCT: 정규화된 벡터에서 COSINE과 동일 효과

 

4가지 함수  핵심 암기법:

함수해석정렬
VECTOR_COSINE_SIMILARITY 방향이 같으면 1 DESC (클수록 유사)
VECTOR_INNER_PRODUCT 내적  DESC (클수록 유사)
VECTOR_L2_DISTANCE 유클리드 거리 ASC (작을수록 유사)
VECTOR_L1_DISTANCE 맨해튼 거리 ASC (작을수록 유사)

시험 핵심  ORDER BY 방향:

  • "유사도" (similarity, product)  DESC
  • "거리" (distance)  ASC
  • 이거 헷갈려서 틀리는 문제 많음!

COSINE vs INNER_PRODUCT:

  • 벡터가 정규화(L2 norm = 1)되어 있으면    같은 결과
  • INNER_PRODUCT가 연산  빠름 (곱셈만 하면 되니까)
  • 정규화   벡터  COSINE이 안전

비용 포인트:

  •  4개 함수 모두 토큰 과금 없음! (순수 수학 연산, compute 비용만)
  • AI_EMBED로 미리 저장해두면 검색할  추가 AI 비용 제로
-- [5-1] 코사인 유사도 (가장 많이 사용)
SELECT
    a.VOC_ID AS id_a,
    b.VOC_ID AS id_b,
    VECTOR_COSINE_SIMILARITY(a.embedding, b.embedding) AS similarity
FROM  FORCE_DB.SH26.T_BRANCH1_VOC  a
CROSS JOIN  FORCE_DB.SH26.T_BRANCH1_VOC  b
WHERE a.VOC_ID < b.VOC_ID
ORDER BY similarity DESC
LIMIT 10;

<!--br {mso-data-placement:same-cell;}-->

ID_A ID_B, SIMILARITY

4 5 0.9838916659
3 5 0.98235947
1 5 0.9783238173
3 4 0.975489141
2 4 0.9738644361
1 3 0.9729813949
1 4 0.9712173343
2 3 0.9638251684
2 5 0.9635627866
1 2 0.9575369954

이렇게 각 데이터간의 코사인 유사도를 확인해볼 수 있어요.

VECTOR_COSINE_SIMILARITY 범위: -1 ~ 1

값의미
1 완전히 같은 방향 (의미적으로 동일)
0 전혀 관련 없음 (직교)
-1 완전히 반대 방향

주의: 1이라고 해서 "텍스트가 글자 그대로 같다"는 아닙니다. 의미적 방향 같다 뜻입니다.

 

 

 

-- [5-2] 유클리드 거리
SELECT
    VECTOR_L2_DISTANCE(
        [1.0, 2.0, 3.0]::VECTOR(FLOAT, 3),
        [4.0, 5.0, 6.0]::VECTOR(FLOAT, 3)
    ) AS l2_dist;
-- 예: 5.196 (작을수록 가까움)

 

반환 결과: 5.196152423 (거리! 니까.작을 수록 가깝다.

 

 

-- [5-3] 내적 INNER_PRODUCT
SELECT
    VECTOR_INNER_PRODUCT(
        [1.0, 2.0, 3.0]::VECTOR(FLOAT, 3),
        [4.0, 5.0, 6.0]::VECTOR(FLOAT, 3)
    ) AS inner_prod;
-- 예: 32.0 (클수록 유사)

 

반환 결과:  32

아, 살짝 다릅니다!

  • 적분(積分) = Integration (쌓을  + 나눌 분)
  • 내적(內積) = Inner Product (안  + 쌓을/곱할 적)

같은 한자 '積'이긴 한데, 수학에서 쓰임이 다릅니다:

  • Product = 곱셈 (두 벡터의 원소끼리 곱해서 더하기)
  • Integration = 적분 (면적을 쌓아 누적)

Inner Product(내적)은 그냥 "원소끼리 곱해서  더한 것":

text
[1, 2, 3] · [4, 5, 6] = 1×4 + 2×5 + 3×6 = 32

172행 실행하면 정확히 32 나올 겁니다. 미적분보다 훨씬 단순한 연산이

 


 

 

-- =============================================================
-- 6. Semantic Search 패턴 (Top-K 검색) ★실전 핵심★
-- =============================================================

-- [6-1] 기본 Top-K 유사도 검색
-- "질문과 가장 유사한 문서 5개를 찾아라"
SELECT
    VOC_ID,
    CUST_CONTENTS,
    VECTOR_COSINE_SIMILARITY(
        embedding,
        AI_EMBED('snowflake-arctic-embed-m-v1.5', '샤워실에 불만인 회원은?')
    ) AS similarity
FROM FORCE_DB.SH26.T_BRANCH1_VOC
ORDER BY similarity DESC
LIMIT 5;

지금 실행한 쿼리 구조 분석:

text
AI_EMBED(모델, '질문') → 질문을 벡터로 변환
VECTOR_COSINE_SIMILARITY(저장된 벡터, 질문 벡터) → 유사도 계산
ORDER BY DESC LIMIT 5 → 가장 유사한 5개 반환

시험 암기 패턴:

  1. 저장된 임베딩 vs 실시간 질문 임베딩 비교
  2. ORDER BY similarity DESC (코사인은 클수록 유사!)
  3. LIMIT N = Top-K

비용 관점:

  • embedding 컬럼  이미 저장되어 있으므로 비용 없음
  • AI_EMBED('...', '샤워실에 불만인 회원은?')   질문 1번만 토큰 과금
  • VECTOR_COSINE_SIMILARITY  과금 없음 (수학 연산)

 5행 비교하든 500만  비교하든 AI_EMBED 비용은 질문 1번분뿐입니다. 이게 "임베딩을 미리 저장하는 이유"이고, 섹션 12 비용 포인트의 핵심!!

 

 

VOC 데이터가  비슷한 주제(고객 상담, 불만, 문의)일 테니 코사인유사도(1 만점)가 모두 0.95 이상인 건 당연한 결과입니다.

 

이게 실무에서 중요한 포인트입니다:

같은 도메인 내의 문서들은 유사도가 전반적으로 높게 나옵니다. 그래서:

  • 일반 문서 검색  0.7 임계값이면 충분
  • 같은 도메인  세밀한 구분  0.9 이상에서도 순위(Top-K)로 구분해야 

시험 관점에서 기억할 것:

  • Top-K 패턴(ORDER BY similarity DESC LIMIT 5)이 임계값보다 실용적인 이유가 바로 이것
  • 모든 문서가 0.95+ 나와도 상대적 순위 여전히 유의미함

지금 결과에서 1등과 5등의 점수 차이가 0.01~0.02 정도일 텐데, 그래도 1등이 가장 관련 높은 VOC입니다.

 

1등으로 나온 데이터는 유사도 = 0.8951120502

실제 상담 내용은 아래와 같아

고객: 저기요, 여기 샤워실 환기 안 되나요? 들어갈 때마다 꿉꿉한 냄새랑 곰팡이 냄새가 너무 심해요.나연: 아, 서윤님 죄송합니다. 저희가 매일 청소는 하고 있는데 워낙 이용객이 몰리는 시간대라...고객: 청소 문제가 아니라 구조 문제 같아요. 배수구도 자주 막히는 것 같고, 습기가 안 빠지니까 씻고 나와도 개운하질 않네요. 당분간 쉬어야겠어요.

 

 

Cortex Search도 내부적으로 같은 원리입니다.

공통 원리:

  1. 소스 데이터를 미리 임베딩  저장 (인덱싱)
  2. 검색  질문만 실시간 임베딩 (비용 1회)
  3. 저장된 벡터와 비교 (수학 연산, AI 비용 없음)

DIY vs Cortex Search 차이:

지금 한 방식 (DIY)Cortex Search
임베딩 생성 직접 AI_EMBED + UPDATE 자동 (서비스가 알아서)
인덱스 없음 (Full Scan) ANN 인덱스 자동 생성
검색 속도   많으면 느림 수백만 행도 빠름
업데이트 직접 WHERE IS NULL TARGET_LAG로 자동 증분
하이브리드 검색 직접 구현 키워드+벡터+리랭킹 내장
적합 규모 수천~수만  수십만~수백만 

시험 판단 기준:

  • "소규모, 간단한 유사도 비교"  DIY (지금  방식)
  • "대규모, 프로덕션, 실시간 검색"  Cortex Search Service

결국 Cortex Search는 지금 직접  작업(임베딩 저장 + 코사인 비교)을 관리형 서비스로 자동화 

-- [6-2] 임계값 기반 필터링
SELECT *
FROM FORCE_DB.SH26.T_BRANCH1_VOC
WHERE VECTOR_COSINE_SIMILARITY(
    embedding,
    AI_EMBED('snowflake-arctic-embed-m-v1.5', '샤워실에 불만인 회원은?')
) > 0.89  -- 유사도 0.7 이상만
ORDER BY VECTOR_COSINE_SIMILARITY(embedding,
    AI_EMBED('snowflake-arctic-embed-m-v1.5', '샤워실에 불만인 회원은?')) DESC;

실무 접근법:

  1. 먼저 Top-K로 결과를 보면서 유사도 분포 파악
  2. "관련 있다/없다" 경계가 어디쯤인지 눈으로 확인
  3.  기준으로 임계값 설정

아까  것처럼:

  • 같은 도메인(VOC) 내부  전부 0.95+  임계값 0.7은 무의미
  • 서로 다른 도메인 혼합  0.3~0.9 분포  0.7이 유효

시험 관점에서는:

  • 임계값 패턴의 구문(WHERE > 0.7)을 아는지가 포인트
  • 실제 값이 뭐가 적절한지는 시험에  나옴
  • "Top-K vs 임계값   쓰는가?"  대부분 Top-K가 실용적 (임계값은 보조 필터)

섹션 6-3 하이브리드 검색도 같은 맥락:

-- [6-3] 하이브리드 검색 (벡터 + 메타데이터 필터)
-- SELECT
--     VOC_ID,
    CUST_CONTENTS,
--     VECTOR_COSINE_SIMILARITY(embedding,
--         AI_EMBED('snowflake-arctic-embed-m-v1.5', 'cloud cost optimization')) AS score
-- FROM FORCE_DB.SH26.T_BRANCH1_VOC
-- WHERE category = 'Engineering'           -- 메타데이터 필터
--   AND created_at >= '2024-01-01'         -- 시간 필터
-- ORDER BY score DESC
-- LIMIT 10;
sql
WHERE category = 'Engineering'      -- 먼저 메타데이터로 범위 축소
  AND created_at >= '2024-01-01'    -- 시간 필터
ORDER BY score DESC LIMIT 10        -- 그 안에서 Top-K

벡터 검색만으로 부족할   메타데이터 필터 + 벡터 유사도 조합. 이게 섹션 11에서 나오는 "클러스터링 키로 간접 최적화"와도 연결됩니다.

 

결국 검색이니, 메타데이터 필터를 적용하고 그다음에 벡터 유사도를 조합해서 가장 가까운 결과를 찾는다. 이거군.

정확합니다. 그게 하이브리드 검색의 핵심 로직입니다.

순서: 필터 먼저  벡터 비교는 좁혀진 범위에서

이게 성능에도 직결됩니다:

  • 100만  전체를 벡터 비교  느림
  • WHERE로 1만 행으로 축소   안에서 벡터 비교  빠름

시험에서  패턴이 나오는 맥락:

  • 섹션 11의 "클러스터링 키로 간접 최적화" = 같은 원리
  • Cortex Search의 ATTRIBUTES =  메타데이터 필터를 서비스 레벨에서 지원하는 

-- =============================================================
-- 7. AI_SIMILARITY — 간편 유사도 (모델 내장)
-- =============================================================

-- 구문: AI_SIMILARITY( <input1>, <input2> )
-- 내부적으로 AI_EMBED + COSINE SIMILARITY 수행
-- ★ 편리하지만 매 호출마다 임베딩 생성 → 배치에는 비효율

 

SELECT AI_SIMILARITY(
    'machine learning model training',
    'artificial intelligence algorithm optimization'
) AS score;

-- 예: 0.3215544415

   요약:

  • AI_SIMILARITY(텍스트A, 텍스트B) = 내부적으로 AI_EMBED(A) + AI_EMBED(B) + COSINE 한번에 처리

시험 비교:

AI_SIMILARITYAI_EMBED + VECTOR_COSINE
코드량 1줄 여러 
비용 매번 임베딩 2회 저장  추가 비용 없음
용도 ad-hoc 1회성 비교 프로덕션 반복 검색

시험 함정:

text
Q: 프로덕션에서 수백만 행을 매번 AI_SIMILARITY로 검색하면?
A: 비효율! 매 행마다 임베딩 생성 → 비용 폭발. AI_EMBED로 미리 저장해야 함.

 

-- 텍스트 vs 이미지 유사도
-- SELECT AI_SIMILARITY(
--     'a red sports car',
--     TO_FILE('@my_stage', 'car_photo.jpg')
-- );

-- ★ AI_SIMILARITY vs 수동 COSINE:
-- AI_SIMILARITY → 간편, 매번 임베딩 생성 (ad-hoc용)
-- AI_EMBED + VECTOR_COSINE → 임베딩 저장 후 반복 검색 (프로덕션용)

 


-- =============================================================
-- 8. 벡터 변환 & 조작 함수
-- =============================================================

-- [배열 ↔ 벡터 변환]
-- 배열 → 벡터
	SELECT [1.0, 2.0, 3.0]::VECTOR(FLOAT, 3);                           

-- 벡터 → 배열
	SELECT [1.0, 2.0, 3.0]::VECTOR(FLOAT, 3)::ARRAY(FLOAT);     -- 타입 캐스팅 가능! ::

-- [벡터 차원 확인]
SELECT VECTOR_DIMENSION([1.0, 2.0, 3.0]::VECTOR(FLOAT, 3)) AS dims;  -- 3

 

-- [벡터 정규화] (L2 norm = 1로 만들기)
-- SELECT VECTOR_NORM_L2(my_vector) AS norm;  -- L2 크기 확인

-- ★ 시험 포인트:
-- • ARRAY → VECTOR 변환 시 차원 수 일치해야 함
-- • 다른 차원의 벡터끼리 비교 → 에러!

시험 포인트 3개만 기억:

  1. ARRAY  VECTOR 상호 변환 가능  ::VECTOR(FLOAT, N) / ::ARRAY(FLOAT)
  2. 변환  차원  일치 필수  배열 원소 5개인데 VECTOR(FLOAT, 3) 캐스팅  에러
  3. JSON 직렬화  VECTOR를 JSON으로 내보내려면 먼저 ARRAY로 변환  처리

실무 쓰임:

  • 외부 시스템에서 임베딩을 배열로 받아옴  VECTOR로 캐스팅해서 저장
  • Snowflake 벡터를 외부로 내보낼   ARRAY로 변환  JSON 처리

-- =============================================================
-- 9. RAG 파이프라인 (Vector 직접 관리 vs Cortex Search)
-- =============================================================

-- ┌───────────────────────────┬──────────────────────────────────────────────────┐
-- │ 방법                      │ 특징                                              │
-- ├───────────────────────────┼──────────────────────────────────────────────────┤
-- │ 직접 관리                 │ VECTOR 컬럼 + AI_EMBED + ORDER BY COSINE         │
-- │ (DIY Vector Search)       │ 유연하지만 인덱스 없으면 Full Scan               │
-- │                           │ 소규모 데이터(수만 행)에 적합                    │
-- ├───────────────────────────┼──────────────────────────────────────────────────┤
-- │ Cortex Search Service     │ 자동 인덱싱, 하이브리드 검색, 리랭킹             │
-- │ (Managed Vector Search)   │ 대규모 데이터에 적합 (수백만 행)                 │
-- │                           │ PRIMARY KEY로 증분 업데이트                       │
-- │                           │ Filter, Scoring, Diversity 기능 내장             │
-- └───────────────────────────┴──────────────────────────────────────────────────┘

-- ★ 시험 시나리오:
-- "수십만 건 이상의 문서에서 실시간 검색" → Cortex Search
-- "수천 건의 내부 데이터에서 간단한 유사도 비교" → DIY Vector

 

 아키텍처 이해 + 시험 판단 문제 영역입니다.

 

-- [9-1] DIY RAG 파이프라인
-- Step 1: 문서 임베딩 생성 & 저장
-- CREATE TABLE knowledge_base AS
-- SELECT
--     doc_id,
--     content,
--     AI_EMBED('snowflake-arctic-embed-m-v1.5', content) AS embedding
-- FROM raw_documents;

-- Step 2: 검색 함수 생성
-- CREATE OR REPLACE FUNCTION search_knowledge(query_text VARCHAR, top_k INT)
-- RETURNS TABLE (doc_id INT, content VARCHAR, score FLOAT)
-- AS
-- $$
--     SELECT doc_id, content,
--         VECTOR_COSINE_SIMILARITY(embedding,
--             AI_EMBED('snowflake-arctic-embed-m-v1.5', query_text)) AS score
--     FROM knowledge_base
--     ORDER BY score DESC
--     LIMIT top_k
-- $$;

-- Step 3: RAG (검색 + 생성)
-- WITH context AS (
--     SELECT LISTAGG(content, '\n\n') AS retrieved_docs
--     FROM TABLE(search_knowledge('What is data mesh?', 3))
-- )
-- SELECT AI_COMPLETE(
--     'claude-sonnet-4-6',
--     PROMPT('Answer based on these documents: {0}\n\nQuestion: {1}',
--         (SELECT retrieved_docs FROM context),
--         'What is data mesh?')
-- ) AS rag_response;

Step 1: AI_EMBED로 문서 임베딩 저장 (knowledge_base 테이블)
Step 2: 검색 함수 생성 (COSINE + ORDER BY + LIMIT)
Step 3: 검색 결과를 AI_COMPLETE에 컨텍스트로 넘겨서 답변 생성

이게 바로 RAG = Retrieval(검색) + Augmented(보강) + Generation(생성)

 

시험 판단 기준  이거만 외우세요:

조건선택
수천~수만 , 간단한 구조 DIY Vector
수십만~수백만  Cortex Search
자동 증분 업데이트 필요 Cortex Search (TARGET_LAG)
ANN 인덱스 필요 (속도) Cortex Search
하이브리드(키워드+벡터+리랭킹) Cortex Search
완전한 커스텀 제어 DIY Vector

 

시험 함정:

text
Q: DIY 벡터 검색에서 ANN(근사 최근접) 인덱스를 만들 수 있는가?
A: 없다! Snowflake는 현재 벡터 전용 ANN 인덱스 미제공.
   대규모엔 Cortex Search를 써야 함.

 

DIY RAG = "내가 모든  직접 제어한다"

DIY RAG의 장점:

  • 임베딩 모델 자유 선택
  • 검색 로직 커스텀 (가중치, 필터, 점수 계산 등)
  • AI_COMPLETE에 넘기는 프롬프트도 완전 제어
  • 비용 구조 투명 (뭐에 얼마 드는지 정확히 파악)

대신 대가:

  • 인덱스 없어서 대규모에서 느림
  • 증분 업데이트 직접 관리 (WHERE embedding IS NULL)
  • 리랭킹, 다양성 제어   직접 구현해야 

시험에서의 포지션:

text
Cortex Search = "관리형, 편하고 빠름, 대규모"
DIY Vector    = "직접 제어, 유연, 소규모"

아까 직접 해본 VOC 테이블 검색이 바로 DIY RAG의 Step 1~2였고, 거기에 AI_COMPLETE만 붙이면 Step 3까지 완성입니다.

 

 

 


-- =============================================================
-- 10. Multi-Index Cortex Search와의 연동
-- =============================================================

-- Cortex Search의 VECTOR INDEXES는 사전 생성된 벡터 컬럼을 활용
-- → AI_EMBED로 미리 벡터를 만들어두면 Search가 그걸 인덱싱

-- [소스 테이블에 벡터 컬럼 준비]
-- CREATE TABLE enriched_docs AS
-- SELECT
--     doc_id,
--     title,
--     body,
--     AI_EMBED('snowflake-arctic-embed-m-v1.5', title) AS title_vec,
--     AI_EMBED('snowflake-arctic-embed-l-v2.0', body) AS body_vec,
--     category
-- FROM raw_docs;

-- [Multi-Index Search Service 생성]
-- CREATE CORTEX SEARCH SERVICE multi_search_svc
--     TEXT INDEXES title, body
--     VECTOR INDEXES
--         title_vec (MODEL = 'snowflake-arctic-embed-m-v1.5'),
--         body_vec  (MODEL = 'snowflake-arctic-embed-l-v2.0')
--     ATTRIBUTES category
--     WAREHOUSE = WH_ENGINEER
--     TARGET_LAG = '1 hour'
-- AS (SELECT * FROM enriched_docs);

 

섹션 10 (Multi-Index)도 같은 맥락:

  • VECTOR INDEXES에 미리 만든 벡터 컬럼을 지정
  • 서로 다른 모델로 title(768차원), body(1024차원) 따로 인덱싱 가능
  • TEXT INDEXES + VECTOR INDEXES = 멀티 인덱스 하이브리드

Multi-Index Cortex Search는 서치서비스를 만들 때, 내가 미리 임베딩한 벡터 컬럼을 지정해서 만들 수 있다

 

 

일반 Cortex Search:

  • TEXT INDEXES만 지정  서비스가 알아서 임베딩 생성

Multi-Index Cortex Search:

  • TEXT INDEXES + VECTOR INDEXES  내가 미리 만든 벡터 컬럼도 활용
  • 서로 다른 모델/차원으로 만든 벡터를 각각 인덱싱 가능
sql
VECTOR INDEXES
    title_vec (MODEL = 'snowflake-arctic-embed-m-v1.5'),   -- 768차원
    body_vec  (MODEL = 'snowflake-arctic-embed-l-v2.0')    -- 1024차원

 이렇게?

  • title = 짧은 텍스트  가벼운 모델(768)로 충분
  • body =  본문  고품질 대형 모델(1024)이 유리
  • 검색   인덱스에서 독립적으로 매칭   정확한 결과

시험에서 물어본다면:

text
Q: Cortex Search에서 사전 생성된 벡터 컬럼을 활용하려면?
A: VECTOR INDEXES에 컬럼명과 MODEL을 지정

 정도로 넘어가면 됩니다. 섹션 11~12 마무리 갈까요?



-- =============================================================
-- 11. 성능 최적화 ★시험 포인트★
-- =============================================================

3가지만 기억:

  1. Snowflake는 벡터 전용 ANN 인덱스 없음  DIY는 항상 Exact Search (Full Scan)
  2. 클러스터링 키로 간접 최적화  WHERE로 범위 축소  벡터 비교
  3. 임베딩 캐싱  자주 검색하는 질문의 임베딩 캐시 테이블에 저장 (AI_EMBED 동일 입력이라도 매번 비용 발생!)


-- [11-1] 벡터 검색 성능 (현재)
-- • Snowflake는 현재 벡터 전용 인덱스(ANN) 미제공 (Exact Search)
-- • 소규모: 직접 ORDER BY COSINE → OK
-- • 대규모: Cortex Search Service 사용 (ANN 자동 관리)

-- [11-2] 클러스터링 키로 간접 최적화
-- ALTER TABLE knowledge_base CLUSTER BY (category);
-- → WHERE category = 'X'로 먼저 필터링 후 벡터 검색 → 스캔 범위 축소

-- [11-3] 임베딩 캐싱 전략
-- • 자주 검색되는 쿼리의 임베딩을 캐시 테이블에 저장
-- • AI_EMBED는 동일 입력이라도 매번 호출 비용 발생!
-- CREATE TABLE query_embedding_cache (
--     query_text VARCHAR PRIMARY KEY,
--     embedding VECTOR(FLOAT, 768),
--     cached_at TIMESTAMP_LTZ DEFAULT CURRENT_TIMESTAMP()
-- );

 

섹션 12: 비용 포인트

  하나로 끝:

함수과금
AI_EMBED 입력 토큰 과금
AI_SIMILARITY 입력 토큰 × 2 (내부 AI_EMBED 2회)
VECTOR_COSINE_SIMILARITY 과금 없음! (compute만)
VECTOR_L2_DISTANCE 과금 없음!
VECTOR_INNER_PRODUCT 과금 없음!
Cortex Search 인덱싱 + 서빙 비용 (별도)

시험 결론  줄:

임베딩을 미리 저장하고 VECTOR 함수로 비교하면 추가 토큰 비용 없음!

 

섹션 13~14: 제한사항 & 시나리오 (최종 정리)

자주 나오는 시험 함정:

  • 다른 차원 비교  에러
  • FLOAT/INT 혼합  에러
  • ORDER BY vector_column  불가 , → 유사도 함수 결과로 ORDER BY
  • 한국어  multilingual-e5-large
  • 이미지  snowflake-arctic-embed-m-v1.5
  • 대규모 검색  Cortex Search 가 대규모 벡터 검색의 표준 솔루션
  • 비용 절감  AI_EMBED 미리 저장 + VECTOR 함수
  • GROUP BY / DISTINCT에 VECTOR 사용 가능
  • JSON으로 직렬화 가능 (ARRAY로 변환 후)

=============================================================
14. 시험 시나리오 정리
=============================================================

Q: "수백만 문서에서 시맨틱 검색을 하려면?"
A: Cortex Search Service (자동 인덱싱, 하이브리드, 리랭킹)

Q: "두 텍스트의 유사도를 간단히 확인하려면?"
A: AI_SIMILARITY (1줄로 끝)

Q: "프로덕션에서 반복적 유사도 검색 비용을 줄이려면?"
A: AI_EMBED로 미리 저장 → VECTOR_COSINE_SIMILARITY (추가 토큰 비용 없음)

Q: "한국어 문서에 적합한 임베딩 모델은?"
A: multilingual-e5-large 또는 voyage-multilingual-2

Q: "이미지와 텍스트를 같이 검색하려면?"
A: snowflake-arctic-embed-m-v1.5 (멀티모달) + Cortex Search Multi-Index

Q: "임베딩 차원이 다른 벡터를 비교하면?"
A: 에러 발생 (같은 차원이어야 함)

 

핵심 흐름이  정리되셨을 겁니다:

VECTOR 타입  AI_EMBED 저장  유사도 함수 비교  Top-K 검색  (대규모면 Cortex Search)

 

 

 

영문 시험에서 자주 나오는 표현 매핑:

한국어 개념영문 시험 표현
임베딩 미리 저장 pre-compute embeddings
유사도 검색 semantic similarity search
가장 유사한 K개 Top-K nearest neighbors
토큰 과금 없음 no token consumption / compute-only
대규모 벡터 검색 vector search at scale
증분 업데이트 incremental refresh / TARGET_LAG
하이브리드 검색 hybrid search (keyword + vector + reranking)
차원 불일치 에러 dimension mismatch error

시험 준비 팁:

  • Snowflake 공식 문서의 "Vector Data Types" / "Cortex AI Functions" 페이지가 시험 출제 기반
  • 문제에서 "cost-effective", "production workload", "at scale" 같은 키워드가 나오면  미리 저장 + Cortex Search 방향
  • "ad-hoc", "quick comparison", "one-time"  AI_SIMILARITY 방향