AIchain 도구: 검색, 변환, 임베딩 (Embeddings)
요약
yait_aichain을 활용하여 검색, 마크다운 변환, 임베딩 기능을 갖춘 AI 파이프라인 구축 방법을 설명합니다. 핵심 의존성을 최소화하고 MCP(Model Context Protocol)를 통해 다양한 도구를 플러그인 방식으로 연결하는 설계 철학을 다룹니다.
핵심 포인트
- yait_aichain은 핵심 의존성을 최소화한 얇은 코어 설계를 지향함
- 검색, 임베딩, 벡터 저장소 등을 플러그형 MCP 서버로 연결 가능
- Perplexity, Brave Search 등 다양한 검색 도구 통합 지원
- MCP 패턴을 통해 외부 API의 의존성 및 속도 제한 문제를 격리
LLM은 학습 중단 시점(training cutoff)까지의 모든 것을 알고 있으며, 그 이후의 일은 전혀 알지 못합니다. 어제의 주가를 묻거나, PDF를 건네주거나, 10,000개의 고객 지원 티켓 중 어떤 것이 중복인지 알려달라고 기대한다면 한계에 부딪힐 것입니다. 도구(Tools)는 바로 그 간극을 메우는 방법입니다.
이 글은 yait_aichain을 사용하여 AI 파이프라인을 구축하는 시리즈의 6번째 기사입니다. 오늘은 세 가지 카테고리를 다룹니다: 실시간 데이터를 위한 검색(search), 범용 문서 인입(ingestion)을 위한 마크다운(Markdown) 변환, 그리고 기본적인 RAG를 훨씬 뛰어넘는 작업을 위한 임베딩(embeddings)입니다.
설계 철학: 얇은 핵심(Thin Core), 플러그형(Pluggable) 모든 것
코드를 작성하기 전에 이해할 가치가 있는 한 가지 아키텍처 결정이 있습니다. yait_aichain은 의도적으로 핵심 의존성(dependency) 범위를 작게 유지합니다. 패키지 내부에 하드 의존성(hard dependency)으로 포함되어 배포되는 도구는 마크다운(Markdown) 변환 단 하나뿐입니다. 그 외의 모든 것 — 검색 제공자(search providers), 임베딩(embeddings), 벡터 저장소(vector stores), 리랭커(rerankers) — 은 별도로 설치하는 선택적 추가 사항(optional extra)이거나, 별도의 프로세스로 실행되는 플러그형 MCP (Model Context Protocol) 서버입니다.
왜 그럴까요? 특화된 도구들은 빠르게 변하기 때문입니다. 검색 API는 나타났다 사라지기를 반복합니다. OpenAI는 2022년 이후로 임베딩 모델을 세 세대나 출시했으며, 그 속도는 줄어들지 않고 있습니다. 이 모든 것을 핵심 라이브러리에 묶어버리면, 제공자가 파괴적 변경(breaking change)을 출시할 때마다 깨지는 취약한 의존성 트리(dependency tree)가 생성될 것입니다. 따라서 범용적인 기능은 내부에 두고, 특화된 기능은 외부에서 플러그인 방식으로 연결합니다.
검색: 모델에게 실시간 데이터 제공하기
2024년 4월까지의 데이터로 학습된 모델은 어제 무슨 일이 일어났는지 말할 수 없습니다. 검색 도구가 이를 해결합니다.
yait_aichain은 선택적 추가 사항으로 **Perplexity 검색 통합(Perplexity search integration)**을 포함하고 있습니다. 먼저 설치한 후 임포트(import)하세요:
pip install yait-aichain[perplexity]
from yait_aichain.tools import searchPerplexity
search = searchPerplexity()
...
단 한 번의 함수 호출과 하나의 문자열 반환 — 근거가 있고, 인용(citation)이 뒷받침되며, 실시간 웹 검색 결과에서 가져온 정보입니다.
하지만 Perplexity가 유일한 선택지는 아닙니다. 빅테크 인덱스(indices)로부터의 독립성을 위해 Brave Search를 선호할 수도 있고, 구조화된 Google 검색 결과를 위해 SerpAPI를 선호할 수도 있습니다. 이러한 제공업체들은 MCP 서버를 통해 연결됩니다. MCP 서버는 yait_aichain이 런타임(runtime)에 발견하고 호출하는 외부 프로세스입니다:
"""
먼저 MCP 서버를 시작하세요:
python your_newsapi_server.py
...
MCP 패턴은 의도적인 설계입니다. NewsAPI 서버는 자체적인 API 키, 자체적인 속도 제한(rate limits), 자체적인 Python 의존성(dependencies)을 가집니다. 이를 별도의 프로세스로 유지한다는 것은 여러분의 핵심 파이프라인(pipeline)을 깨끗하게 유지할 수 있음을 의미합니다. 다른 MCP 서버를 가리키는 것만으로 Brave를 SerpAPI로 교체할 수 있으며, 여러분의 Chain(체인) 내 코드를 변경할 필요가 없습니다.
MarkItDownTool: 데이터 준비를 위한 80%의 솔루션
모든 개발자가 마주하는 시나리오가 있습니다. LLM이 PDF 보고서, DOCX 계약서, PowerPoint 슬라이드, 그리고 URL을 처리해야 하는 상황입니다. 각 형식은 서로 다른 파서(parser)를 필요로 합니다. 각 파서는 저마다의 특이점, 예외 케이스(edge cases), 의존성을 가지고 있습니다.
또는 단 한 줄을 사용할 수도 있습니다:
from yait_aichain.tools import convertToMD
tool = convertToMD()
...
내부적으로 convertToMD는 Microsoft의 오픈 소스 markitdown 라이브러리를 래핑(wrap)하고 있으며, yait_aichain의 하드 의존성(hard dependency)으로 번들링되어 있어 별도의 설치가 필요하지 않습니다. 이 도구는 PDF, DOCX, PPTX, XLSX, HTML 및 URL을 즉시 처리할 수 있습니다. 출력물은 항상 Markdown(마크다운)이며, 이는 LLM이 가장 잘 소비하는 형식입니다.
설정 객체(configuration objects)도, 형식 감지 로직(format detection logic)도, 파싱 파이프라인(parsing pipelines)도 필요 없습니다. 단 한 번의 호출로 거의 모든 문서를 Skill(스킬)이나 Chain(체인)에서 즉시 사용할 수 있는 깨끗한 Markdown으로 변환합니다. 이것이 바로 이 도구가 yait_aichain 내부에 하드 의존성으로 존재하는 유일한 도구인 이유입니다. 문서에서 Markdown으로의 변환은 핵심(core)에 자리 잡을 만큼 충분히 범용적입니다.
Embeddings: 기본적인 RAG를 넘어
개발자들이 "임베딩 (Embeddings)"이라는 말을 들으면 보통 검색 증강 생성 (RAG, Retrieval-Augmented Generation)을 떠올립니다. 문서를 청크(chunk)로 나누고, 임베딩하고, 벡터 데이터베이스(vector database)에 저장한 뒤, 쿼리 시점에 검색하는 방식입니다. 그것은 하나의 사용 사례일 뿐, 유일한 사례는 아닙니다.
from yait_aichain.tools import Embedding
emb = Embedding(model="text-embedding-3-small")
...
각 호출은 float 벡터 리스트를 반환합니다. 이 벡터들을 어떻게 활용하느냐에 따라 사용 사례(use case)가 결정됩니다.
시맨틱 검색 (Semantic search). 키워드 매칭을 완전히 건너뜁니다. "인증 문제 (authentication issues)"라는 쿼리는 비밀번호 재설정, SSO 실패, 2FA 문제에 관한 티켓들을 찾아낼 것입니다. 단어가 아닌 의미가 일치하기 때문입니다.
중복 제거 (Deduplication). 고객 지원 티켓 간의 코사인 유사도 (cosine similarity)를 비교합니다. 위의 티켓 0, 1, 3번은 서로 밀접하게 클러스터링될 것입니다. 표현 방식이 다르더라도 의미론적으로 동일하기 때문입니다. 유사도 임계값 (similarity threshold)을 0.92로 설정하면, 사람이 단 하나도 읽지 않고도 수천 개의 항목 중에서 중복 항목을 자동으로 표시할 수 있습니다.
클러스터링 (Clustering). 벡터를 k-means 또는 HDBSCAN에 입력합니다. 단 하나의 정규 표현식 (regex)도 작성하지 않고 제품 리뷰를 테마별로 그룹화할 수 있습니다. 연구 논문 코퍼스 (corpus)에서 자연스러운 주제 경계를 찾아낼 수 있습니다.
VectorDB 클래스는 빠른 프로토타이핑을 위한 인프로세스 (in-process) 벡터 저장소를 제공합니다:
from yait_aichain.tools import VectorDB, vectorQuery
db = VectorDB()
...
참고: vectorQuery는 VectorDB의 메서드가 아닌 독립적인 함수입니다. 이는 파이프라인 컨텍스트에서 여러 데이터베이스 인스턴스에 걸쳐 작동하기 때문이며, 이러한 분리는 의도된 설계입니다.
결과 품질이 중요하고 문서 세트가 방대한 경우, 리랭킹 (reranking) 단계를 추가하세요:
from yait_aichain.tools import Reranker
reranker = Reranker()
...
리랭커는 벡터 검색으로부터 얻은 거친 (coarse) 결과들을 가져와 크로스 인코더 (cross-encoder)를 사용하여 재정렬합니다. 비교당 비용은 더 높지만, BEIR와 같은 공개 벤치마크에서 크로스 인코더 리랭킹은 벡터 검색만 사용할 때보다 top-k 위치에서의 정밀도 (precision)를 일관되게 향상시킵니다. results를 후보군 (candidate pool)으로, ranked를 모델에 전달할 최종 정렬된 리스트로 생각하십시오.
커스텀 도구 (Custom Tools): 직접 구축하기
yait_aichain의 모든 도구는 동일한 패턴을 따릅니다: Tool을 상속(subclass)받고, name과 description을 정의하며, run(self, input: str)을 구현합니다. 이 단일 문자열 시그니처(single-string signature) 덕분에 프레임워크는 표준 LLM 도구 호출 프로토콜(tool-calling protocol)을 통해 사용자의 도구를 호출할 수 있습니다. 즉, 모델이 문자열(또는 사용자가 직접 파싱하는 JSON 블록)을 보내면, 사용자의 도구가 문자열을 반환하는 방식입니다. 다음은 실제 작동하는 환율 변환 도구의 예시입니다:
import json
import urllib3
from yait_aichain.tools import Tool
...
Skill의 tools=[] 파라미터는 어떤 Tool 인스턴스 리스트든 수용합니다. 모델은 도구의 이름과 설명을 보고, 언제 도구를 호출할지 결정하며, 그 결과를 자신의 응답에 통합합니다. 여러분은 로직을 한 번만 작성하면 됩니다. 프레임워크는 지원되는 8개의 모든 제공업체 — OpenAI, Anthropic, Google Gemini, xAI Grok, Mistral, Groq, Ollama, 그리고 모든 OpenAI 호환 엔드포인트 — 에 걸쳐 도구 호출 프로토콜을 처리합니다.
무엇이 어디에 위치하는가
| yait_aichain 내부 | 외부 (플러그인 방식) |
|---|---|
convertToMD — Markdown 변환 | 검색 (선택적 추가 기능을 통한 Perplexity; MCP를 통한 Brave, SerpAPI) |
| ... |
이러한 경계는 의도된 것입니다. Markdown 변환은 보편적입니다. 모든 파이프라인(pipeline)은 문서를 입력받아야 하기 때문입니다. 반면 검색 제공업체, 임베딩 모델(embedding models), 벡터 저장소(vector stores)는 프로젝트마다 달라질 수 있는 주관적인 선택 사항입니다. 이들을 외부에 둠으로써 pip install yait-aichain 기본 설치 패키지를 가볍게 유지할 수 있습니다. 실제로 사용하는 것만 추가하십시오.
도구는 언어 모델이 할 수 있는 일을 확장합니다: 오늘의 뉴스를 읽거나, 회사의 PDF를 파싱하거나, 수천 개의 문서에서 의미론적 패턴(semantic patterns)을 찾아내는 일 등을 수행합니다. API 표면(API surface)은 작게 유지되지만, 기능은 프로젝트와 함께 성장합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기