진짜, 오랜만에 돌아왔습니다.
입사하고 너무 바쁜 나머지 공부를 하지 못했네요.
추석인 김에 다시 학습을 재개합니다 ✨
오늘의 주제는 LangChain의 Document Loader 중 CSV 데이터를 불러오는 방법입니다.
RAG 파이프라인에서 “데이터를 어떻게 문서화할 것인가”가 출발점이 되는데, 그중 가장 기본이 되는 것이 바로 CSV Loader입니다.
1. 왜 CSV Loader인가?
많은 데이터가 CSV 파일로 저장됩니다.
예를 들어:
- 고객 문의 로그
- 상품 정보 DB 덤프
- 연구 데이터셋
이러한 CSV 파일을 LLM에 연결해 질문-답변(QA)이나 검색·분석에 활용하려면, 먼저 LangChain의 Document 객체로 변환해야 합니다.
이 과정을 간단하게 해주는 도구가 바로 CSVLoader입니다.
기본 사용법
loader = CSVLoader(
file_path="./data/titanic.csv", source_column="PassengerId"
) # CSV 로더 설정, 파일 경로 및 소스 컬럼 지정
docs = loader.load() # 데이터 로드
print(docs[1]) # 데이터 출력
- file_path: CSV 파일 경로
- encoding: 한글 CSV는 utf-8 지정이 안전
이렇게 하면 CSV 한 행(row)이 곧 하나의 Document가 됩니다.
즉, documents는 row 단위 문서 리스트라고 이해할 수 있습니다.
한 번, 첫번째 컬럼의 page_content를 확인해보겠습니다.
print(docs[1].page_content)
출력 결과:
PassengerId: 2
Survived: 1
Pclass: 1
Name: Cumings, Mrs. John Bradley (Florence Briggs Thayer)
Sex: female
Age: 38
SibSp: 1
Parch: 0
Ticket: PC 17599
Fare: 71.2833
Cabin: C85
Embarked: C
CSV 파싱 및 로딩 커스터마이징
LangChain은 Python 내장 csv 모듈을 그대로 활용하기 때문에, csv_args를 통해 다양한 커스터마이징이 가능합니다.
# 컬럼정보:
# PassengerId,Survived,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked
# CSV 파일 경로
loader = CSVLoader(
file_path="./data/titanic.csv",
csv_args={
"delimiter": ",", # 구분자
"quotechar": '"', # 인용 부호 문자
"fieldnames": [
"Passenger ID",
"Survival (1: Survived, 0: Died)",
"Passenger Class",
"Name",
"Sex",
"Age",
"Number of Siblings/Spouses Aboard",
"Number of Parents/Children Aboard",
"Ticket Number",
"Fare",
"Cabin",
"Port of Embarkation",
], # 필드 이름
},
)
# 데이터 로드
docs = loader.load()
# 데이터 출력
print(docs[1].page_content)
출력 결과:
Passenger ID: 1
Survival (1: Survived, 0: Died): 0
Passenger Class: 3
Name: Braund, Mr. Owen Harris
Sex: male
Age: 22
Number of Siblings/Spouses Aboard: 1
Number of Parents/Children Aboard: 0
Ticket Number: A/5 21171
Fare: 7.25
Cabin:
Port of Embarkation: S
👉 각 row가 Key: Value 형태의 텍스트 로 변환되어 저장됩니다.
이렇게 만들어진 page_content 가 이후 Embedding → Vector Store → Retriever에 활용되는 기본 단위가 됩니다.
문서 전체를 XML 문서 형식으로 처리하려는 경우
만약 데이터를 LLM에 XML 포맷으로 전달하고 싶다면 간단히 후처리를 할 수도 있습니다.
row = docs[1].page_content.split("\\n")
row_str = "<row>"
for element in row:
splitted_element = element.split(":")
value = splitted_element[-1]
col = ":".join(splitted_element[:-1])
row_str += f"<{col}>{value.strip()}</{col}>"
row_str += "</row>"
print(row_str)
출력 결과:
<row><PassengerId>2</PassengerId><Survived>1</Survived><Pclass>1</Pclass><Name>Cumings, Mrs. John Bradley (Florence Briggs Thayer)</Name><Sex>female</Sex><Age>38</Age><SibSp>1</SibSp><Parch>0</Parch><Ticket>PC 17599</Ticket><Fare>71.2833</Fare><Cabin>C85</Cabin><Embarked>C</Embarked></row>
for doc in docs[1:]:
row = doc.page_content.split("\\n")
row_str = "<row>"
for element in row:
splitted_element = element.split(":")
value = splitted_element[-1]
col = ":".join(splitted_element[:-1])
row_str += f"<{col}>{value.strip()}</{col}>"
row_str += "</row>"
print(row_str)
source_column 인자를 사용하여 각 행에서 생성된 문서의 출처를 지정하세요. 그렇지 않으면 모든 문서의 출처로 file_path가 사용됩니다.
이는 CSV 파일에서 로드된 문서를 출처를 사용하여 질문에 답하는 체인에 사용할 때 유용합니다.
loader = CSVLoader(
file_path="./data/titanic.csv", source_column="PassengerId"
) # CSV 로더 설정, 파일 경로 및 소스 컬럼 지정
docs = loader.load() # 데이터 로드
print(docs[1]) # 데이터 출력
2. UnstructuredCSVLoader
LangChain에는 단순 CSVLoader 외에도 다양한 변형이 있습니다.
CSV를 HTML 요소 단위로 불러올 수 있습니다.
웹 기반 문서 분석이나 구조적 태깅이 필요한 경우 적합합니다.
from langchain_community.document_loaders.csv_loader import UnstructuredCSVLoader
# 비구조화 CSV 로더 인스턴스 생성
loader = UnstructuredCSVLoader(file_path="./data/titanic.csv", mode="elements")
# 문서 로드
docs = loader.load()
# 첫 번째 문서의 HTML 텍스트 메타데이터 출력
print(docs[0].metadata["text_as_html"][:1000])
출력 결과:
<table><tr><td>PassengerId</td><td>Survived</td><td>Pclass</td><td>Name</td><td>Sex</td><td>Age</td><td>SibSp</td><td>Parch</td><td>Ticket</td><td>Fare</td><td>Cabin</td><td>Embarked</td></tr><tr><td>1</td><td>0</td><td>3</td><td>Braund, Mr. Owen Harris</td><td>male</td><td>22</td><td>1</td><td>0</td><td>A/5 21171</td><td>7.25</td><td/><td>S</td></tr><tr><td>2</td><td>1</td><td>1</td><td>Cumings, Mrs. John Bradley (Florence Briggs Thayer)</td><td>female</td><td>38</td><td>1</td><td>0</td><td>PC 17599</td><td>71.2833</td><td>C85</td><td>C</td></tr><tr><td>3</td><td>1</td><td>3</td><td>Heikkinen, Miss. Laina</td><td>female</td><td>26</td><td>0</td><td>0</td><td>STON/O2. 3101282</td><td>7.925</td><td/><td>S</td></tr><tr><td>4</td><td>1</td><td>1</td><td>Futrelle, Mrs. Jacques Heath (Lily May Peel)</td><td>female</td><td>35</td><td>1</td><td>0</td><td>113803</td><td>53.1</td><td>C123</td><td>S</td></tr><tr><td>5</td><td>0</td><td>3</td><td>Allen, Mr. William Henry</td><td>male</td><td>35</
3. DataFrameLoader
Pandas DataFrame과 결합해 유연한 데이터 로딩이 가능합니다.
즉, pandas로 미리 전처리를 한 뒤 필요한 컬럼만 LangChain 문서로 변환할 수 있죠.
import pandas as pd
# CSV 파일 읽기
df = pd.read_csv("./data/titanic.csv")
마무리
오늘은 LangChain의 CSV Loader와 변형 로더들을 다뤄보았습니다.
- CSV → Document 변환 원리
- csv_args로 커스터마이징
- XML 등 포맷 응용
- UnstructuredCSVLoader, DataFrameLoader 확장
📌 RAG 파이프라인의 시작은 결국 데이터 로딩입니다.
데이터를 어떻게 불러오느냐가 곧 검색 정확도와 응답 품질을 좌우합니다.
읽어주셔서 감사합니다!!