SemanticChunker 사용 시 AttributeError 해결 과정 (feat. Wrapper 클래스)LangChain, SemanticChunker, SentenceTransformer, AttributeError, HuggingFaceEmbeddings최근 RAG(Retrieval-Augmented Generation) 파이프라인의 성능을 높이기 위해, LangChain에서 제공하는 SemanticChunker를 도입하는 과정에서 흥미로운 오류를 만났습니다.
의미 기반으로 텍스트를 분할하기 위해 sentence-transformers 라이브러리로 한국어 임베딩 모델을 불러와 SemanticChunker에 전달했는데, 아래와 같은 에러가 발생했습니다.
AttributeError: 'SentenceTransformer' object has no attribute 'embed_documents'
분명 임베딩 모델 객체를 넘겨줬는데, 왜 embed_documents라는 속성이 없다는 오류가 발생했을까요? 이 글에서는 이 문제의 원인을 분석하고, LangChain의 아키텍처를 이해하며 어떻게 해결했는지 그 과정을 공유하고자 합니다.
문제를 일으켰던 코드는 다음과 같습니다. sentence-transformers로 모델을 로드하여 SemanticChunker의 embeddings 인자로 바로 전달했습니다.
from sentence_transformers import SentenceTransformer
from langchain_experimental.text_splitter import SemanticChunker
# 1. sentence-transformers로 임베딩 모델 직접 로드
model_name = "snunlp/KR-SBERT-V40K-klueNLI-augSTS"
embedding_model = SentenceTransformer(model_name)
# 2. SemanticChunker에 그대로 전달
text_splitter = SemanticChunker(
embeddings=embedding_model, #
breakpoint_threshold_type="percentile"
)
# 3. 문서 생성 시도 -> AttributeError 발생!
chunks = text_splitter.create_documents([full_text])
결론부터 말하면, 이 문제는 **LangChain이 기대하는 '표준 인터페이스'**와 sentence-transformers 라이브러리가 제공하는 객체의 인터페이스가 달라서 발생했습니다.
마치 전기 콘센트와 플러그의 모양이 맞지 않는 것과 같습니다.
**
SemanticChunker(콘센트)**는 LangChain 생태계의 부품으로,embed_documents라는 이름의 메소드('세모 모양 플러그')를 가진 임베딩 객체를 받도록 설계되어 있습니다.**
SentenceTransformer객체 (전자제품)**는encode라는 메소드('동그란 모양 플러그')를 통해 문장을 임베딩합니다.
SemanticChunker는 embedding_model.embed_documents()를 호출하려고 했지만, 실제 객체에는 embed_documents가 없고 encode만 있으니 AttributeError가 발생한 것입니다.
LangChain은 이런 문제를 해결하기 위해 외부 라이브러리를 LangChain 표준에 맞게 감싸주는 래퍼(Wrapper) 클래스를 제공합니다. sentence-transformers를 위한 래퍼가 바로 **HuggingFaceEmbeddings**입니다.
HuggingFaceEmbeddings는 내부에 SentenceTransformer 모델을 품고, 외부에는 LangChain이 알아볼 수 있는 embed_documents 메소드를 노출시켜주는 '모양 변환 어댑터' 역할을 합니다.
# langchain_community에서 어댑터 역할을 할 래퍼 클래스를 임포트
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_experimental.text_splitter import SemanticChunker
# 1. 사용할 모델 이름 정의
model_name = "snunlp/KR-SBERT-V40K-klueNLI-augSTS"
# 2. SentenceTransformer 대신 HuggingFaceEmbeddings 래퍼 사용
# 이제 embedding_model은 LangChain 표준을 따르는 객체가 됩니다.
embedding_model = HuggingFaceEmbeddings(model_name=model_name)
# 3. SemanticChunker에 호환되는 객체 전달
text_splitter = SemanticChunker(
embeddings=embedding_model,
breakpoint_threshold_type="percentile"
)
# 4. 정상적으로 실행됨!
chunks = text_splitter.create_documents([full_text])
print("성공적으로 청킹 완료!")
이번 오류 해결 과정을 통해 다음과 같은 중요한 점을 배울 수 있었습니다.
LangChain과 같은 프레임워크는 단순히 기능의 집합이 아니라, 정해진 '약속(Interface)'에 따라 각 부품이 유기적으로 연결되는 시스템이다.
외부 라이브러리를 LangChain과 연동할 때는, 해당 라이브러리를 직접 사용하기보다 LangChain이 제공하는 래퍼 클래스가 있는지 먼저 확인하는 습관을 들이는 것이 좋습니다. 이 래퍼들이 바로 서로 다른 모양의 플러그와 콘센트를 연결해주는 고마운 '어댑터'이기 때문입니다.
혹시 저와 같은 AttributeError를 만나신 분들께 이 글이 도움이 되기를 바랍니다.