๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

MongoDB์—์„œ ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•

Python์œผ๋กœ MongoDB์—์„œ ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์„ธ์š”. ๋ฒกํ„ฐ ์ž„๋ฒ ๋”ฉ์„ ์ƒ์„ฑํ•˜๊ณ , Vector Search ์ธ๋ฑ์Šค๋ฅผ ๋งŒ๋“ค๊ณ , $vectorSearch ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
ยท 9๋ถ„ ์ฝ๊ธฐ

AI์™€ ํƒํ—˜ํ•ด ๋ณด์„ธ์š”

์ด๋Ÿฐ ์ˆœ๊ฐ„์—๋Š” ์ผ๋ฐ˜์ ์ธ ํ…์ŠคํŠธ ๊ฒ€์ƒ‰์ด ํ•œ๊ณ„๋ฅผ ๋“œ๋Ÿฌ๋ƒ…๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

  • ๊ณ ๊ฐ์ง€์› ํฌํ„ธ์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ๋„์›€๋ง ๋ฌธ์„œ์— ์“ฐ์ธ ์ •ํ™•ํ•œ ๋ฌธ๊ตฌ ๋Œ€์‹  "์ „์›์ด ์ผœ์ง€์ง€ ์•Š์Œ"์ด๋ผ๊ณ  ์ž…๋ ฅํ•˜๋ฉด ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ˜ํ™˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ด์ปค๋จธ์Šค ํ”Œ๋žซํผ์—์„œ ์‡ผํ•‘๊ฐ์ด "๊ฒจ์šธ์— ๋”ฐ๋œปํ•œ ๊ฒƒ"์„ ๊ฒ€์ƒ‰ํ•˜๋ฉด ์ œํ’ˆ ์„ค๋ช…์— ๊ทธ ์ •ํ™•ํ•œ ๋‹จ์–ด๊ฐ€ ์—†์–ด ์•„๋ฌด๊ฒƒ๋„ ์ฐพ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.
  • ์ง€์‹ ๋ฒ ์ด์Šค๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋ฌธ์„œ์™€ ๋‹ค๋ฅธ ํ‘œํ˜„์œผ๋กœ ์งˆ๋ฌธํ•˜๋ฉด ์˜ฌ๋ฐ”๋ฅธ ๋ฌธ์„œ๋ฅผ ๋†“์นฉ๋‹ˆ๋‹ค.

์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰์€ ์ด๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ์ •ํ™•ํ•œ ๋‹จ์–ด ์ผ์น˜๊ฐ€ ์•„๋‹ˆ๋ผ, ์ฟผ๋ฆฌ์˜ ์˜๋ฏธ์™€ ์˜๋„๋ฅผ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” Python๊ณผ ๋ฌด๋ฃŒ nomic-embed-text-v1 ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด MongoDB์—์„œ ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

์ฐธ๊ณ : nomic-embed-text-v1์€ ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œํ•˜๋ฉด ์•ฝ 0.27GB์ด๋ฏ€๋กœ, ์ด ํŠœํ† ๋ฆฌ์–ผ์˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— ์ตœ์†Œ 1GB ์ด์ƒ์˜ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ RAM์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. ์ฒ˜์Œ ์‹คํ–‰ ์‹œ ๋ชจ๋ธ์ด Hugging Face์—์„œ ๋‹ค์šด๋กœ๋“œ๋˜๋ฏ€๋กœ ์ธํ„ฐ๋„ท ์—ฐ๊ฒฐ ์†๋„์— ๋”ฐ๋ผ ์‹œ๊ฐ„์ด ๋” ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ดํ›„ ์‹คํ–‰์—์„œ๋Š” ๋กœ์ปฌ ์บ์‹œ์—์„œ ๋ชจ๋ธ์ด ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค. CPU ์ถ”๋ก ์€ GPU ์ถ”๋ก ๋ณด๋‹ค ํ›จ์”ฌ ๋А๋ฆฝ๋‹ˆ๋‹ค. ์ „์šฉ GPU๊ฐ€ ์—†๋Š” ๋จธ์‹ ์—์„œ๋Š” ๋ชจ๋ธ์ด CPU์—์„œ ์‹คํ–‰๋˜์–ด VRAM ๋Œ€์‹  RAM์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์ž„๋ฒ ๋”ฉ ์ƒ์„ฑ์— ์‹œ๊ฐ„์ด ๋” ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ ๋‹ค์Œ์„ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฒกํ„ฐ ์ž„๋ฒ ๋”ฉ์ด ๋ฌด์—‡์ด๋ฉฐ ์˜๋ฏธ๋ฅผ ์–ด๋–ป๊ฒŒ ํ‘œํ˜„ํ•˜๋Š”์ง€
  • MongoDB์—์„œ ์ž„๋ฒ ๋”ฉ์„ ์ƒ์„ฑํ•˜๊ณ  ์ €์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•
  • MongoDB Vector Search ์ธ๋ฑ์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•
  • ์‚ฌ์šฉ์ž ์ฟผ๋ฆฌ๋ฅผ ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•
  • $vectorSearch ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ์„ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ํ•ด์„ํ•˜๋Š” ๋ฐฉ๋ฒ•

์ด ํŠœํ† ๋ฆฌ์–ผ์˜ ๋ชจ๋“  ์ฝ”๋“œ ์ƒ˜ํ”Œ์€ GitHub ์ €์žฅ์†Œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ…์ŠคํŠธ ๊ฒ€์ƒ‰ vs ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰

ํ…์ŠคํŠธ ๊ฒ€์ƒ‰์€ ์ฟผ๋ฆฌ์— ํฌํ•จ๋œ ์ •ํ™•ํ•œ ๋‹จ์–ด๋ฅผ ํฌํ•จํ•˜๋Š” ๋ฌธ์„œ๋ฅผ ๋งค์นญํ•ฉ๋‹ˆ๋‹ค. ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰์€ ์ „ํ˜€ ๋‹ค๋ฅธ ๋‹จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ์ฟผ๋ฆฌ์™€ ๊ฐ™์€ ์˜๋ฏธ๋ฅผ ๋‹ด์€ ๋ฌธ์„œ๋ฅผ ๋งค์นญํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ํ‘œ๋Š” "heart problems"๋ผ๋Š” ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ์— ๋Œ€ํ•ด ๊ฐ ์ ‘๊ทผ ๋ฐฉ์‹์ด ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

๋ฌธ์„œ ํ…์ŠคํŠธํ…์ŠคํŠธ ๊ฒ€์ƒ‰์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰ํ…์ŠคํŠธ ๊ฒ€์ƒ‰์ด ๋ฐ˜ํ™˜ํ•˜๋Š” ์ด์œ 
"...heart problems in adults..."์˜ˆ์˜ˆ์ •ํ™•ํ•œ ๋‹จ์–ด "heart problems"๋ฅผ ํฌํ•จํ•จ
"...cardiac conditions and symptoms..."์•„๋‹ˆ์š”์˜ˆ์ •ํ™•ํ•œ ๋‹จ์–ด "heart problems"๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š์Œ
"...risk factors for heart disease..."์•„๋‹ˆ์š”์˜ˆ์ •ํ™•ํ•œ ๋‹จ์–ด "heart problems"๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š์Œ
"...chest pain and shortness of breath..."์•„๋‹ˆ์š”์˜ˆ์ •ํ™•ํ•œ ๋‹จ์–ด "heart problems"๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š์Œ

์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰ ํ•ต์‹ฌ ๊ฐœ๋…

MongoDB์˜ ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰์—๋Š” ์„ธ ๊ฐ€์ง€ ๊ฐœ๋…์ด ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ์ดํ•ดํ•˜๋ฉด ์ด ํŠœํ† ๋ฆฌ์–ผ์˜ ๊ฐ ๋‹จ๊ณ„๊ฐ€ ์™œ ๊ทธ๋ ‡๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

๋ฒกํ„ฐ ์ž„๋ฒ ๋”ฉ

์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์€ ํ…์ŠคํŠธ๋ฅผ ๋ฒกํ„ฐ๋ผ ๋ถˆ๋ฆฌ๋Š” ๊ณ ์ • ๊ธธ์ด์˜ ์ˆซ์ž ๋ชฉ๋ก์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋ฒกํ„ฐ์˜ ๊ฐ ์ˆซ์ž๋Š” ์˜๋ฏธ์˜ ํ•œ ์ฐจ์›์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์œ ์‚ฌํ•œ ์˜๋ฏธ์˜ ๋‘ ํ…์ŠคํŠธ๋Š” ์ˆ˜์น˜์ ์œผ๋กœ ์„œ๋กœ ๊ฐ€๊นŒ์šด ๋ฒกํ„ฐ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. "cardiac conditions"์™€ "heart problems"๋Š” ๋‹จ์–ด๋ฅผ ๊ณต์œ ํ•˜์ง€ ์•Š๋”๋ผ๋„ ๋ฒกํ„ฐ ๊ณต๊ฐ„์—์„œ๋Š” ์„œ๋กœ ๊ฐ€๊น๊ฒŒ ์œ„์น˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ทผ์ ‘์„ฑ์ด ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

์ด ํŠœํ† ๋ฆฌ์–ผ์€ ๋กœ์ปฌ ๋จธ์‹ ์—์„œ ์™„์ „ํžˆ ์‹คํ–‰๋˜๋Š” ๋ฌด๋ฃŒ ์˜คํ”ˆ ์†Œ์Šค ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ nomic-embed-text-v1์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ฒ˜์Œ ์‹คํ–‰ํ•˜๋ฉด ๋ชจ๋ธ์ด Hugging Face์—์„œ ์ž๋™์œผ๋กœ ๋‹ค์šด๋กœ๋“œ๋˜์–ด ์ดํ›„ ์‹คํ–‰์„ ์œ„ํ•ด ๋กœ์ปฌ์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ์ด ๋ชจ๋ธ์€ ์ž…๋ ฅ๋‹น 768๊ฐœ์˜ ์ˆซ์ž๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๋ฒกํ„ฐ ๊ฒ€์ƒ‰ ์ธ๋ฑ์Šค

๋ฒกํ„ฐ ๊ฒ€์ƒ‰ ์ธ๋ฑ์Šค๋Š” ์–ด๋–ค ํ•„๋“œ์— ์ž„๋ฒ ๋”ฉ์ด ์ €์žฅ๋˜์–ด ์žˆ๋Š”์ง€, ๋ช‡ ์ฐจ์›์ธ์ง€, ๋น„๊ต์— ์–ด๋–ค ์œ ์‚ฌ๋„ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ• ์ง€ MongoDB์— ์•Œ๋ ค์ค๋‹ˆ๋‹ค. ์–ด๋–ค $vectorSearch ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— ๋ฐ˜๋“œ์‹œ ์ด ์ธ๋ฑ์Šค๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

$vectorSearch ์ง‘๊ณ„ ๋‹จ๊ณ„

$vectorSearch๋Š” ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ง‘๊ณ„ ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ ๋ฒกํ„ฐ๋ฅผ ๋ฐ›์•„ ์ธ๋ฑ์‹ฑ๋œ ํ•„๋“œ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ , ์‹œ๋งจํ‹ฑ ์œ ์‚ฌ๋„ ์ˆœ์œผ๋กœ ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ $project ๋“ฑ์˜ ๋‹จ๊ณ„์™€ ํ•จ๊ป˜ ์ฒด์ด๋‹ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ์‹œ์ž‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์‚ฌ์ „ ์ค€๋น„ ์‚ฌํ•ญ

์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ๋‹ค์Œ์„ ์ค€๋น„ํ•˜์„ธ์š”.

  • Python 3.8 ์ด์ƒ ์„ค์น˜
  • M0 (๋ฌด๋ฃŒ ํ‹ฐ์–ด) ํด๋Ÿฌ์Šคํ„ฐ๊ฐ€ ์„ค์ •๋œ MongoDB Atlas ๊ณ„์ •
  • pymongo 4.7 ์ด์ƒ, sentence-transformers, einops Python ํŒจํ‚ค์ง€ ์„ค์น˜
  • Python๊ณผ MongoDB ์ปฌ๋ ‰์…˜์— ๋Œ€ํ•œ ๊ธฐ๋ณธ ์ง€์‹
  • Atlas ์—ฐ๊ฒฐ ๋ฌธ์ž์—ด(Atlas UI์˜ **Database > Connect > Drivers**์—์„œ ํ™•์ธ ๊ฐ€๋Šฅ)
  • ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— Atlas์—์„œ IP ์ฃผ์†Œ๊ฐ€ ํ—ˆ์šฉ๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Atlas UI์˜ **Security > Network Access**๋กœ ์ด๋™ํ•˜์—ฌ ํ˜„์žฌ IP ์ฃผ์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜์„ธ์š”.

ํ”„๋กœ์ ํŠธ ์„ค์ •

ํ”„๋กœ์ ํŠธ์šฉ ํด๋”๋ฅผ ๋งŒ๋“ค๊ณ  ํ„ฐ๋ฏธ๋„์—์„œ ํ•ด๋‹น ํด๋”๋กœ ์ด๋™ํ•˜์„ธ์š”.

mkdir mongodb-semantic-search
cd mongodb-semantic-search

ํ”„๋กœ์ ํŠธ ์ข…์†์„ฑ์„ ๊ฒฉ๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ€์ƒ ํ™˜๊ฒฝ์„ ์ƒ์„ฑํ•˜๊ณ  ํ™œ์„ฑํ™”ํ•˜์„ธ์š”.

python -m venv venv
source venv/bin/activate

Windows์—์„œ๋Š” ๋‹ค์Œ์œผ๋กœ ๊ฐ€์ƒ ํ™˜๊ฒฝ์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค.

venv\Scripts\activate

์ด์ œ ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜์„ธ์š”.

pip install pymongo sentence-transformers einops

์ด ํŠœํ† ๋ฆฌ์–ผ์˜ ๊ฐ ๋‹จ๊ณ„๋งˆ๋‹ค ํ•˜๋‚˜์˜ Python ํŒŒ์ผ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๋ชจ๋“  ํŒŒ์ผ์€ mongodb-semantic-search ํด๋”์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

์ž„๋ฒ ๋”ฉ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํŒŒ์ผ ๋งŒ๋“ค๊ธฐ

embedding_utils.py๋ผ๋Š” ํŒŒ์ผ์„ ๋งŒ๋“œ์„ธ์š”. ์ด ํŒŒ์ผ์—๋Š” ํŠœํ† ๋ฆฌ์–ผ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ์ž„๋ฒ ๋”ฉ ํ•จ์ˆ˜๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

from sentence_transformers import SentenceTransformer

# Load the free, open-source embedding model.
# The model downloads from Hugging Face on first run and saves locally.
# trust_remote_code=True is required by this model:
model = SentenceTransformer("nomic-ai/nomic-embed-text-v1", trust_remote_code=True)


def get_embedding(text, precision="float32"):
    # Use this function when embedding text you plan to store in MongoDB:
    return model.encode(text, precision=precision).tolist()


def get_query_embedding(text, precision="float32"):
    # Use this function when embedding a user's search query:
    return model.encode(text, precision=precision).tolist()

๊ฒฝ๊ณ : trust_remote_code=True๋Š” Hugging Face์—์„œ ๋‹ค์šด๋กœ๋“œ๋œ ๋ชจ๋ธ๋ณ„ Python ์ฝ”๋“œ๋ฅผ ๋กœ์ปฌ ๋จธ์‹ ์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. Hugging Face์˜ ๋ชจ๋ธ ์†Œ์Šค๊ฐ€ ์†์ƒ๋˜๊ฑฐ๋‚˜ ์•…์˜์ ์ธ ๋ณ€๊ฒฝ์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜๋ฉด ํ•ด๋‹น ์ฝ”๋“œ๊ฐ€ ํ™˜๊ฒฝ์—์„œ ์ž๋™์œผ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ์ด ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ฃผ์˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋ฒกํ„ฐ ์ž„๋ฒ ๋”ฉ ์ƒ์„ฑ ๋ฐ ์ €์žฅ

generate_embeddings.py๋ผ๋Š” ํŒŒ์ผ์„ ๋งŒ๋“œ์„ธ์š”. ์ด ํŒŒ์ผ์€ embedding_utils.py์—์„œ ์ž„๋ฒ ๋”ฉ ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ ธ์™€ ๊ฐ ๋ฌธ์„œ์˜ text ํ•„๋“œ์— ๋Œ€ํ•œ ๋ฒกํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ž„๋ฒ ๋”ฉ์„ ํฌํ•จํ•œ ์ „์ฒด ๋ฌธ์„œ๋ฅผ MongoDB์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

from embedding_utils import get_embedding
from pymongo import MongoClient

# Replace the placeholder with your Atlas connection string:
mongodb_client = MongoClient(
    "mongodb+srv://<USERNAME>:<PASSWORD>@<HOST>/",
    appname="devrel-tutorial-python-semantic-search"
)

collection = mongodb_client["sample_db"]["documents"]

# Sample data:
sample_documents = [
    {
        "title": "MongoDB Atlas",
        "text": "MongoDB Atlas is a fully managed cloud database."
    },
    {
        "title": "Vector Search",
        "text": "Vector search finds results based on semantic meaning."
    },
    {
        "title": "Nomic AI",
        "text": "nomic-embed-text-v1 is a free, open-source embedding model."
    },
]

docs_to_insert = []

for doc in sample_documents:
    embedding = get_embedding(doc["text"])
    docs_to_insert.append({
        "title": doc["title"],
        "text": doc["text"],
        # The vector lives alongside your original data in the same document:
        "embedding": embedding
    })

# Drop the collection before each run to avoid inserting duplicate documents:
collection.drop()

result = collection.insert_many(docs_to_insert)
print(f"Inserted {len(result.inserted_ids)} documents with embeddings.")

mongodb_client.close()

์œ„ ์ฝ”๋“œ์—์„œ collection.drop()์€ ๋งค ์‹คํ–‰ ์ „์— ์ปฌ๋ ‰์…˜์˜ ๋ชจ๋“  ๋ฌธ์„œ์™€ ์ธ๋ฑ์Šค๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. generate_embeddings.py์—์„œ ์ด ์ค„ ์—†์ด ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋ฉด ๋ฌธ์„œ๊ฐ€ ์ค‘๋ณต ์‚ฝ์ž…๋˜์–ด $vectorSearch๊ฐ€ ๋™์ผํ•œ ๋ฌธ์„œ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ปฌ๋ ‰์…˜์„ ๋“œ๋กญํ•˜๋ฉด ๋ฒกํ„ฐ ๊ฒ€์ƒ‰ ์ธ๋ฑ์Šค๋„ ์‚ญ์ œ๋˜๋ฏ€๋กœ, generate_embeddings.py๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•  ๋•Œ๋งˆ๋‹ค create_vector_index.py๋ฅผ ์žฌ์‹คํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜์„ธ์š”.

python generate_embeddings.py

ํ„ฐ๋ฏธ๋„์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

<All keys matched successfully>
Inserted 3 documents with embeddings.

์ด์ œ MongoDB์˜ ๊ฐ ๋ฌธ์„œ์—๋Š” ์›๋ณธ ํ…์ŠคํŠธ์™€ 768์ฐจ์› ๋ฒกํ„ฐ๊ฐ€ embedding ํ•„๋“œ์— ํ•จ๊ป˜ ์ €์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฒกํ„ฐ๋Š” ๋™์ผํ•œ ๋ฌธ์„œ ๋‚ด ๋ฐ์ดํ„ฐ์™€ ๋‚˜๋ž€ํžˆ ์กด์žฌํ•˜๋ฏ€๋กœ, ์ฟผ๋ฆฌ ์‹œ ๋ณ„๋„์˜ ์ €์žฅ์†Œ๋‚˜ ์กฐํšŒ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

MongoDB Vector Search ์ธ๋ฑ์Šค ๋งŒ๋“ค๊ธฐ

create_vector_index.py๋ผ๋Š” ํŒŒ์ผ์„ ๋งŒ๋“œ์„ธ์š”. ์ด ํŒŒ์ผ์€ embedding ํ•„๋“œ์— ๋ฒกํ„ฐ ๊ฒ€์ƒ‰ ์ธ๋ฑ์Šค๋ฅผ ์ •์˜ํ•˜๊ณ  ์ƒ์„ฑํ•˜์—ฌ MongoDB๊ฐ€ ์ปฌ๋ ‰์…˜์— ๋Œ€ํ•ด $vectorSearch ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์ธ๋ฑ์Šค ์ •์˜์—๋Š” ์„ธ ๊ฐ€์ง€ ํ•„๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

  • path: ์ž„๋ฒ ๋”ฉ์ด ์ €์žฅ๋œ ํ•„๋“œ(์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” embedding)
  • numDimensions: ๋ชจ๋ธ์˜ ์ถœ๋ ฅ ํฌ๊ธฐ์™€ ์ผ์น˜ํ•ด์•ผ ํ•จ(nomic-embed-text-v1์€ 768)
  • similarity: ๋น„๊ต ํ•จ์ˆ˜(์ด ๋ชจ๋ธ์—๋Š” cosine์ด ์ ํ•ฉ)

numDimensions ๊ฐ’์€ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ๊ณผ ์ •ํ™•ํžˆ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ถˆ์ผ์น˜ ์‹œ ์ธ๋ฑ์Šค ์ƒ์„ฑ์ด ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.

from pymongo.mongo_client import MongoClient
from pymongo.operations import SearchIndexModel
import time

# Replace the placeholder with your Atlas connection string:
mongodb_client = MongoClient(
    "mongodb+srv://<USERNAME>:<PASSWORD>@<HOST>/",
    appname="devrel-tutorial-python-semantic-search"
)

# Point to the same database and collection you used in the previous step:
database = mongodb_client["sample_db"]
collection = database["documents"]

# Define the vector search index.
# The three required fields tell MongoDB what to index and how to compare vectors:
search_index_model = SearchIndexModel(
    definition={
        "fields": [
            {
                "type": "vector",
                "path": "embedding",      # The field name from generate_embeddings.py
                "numDimensions": 768,     # nomic-embed-text-v1 always outputs 768 dimensions
                "similarity": "cosine"    # Recommended similarity function for this model
            }
        ]
    },
    name="vector_index",
    type="vectorSearch"
)

result = collection.create_search_index(model=search_index_model)
print("New search index named " + result + " is building.")

# Poll every five seconds until the index is ready to accept queries:
print("Polling to check if the index is ready. This may take up to a minute.")

predicate = lambda index: index.get("queryable") is True

while True:
    indices = list(collection.list_search_indexes(result))
    if len(indices) and predicate(indices[0]):
        break
    time.sleep(5)

print(result + " is ready for querying.")

mongodb_client.close()

์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜์„ธ์š”.

python create_vector_index.py

ํ„ฐ๋ฏธ๋„์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

New search index named vector_index is building.
Polling to check if the index is ready. This may take up to a minute.
vector_index is ready for querying.

์ธ๋ฑ์Šค ๋นŒ๋“œ๋Š” ์ตœ๋Œ€ 1๋ถ„ ์ •๋„ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค. ํด๋ง ๋ฃจํ”„๋Š” 5์ดˆ๋งˆ๋‹ค ํ™•์ธํ•˜๋ฉฐ, MongoDB๊ฐ€ ์ธ๋ฑ์Šค๊ฐ€ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ์ž„์„ ํ™•์ธํ•  ๋•Œ์—๋งŒ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค. "vector_index is ready for querying." ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๊ธฐ ์ „์—๋Š” ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ๋„˜์–ด๊ฐ€์ง€ ๋งˆ์„ธ์š”.

๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ๋ฅผ ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜

generate_query_vector.py๋ผ๋Š” ํŒŒ์ผ์„ ๋งŒ๋“œ์„ธ์š”. ์ด ํŒŒ์ผ์€ embedding_utils.py์˜ get_query_embedding() ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. generate_query_vector.py๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋กœ๋“œ๋˜๊ณ  768์ฐจ์› ๋ฒกํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.

  • get_query_embedding() ํ•จ์ˆ˜๋Š” ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ ์ž„ํฌํŠธํ•ฉ๋‹ˆ๋‹ค.
  • ๋ชจ๋ธ์ด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ๋‹จ๋…์œผ๋กœ ์‹คํ–‰ํ•ด ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ๋„ ์ฒซ ๋‹จ๊ณ„์™€ ๋™์ผํ•œ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ชจ๋ธ์€ ๋‹ค๋ฅธ ์ˆ˜์น˜ ๊ณต๊ฐ„์˜ ๋ฒกํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋น„๊ต๊ฐ€ ๋ฌด์˜๋ฏธํ•ด์ง‘๋‹ˆ๋‹ค.

from embedding_utils import get_query_embedding

user_query = "I need an automated, scalable system for serious information storage"
query_vector = get_query_embedding(user_query)
print(f"Query: '{user_query}'")
print(f"Vector dimensions: {len(query_vector)}")
print(f"First 5 values: {query_vector[:5]}")

์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜์„ธ์š”.

python generate_query_vector.py

๋‹ค์Œ๊ณผ ์œ ์‚ฌํ•œ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

<All keys matched successfully>
Query: 'I need an automated, scalable system for serious information storage'
Vector dimensions: 768
First 5 values: [0.0025914530269801617, 0.09862980246543884, -0.023092379793524742, -0.0171672236174345, -0.05548065900802612]

์œ„ ์ถœ๋ ฅ์—์„œ Vector dimensions: 768์€ ๋ชจ๋ธ ์ถœ๋ ฅ์ด ์ €์žฅ๋œ ์ž„๋ฒ ๋”ฉ๊ณผ ์ผ์น˜ํ•จ์„ ํ™•์ธํ•ด ์ค๋‹ˆ๋‹ค.

$vectorSearch ์ฟผ๋ฆฌ ์‹คํ–‰

run_vector_search.py๋ผ๋Š” ํŒŒ์ผ์„ ๋งŒ๋“œ์„ธ์š”. ์ด ํŒŒ์ผ์€ embedding_utils.py์˜ get_query_embedding() ํ•จ์ˆ˜๋ฅผ ์ž„ํฌํŠธํ•˜์—ฌ ์‚ฌ์šฉ์ž์˜ ๊ฒ€์ƒ‰์–ด๋ฅผ ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. run_vector_search.py๋Š” $vectorSearch ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ์„ ์‹คํ–‰ํ•˜๊ณ , ์‹œ๋งจํ‹ฑ ์œ ์‚ฌ๋„ ์ˆœ์œผ๋กœ ์ •๋ ฌ๋œ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

from embedding_utils import get_query_embedding
from pymongo import MongoClient

# Replace the placeholder with your Atlas connection string:
mongodb_client = MongoClient(
    "mongodb+srv://<USERNAME>:<PASSWORD>@<HOST>/",
    appname="devrel-tutorial-python-semantic-search"
)

collection = mongodb_client["sample_db"]["documents"]

# Generate a query vector from the user's search input:
user_query = "I need an automated, scalable system for serious information storage"
query_vector = get_query_embedding(user_query)

# Define the $vectorSearch aggregation pipeline:
pipeline = [
    {
        "$vectorSearch": {
            "index": "vector_index",      # The index created in create_vector_index.py
            "path": "embedding",          # The field that holds your stored vectors
            "queryVector": query_vector,  # The vector generated from the user's query
            "numCandidates": 150,         # How many neighbors MongoDB considers
            "limit": 3                    # How many results to return
        }
    },
    {
        "$project": {
            "_id": 0,
            "title": 1,
            "text": 1,
            "score": {
                "$meta": "vectorSearchScore"  # Relevance score for each result
            }
        }
    }
]

results = collection.aggregate(pipeline)

print(f"\nTop results for query: '{user_query}'\n")

for doc in results:
    print(f"Title: {doc['title']}")
    print(f"Text:  {doc['text']}")
    print(f"Score: {doc['score']:.4f}")
    print()

mongodb_client.close()

์œ„ ์ฝ”๋“œ์—์„œ ๋‘ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๊ฒ€์ƒ‰ ๋™์ž‘์„ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.

  • numCandidates๋Š” ์ตœ์ข… ๊ฒฐ๊ณผ๋กœ ์ขํžˆ๊ธฐ ์ „์— MongoDB๊ฐ€ ์ดˆ๊ธฐ ๊ฒ€์ƒ‰ ํ’€์—์„œ ๊ฒ€์‚ฌํ•˜๋Š” ๊ฐœ์ˆ˜์ž…๋‹ˆ๋‹ค. ๊ฐ’์„ ํฌ๊ฒŒ ํ•˜๋ฉด ์žฌํ˜„์œจ์ด ๊ฐœ์„ ๋˜์ง€๋งŒ ์•ฝ๊ฐ„ ๋” ์˜ค๋ž˜ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค.
  • limit์€ ๋ฐ˜ํ™˜ํ•  ๊ฒฐ๊ณผ ์ˆ˜๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” limit์„ 3์œผ๋กœ, numCandidates๋ฅผ 150์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ์‹œ์ž‘์ ์€ numCandidates๋ฅผ limit์˜ 10~15๋ฐฐ๋กœ ๋‘๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด์ œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜์„ธ์š”.

python run_vector_search.py

๋‹ค์Œ๊ณผ ์œ ์‚ฌํ•œ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

<All keys matched successfully>

Top results for query: 'I need an automated, scalable system for serious information storage.'

Title: MongoDB Atlas
Text:  MongoDB Atlas is a fully managed cloud database.
Score: 0.7211

Title: Nomic AI
Text:  nomic-embed-text-v1 is a free, open-source embedding model.
Score: 0.6818

Title: Vector Search
Text:  Vector search finds results based on semantic meaning.
Score: 0.6642

์ฟผ๋ฆฌ "I need an automated, scalable system for serious information storage"์™€ "MongoDB Atlas is a fully managed cloud database."๋Š” ๋‹จ์–ด๋ฅผ ๊ณต์œ ํ•˜์ง€ ์•Š์ง€๋งŒ, "MongoDB Atlas"๊ฐ€ ๊ฐ€์žฅ ๋†’์€ ์ ์ˆ˜๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค. ๋‘ ๋ฌธ์žฅ์˜ ๋ฒกํ„ฐ๊ฐ€ ์˜๋ฏธ์ƒ ๊ฐ€๊น๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. "...์ •๋ณด ์ €์žฅ์„ ์œ„ํ•œ ์ž๋™ํ™”๋˜๊ณ  ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์‹œ์Šคํ…œ"์€ ์˜๋ฏธ์ ์œผ๋กœ "...์™„์ „ ๊ด€๋ฆฌํ˜• ํด๋ผ์šฐ๋“œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค"์— ๋งคํ•‘๋ฉ๋‹ˆ๋‹ค. ๋™์ผํ•œ ์ฟผ๋ฆฌ๋กœ ํ…์ŠคํŠธ ๊ฒ€์ƒ‰์„ ํ•˜๋ฉด ์–ด๋–ค ๋ฌธ์„œ์—๋„ ์ •ํ™•ํ•œ ์ฟผ๋ฆฌ ๋‹จ์–ด๊ฐ€ ์—†์œผ๋ฏ€๋กœ ๊ฒฐ๊ณผ๊ฐ€ 0๊ฑด์ด ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์˜๋„ํ•œ ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š” ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰์ž…๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ์ •๋ฆฌ

  • MongoDB Vector Search๋Š” M0 ๋ฌด๋ฃŒ ํ‹ฐ์–ด ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์œ ๋ฃŒ ํ”Œ๋žœ์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ €์žฅ์šฉ ์ž„๋ฒ ๋”ฉ ์ƒ์„ฑ๊ณผ ์ฟผ๋ฆฌ ๋ฒกํ„ฐ ์ƒ์„ฑ ๋ชจ๋‘์— ๋™์ผํ•œ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋ธ์„ ์„ž์–ด ์‚ฌ์šฉํ•˜๋ฉด ๊ฒฐ๊ณผ๊ฐ€ ๋ฌด์˜๋ฏธํ•ด์ง‘๋‹ˆ๋‹ค.
  • numDimensions๋Š” ์ธ๋ฑ์Šค ์ •์˜์—์„œ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์˜ ์ถœ๋ ฅ ํฌ๊ธฐ์™€ ์ •ํ™•ํžˆ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. nomic-embed-text-v1์€ ํ•ญ์ƒ 768์ฐจ์›์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • input_type="document"๋Š” ์ €์žฅ์— ์ตœ์ ํ™”๋œ ์ž„๋ฒ ๋”ฉ์„, input_type="query"๋Š” ๊ฒ€์ƒ‰์— ์ตœ์ ํ™”๋œ ์ž„๋ฒ ๋”ฉ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ๋‹จ๊ณ„์—์„œ ์˜ฌ๋ฐ”๋ฅธ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์„ธ์š”.
  • numCandidates๋Š” MongoDB๊ฐ€ ์ตœ์ข… limit ๊ฒฐ๊ณผ๋กœ ์ขํžˆ๊ธฐ ์ „์— ํƒ์ƒ‰ํ•˜๋Š” ๋ฒ”์œ„๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. ๊ฐ’์„ ํฌ๊ฒŒ ํ•˜๋ฉด ์žฌํ˜„์œจ์ด ํ–ฅ์ƒ๋˜์ง€๋งŒ ์ฟผ๋ฆฌ ์‹œ๊ฐ„์ด ๋Š˜์–ด๋‚ฉ๋‹ˆ๋‹ค.
  • vectorSearchScore๋Š” ์‹œ๋งจํ‹ฑ ์œ ์‚ฌ๋„๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋žญํ‚นํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์—๋Š” ์ฟผ๋ฆฌ์˜ ์ •ํ™•ํ•œ ๋‹จ์–ด๊ฐ€ ํฌํ•จ๋  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ ์ˆ˜ ๋ฒ”์œ„๋Š” ๋ชจ๋ธ๊ณผ ๋ฐ์ดํ„ฐ์…‹์— ๋”ฐ๋ผ ๋‹ค๋ฅด์ง€๋งŒ, nomic-embed-text-v1์˜ ์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„ ๊ธฐ์ค€์œผ๋กœ ๋‹ค์Œ ๊ฒฝ๊ณ„๊ฐ’์ด ์œ ์šฉํ•œ ์‹œ์ž‘์ ์ž…๋‹ˆ๋‹ค.
    • 0.9 ์ด์ƒ: ์˜๋ฏธ๊ฐ€ ๊ฑฐ์˜ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์„œ์™€ ์ฟผ๋ฆฌ๊ฐ€ ์‹œ๋งจํ‹ฑํ•˜๊ฒŒ ๊ฑฐ์˜ ๊ฐ™์Šต๋‹ˆ๋‹ค.
    • 0.7~0.9: ๋†’์€ ๊ด€๋ จ์„ฑ. ๋ฌธ์„œ๊ฐ€ ์ฟผ๋ฆฌ ์˜๋„์™€ ๋ช…ํ™•ํžˆ ๊ด€๋ จ๋ฉ๋‹ˆ๋‹ค.
    • 0.5~0.7: ๋ณดํ†ต ๊ด€๋ จ์„ฑ. ์ฃผ์ œ๋Š” ๊ฐ™์ง€๋งŒ ํ”„๋ ˆ์ด๋ฐ์ด๋‚˜ ๋ฌธ๋งฅ์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค.
    • 0.5 ๋ฏธ๋งŒ: ๋‚ฎ์€ ๊ด€๋ จ์„ฑ. ์—ฐ๊ด€์„ฑ์ด ์•ฝํ•ด ์œ ์šฉํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํŠœํ† ๋ฆฌ์–ผ์˜ ๋ชจ๋“  ์ฝ”๋“œ ์ƒ˜ํ”Œ์€ GitHub ์ €์žฅ์†Œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถ”๊ฐ€๋กœ ์ฝ๊ธฐ

  • MongoDB Vector Search ๊ฐœ์š”๋Š” ํ•„ํ„ฐ๋ง๊ณผ ์–‘์žํ™” ๋“ฑ MongoDB Vector Search์˜ ์ „์ฒด ๊ธฐ๋Šฅ์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค.
  • ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰ ๋ฐฉ๋ฒ•์€ ํ•˜๋‚˜์˜ ์ฟผ๋ฆฌ์—์„œ ๋ฒกํ„ฐ ๊ฒ€์ƒ‰๊ณผ ์ „์ฒด ํ…์ŠคํŠธ ๊ฒ€์ƒ‰์„ ๊ฒฐํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
  • ๋ฒกํ„ฐ ์ž„๋ฒ ๋”ฉ ์ƒ์„ฑ ๋ฐฉ๋ฒ•์€ Voyage AI, OpenAI ๋ฐ ๊ธฐํƒ€ ์˜คํ”ˆ ์†Œ์Šค ๋ชจ๋ธ ์ œ๊ณต์ž์˜ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปฌ๋ ‰์…˜์˜ ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๋ฒกํ„ฐ ์ž„๋ฒ ๋”ฉ์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
  • MongoDB๋กœ RAG(Retrieval-Augmented Generation)๋Š” ๊ฒ€์ƒ‰ ์ฆ๊ฐ• ์ƒ์„ฑ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ฒ€์ƒ‰ ๊ณ„์ธต์œผ๋กœ ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

FAQs

์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰์„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ์œ ๋ฃŒ Atlas ํ”Œ๋žœ์ด ํ•„์š”ํ•œ๊ฐ€์š”?

์•„๋‹ˆ์š”. ์ด ํŠœํ† ๋ฆฌ์–ผ์˜ ๋„ค ๋‹จ๊ณ„ ๋ชจ๋‘ ๋ฌด๋ฃŒ์ธ M0 ๋ฌด๋ฃŒ ํ‹ฐ์–ด ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

์ €์žฅ๋œ ๋ฌธ์„œ์™€ ๋‹ค๋ฅธ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋‚˜์š”?

๊ฒฐ๊ณผ๊ฐ€ ๋ฌด์˜๋ฏธํ•ด์ง‘๋‹ˆ๋‹ค. ์„œ๋กœ ๋‹ค๋ฅธ ๋ชจ๋ธ์€ ํ…์ŠคํŠธ๋ฅผ ๋‹ค๋ฅธ ์ˆ˜์น˜ ๊ณต๊ฐ„์— ๋งคํ•‘ํ•˜๋ฏ€๋กœ ๋ฒกํ„ฐ๋ฅผ ๋น„๊ตํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ธ๋ฑ์‹ฑ๊ณผ ์ฟผ๋ฆฌ ๋ชจ๋‘์— ํ•ญ์ƒ ๋™์ผํ•œ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

`numCandidates`์™€ `limit`์˜ ์ฐจ์ด๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

numCandidates๋Š” ๊ฒ€์ƒ‰ ์ค‘์— MongoDB๊ฐ€ ๊ฒ€์‚ฌํ•˜๋Š” ๋ฒกํ„ฐ ์ˆ˜์ด๊ณ , limit๋Š” ์ƒ์œ„ ๊ฒฐ๊ณผ ์ค‘ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐœ์ˆ˜์ž…๋‹ˆ๋‹ค. numCandidates ๊ฐ’์„ ๋†’์ด๋ฉด ์ฟผ๋ฆฌ๊ฐ€ ์•ฝ๊ฐ„ ๋А๋ ค์ง€๋Š” ๋Œ€๊ฐ€๋กœ ๊ฒฐ๊ณผ ํ’ˆ์งˆ์ด ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ์‹œ์ž‘์ ์€ numCandidates๋ฅผ limit์˜ 10~15๋ฐฐ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰๊ณผ ํ…์ŠคํŠธ ๊ฒ€์ƒ‰์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‚˜์š”?

์˜ˆ. MongoDB๋Š” ํ•˜๋‚˜์˜ ํŒŒ์ดํ”„๋ผ์ธ์—์„œ $vectorSearch์™€ $search๋ฅผ ๊ฒฐํ•ฉํ•˜๋Š” ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๊ฒ€์ƒ‰์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

์˜์–ด ์ด์™ธ์˜ ์–ธ์–ด์—์„œ๋„ ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰์ด ์ž‘๋™ํ•˜๋‚˜์š”?

์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. nomic-embed-text-v1์€ ์ฃผ๋กœ ์˜์–ด ํ…์ŠคํŠธ๋กœ ํ•™์Šต๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๊ตญ์–ด ์‚ฌ์šฉ ์‚ฌ๋ก€์˜ ๊ฒฝ์šฐ ๋ฐ์ดํ„ฐ์— ํฌํ•จ๋œ ์–ธ์–ด๋กœ ํ•™์Šต๋œ ๋‹ค๊ตญ์–ด ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์„ ์„ ํƒํ•˜์„ธ์š”.

์ฃผ์ œ