โ† ๋ฉ”์ธ์œผ๋กœ

๐Ÿง  RAG ๊ตฌ์ถ• ๊ณ„ํš

๊ฒ€์ธก์š”์ฒญ์„œ PDF ์ž๋™ ๊ฒ€์ƒ‰ ยท ์–ด์ œ(2026-06-30) ์กฐ์‚ฌ ๊ฒฐ๊ณผ + ๊ตฌ์ถ• ํŒจํ„ด ๋ฉ”๋ชจ

โธ๏ธ ํ˜„์žฌ ์ƒํƒœ: ๋ณด๋ฅ˜

ํŠธ๋ฆฌ๊ฑฐ ์กฐ๊ฑด: ๊ฒ€์ธก์š”์ฒญ์„œ PDF๊ฐ€ ์ˆ˜์‹ญ~์ˆ˜๋ฐฑ ์žฅ ๋ชจ์ด๋ฉด ์ง„ํ–‰. ํ˜„์žฌ ๋ฐ์ดํ„ฐ ๋ถ€์กฑ โ†’ ์ฝ”๋“œ ์ž‘์„ฑ 0, ํŒจํ„ด๋งŒ ํ™•๋ฆฝ.

๋‹ค์Œ ์•ก์…˜: ๊ฒ€์ธก์š”์ฒญ์„œ ๋ˆ„์  โ†’ 50์žฅ ์ด์ƒ ์‹œ PoC (1์žฅ) โ†’ 5์žฅ โ†’ ์ „๋Ÿ‰ ์ˆœ์„œ๋กœ ์ธ๋ฑ์‹ฑ.

๐Ÿ“‘ ๋ชฉ์ฐจ 1. RAG๋ž€? (์ดˆ๋“ฑํ•™์ƒ์šฉ ๋น„์œ ) 2. ํ™•๋ฆฝ๋œ ๊ตฌ์ถ• ํŒจํ„ด (2026-06-30) 3. ๊ธฐ์ˆ  ์Šคํƒ (bge-m3 + ChromaDB) 4. PoC ์ฝ”๋“œ (1์žฅ ํ…Œ์ŠคํŠธ์šฉ) 5. ์˜ต์…˜ ๋น„๊ต (์Šคํฌ๋ฆฝํŠธ vs MCP) 6. ์ง„ํ–‰ ํŠธ๋ฆฌ๊ฑฐ & ์ฒดํฌ๋ฆฌ์ŠคํŠธ 7. ์•Œ๋ ค์ง„ ํ•จ์ •

1. RAG๋ž€? (์ดˆ๋“ฑํ•™์ƒ์šฉ ๋น„์œ )

AI ์ฑ…์ƒ ์œ„์˜ ๋น„์„œ

๐Ÿค– AI(LLM)๋Š” ๊ณต๋ถ€๋งŒ ๋งŽ์ด ํ•ด์„œ "์šฐ๋ฆฌ ํšŒ์‚ฌ ๋งค๋‰ด์–ผ", "์†Œ์žฅ๋‹˜ ๊ฒ€์ธก์š”์ฒญ์„œ" ๊ฐ™์€ ๊ฑด ๋ชฐ๋ผ์š”.

๐Ÿ’ก RAG = "์งˆ๋ฌธํ•˜๊ธฐ ์ „์— ์ฑ…์ƒ ์œ„์— ๊ด€๋ จ ๋ฌธ์„œ ํŽผ์ณ๋†“๊ธฐ"

๐Ÿ• ํ”ผ์ž ๊ฐ€๊ฒŒ ๋น„์œ :
โ€ข AI๋งŒ ์“ธ ๋•Œ: "ํ”ผ์ž ์ฃผ๋ฌธ ๋ฐ›์„๊ฒŒ์š”!" (๋ฉ”๋‰ดํŒ ์•ˆ ๋ด„)
โ€ข RAG ๋ถ™์ด๋ฉด: "ํ”ผ์ž ์ฃผ๋ฌธ ๋ฐ›์„๊ฒŒ์š”!" + ๋ฉ”๋‰ดํŒ ํŽผ์ณ๋†“๊ณ  โ†’ "ํŽ˜ํผ๋กœ๋‹ˆ 12,000์›, ๋ถˆ๊ณ ๊ธฐ 14,000์›์ž…๋‹ˆ๋‹ค" ์ •ํ™•ํžˆ ๋Œ€๋‹ต

๊ตฌ์„ฑ 3๊ฐ€์ง€

2. ํ™•๋ฆฝ๋œ ๊ตฌ์ถ• ํŒจํ„ด (2026-06-30)

โœ… ์–ด์ œ ํ™•์ • โ€” miniMax ์šฐ์„  ์‚ฌ์šฉ

๐Ÿ“‚ ์ง€์› ํŒŒ์ผ ํ˜•์‹ (ํ™•์žฅ ๊ฐ€๋Šฅ)

ํ˜•์‹์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•๋น„๊ณ 
PDFpypdf / vision_analyze (SINDOH)๊ฒ€์ธก์š”์ฒญ์„œ 9์ชฝ SINDOH ํ‘๋ฐฑ โ†’ vision ์šฐ์„ 
DOCX/XLSX/PPTXpython-docx, openpyxl, python-pptx
TXT / HTML์ง์ ‘ read
์ด๋ฏธ์ง€OCR (tesseract) or vision_analyze
์Œ์„ฑwhisperTBM ๋…น์Œ ๋“ฑ
์ด๋ฉ”์ผmailbox ํŒŒ์‹ฑ (.eml/.mbox)

3. ๊ธฐ์ˆ  ์Šคํƒ (bge-m3 + ChromaDB)

๊ณ„์ธต์„ ํƒ์ด์œ 
์ž„๋ฒ ๋”ฉBAAI/bge-m3ํ•œ๊ธ€ ์šฐ์ˆ˜, ๋กœ์ปฌ ๋ฌด๋ฃŒ, 567M params, 8K ํ† ํฐ ์ปจํ…์ŠคํŠธ
Vector DBchromadb (PersistentClient)ํŒŒ์ผ ํ•˜๋‚˜๋ฉด ๋, PostgreSQL ๋ถˆํ•„์š”
๊ฒ€์ƒ‰chromadb query()์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„ ๊ธฐ๋ณธ
๋‹ต๋ณ€ LLMminiMax (๊ธฐ๋ณธ) โ†’ ํ•„์š”์‹œ fallbackFAL/OpenRouter๋ณด๋‹ค ์šฐ์„ 
PDF ํ…์ŠคํŠธpypdf ์šฐ์„ , ๊นจ์ง€๋ฉด vision_analyzeSINDOH ํ‘๋ฐฑ ์ธ์‡„๋Š” vision ํ•„์ˆ˜

๐Ÿ’ฐ ๋น„์šฉ

4. PoC ์ฝ”๋“œ (1์žฅ ํ…Œ์ŠคํŠธ์šฉ)

๊ฒ€์ธก์š”์ฒญ์„œ 1์žฅ๋งŒ ๊ฐ€์ง€๊ณ  1์‹œ๊ฐ„ ์•ˆ์— ์ž‘๋™ ํ™•์ธํ•˜๋Š” ํŒจํ„ด:

4-1. ํŒจํ‚ค์ง€ ์„ค์น˜

uv pip install --python /home/jaekyung/.hermes/hermes-agent/venv/bin/python \
    chromadb sentence-transformers pypdf

4-2. PDF โ†’ ์กฐ๊ฐ โ†’ ์ž„๋ฒ ๋”ฉ

import chromadb
from pypdf import PdfReader
from sentence_transformers import SentenceTransformer
import glob

# 1) DB
client = chromadb.PersistentClient(path="/home/jaekyung/rag-db")
collection = client.get_or_create_collection("inspec-reports")

# 2) ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ (ํ•œ๊ธ€ bge-m3)
model = SentenceTransformer("BAAI/bge-m3")

# 3) PDF ์ฝ๊ธฐ โ†’ ๋‹จ๋ฝ ์กฐ๊ฐ
def pdf_to_chunks(path):
    try:
        reader = PdfReader(path)
        text = "\n\n".join(p.extract_text() or "" for p in reader.pages)
    except Exception:
        # SINDOH ํ‘๋ฐฑ โ†’ vision ํ•„์š” (skill: pdf-split-by-marker)
        text = vision_analyze(path)  # placeholder
    return [c for c in text.split("\n\n") if len(c.strip()) > 30]

# 4) ์ธ๋ฑ์‹ฑ (์žฌ๊ท€)
for pdf in glob.glob("/mnt/ssd500/var/inspec-reports/**/*.pdf", recursive=True):
    chunks = pdf_to_chunks(pdf)
    embs = model.encode(chunks).tolist()
    ids = [f"{pdf}-{i}" for i in range(len(chunks))]
    metadatas = [{"source": pdf, "chunk_id": i} for i in range(len(chunks))]
    collection.add(documents=chunks, embeddings=embs, ids=ids, metadatas=metadatas)
    print(f"โœ“ {pdf}: {len(chunks)} chunks")

4-3. ๊ฒ€์ƒ‰ + ๋‹ต๋ณ€

def rag_search(query: str, n=5):
    q_emb = model.encode([query]).tolist()
    results = collection.query(query_embeddings=q_emb, n_results=n)
    chunks = results["documents"][0]
    sources = [m["source"] for m in results["metadatas"][0]]
    return list(zip(chunks, sources))

# ์‚ฌ์šฉ
for chunk, src in rag_search("์ž‘๋…„ 3์›” ๊ฑด์ถ• ๊ฒ€์ธก"):
    print(f"[{src}]\n{chunk}\n---")

5. ์˜ต์…˜ ๋น„๊ต (์Šคํฌ๋ฆฝํŠธ vs MCP)

์˜ต์…˜์ž‘์—…๋Ÿ‰์žฅ์ ๋‹จ์ 
A. Python ์Šคํฌ๋ฆฝํŠธ 1์‹œ๊ฐ„ ์ฆ‰์‹œ ํ…Œ์ŠคํŠธ, ํ™•์žฅ ์ž์œ ๋„ ์ตœ๊ณ , MCP ํ•จ์ • ์—†์Œ UI ์—†์Œ (CLI/์ฑ„ํŒ…์œผ๋กœ๋งŒ ์‚ฌ์šฉ)
B. RAG MCP ์„œ๋ฒ„ 1์ผ ํ—ค๋ฅด๋ฉ”์Šค ๋„๊ตฌ๋กœ ์ž๋™ ํ†ตํ•ฉ, "๊ฒ€์ธก์š”์ฒญ์„œ ์ฐพ์•„์ค˜" ํ•œ๋งˆ๋”” MCP ๋“ฑ๋ก ํ•จ์ • ๊ฐ€๋Šฅ (chrome-devtools ์ฃฝ์Œ ์‚ฌ๋ก€ ์žˆ์Œ)
๐ŸŽฏ ์†Œ์žฅ๋‹˜ ์ถ”์ฒœ: ์˜ต์…˜ A โ†’ B ์ˆœ์„œ
๋จผ์ € A๋กœ ํŒจํ„ด ๊ฒ€์ฆ, ์•ˆ์ •๋˜๋ฉด B๋กœ ์Šน๊ฒฉ.

6. ์ง„ํ–‰ ํŠธ๋ฆฌ๊ฑฐ & ์ฒดํฌ๋ฆฌ์ŠคํŠธ

๐Ÿš€ ์ง„ํ–‰ ํŠธ๋ฆฌ๊ฑฐ

๐Ÿ“‹ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

7. ์•Œ๋ ค์ง„ ํ•จ์ •

๐Ÿ“… ์ง„ํ–‰ ๋กœ๊ทธ (์˜ˆ์ •)

๋‚ ์งœ๋‹จ๊ณ„์ƒํƒœ
2026-06-30์กฐ์‚ฌ + ํŒจํ„ด ํ™•๋ฆฝ์™„๋ฃŒ
2026-07-01ํ™ˆํŽ˜์ด์ง€ ์นด๋“œ + ๊ณ„ํš ํŽ˜์ด์ง€์™„๋ฃŒ
2026-07-??๊ฒ€์ธก์š”์ฒญ์„œ 50์žฅโ†‘ ํ™•์ธ โ†’ PoC ์‹œ์ž‘๋Œ€๊ธฐ
-์˜ต์…˜ A (Python ์Šคํฌ๋ฆฝํŠธ) PoC๋ฏธ์ •
-์˜ต์…˜ B (MCP ์„œ๋ฒ„) ์Šน๊ฒฉ๋ฏธ์ •

์ž‘์„ฑ: 2026-07-01 ยท ์–ด์ œ(6/30) ์„ธ์…˜ ๋ฉ”๋ชจ ๊ธฐ๋ฐ˜ ยท ๋ฉ”์ธ์œผ๋กœ