Skip to main content

Bronze / Silver / Gold 텍스트 처리 실습 라이브러리

Project description

rag_lab

Bronze / Silver / Gold 3단계로 텍스트를 처리하는 RAG 실습용 라이브러리.

설치

pip install rag-lab-bsg

설치 패키지명은 rag-lab-bsg 이지만, 임포트 이름은 rag_lab 입니다.

노트북 실습용으로 로컬에서 개발 모드로 설치하려면 프로젝트 루트(code/)에서 다음을 한 번만 실행합니다.

uv pip install -e ".[notebook]"

-e 로 설치하면 rag_lab/ 코드를 고칠 때마다 다시 설치할 필요가 없습니다.

단계 요약

단계 함수 입력 출력 핵심 동작
Bronze bronze.to_text(input_path) PDF / TXT / MD data/dummy/bronze.txt 원본 보존, 페이지 사이는 빈 줄로만 구분
Silver silver.split(input_path) bronze.txt data/dummy/silver.jsonl CharacterTextSplitter — 의미 무시, 글자 수로 분할
Gold gold.split(source) silver.jsonl 또는 문자열 data/dummy/gold.jsonl RecursiveCharacterTextSplitter — 단락 → 줄 → 종결 → 어절

각 단계의 함수는

  • 다음 단계 입력으로 쓸 산출물(.txt / .jsonl) 경로를 반환하고
  • 호출 결과를 화면에도 짧게 출력합니다.

요구 사항

  • Python 3.10+
  • langchain-community, langchain-text-splitters, pypdf

실습 가이드 — Bronze → Silver → Gold

practice.ipynb 의 실행 흐름을 그대로 옮긴 단계별 실습 가이드입니다. rag_lab 라이브러리를 import 해서 세 단계를 직접 실행해 봅니다.

사전 준비

from pathlib import Path

from rag_lab import bronze, silver, gold

1. Bronze — 원본 그대로 .txt 로 저장

data/input/ 에 PDF 를 넣어 두면 그 PDF 를 쓰고, 없으면 아래 코드에서 샘플 텍스트 파일을 만들어 그것을 입력으로 씁니다.

INPUT_DIR = Path("data/input")
pdfs = sorted(INPUT_DIR.glob("*.pdf")) if INPUT_DIR.exists() else []

if pdfs:
    input_path = pdfs[0]
else:
    input_path = Path("data/dummy/_sample.txt")
    input_path.parent.mkdir(parents=True, exist_ok=True)
    input_path.write_text(
        "임플란트 시술 매뉴얼 (샘플)\n\n"
        "1. 개요\n임플란트는 치아가 결손된 부위에 인공 치근을 식립하여 자연치와 유사한 기능을 회복하는 치료법이다. "
        "시술은 진단, 식립, 보철 단계로 구분되며 각 단계마다 정밀한 계획이 필요하다.\n\n"
        "2. 적응증\n- 단일 치아 결손\n- 부분 무치악\n- 완전 무치악\n"
        "환자의 골량과 골질, 전신 건강 상태를 종합적으로 평가한 후 시술 여부를 결정한다.\n\n"
        "3. 시술 절차\n3.1 진단 단계\n구강 검사, 파노라마 방사선 촬영, CBCT 영상을 통해 식립 위치를 결정한다. "
        "보철 계획을 먼저 수립한 뒤 역으로 식립 위치를 정하는 보철 주도형 진단이 권장된다.\n"
        "3.2 식립 단계\n국소마취 후 점막을 절개하고 드릴링하여 픽스처를 식립한다. 일차 안정성이 확보되어야 한다.\n"
        "3.3 보철 단계\n골 유착 기간(일반적으로 3~6개월) 이후 인상 채득, 지대주 연결, 최종 보철물 장착으로 마무리된다.\n",
        encoding="utf-8",
    )

bronze_txt = bronze.to_text(input_path)
bronze_txt

실행 결과 예시:

[Bronze] 누비슨 플랫폼 활용 부정 방지 전략.pdf → data/dummy/bronze.txt  (1,848자, PDF, 3페이지 합본)

PosixPath('data/dummy/bronze.txt')

생성된 텍스트는 다음과 같이 확인합니다.

print(bronze_txt.read_text(encoding="utf-8"))

2. Silver — 의미와 무관하게 글자 수로 단순 분할

chunk_size=500 으로 잘라서 다음 단계(Gold)에 넘길 기준 산출물을 만듭니다.

silver_jsonl = silver.split(bronze_txt, chunk_size=500, chunk_overlap=30)
silver_chunks = silver.load_chunks(silver_jsonl)

for c in silver_chunks:
    print(f"#{c['chunk_id']} ({c['char_len']}자) \n {c['text']}...")
    print("========================================================================================")

실행 결과 예시:

[Silver] bronze.txt → data/dummy/silver.jsonl  (4청크, 평균 478자, 최대 500자, chunk_size=500, overlap=30)
#0 (499자)
 누비슨 플랫폼 활용한 부정 방지 전략 및 인프라 제안 ...
#1 (484자)
 데이터를수집합니다.    육안으로는확인하기힘든 ...
#2 (500자)
 ion):Edge AI 단계. ...
#3 (430자)
 에업데이트하여차기경주시예측정확도를높이는학습 ...

CharacterTextSplitter 는 우선 separator(기본 "") 로 잘라 낸 뒤에야 chunk_size 를 적용하므로, separator 가 비어 있으면 글자 수에서 딱 끊깁니다. 한국어 문장 중간이 어색하게 잘리는 빈도를 직접 눈으로 확인하는 것이 이 단계의 학습 포인트입니다.

3. Gold — 의미 단위로 재귀 분할

gold.split 은 두 가지 입력을 모두 받습니다.

  • (a) Silver 의 .jsonl 경로 — 청크들을 다시 이어붙여 원본 텍스트로 복원한 뒤 분할
  • (b) raw 텍스트 문자열silver_chunks[0]['text'] 처럼 청크 한 개만 따로 넘기는 경우

separators 우선순위(단락 → 줄 → 종결 → 어절) 대로 잘라 내므로, 같은 chunk_size 라도 Silver 보다 단락/문장 경계가 살아 있을 확률이 높습니다.

여기서는 Silver 의 첫 번째 청크 하나만 다시 의미 단위로 잘게 잘라 봅니다.

gold_jsonl = gold.split(silver_chunks[0]['text'], chunk_size=100, chunk_overlap=30)
gold_chunks = gold.load_chunks(gold_jsonl)

for c in gold_chunks:
    print(f"#{c['chunk_id']} ({c['char_len']}자) \n {c['text']}...")
    print("========================================================================================")

실행 결과 예시:

[Gold] <text 499자> → data/dummy/gold.jsonl  (8청크, 평균 60자, chunk_size=100, overlap=30)
#0 (88자)
 누비슨 플랫폼 활용한 부정 방지 전략 및 인프라 제안 ...
#1 (58자)
 단순한'  사후적발'   을넘어 '     사전예방및실시간차단 ' ...
#2 (68자)
 누비슨플랫폼을활용해부정행위를방지하고예측하는구체적인전략을제안합니다 . ...
#3 (44자)
 선수와자전거에부착된센서를통해신체데이터와물리적데이터를실시간으로수집하여분석합니다 . ...
#4 (58자)
 ●   생체데이터모니터링 :  선수의심박수, ...
...

Silver chunk_size=500 으로 만든 한 청크(499자)를 Gold chunk_size=100 으로 다시 자르면 8개 청크, 평균 60자가 나옵니다. 단락 / 줄 / 다. / 요. 구분자가 우선순위대로 적용되어 의미 경계에서 끊기는 빈도가 올라갑니다.

Silver vs Gold 비교

청크 개수, 평균/최소/최대 길이를 한눈에 비교해 봅니다.

def stats(chunks):
    lens = [c["char_len"] for c in chunks] or [0]
    return {
        "개수": len(chunks),
        "평균": round(sum(lens) / len(lens), 1),
        "최소": min(lens),
        "최대": max(lens),
    }

print("Silver:", stats(silver_chunks))
print("Gold  :", stats(gold_chunks))

print("\n— Silver #0 ——————————————")
print(silver_chunks[0]["text"])
print("\n— Gold #0 ————————————————")
print(gold_chunks[0]["text"])

실행 결과 예시:

Silver: {'개수': 4, '평균': 478.2, '최소': 430, '최대': 500}
Gold  : {'개수': 8, '평균': 60.5, '최소': 27, '최대': 88}

같은 원본 일부(Silver #0, 499자)를 Gold 가 다시 평균 60자 단위로 잘게 쪼개면서, 시작 지점이 자연스러운 단락 경계(누비슨 플랫폼 활용한 부정 방지 전략 및 인프라 제안 으로 시작) 에 맞춰진 것을 확인할 수 있습니다.

4. 직접 바꿔 보기

다음을 바꿔 가며 결과 차이를 관찰해 봅니다.

  • Silver chunk_size 를 100 / 300 / 800 등으로 바꿔 청크 수와 평균 길이가 어떻게 달라지는지
  • Gold separators 리스트에서 "다. ", "요. " 를 맨 앞으로 옮기면 한국어 종결 경계가 얼마나 더 잘 살아나는지
  • Silver 의 다른 청크(silver_chunks[1]['text'] 등) 를 Gold 에 넣어 단락별로 어떻게 잘리는지

separators 순서를 바꿔서 Gold 결과를 비교하는 예시입니다.

gold.split(
    silver_chunks[0]['text'],
    output_path="data/dummy/_gold_custom.jsonl",
    chunk_size=100,
    chunk_overlap=30,
    separators=["다. ", "요. ", "\n\n", "\n", ". ", " ", ""],
)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rag_lab_bsg-0.1.4.tar.gz (8.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rag_lab_bsg-0.1.4-py3-none-any.whl (11.1 kB view details)

Uploaded Python 3

File details

Details for the file rag_lab_bsg-0.1.4.tar.gz.

File metadata

  • Download URL: rag_lab_bsg-0.1.4.tar.gz
  • Upload date:
  • Size: 8.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.6.3

File hashes

Hashes for rag_lab_bsg-0.1.4.tar.gz
Algorithm Hash digest
SHA256 b7a7b205068d2b991d40dbe2bb10c64aec74eb3a27238d412d6b9db06540b969
MD5 42b22dc1465cfd1406eed3c12ead8d5d
BLAKE2b-256 9c5198b1c7611af03359e85df340996d27553affbfee6ed10b81a870158c538a

See more details on using hashes here.

File details

Details for the file rag_lab_bsg-0.1.4-py3-none-any.whl.

File metadata

File hashes

Hashes for rag_lab_bsg-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 f1c749e43a9104a2251f149081b73b1088193f986e4fac7799492833bc747974
MD5 e0e02e8dae4980cddfa72a1787d91387
BLAKE2b-256 c45b5e4a3ebd7c1f128e99c76793970a3e09173156da1e8175ee35d067ea4d5f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page