[TIL-0216] LlamaIndex๋ž€?

jinyยท2026๋…„ 2์›” 17์ผ

AI Agent ์‹ค์Šต

๋ชฉ๋ก ๋ณด๊ธฐ
3/21

๐ŸŒŸ ๊ฐœ์š”

AI Agent ์Šคํ„ฐ๋””์—์„œ AI Agent ๊ธฐ๋ฐ˜์˜ ์ธํ”Œ๋ฃจ์–ธ์„œ ๋งค์นญ ํ”Œ๋žซํผ์„ ์‹ค์Šต ํ”„๋กœ์ ํŠธ๋กœ ์ง„ํ–‰ํ•˜๊ณ  ์žˆ๋‹ค. ๊ด‘๊ณ ์ฃผ๊ฐ€ ๊ด‘๊ณ  ์ปจ์…‰, ์•„์ดํ…œ, ์˜ˆ์‚ฐ ๋“ฑ์„ ์ž…๋ ฅํ•˜๋ฉด, LangGraph ๊ธฐ๋ฐ˜ AI Agent๊ฐ€ DB์—์„œ ์ตœ์ ์˜ ์ธํ”Œ๋ฃจ์–ธ์„œ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์ถ”์ฒœํ•ด์ฃผ๋Š” ์„œ๋น„์Šค์ด๋‹ค.

์Šคํ„ฐ๋””์—์„œ๋Š” ํ”„๋กœ์ ํŠธ ์‹ค์Šต๊ณผ ๋ณ‘ํ–‰ํ•˜์—ฌ UC Berkeley์˜ LLM Agent ๊ฐ•์˜๋ฅผ ํ•œ ๊ฐ•์˜์”ฉ ์ˆ˜๊ฐ•ํ•˜๊ณ  ์žˆ๋Š”๋ฐ, ์ด ๊ฐ•์˜๋ฅผ ํ†ตํ•ด LlamaIndex๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

๊ธฐ์กด ํ”„๋กœ์ ํŠธ๋Š” SQL ๊ธฐ๋ฐ˜์˜ ์ •ํ™• ๋งค์นญ(์นดํ…Œ๊ณ ๋ฆฌ๋ช…, ํ”Œ๋žซํผ, ํŒ”๋กœ์›Œ ์ˆ˜ ๋ฒ”์œ„)์œผ๋กœ ์ธํ”Œ๋ฃจ์–ธ์„œ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ, LlamaIndex๋ฅผ ๋„์ž…ํ•˜๋ฉด ์ž์—ฐ์–ด ๊ธฐ๋ฐ˜ ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰๊ณผ ๊ณผ๊ฑฐ ์„ฑ๊ณต ์‚ฌ๋ก€๋ฅผ ๊ทผ๊ฑฐ๋กœ ํ•œ RAG ๋ถ„์„์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค๋Š” ์ ์—์„œ ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ์— ๋„์ž…ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ์— ๋„์ž…ํ•œ LlamaIndex ๊ด€๋ จ ์ฝ”๋“œ๋“ค์„ ๋ถ„์„ํ•˜๊ธฐ ์ „์—, LlamaIndex๊ฐ€ ์ •ํ™•ํžˆ ๋ฌด์—‡์ด๊ณ , ์–ด๋–ค ๊ฐœ๋…๋“ค๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋Š”์ง€ ์ œ๋Œ€๋กœ ์•Œ์•„๋ณด์ž.


๐ŸŒŸ LlamaIndex๋ž€?

LlamaIndex(๊ตฌ GPT Index)๋Š” LLM ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•œ ๋ฐ์ดํ„ฐ ํ”„๋ ˆ์ž„์›Œํฌ์ด๋‹ค.
ํ•ต์‹ฌ ๋ชฉ์ ์€ ์™ธ๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ LLM์— ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
LLM(GPT-4, Claude ๋“ฑ)์€ ํ•™์Šต ๋ฐ์ดํ„ฐ๊นŒ์ง€๋งŒ ์•Œ๊ณ  ์žˆ๊ณ , ์‚ฌ์šฉ์ž์˜ ๊ฐœ์ธ ๋ฐ์ดํ„ฐ(DB, ๋ฌธ์„œ, API ๋“ฑ)๋Š” ๋ชจ๋ฅธ๋‹ค. LlamaIndex๋Š” ์ด ๊ฐ„๊ทน์„ ๋ฉ”์›Œ์ค€๋‹ค.


๐ŸŒŸ ์™œ ํ•„์š”ํ•œ๊ฐ€?

๋ฌธ์ œLlamaIndex์˜ ํ•ด๊ฒฐ
LLM์€ ๋‚ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋ฆ„์™ธ๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ธ๋ฑ์‹ฑํ•˜์—ฌ LLM์— ์ œ๊ณต
๋ฌธ์„œ๊ฐ€ ๋„ˆ๋ฌด ๊ธธ์–ด ์ปจํ…์ŠคํŠธ์— ์•ˆ ๋“ค์–ด๊ฐ์ฒญํ‚น + ์ž„๋ฒ ๋”ฉ์œผ๋กœ ๊ด€๋ จ ๋ถ€๋ถ„๋งŒ ๊ฒ€์ƒ‰
๋‹จ์ˆœ ๊ฒ€์ƒ‰์€ ์˜๋ฏธ๋ฅผ ๋ชป ์žก์Œ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰(๋ฒกํ„ฐ ์œ ์‚ฌ๋„) ์ œ๊ณต
๋ฐ์ดํ„ฐ ์†Œ์Šค๊ฐ€ ๋‹ค์–‘ํ•จํ†ตํ•ฉ ์ปค๋„ฅํ„ฐ(PDF, DB, API, ์›น ๋“ฑ) ์ œ๊ณต

๐ŸŒŸ ํ•ต์‹ฌ ๊ฐœ๋… 1: Document & Node

๐Ÿ’ก ์›๋ณธ ๋ฐ์ดํ„ฐ โ†’ Document โ†’ Node(์ฒญํฌ)

โœ… Document

Document๋Š” LlamaIndex์—์„œ ์›๋ณธ ๋ฐ์ดํ„ฐ ํ•˜๋‚˜๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ฐ์ฒด์ด๋‹ค.
PDF ํŒŒ์ผ ํ•˜๋‚˜, DB ํ–‰ ํ•˜๋‚˜, ์›น ํŽ˜์ด์ง€ ํ•˜๋‚˜ ๋“ฑ์ด ๊ฐ๊ฐ ํ•˜๋‚˜์˜ Document๊ฐ€ ๋œ๋‹ค.

๐Ÿ’ก Document = text(์ž„๋ฒ ๋”ฉ ๋Œ€์ƒ, ๊ฒ€์ƒ‰์˜ ๊ธฐ์ค€) + metadata(๋ถ€๊ฐ€ ์ •๋ณด, ํ•„ํ„ฐ๋ง์šฉ)

  • text๋งŒ ๋„ฃ๊ธฐ (๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ์ƒ์„ฑ)

    from llama_index.core import Document
    
    doc = Document(text="์ธํ”Œ๋ฃจ์–ธ์„œ ๊น€์ฒ ์ˆ˜๋Š” ๋ทฐํ‹ฐ ์นดํ…Œ๊ณ ๋ฆฌ ์œ ํŠœ๋ฒ„์ž…๋‹ˆ๋‹ค.")
    • text์— ๋“ค์–ด๊ฐ€๋Š” ๋ฌธ์ž์—ด์ด ๋‚˜์ค‘์— ์ž„๋ฒ ๋”ฉ(๋ฒกํ„ฐ ๋ณ€ํ™˜)์˜ ๋Œ€์ƒ์ด ๋œ๋‹ค.
    • ์ด ํ…์ŠคํŠธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์œ ์‚ฌ๋„๋ฅผ ๊ณ„์‚ฐํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๊ฒ€์ƒ‰์— ํ™œ์šฉํ•˜๊ณ  ์‹ถ์€ ์ •๋ณด๋Š” ๋ฐ˜๋“œ์‹œ text์— ํฌํ•จ์‹œ์ผœ์•ผ ํ•œ๋‹ค.
  • metadata๋ฅผ ํ•จ๊ป˜ ๋„ฃ๊ธฐ
    doc = Document(
    	text="์ธํ”Œ๋ฃจ์–ธ์„œ ๊น€์ฒ ์ˆ˜๋Š” ๋ทฐํ‹ฐ ์นดํ…Œ๊ณ ๋ฆฌ ์œ ํŠœ๋ฒ„์ž…๋‹ˆ๋‹ค.",
       metadata={
       	"influencer_id": "123",
           "total_followers": 150000,
           "categories": ["๋ทฐํ‹ฐ", "๋ผ์ดํ”„์Šคํƒ€์ผ"],
       },
    )
    • metadata๋Š” ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์™€ ํ•จ๊ป˜ ๋”ธ๋ ค์˜ค๋Š” ๋ถ€๊ฐ€ ์ •๋ณด์ด๋‹ค.
    • ์ž„๋ฒ ๋”ฉ์—๋Š” ์‚ฌ์šฉ๋˜์ง€ ์•Š์ง€๋งŒ, ๊ฒ€์ƒ‰ ํ›„ ํ•„ํ„ฐ๋ง์ด๋‚˜ ๊ฒฐ๊ณผ ํ‘œ์‹œ์— ํ™œ์šฉ๋œ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด "ํŒ”๋กœ์›Œ 10๋งŒ ์ด์ƒ๋งŒ ํ•„ํ„ฐ๋ง" ๊ฐ™์€ ํ›„์ฒ˜๋ฆฌ๋ฅผ metadata๋กœ ํ•  ์ˆ˜ ์žˆ๋‹ค.

โœ… Node์™€ ์ฒญํ‚น(Chunking)

์‹ค์ œ ๋ฐ์ดํ„ฐ๋Š” ๋ณดํ†ต Document ํ•˜๋‚˜๊ฐ€ ๋งค์šฐ ๊ธธ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด PDF ํ•œ ์žฅ์ด ์ˆ˜์ฒœ ๊ธ€์ž์ผ ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฑธ ํ†ต์จฐ๋กœ ์ž„๋ฒ ๋”ฉํ•˜๋ฉด ๋‘ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค.

  1. ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์˜ ํ† ํฐ ์ œํ•œ: ๋Œ€๋ถ€๋ถ„์˜ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์€ ์ž…๋ ฅ ๊ธธ์ด์— ์ œํ•œ์ด ์žˆ์Œ (์˜ˆ: 8192 ํ† ํฐ)
  2. ๊ฒ€์ƒ‰ ์ •ํ™•๋„ ์ €ํ•˜: ๋ฌธ์„œ๊ฐ€ ๊ธธ์ˆ˜๋ก ๋ฒกํ„ฐ๊ฐ€ "ํ‰๊ท ์ ์ธ" ์˜๋ฏธ๋ฅผ ๊ฐ–๊ฒŒ ๋˜์–ด, ํŠน์ • ๋ถ€๋ถ„์„ ์ •ํ™•ํžˆ ์ฐพ๊ธฐ ์–ด๋ ค์›€

๊ทธ๋ž˜์„œ Document๋ฅผ ์ž‘์€ ์กฐ๊ฐ(Node)์œผ๋กœ ์ชผ๊ฐœ๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•˜๋‹ค. ์ด๊ฒƒ์ด ์ฒญํ‚น(Chunking)์ด๋‹ค.

from llama_index.core.node_parser import SentenceSplitter

parser = SentenceSplitter(chunk_size=512, chunk_overlap=50)
nodes = parser.get_nodes_from_documents([doc])
  • chunk_size=512: ํ•œ Node์˜ ์ตœ๋Œ€ ํ† ํฐ ์ˆ˜. ํ•˜๋‚˜์˜ ์ฒญํฌ๊ฐ€ ์ตœ๋Œ€ 512ํ† ํฐ๊นŒ์ง€ ๋‹ด๊ธธ ์ˆ˜ ์žˆ๋‹ค.

  • chunk_overlap=50: ์ธ์ ‘ํ•œ Node ๊ฐ„์— 50ํ† ํฐ์„ ๊ฒน์น˜๊ฒŒ ํ•œ๋‹ค.

    • overlap ์—†์ด ์ž๋ฅด๋Š” ๊ฒฝ์šฐ (chunk_overlap=0)
      Node 1: "๊น€์ฒ ์ˆ˜๋Š” ๋ทฐํ‹ฐ ์œ ํŠœ๋ฒ„์ด๋‹ค. ์ฃผ๋กœ ํ™”์žฅํ’ˆ ๋ฆฌ๋ทฐ๋ฅผ ํ•˜๋ฉฐ, ํŠนํžˆ ์Šคํ‚จ์ผ€์–ด ์ œํ’ˆ์— ๋Œ€ํ•œ ์ „๋ฌธ์„ฑ์ด ๋†’๋‹ค. ์ตœ๊ทผ์—๋Š” LG์ƒํ™œ๊ฑด๊ฐ•๊ณผ"
      Node 2: "ํ˜‘์—…ํ•˜์—ฌ ํฐ ์„ฑ๊ณผ๋ฅผ ๋ƒˆ๋‹ค. ํ•ด๋‹น ์บ ํŽ˜์ธ์—์„œ ์กฐํšŒ์ˆ˜ 50๋งŒ, ์ข‹์•„์š” 3๋งŒ์„ ๋‹ฌ์„ฑํ–ˆ๋‹ค..."

      ๐Ÿ‘‰ "LG์ƒํ™œ๊ฑด๊ฐ•๊ณผ ํ˜‘์—…ํ•˜์—ฌ ํฐ ์„ฑ๊ณผ๋ฅผ ๋ƒˆ๋‹ค"๋ผ๋Š” ๋ฌธ๋งฅ์ด ๋‘ Node๋กœ ๋ถ„๋ฆฌ๋˜์–ด ์˜๋ฏธ๊ฐ€ ๋Š๊ธด๋‹ค. "LG์ƒํ™œ๊ฑด๊ฐ•๊ณผ" ๊ฒ€์ƒ‰ ์‹œ Node 1์—์„œ ๊ฑธ๋ฆฌ์ง€๋งŒ, ์„ฑ๊ณผ ์ •๋ณด๋Š” Node 2์—๋งŒ ์žˆ๋‹ค.

    • overlap ์žˆ๋Š” ๊ฒฝ์šฐ (chunk_overlap=50)
      Node 1: "๊น€์ฒ ์ˆ˜๋Š” ๋ทฐํ‹ฐ ์œ ํŠœ๋ฒ„์ด๋‹ค. ์ฃผ๋กœ ํ™”์žฅํ’ˆ ๋ฆฌ๋ทฐ๋ฅผ ํ•˜๋ฉฐ, ํŠนํžˆ ์Šคํ‚จ์ผ€์–ด ์ œํ’ˆ์— ๋Œ€ํ•œ ์ „๋ฌธ์„ฑ์ด ๋†’๋‹ค. ์ตœ๊ทผ์—๋Š” LG์ƒํ™œ๊ฑด๊ฐ•๊ณผ ํ˜‘์—…ํ•˜์—ฌ ํฐ ์„ฑ๊ณผ๋ฅผ ๋ƒˆ๋‹ค."
      Node 2: "์ตœ๊ทผ์—๋Š” LG์ƒํ™œ๊ฑด๊ฐ•๊ณผ ํ˜‘์—…ํ•˜์—ฌ ํฐ ์„ฑ๊ณผ๋ฅผ ๋ƒˆ๋‹ค. ํ•ด๋‹น ์บ ํŽ˜์ธ์—์„œ ์กฐํšŒ์ˆ˜ 50๋งŒ, ์ข‹์•„์š” 3๋งŒ์„ ๋‹ฌ์„ฑํ–ˆ๋‹ค..."

      ๐Ÿ‘‰ ๊ฒน์น˜๋Š” ๊ตฌ๊ฐ„ ๋•๋ถ„์— ๋ฌธ๋งฅ์ด ์œ ์ง€๋œ๋‹ค.

โœ… SentenceSplitter์˜ ๋™์ž‘ ๋ฐฉ์‹

SentenceSplitter๋Š” ๋ฌธ์žฅ ๊ฒฝ๊ณ„๋ฅผ ์กด์ค‘ํ•˜๋ฉด์„œ ๋‚˜๋ˆ„๋Š” ๋„๊ตฌ๋กœ, LlamaIndex๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ์ž๋™ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค.
์‹ค์ œ๋กœ VectorStoreIndex.from_documents(documents)๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, LlamaIndex๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ๋‹ค์Œ ๊ณผ์ •์„ ์ž๋™ ์ˆ˜ํ–‰ํ•œ๋‹ค.

  1. Document๋ฅผ Node๋กœ ๋ถ„ํ•  (๊ธฐ๋ณธ๊ฐ’: SentenceSplitter, chunk_size=1024)
  2. ๊ฐ Node๋ฅผ ์ž„๋ฒ ๋”ฉ
  3. Vector Store์— ์ €์žฅ

๋ช…์‹œ์ ์œผ๋กœ SentenceSplitter๋ฅผ ์ง์ ‘ ์“ฐ๋Š” ๊ฒฝ์šฐ๋Š” ๊ธฐ๋ณธ๊ฐ’(1024ํ† ํฐ)์ด ์•„๋‹Œ ๋‹ค๋ฅธ ์„ค์ •์„ ์“ฐ๊ณ  ์‹ถ์„ ๋•Œ์ด๋‹ค.
๋‚ด๋ถ€์ ์œผ๋กœ ., !, ?, \n ๊ฐ™์€ ๋ฌธ์žฅ ๊ตฌ๋ถ„์ž๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ถ„ํ• ํ•œ ๋’ค, chunk_size์— ๋งž๊ฒŒ ๋ฌธ์žฅ๋“ค์„ ๋ฌถ๋Š”๋‹ค.

  • ๋‹จ์ˆœ ๊ธ€์ž ์ˆ˜๋กœ ์ž๋ฅด๊ธฐ: "๊น€์ฒ ์ˆ˜๋Š” ๋ทฐํ‹ฐ ์œ ํŠœ๋ฒ„์ด๋‹ค. ์ฃผ๋กœ ํ™”์žฅ" ๐Ÿ‘ˆ ๋‹จ์–ด ์ค‘๊ฐ„์—์„œ ์ž˜๋ฆผ
  • SentenceSplitter๋กœ ์ž๋ฅด๊ธฐ: "๊น€์ฒ ์ˆ˜๋Š” ๋ทฐํ‹ฐ ์œ ํŠœ๋ฒ„์ด๋‹ค." ๐Ÿ‘ˆ ๋ฌธ์žฅ ๋‹จ์œ„๋กœ ์ž˜๋ฆผ

โœ… Node์˜ ๊ตฌ์กฐ

์ƒ์„ฑ๋œ Node๋Š” ์›๋ณธ Document์˜ ์ •๋ณด๋ฅผ ๊ทธ๋Œ€๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

for node in nodes:
	print(node.text)           # ์ฒญํฌ ํ…์ŠคํŠธ
    print(node.metadata)       # Document์—์„œ ์ƒ์†๋ฐ›์€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ
    print(node.relationships)  # ์ด์ „/๋‹ค์Œ Node์™€์˜ ๊ด€๊ณ„
    print(node.node_id)        # ๊ณ ์œ  ID

ํŠนํžˆ relationships๊ฐ€ ์ค‘์š”ํ•˜๋‹ค. Node๋Š” ์ž์‹ ์˜ ์ด์ „ Node, ๋‹ค์Œ Node, ์›๋ณธ Document์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ์œ ์ง€ํ•œ๋‹ค. ๋•๋ถ„์— ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์—์„œ "์•ž๋’ค ๋งฅ๋ฝ"์„ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๋‹ค.

โœ… ์ •๋ฆฌ: Document์—์„œ ๊ฒ€์ƒ‰๊นŒ์ง€์˜ ์ „์ฒด ํ๋ฆ„


๐ŸŒŸ ํ•ต์‹ฌ ๊ฐœ๋… 2: Embedding (์ž„๋ฒ ๋”ฉ)

โœ… ์˜๋ฏธ

ํ…์ŠคํŠธ๋ฅผ ๊ณ ์ฐจ์› ๋ฒกํ„ฐ(์ˆซ์ž ๋ฐฐ์—ด)๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

"๋ทฐํ‹ฐ ์œ ํŠœ๋ฒ„" โ†’ [0.12, -0.34, 0.56, ..., 0.78]  (1536์ฐจ์›)
"ํ™”์žฅํ’ˆ ๋ฆฌ๋ทฐ์–ด" โ†’ [0.11, -0.33, 0.55, ..., 0.77]  (๋น„์Šทํ•œ ๋ฒกํ„ฐ)
"๊ฒŒ์ž„ ์ŠคํŠธ๋ฆฌ๋จธ" โ†’ [-0.45, 0.67, -0.12, ..., 0.23]  (๋‹ค๋ฅธ ๋ฒกํ„ฐ)

์˜๋ฏธ๊ฐ€ ๋น„์Šทํ•œ ํ…์ŠคํŠธ๋Š” ๋ฒกํ„ฐ ๊ณต๊ฐ„์—์„œ ๊ฐ€๊นŒ์ด ์œ„์น˜ํ•œ๋‹ค. ์ด๊ฒƒ์ด ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰์˜ ์›๋ฆฌ์ด๋‹ค.

โœ… ํด๋ผ์šฐ๋“œ API ๋ชจ๋ธ (OpenAI)

from llama_index.embeddings.openai import OpenAiEmbedding
embed_model = OpenAIEmbedding(model="text-embedding-3-small")
  • ํ…์ŠคํŠธ๋ฅผ OpenAI ์„œ๋ฒ„๋กœ ์ „์†กํ•˜์—ฌ ์ž„๋ฒ ๋”ฉ ๋ฒกํ„ฐ๋ฅผ ๋ฐ›์•„์˜ด
  • ์ธํ„ฐ๋„ท ์—ฐ๊ฒฐ ํ•„์š”
  • API ํ˜ธ์ถœ๋งˆ๋‹ค ๋น„์šฉ ๋ฐœ์ƒ (ํ† ํฐ๋‹น ๊ณผ๊ธˆ)
  • ๋‚ด ์ปดํ“จํ„ฐ ์„ฑ๋Šฅ๊ณผ ๋ฌด๊ด€ํ•˜๊ฒŒ ๋น ๋ฆ„
  • OPENAI_API_KEY ํ•„์š”

โœ… ๋กœ์ปฌ ๋ชจ๋ธ (HuggingFace)

from llama_index.embeddings.huggingface import HuggingFaceEmbedding
embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")
  • ๋ชจ๋ธ์„ ๋‚ด ์ปดํ“จํ„ฐ์— ๋‹ค์šด๋กœ๋“œ๋ฐ›์•„์„œ ์ง์ ‘ ์‹คํ–‰
  • ์ธํ„ฐ๋„ท ์—†์ด๋„ ๋™์ž‘ (์ตœ์ดˆ ๋‹ค์šด๋กœ๋“œ๋งŒ ํ•„์š”)
  • ๋ฌด๋ฃŒ
  • ๋‚ด ์ปดํ“จํ„ฐ CPU/GPU ์„ฑ๋Šฅ์— ์˜์กด
  • API ํ‚ค ๋ถˆํ•„์š”

๐ŸŒŸ ํ•ต์‹ฌ ๊ฐœ๋… 3: Index (์ธ๋ฑ์Šค)

Node๋“ค์„ ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅํ•œ ๊ตฌ์กฐ๋กœ ์กฐ์งํ•˜๋Š” ๊ฒƒ์ด๋‹ค. LlamaIndex์˜ ์ด๋ฆ„์ด ์—ฌ๊ธฐ์„œ ์™”๋‹ค.

from llama_index.core import VectorStoreIndex

index = VectorStoreIndex.from_documents(documents)

โœ… VectorStoreIndex ๋™์ž‘ ์›๋ฆฌ

Documents โ†’ ์ฒญํ‚น โ†’ Nodes โ†’ ์ž„๋ฒ ๋”ฉ โ†’ ๋ฒกํ„ฐ ์ €์žฅ
                                         โ†“
์งˆ์˜ โ†’ ์งˆ์˜ ์ž„๋ฒ ๋”ฉ โ†’ ์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„ ๊ณ„์‚ฐ โ†’ ์ƒ์œ„ K๊ฐœ ๋…ธ๋“œ ๋ฐ˜ํ™˜

VectorStoreIndex๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ์ธ๋ฑ์‹ฑ ๋‹จ๊ณ„์™€, ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ์—์„œ ์ฐพ๋Š” ๊ฒ€์ƒ‰ ๋‹จ๊ณ„๋กœ ๋‚˜๋‰œ๋‹ค.

1๋‹จ๊ณ„: ์ธ๋ฑ์‹ฑ (๋ฐ์ดํ„ฐ ์ €์žฅ)

Documents โ†’ ์ฒญํ‚น โ†’ Nodes โ†’ ์ž„๋ฒ ๋”ฉ โ†’ ๋ฒกํ„ฐ ์ €์žฅ
  1. Documents ์ƒ์„ฑ

    doc = Document(
    	text="๊น€์ฒ ์ˆ˜: ๋ทฐํ‹ฐ ์ „๋ฌธ ์œ ํŠœ๋ฒ„. ์นดํ…Œ๊ณ ๋ฆฌ: ๋ทฐํ‹ฐ, ๋ผ์ดํ”„์Šคํƒ€์ผ. ํŒ”๋กœ์›Œ: 150000๋ช….",
      metadata={"influencer_id": "123", "total_followers": 150000},
    )

    ์ธํ”Œ๋ฃจ์–ธ์„œ 50๋ช…์ด๋ฉด Document 50๊ฐœ๊ฐ€ ๋งŒ๋“ค์–ด์ง„๋‹ค.

  2. ์ฒญํ‚น โ†’ Nodes

    Document 1 ("๊น€์ฒ ์ˆ˜: ๋ทฐํ‹ฐ ์ „๋ฌธ ์œ ํŠœ๋ฒ„...") โ†’ Node 1
    Document 2 ("์ด์˜ํฌ: ์Šคํ‚จ์ผ€์–ด ์ „๋ฌธ...") โ†’ Node 2
    Document 3 ("๋ฐ•์ง€๋ฏผ: ๋ฉ”์ดํฌ์—… ์ „๋ฌธ...") โ†’ Node 3
    ...

    ์ด ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ธํ”Œ๋ฃจ์–ธ์„œ ํ•œ ๋ช…๋‹น ํ…์ŠคํŠธ๊ฐ€ ์งง์•„์„œ Document 1๊ฐœ = Node 1๊ฐœ์ด๋‹ค.
    ๋งŒ์•ฝ ํ…์ŠคํŠธ๊ฐ€ ๊ธธ์—ˆ๋‹ค๋ฉด Document 1๊ฐœ๊ฐ€ ์—ฌ๋Ÿฌ Node๋กœ ์ชผ๊ฐœ์ง„๋‹ค.

  3. ์ž„๋ฒ ๋”ฉ (ํ•ต์‹ฌ)
    ๊ฐ Node์˜ ํ…์ŠคํŠธ๋ฅผ ์ˆซ์ž ๋ฐฐ์—ด(๋ฒกํ„ฐ)๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค. ์ด๊ฒŒ VectorStoreIndex์˜ ํ•ต์‹ฌ์ด๋‹ค.

    Node 1 "๊น€์ฒ ์ˆ˜: ๋ทฐํ‹ฐ ์ „๋ฌธ ์œ ํŠœ๋ฒ„..."
        โ†“ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ (OpenAI text-embedding-ada-002)
       [0.12, -0.34, 0.56, 0.01, ..., 0.78]   โ† 1536์ฐจ์› ๋ฒกํ„ฐ
    
    Node 2 "์ด์˜ํฌ: ์Šคํ‚จ์ผ€์–ด ์ „๋ฌธ..."
        โ†“ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ
        [0.11, -0.33, 0.55, 0.02, ..., 0.77]   โ† ๋ทฐํ‹ฐ์™€ ๋น„์Šท โ†’ ๋ฒกํ„ฐ๋„ ๋น„์Šท!
    
    Node 3 "์ •๋ฏผ์ˆ˜: ๊ฒŒ์ž„ ์ŠคํŠธ๋ฆฌ๋จธ..."
        โ†“ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ
        [-0.45, 0.67, -0.12, 0.89, ..., 0.23]  โ† ๋ทฐํ‹ฐ์™€ ๋‹ค๋ฆ„ โ†’ ๋ฒกํ„ฐ๋„ ๋‹ค๋ฆ„!

    ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ด์œ ๋Š”, ํ…์ŠคํŠธ๋ผ๋ฆฌ๋Š” "์˜๋ฏธ์  ์œ ์‚ฌ๋„"๋ฅผ ์ง์ ‘ ๊ณ„์‚ฐํ•  ์ˆ˜ ์—†์ง€๋งŒ, ๋ฒกํ„ฐ๋ผ๋ฆฌ๋Š” ์ˆ˜ํ•™์ ์œผ๋กœ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  4. ๋ฒกํ„ฐ ์ €์žฅ
    ๋ณ€ํ™˜๋œ ๋ฒกํ„ฐ๋“ค์„ Vector Store์— ์ €์žฅํ•œ๋‹ค.์ด ๊ณผ์ •์ด VectorStoreIndex.from_documents(documents) ํ•œ ์ค„๋กœ ์ „๋ถ€ ์‹คํ–‰๋œ๋‹ค.

2๋‹จ๊ณ„: ๊ฒ€์ƒ‰ (์งˆ์˜)

์งˆ์˜ โ†’ ์งˆ์˜ ์ž„๋ฒ ๋”ฉ โ†’ ์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„ ๊ณ„์‚ฐ โ†’ ์ƒ์œ„ K๊ฐœ ๋…ธ๋“œ ๋ฐ˜ํ™˜
  1. ์งˆ์˜ ์ž„๋ฒ ๋”ฉ
    ์‚ฌ์šฉ์ž์˜ ์งˆ์˜๋„ ๋™์ผํ•œ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ๋กœ ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

    "์นœํ™˜๊ฒฝ ๋ทฐํ‹ฐ ์ธํ”Œ๋ฃจ์–ธ์„œ ์ถ”์ฒœํ•ด์ค˜"
       โ†“ ๊ฐ™์€ ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ
       [0.13, -0.31, 0.54, 0.03, ..., 0.76]   โ† ์งˆ์˜ ๋ฒกํ„ฐ

    ๊ฐ™์€ ๋ชจ๋ธ์„ ์จ์•ผ ๊ฐ™์€ ๋ฒกํ„ฐ ๊ณต๊ฐ„์—์„œ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค. ์ธ๋ฑ์‹ฑ ๋•Œ OpenAI ๋ชจ๋ธ์„ ์ผ์œผ๋ฉด, ๊ฒ€์ƒ‰ ๋•Œ๋„ OpenAI ๋ชจ๋ธ์„ ์จ์•ผ ํ•œ๋‹ค.

  2. ์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„ ๊ณ„์‚ฐ
    ์งˆ์˜ ๋ฒกํ„ฐ์™€ ์ €์žฅ๋œ ๋ชจ๋“  ๋ฒกํ„ฐ ์‚ฌ์ด์˜ ์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค.
    ์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„๋Š” ๋‘ ๋ฒกํ„ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฐฉํ–ฅ์ด ์–ผ๋งˆ๋‚˜ ๋น„์Šทํ•œ์ง€๋ฅผ -1~1 ์‚ฌ์ด ๊ฐ’์œผ๋กœ ๋‚˜ํƒ€๋‚ธ ๊ฒƒ์œผ๋กœ, 1์— ๊ฐ€๊นŒ์šฐ๋ฉด ์˜๋ฏธ๊ฐ€ ๋น„์Šทํ•˜๊ณ , 0์— ๊ฐ€๊นŒ์šฐ๋ฉด ๊ด€๋ จ์ด ์—†๊ณ , -1์— ๊ฐ€๊นŒ์šฐ๋ฉด ์˜๋ฏธ๊ฐ€ ๋ฐ˜๋Œ€์ด๋‹ค.

    ์งˆ์˜ ๋ฒกํ„ฐ: [0.13, -0.31, 0.54, ...]  ("์นœํ™˜๊ฒฝ ๋ทฐํ‹ฐ ์ธํ”Œ๋ฃจ์–ธ์„œ ์ถ”์ฒœํ•ด์ค˜")
    
    vs Node 1 [0.12, -0.34, 0.56, ...]  ("๊น€์ฒ ์ˆ˜: ๋ทฐํ‹ฐ ์ „๋ฌธ ์œ ํŠœ๋ฒ„")
     โ†’ ์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„: 0.94  โœ… ๋งค์šฐ ์œ ์‚ฌ!
    
    vs Node 2 [0.11, -0.33, 0.55, ...]  ("์ด์˜ํฌ: ์Šคํ‚จ์ผ€์–ด ์ „๋ฌธ")
     โ†’ ์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„: 0.91  โœ… ์œ ์‚ฌ!
    
    vs Node 3 [-0.45, 0.67, -0.12, ...]  ("์ •๋ฏผ์ˆ˜: ๊ฒŒ์ž„ ์ŠคํŠธ๋ฆฌ๋จธ")
     โ†’ ์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„: 0.23  โŒ ๊ด€๋ จ ์—†์Œ
  3. ์ƒ์œ„ K๊ฐœ ๋…ธ๋“œ ๋ฐ˜ํ™˜
    ์œ ์‚ฌ๋„ ์ ์ˆ˜๊ฐ€ ๋†’์€ ์ˆœ์„œ๋กœ ์ •๋ ฌํ•˜์—ฌ ์ƒ์œ„ K๊ฐœ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

    similarity_top_k=3 ์ด๋ฉด:
    
    1์œ„: Node 1 (๊น€์ฒ ์ˆ˜: ๋ทฐํ‹ฐ ์ „๋ฌธ)     ์œ ์‚ฌ๋„: 0.94
    2์œ„: Node 2 (์ด์˜ํฌ: ์Šคํ‚จ์ผ€์–ด ์ „๋ฌธ)  ์œ ์‚ฌ๋„: 0.91
    3์œ„: Node 7 (๋ฐ•์ง€๋ฏผ: ๋ฉ”์ดํฌ์—… ์ „๋ฌธ)  ์œ ์‚ฌ๋„: 0.88
    โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
    4์œ„: Node 5 (์ตœ์ˆ˜์ง„: ํŒจ์…˜ ์ „๋ฌธ)     ์œ ์‚ฌ๋„: 0.72  โ† ์—ฌ๊ธฐ๋ถ€ํ„ฐ ์ž˜๋ฆผ
    ...

โœ… ์ฃผ์š” ์ธ๋ฑ์Šค ์œ ํ˜•

์ธ๋ฑ์Šค์„ค๋ช…์šฉ๋„
VectorStoreIndex๋ฒกํ„ฐ ์œ ์‚ฌ๋„ ๊ธฐ๋ฐ˜ ๊ฒ€์ƒ‰๊ฐ€์žฅ ๋ฒ”์šฉ์ , ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰
KnowledgeGraphIndex์ง€์‹ ๊ทธ๋ž˜ํ”„ ๊ตฌ์กฐ์—”ํ‹ฐํ‹ฐ ๊ฐ„ ๊ด€๊ณ„ ํŒŒ์•…
SummaryIndex์ „์ฒด ๋ฌธ์„œ ์š”์•ฝ๋ฌธ์„œ ์ „์ฒด๋ฅผ ๋‹ค ์ฝ์–ด์•ผ ํ•  ๋•Œ
TreeIndexํŠธ๋ฆฌ ๊ตฌ์กฐ ์š”์•ฝ๊ณ„์ธต์  ์š”์•ฝ
KeywordTableIndexํ‚ค์›Œ๋“œ ๊ธฐ๋ฐ˜ ๊ฒ€์ƒ‰์ •ํ™•ํ•œ ํ‚ค์›Œ๋“œ ๋งค์นญ

๐ŸŒŸ ํ•ต์‹ฌ ๊ฐœ๋… 4: Retriever & Query Engine

์ด ๋‘˜์˜ ์ฐจ์ด๋ฅผ ํ•œ ๋งˆ๋””๋กœ ํ•˜๋ฉด, Retriever๋Š” ๊ฒ€์ƒ‰๋งŒ, Query Engine์€ ๊ฒ€์ƒ‰ + LLM ๋‹ต๋ณ€ ์ƒ์„ฑ์ด๋‹ค.

โœ… Retriever: ๊ด€๋ จ ๋ฌธ์„œ๋ฅผ ์ฐพ์•„์˜ค๊ธฐ๋งŒ ํ•˜๋Š” ๊ฒƒ

retriever = index.as_retriever(similarity_top_k=5)
nodes = retriever.retrieve("๋ทฐํ‹ฐ ์นดํ…Œ๊ณ ๋ฆฌ ์ธํ”Œ๋ฃจ์–ธ์„œ ์ฐพ์•„์ค˜")
  • ๋™์ž‘ ๊ณผ์ •
  • ๋ฐ˜ํ™˜๋˜๋Š” nodes์˜ ํ˜•ํƒœ

    for node in nodes:
    	print(node.get_text())  # "๊น€์ฒ ์ˆ˜: ๋ทฐํ‹ฐ ์ „๋ฌธ ์œ ํŠœ๋ฒ„. ์นดํ…Œ๊ณ ๋ฆฌ: ๋ทฐํ‹ฐ, ๋ผ์ดํ”„์Šคํƒ€์ผ..."
       print(node.get_score()) # 0.9234 (์œ ์‚ฌ๋„ ์ ์ˆ˜)
       print(node.metadata)    # {"influender_id": "123", "total_followers": 150000}
  • LLM์„ ์ „ํ˜€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ๋กœ ๋ฒกํ„ฐ ์œ ์‚ฌ๋„๋งŒ ๊ณ„์‚ฐํ•ด์„œ ๊ฒฐ๊ณผ๋ฅผ ๋Œ๋ ค์ค€๋‹ค. ๊ทธ๋ž˜์„œ ๋น ๋ฅด๊ณ  ๋น„์šฉ๋„ ์ ๋‹ค.

โœ… Query Engine: ๊ฒ€์ƒ‰ํ•˜๊ณ  LLM์ด ๋‹ต๋ณ€๊นŒ์ง€ ์ƒ์„ฑ

query_engine = index.as_query_engine(similarity_top_k=5)
response = query_engine.query("๋ทฐํ‹ฐ ์นดํ…Œ๊ณ ๋ฆฌ ์ธํ”Œ๋ฃจ์–ธ์„œ ์ถ”์ฒœํ•ด์ค˜")
  • ๋™์ž‘ ๊ณผ์ •

  • LLM์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ, ์ž์—ฐ์–ด๋กœ ์ •๋ฆฌ๋œ ๋‹ต๋ณ€์ด ๋‚˜์˜จ๋‹ค.

โœ… ๊ฐ™์€ ์งˆ๋ฌธ, ๋‹ค๋ฅธ ๊ฒฐ๊ณผ


๐ŸŒŸ ํ•ต์‹ฌ ๊ฐœ๋… 5: Storage (์ €์žฅ)

โœ… ์™œ ์ €์žฅ์ด ํ•„์š”ํ•œ๊ฐ€?

VectorStoreIndex.from_documents()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋‚ด๋ถ€์ ์œผ๋กœ ๋ชจ๋“  Documents์— ๋Œ€ํ•ด ์ž„๋ฒ ๋”ฉ API๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

  • ์ธํ”Œ๋ฃจ์–ธ์„œ 50๋ช… ์ธ๋ฑ์‹ฑ ์‹œ: ์ž„๋ฒ ๋”ฉ API ํ˜ธ์ถœ 50๋ฒˆ โžก๏ธ ๋น„์šฉ ๋ฐœ์ƒ + ์‹œ๊ฐ„ ์†Œ์š”
  • ๋‹ค์Œ์— ์•ฑ์„ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋ฉด: ๋˜ 50๋ฒˆ ํ˜ธ์ถœ? โžก๏ธ ๋ˆ ๋‚ญ๋น„ + ์‹œ๊ฐ„ ๋‚ญ๋น„

๊ทธ๋ž˜์„œ ํ•œ ๋ฒˆ ๋งŒ๋“  ์ธ๋ฑ์Šค๋ฅผ ๋””์Šคํฌ์— ์ €์žฅํ•ด๋‘๊ณ , ๋‹ค์Œ์—๋Š” ์ €์žฅ๋œ ๊ฒƒ์„ ๋กœ๋“œ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค. ์ž„๋ฒ ๋”ฉ API๋ฅผ ๋‹ค์‹œ ํ˜ธ์ถœํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

โœ… ๋ฐฉ๋ฒ• 1: ๋กœ์ปฌ ํŒŒ์ผ ์ €์žฅ (LlamaIndex ๊ธฐ๋ณธ ์ œ๊ณต)

index.storage_context.persist(persist_dir="./storage")

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ./storage/ ํด๋”์— JSON ํŒŒ์ผ๋“ค์ด ์ƒ๊ธด๋‹ค.

./storage/
โ”œโ”€โ”€ docstore.json          โ† Document/Node ์›๋ณธ ํ…์ŠคํŠธ + ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ
โ”œโ”€โ”€ index_store.json       โ† ์ธ๋ฑ์Šค ๊ตฌ์กฐ ์ •๋ณด
โ””โ”€โ”€ default__vector_store.json  โ† ์ž„๋ฒ ๋”ฉ ๋ฒกํ„ฐ๊ฐ’๋“ค

๋”ฐ๋ผ์„œ ๋‹ค์Œ ์‹คํ–‰ ์‹œ์—๋Š” ๋กœ๋“œ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.

from llama_index.core import StorageContext, load_index_from_storage

storage_context = StorageContext.from_defaults(persist_dir="./storage")
index = load_index_from_storage(storage_context)
  • ์žฅ์ : ๋ณ„๋„ DB ์„ค์น˜ ์—†์ด ๋ฐ”๋กœ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ๋‹จ์ : ๋กœ๋“œ ์‹œ ๋ชจ๋“  ๋ฒกํ„ฐ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ฆฐ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ˆ˜์‹ญ๋งŒ ๊ฑด ์ด์ƒ์ด๋ฉด ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ถ€์กฑํ•˜๋‹ค.

โœ… ๋ฐฉ๋ฒ• 2: ๋ฒกํ„ฐ DB ์—ฐ๋™ (ChromaDB)

import chromadb
from llama_index.vector_stores.chroma import ChromaVectorStore

# chromaDB ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ (๋””์Šคํฌ์— ์˜๊ตฌ ์ €์žฅ)
chroma_client = chromadb.PersistentClient(path="./chroma_db")

# ์ปฌ๋ ‰์…˜ = ๋ฒกํ„ฐ๋ฅผ ๋‹ด๋Š” ๊ทธ๋ฃน (DB์˜ ํ…Œ์ด๋ธ”๊ณผ ๋น„์Šทํ•œ ๊ฐœ๋…)
collection = chroma_client.get_or_create_collection("influencer_profiles")

## LlamaIndex๊ฐ€ ์ด ์ปฌ๋ ‰์…˜์„ ๋ฒกํ„ฐ ์ €์žฅ์†Œ๋กœ ์‚ฌ์šฉํ•˜๋„๋ก ์—ฐ๊ฒฐ
vector_store = ChromaVectorStore(chroma_collection=collection)

๋””์Šคํฌ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ ์ €์žฅ๋œ๋‹ค.

./chroma_db/
โ”œโ”€โ”€ chroma.sqlite3          โ† ๋ฒกํ„ฐ + ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ SQLite๋กœ ์ €์žฅ๋จ
โ””โ”€โ”€ [๋‚ด๋ถ€ ํŒŒ์ผ๋“ค...]
  • ์žฅ์ : ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ณ , ํ•„์š”ํ•œ ๋ฒกํ„ฐ๋งŒ ์ฝ์–ด์˜จ๋‹ค. ๊ฒ€์ƒ‰ ์ตœ์ ํ™”๊ฐ€ ๋‚ด์žฅ๋˜์–ด ์žˆ๋‹ค.
  • ๋‹จ์ : ๋ณ„๋„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•ด์•ผ ํ•œ๋‹ค. (pip install chromadb)

โœ… ๋‘ ๋ฐฉ์‹์˜ ์ฐจ์ด

๋กœ์ปฌ ํŒŒ์ผ์— ์ €์žฅChromaDB์— ์ €์žฅ
์ €์žฅindexโ†’JSON ํŒŒ์ผ๋กœ ์ง๋ ฌํ™”indexโ†’ChromaDB๊ฐ€ ์ž์ฒด ํ˜•์‹์œผ๋กœ ์ €์žฅ
๋กœ๋“œJSON ํŒŒ์ผ ์ „์ฒด๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ฆผ์—ฐ๊ฒฐ๋งŒ ๋งบ๊ณ , ์‹ค์ œ ๋ฐ์ดํ„ฐ๋Š” ๊ฒ€์ƒ‰ ์‹œ์—๋งŒ ์ฝ์Œ
๊ฒ€์ƒ‰๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋ฒกํ„ฐ ๋น„๊ตChromaDB๊ฐ€ ์ตœ์ ํ™”๋œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ๋ฒกํ„ฐ ๋น„๊ต

๐ŸŒŸ RAG (Retrieval-Augmented Generation)

LlamaIndex์˜ ๊ฐ€์žฅ ๋Œ€ํ‘œ์ ์ธ ํŒจํ„ด์ด๋‹ค.

  • RAG๊ฐ€ ์—†์œผ๋ฉด: LLM์ด ํ•™์Šต ๋ฐ์ดํ„ฐ๋งŒ์œผ๋กœ ๋‹ต๋ณ€ (ํ™˜๊ฐ ์œ„ํ—˜)
  • RAG๊ฐ€ ์žˆ์œผ๋ฉด: ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทผ๊ฑฐ๋กœ ๋‹ต๋ณ€ (์ •ํ™•๋„ ํ–ฅ์ƒ)

๐ŸŒŸ LlamaIndex์˜ ์•„ํ‚คํ…์ฒ˜ ๊ณ„์ธต

1. Connection Layer (์—ฐ๊ฒฐ ๊ณ„์ธต)

  • ์—ญํ• : ์„ธ์ƒ์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” '์ž…๊ตฌ'์ด๋‹ค.
  • ํ•ต์‹ฌ ์š”์†Œ: Data Loaders (LlamaHub)
  • ์ƒ์„ธ: PDF, Notion, Slack, SQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋“ฑ ํฉ์–ด์ ธ ์žˆ๋Š” ์›๋ณธ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด์˜จ๋‹ค. LlamaHub๋Š” ์ˆ˜๋ฐฑ ๊ฐœ์˜ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ์—ฐ๊ฒฐํ•ด ์ฃผ๋Š” ์ผ์ข…์˜ '์–ด๋Œ‘ํ„ฐ ์‹œ์žฅ'๊ณผ ๊ฐ™๋‹ค.

2. Data Layer (๋ฐ์ดํ„ฐ ๊ณ„์ธต)

  • ์—ญํ• : ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ AI๊ฐ€ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ์ข‹๊ฒŒ '์†์งˆ'ํ•˜๋Š” ๊ณณ์ด๋‹ค.
  • ํ•ต์‹ฌ ์š”์†Œ: Document, Node, Embedding
  • ์ƒ์„ธ
    • Document: ํŒŒ์ผ ์ „์ฒด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ํฐ ๋‹จ์œ„์ด๋‹ค.
    • Node: ๋ฌธ์„œ๋ฅผ SentenceSplitter ๋“ฑ์œผ๋กœ ์ชผ๊ฐ  ์ž‘์€ ์กฐ๊ฐ(Chunk)์ด๋‹ค. ๊ฒ€์ƒ‰์˜ ์ตœ์†Œ ๋‹จ์œ„๊ฐ€ ๋œ๋‹ค.
    • Embedding: ํ…์ŠคํŠธ ์กฐ๊ฐ์„ ์ˆซ์ž๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์˜๋ฏธ๋ฅผ ๋ถ€์—ฌํ•œ๋‹ค.

3. Index Layer (์ธ๋ฑ์Šค ๊ณ„์ธต)

  • ์—ญํ• : ์†์งˆ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ๊ธฐ ์‰ฝ๊ฒŒ '์ •๋ฆฌ'ํ•˜์—ฌ ์ €์žฅํ•˜๋Š” ์ฐฝ๊ณ ์ด๋‹ค.
  • ํ•ต์‹ฌ ์š”์†Œ: VectorStore, KG(Knowledge Graph), Summary Index
  • ์ƒ์„ธ
    • VectorStore: ChromaDB์ฒ˜๋Ÿผ ๋ฒกํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์œ ์‚ฌ๋„ ๊ฒ€์ƒ‰์„ ์ง€์›ํ•œ๋‹ค.
    • KG: ๋ฐ์ดํ„ฐ ๊ฐ„์˜ ๊ด€๊ณ„(์ฒ ์ˆ˜-์•„๋น -์˜ํฌ)๋ฅผ ๊ทธ๋ž˜ํ”„ ํ˜•ํƒœ๋กœ ์ €์žฅํ•œ๋‹ค.
    • Summary Index: ๋ฌธ์„œ ์ „์ฒด์˜ ์š”์•ฝ๋ณธ์„ ๊ด€๋ฆฌํ•œ๋‹ค.

4. Orchestration Layer (์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ ๊ณ„์ธต)

  • ์—ญํ• : ์งˆ๋ฌธ์— ๋งž๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ๊ณ  ๋‹ต๋ณ€์„ ๋งŒ๋“œ๋Š” '์ง€ํœ˜์ž'์ด๋‹ค.
  • ํ•ต์‹ฌ ์š”์†Œ: Retriever, Response Synthesizer
  • ์ƒ์„ธ
    • Retriever: ์งˆ๋ฌธ๊ณผ ๊ฐ€์žฅ ๊ด€๋ จ ์žˆ๋Š” ๋…ธ๋“œ(Node)๋ฅผ ์ธ๋ฑ์Šค์—์„œ ์ฐพ์•„์˜จ๋‹ค.
    • Response Synthesizer: ์ฐพ์•„์˜จ ๋…ธ๋“œ๋“ค๊ณผ ์งˆ๋ฌธ์„ ํ•ฉ์ณ LLM์—๊ฒŒ ์ „๋‹ฌํ•˜๊ณ , ์ตœ์ข… ๋‹ต๋ณ€์„ ์กฐ๋ฆฝํ•œ๋‹ค.

5. Application Layer (์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ณ„์ธต)

  • ์—ญํ• : ์‚ฌ์šฉ์ž๊ฐ€ ์‹ค์ œ๋กœ ๋งˆ์ฃผํ•˜๋Š” '์„œ๋น„์Šค ์ฐฝ๊ตฌ'์ด๋‹ค.
  • ํ•ต์‹ฌ ์š”์†Œ: Query Engine, Chat Engine, Agent
  • ์ƒ์„ธ
    • Query Engine: ๋‹จ๋ฐœ์„ฑ ์งˆ๋ฌธ์— ๋‹ตํ•œ๋‹ค. (์˜ˆ: "์ด ๋ฌธ์„œ ์š”์•ฝํ•ด์ค˜")
    • Chat Engine: ๋Œ€ํ™” ๋งฅ๋ฝ์„ ๊ธฐ์–ตํ•˜๋ฉฐ ๋Œ€ํ™”ํ•œ๋‹ค. (์˜ˆ: "๋ฐฉ๊ธˆ ๋งํ•œ ๊ฑฐ ๋” ์ž์„ธํžˆ ์•Œ๋ ค์ค˜")
    • Agent: ์Šค์Šค๋กœ ํŒ๋‹จํ•˜์—ฌ ์–ด๋–ค ๋„๊ตฌ๋ฅผ ์“ธ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๋˜‘๋˜‘ํ•œ ๋น„์„œ์ด๋‹ค.

๐ŸŒŸ ๋ฐ์ดํ„ฐ ์ปค๋„ฅํ„ฐ (LlamaHub)

LlamaIndex๋Š” 160๊ฐœ ์ด์ƒ์˜ ๋ฐ์ดํ„ฐ ์†Œ์Šค ์ปค๋„ฅํ„ฐ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

  • ์›น ํŽ˜์ด์ง€

    from llama_index.readers.web import SimpleWebPageReader
  • PDF

    from llama_index.readers.file import PDFReader
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค

    from llama_index.readers.database import DatabaseReader
  • CSV

    from llama_index.readers.file import CSVReader

์ด ๋ฐ–์—๋„ Notion, Slack, Google Docs ๋“ฑ ์ˆ˜์‹ญ ๊ฐ€์ง€์ด๋‹ค.


๐ŸŒŸ LlamaIndex vs. LangChain

ํ•ญ๋ชฉLlamaIndexLangChain
ํ•ต์‹ฌ ๋ชฉ์ ๋ฐ์ดํ„ฐ ์ธ๋ฑ์‹ฑ & ๊ฒ€์ƒ‰ (RAG)LLM ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜
๊ฐ•์ ๋‹ค์–‘ํ•œ ์ธ๋ฑ์Šค, ์ž„๋ฒ ๋”ฉ, ๊ฒ€์ƒ‰ ์ตœ์ ํ™”Agent, Chain, ๋„๊ตฌ ์—ฐ๊ฒฐ
์ด ํ”„๋กœ์ ํŠธ์—์„œ๋ฒกํ„ฐ ๊ฒ€์ƒ‰, KG ์ธ๋ฑ์ŠคAgent ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ (LangGraph)
๋น„์œ ๋„์„œ๊ด€ ์‚ฌ์„œ (๋ฐ์ดํ„ฐ๋ฅผ ์ •๋ฆฌํ•˜๊ณ  ์ฐพ์•„์คŒ)ํ”„๋กœ์ ํŠธ ๋งค๋‹ˆ์ € (์ž‘์—…์„ ์—ฐ๊ฒฐํ•˜๊ณ  ์กฐ์œจ)

0๊ฐœ์˜ ๋Œ“๊ธ€