AI 패권을 위한 싸움
이 게시물은 원래 The Sequence에 게시되었습니다.
LangChain이란 무엇인가
대규모 언어 모델(LLM)은 새로운 기술의 물결입니다. 거대 기업인 Google과 Microsoft는 AI 전투에서 싸우고 검색 왕관을 차지하기 위해 콜로세움에 들어서고 있습니다. 이 거대한 싸움은 LLM 혁신의 시작일 뿐이며, LangChain은 이를 더욱 발전시키는 데 도움을 주기 위해 등장했습니다. LLM만으로도 제한된 메모리와 응답에서 환각을 일으키는 경향이 있지만 훌륭한 대화 능력을 제공합니다. 이러한 환각의 예는 ChatGPT에게 "Read Dead Redemption의 난이도 수준은 무엇인가요"라고 물었을 때입니다. ChatGPT는 난이도 설정이 없다고 답할 것입니다. RDR에는 3개의 설정된 난이도 수준이 있으므로 이 답변은 틀렸습니다. LLM은 가중치를 사용해 답변을 생성하기 때문에 정보를 검증하거나 출처를 제공하는 것이 불가능합니다.
LLM이 질문에 답하고 우리의 데이터를 요약하기를 원한다면 어떨까요?
답변 출처를 제공할 수 있는 기능을 원한다면 어떨까요?
LLM이 토큰 제한을 벗어난 이전 대화를 기억하기를 원한다면 어떨까요?
바로 여기서 LangChain이 등장합니다. LangChain은 LLM의 유용성을 더욱 확장하기 위해 다양한 계산과 지식을 LLM과 함께 연결할 수 있게 해주는 프레임워크입니다. LangChain을 사용하면 도메인 특화 챗봇, 특정 계산을 위한 액션 에이전트 등을 만들 수 있습니다.
Milvus가 수행하는 역할
그렇다면 Milvus는 어디에 사용될까요? LLM은 한 번에 일정량의 토큰(약 네 글자)만 처리할 수 있으므로, LLM은 대형 문서나 문서 모음을 분석할 수 없습니다. 이를 우회하기 위해 모든 문서를 데이터베이스에 저장하고, 입력 질문과 관련된 문서만 검색한 다음, 해당 문서를 LLM에 넣어 답변을 생성할 수 있습니다. Milvus는 이에 완벽합니다. 시맨틱 검색을 활용해 더 관련성 높은 문서를 더 빠르게 검색할 수 있기 때문입니다. 먼저 분석할 모든 문서를 가져와 텍스트를 임베딩으로 변환합니다. 중요한 이점은 원래의 LLM을 사용해 임베딩을 생성할 수 있으며, 궁극적으로 검색 과정에 LLM의 "사고 과정"을 유지할 수 있다는 점입니다. 모든 데이터가 임베딩되면, (임베딩과 원문 텍스트)를 모든 메타데이터와 함께 Milvus에 저장할 수 있습니다. 그런 다음 쿼리가 들어오면 쿼리 텍스트를 가져와 동일한 모델로 임베딩하고, 관련 텍스트를 검색한 뒤, 이를 LLM에 넣어 답변을 생성할 수 있습니다. 이 파이프라인은 단순하게 들리지만, 이를 만드는 데는 많은 작업이 필요할 수 있습니다. 다행히 LangChain은 이러한 파이프라인을 쉽게 수행할 수 있게 해주며, 벡터 데이터베이스를 위한 VectorStore 래퍼를 제공합니다.
통합
다음은 제가 Milvus와 LangChain 사이에서 작업한 통합입니다.
class VectorStore(ABC):
"""Interface for vector stores."""
@abstractmethod
def add_texts(
self,
texts: Iterable[str],
metadatas: Optional[List[dict]] = None,
**kwargs: Any,
) -> List[str]:
"""Run more texts through the embeddings and add to the vectorstore."""
@abstractmethod
def similarity_search(
self, query: str, k: int = 4, **kwargs: Any
) -> List[Document]:
"""Return docs most similar to query."""
def max_marginal_relevance_search(
self, query: str, k: int = 4, fetch_k: int = 20
) -> List[Document]:
"""Return docs selected using the maximal marginal relevance."""
raise NotImplementedError
@classmethod
@abstractmethod
def from_texts(
cls: Type[VST],
texts: List[str],
embedding: Embeddings,
metadatas: Optional[List[dict]] = None,
**kwargs: Any,
) -> VST:
"""Return VectorStore initialized from texts and embeddings."""
앞서 언급했듯이, Milvus를 LangChain에 통합하려면 VectorStore 클래스를 확장해야 합니다. 이를 위해 몇 가지 핵심 함수인 add_texts(), similarity_search(), max_marginal_relevance_search(), from_text()를 구현해야 했습니다. Milvus VectorStore는 대부분의 사용 사례에서 간단한 파이프라인을 따릅니다. 먼저 Documents 컬렉션을 받는 것으로 시작합니다. 대부분의 LLM 프로젝트에서 Document는 원본 텍스트와 그에 수반되는 모든 메타데이터를 포함하는 데이터 클래스입니다. Document의 메타데이터는 일반적으로 JSON 기반이므로 Milvus 내에서 더 쉽게 저장할 수 있습니다. Milvus VectorStore가 Document를 소비하면, 제공된 임베딩 함수를 사용하여 그 안에 있는 텍스트를 임베딩합니다. 대부분의 프로덕션 시스템에서 이러한 임베딩 함수는 보통 OpenAI, Cohere 등과 같은 서드파티 LLM 서비스입니다. 하지만 텍스트 입력을 받아 벡터를 반환하는 함수를 제공하기만 하면 자체 모델을 사용할 수도 있습니다. 파이프라인의 이 단계에서 LangChain은 제어권을 Milvus 자체로 넘깁니다. Milvus는 임베딩, 원본 텍스트, 메타데이터를 받아 컬렉션에 저장합니다. 이러한 문서가 컬렉션에 점점 더 많이 들어오면, 저장된 모든 임베딩에서 더 빠르게 검색할 수 있도록 인덱스가 생성됩니다.
이 파이프라인의 마지막 단계는 관련 데이터를 검색하는 것입니다. 사용자가 질문을 보내면 텍스트와 메타데이터 필터가 Milvus VectorStore로 전송됩니다. 이전과 동일한 임베딩 함수를 사용하여 Milvus는 질문을 임베딩하고 데이터 전체에서 유사도 검색을 수행합니다. Milvus는 VectorStore로서 두 가지 유형의 검색을 제공합니다. 하나는 객체를 수정되지 않은 순서로 반환하는 기본 검색이고, 다른 하나는 최대 한계 관련성 순서를 사용하는 검색입니다. 최대 한계 관련성 순서는 입력과 코사인 유사도가 가장 높은 임베딩을 가진 예제를 찾은 다음, 이미 선택된 예제와의 근접성에 페널티를 부여하면서 반복적으로 추가하는 방식으로 작동합니다.
Milvus를 LangChain에 통합하는 과정에는 몇 가지 문제가 있었는데, 그중 가장 두드러진 것은 Milvus가 JSON을 처리할 수 없다는 점이었습니다. JSON 지원이 없기 때문에 Milvus용 구성이 생성되는 방식의 특성상 어려움이 있었습니다. 현재 Milvus VectorStore를 사용하는 방법은 두 가지뿐입니다. 이미 존재하는 Milvus 컬렉션에 VectorStore를 생성하거나, Milvus에 전달된 첫 번째 문서를 기반으로 VectorStore를 생성하는 것입니다. Collection이 이미 존재하는 경우 스키마는 확정되어 있습니다. 추가되는 모든 데이터는 스키마를 정확히 따라야 하며, 데이터가 누락되거나 형식이 잘못된 경우 시스템은 해당 항목 전체를 무시합니다.
마찬가지로, Collection이 생성된 후 Document에 추가 메타데이터가 더해지면 해당 추가 메타데이터는 무시됩니다. 이는 매우 적응력 있는 시스템에는 적합하지 않으며, 입력을 정리하는 데 상당한 추가 작업과 새 컬렉션을 생성하는 데 드는 추가 작업을 초래합니다. 다행히 버전 2.3에서 Milvus는 JSON을 저장할 수 있는 기능을 추가할 예정이며, 이를 통해 이 통합과 향후의 모든 통합이 단순화될 것입니다. Milvus 2.3은 현재 베타 버전이므로 자유롭게 확인해 보시고 피드백을 보내 주세요!
결론
그 결과는 LLM을 위한 작업 메모리이자 지식 베이스입니다. 통합이 병합된 이후 LangChain은 약간 변경되어 Retrievers라는 개념을 도입했습니다. Retrievers는 외부 스토리지에 연결하는 방법이며 LangChain이 앞으로 나아갈 방향입니다. 이 프로젝트의 빠르게 변화하는 특성으로 인해 Milvus VectorStore에 있는 코드는 더 깔끔해질 수 있으며, 다음 단계는 이를 정리하고 이 retriever 기능도 추가하는 것입니다. 앞서 언급했듯이 Milvus는 동적 스키마를 처리할 수 없어, 미리 만들어진 컬렉션과 데이터가 누락된 삽입을 다루는 것이 매우 어렵습니다. Milvus가 JSON 메타데이터를 지원하게 되면, 이 통합으로 돌아와 다시 작업할 때가 될 것입니다.
전반적으로 이 프로젝트를 작업한 것은 훌륭한 경험이었습니다. 커뮤니티는 친절하고, Harrison은 매우 적극적이며 도움이 됩니다. LangChain 프로젝트가 도달할 높이를 기대하고 있습니다.
계속 읽기

Notion's Vector Search Is Excellent. Their Next Problem Is Harder.
Notion solved vector search scaling in two years. The next bottleneck — offline context engineering, unified data, and the real-time/offline gap — is harder.

Milvus 2.6.x Now Generally Available on Zilliz Cloud, Making Vector Search Faster, Smarter, and More Cost-Efficient for Production AI
Milvus 2.6.x is now GA on Zilliz Cloud, delivering faster vector search, smarter hybrid queries, and lower costs for production RAG and AI applications.

Zilliz Cloud Update: Smarter Autoscaling for Cost Savings, Stronger Compliance with Audit Logs, and More
What's new in Zilliz Cloud? Smarter autoscaling with scale-down, audit logs GA, enhanced SSO, and Milvus 2.6 in Private Preview.



