OpenDMA를 사용하여 LlamaIndex와 Alfresco 연결하기: 리더, 검색기 및 에이전트 도구
요약
OpenDMA는 LlamaIndex와 같은 AI 애플리케이션이 Alfresco와 같은 복잡한 문서 관리 시스템(DMS/ECM)에 연결할 수 있도록 돕는 벤더 중립적 API입니다. 이 통합은 콘텐츠 인덱싱, 실시간 검색, 에이전트 도구 제공 등 세 가지 기능을 모두 지원합니다. 이를 통해 개발자는 ECM의 복잡성을 직접 다룰 필요 없이 LlamaIndex 코드를 유지할 수 있습니다.
핵심 포인트
- OpenDMA는 Alfresco와 같은 DMS를 위한 벤더 중립적 API 역할을 합니다.
- LlamaIndex 통합은 콘텐츠 수집, 실시간 검색, 에이전트 도구 기능을 모두 제공합니다.
- 개발자는 OpenDMA REST 엔드포인트를 통해 ECM의 복잡한 구조(메타데이터, 권한 등)에 접근할 수 있습니다.
LlamaIndex를 Alfresco에 연결하는 것은 처음에는 간단해 보입니다. 문서를 읽고 텍스트를 추출한 다음 인덱스를 구축하면 됩니다. 하지만 실제로는 저장소(repository)의 컨텍스트가 매우 빠르게 중요해집니다.
이 지점에서 보통 거리가 있어 보이는 세 가지 다른 작업이 있습니다:
- Alfresco 콘텐츠를 LlamaIndex
Index(예:VectorStoreIndex)에 수집하기 - 별도의 벡터 저장소를 구축하지 않고 Alfresco에서 실시간으로 콘텐츠 검색하기
- 에이전트에게 Alfresco를 탐색하고, 메타데이터를 검사하며, 검색하고, 선택된 문서를 읽을 수 있는 도구를 제공하기
OpenDMA LlamaIndex 통합은 이 세 가지 기능을 모두 제공합니다. 저장소가 애플리케이션 흐름의 어느 단계에 있어야 하느냐에 따라 AlfrescoReader, AlfrescoRetriever 또는 AlfrescoToolSpec을 사용할 수 있습니다.
흥미로운 부분은 Alfresco에서 바이트를 한 번 가져오는 것이 아닙니다. 흥미로운 부분은 저장소 컨텍스트, 즉 사이트(site), 경로(path), 유형(type), 측면(aspects), 속성(properties), 권한(permissions) 및 저장소가 이미 가지고 있는 쿼리 언어를 유지하는 것입니다.
이 글의 예제는 OpenDMA Alfresco–LlamaIndex 샘플 리포지토리에서 실행 가능한 Python 프로젝트로 제공됩니다. 해당 리포지토리를 클론하고 아래의 예제를 따라 해보세요.
LlamaIndex와 Alfresco 간의 OpenDMA
OpenDMA는 문서 관리(Document Management) 및 ECM 시스템을 위한 벤더 중립적 API입니다. OpenDMA 어댑터는 데이터베이스 드라이버와 유사한 역할을 수행합니다. 즉, Alfresco와 같은 구체적인 시스템을 OpenDMA 모델에 매핑합니다.
Python LlamaIndex 애플리케이션의 경우 중요한 부분은 OpenDMA REST 엔드포인트입니다. 애플리케이션은 HTTP를 통해 OpenDMA와 통신합니다. 이 엔드포인트 뒤에서, Alfresco 어댑터는 Alfresco 오브젝트, 폴더, 문서, 콘텐츠 스트림, 메타데이터, 클래스, 측면(aspects), 그리고 검색 기능을 OpenDMA API로 매핑합니다.
이를 통해 LlamaIndex 코드가 ECM 레벨에 머무르게 됩니다. 애플리케이션은 노드, 콘텐츠 다운로드, 사이트, 검색, 측면 및 속성에 대한 Alfresco Content Services REST API 호출을 자체 코드에 분산할 필요가 없습니다.
동일한 애플리케이션 구조는 다른 OpenDMA 어댑터를 통해 다른 ECM 시스템(예: Documentum, FileNet P8, OnBase, CMOD, OpenText 또는 SharePoint)에서도 사용할 수 있습니다. 엔터프라이즈 배포 환경에서 OpenDMA 또는 ECI 계층은 감사(auditing), ID 변환(identity translation), RBAC(역할 기반 접근 제어), SIEM 통합, 또는 ID 포워딩과 같은 관심사들이 속하는 곳이기도 합니다.
인덱스를 구축하려면 AlfrescoReader 사용하기
AlfrescoReader는 LlamaIndex의 Alfresco 리더로, 콘텐츠를 수집(ingestion)할 때 사용합니다. Alfresco 콘텐츠를 LlamaIndex의 Index(예: VectorStoreIndex)에 로드하고 싶을 때 이를 사용하십시오.
이것은 OpenDMA를 통해 노출된 Alfresco 저장소용 편의 리더입니다. Alfresco 기본값을 사용하며 Alfresco 사이트 약어 이름(short names)을 이해합니다. 다음 예시는 표준 Alfresco 샘플 설정의 swsdp 사이트에서 읽고 레거시 Word 문서를 위해 Docling을 사용합니다:
from llama_index.core import VectorStoreIndex
from llama_index.readers.docling import DoclingReader
from llama_index.readers.opendma import AlfrescoReader
...
반환되는 각 LlamaIndex Document는 text 필드에 추출된 텍스트와 metadata 필드에 OpenDMA 메타데이터를 포함합니다.
sites 매개변수는 Alfresco에서 유용하지만, 유일한 로딩 전략은 아닙니다. 이 리더는 또한 문서 ID, 폴더 ID, 재귀적 폴더 순회(recursive folder traversal), 그리고 OpenDMA 쿼리를 지원합니다. 사이트를 읽을 때, 이것이 단순히 문서 라이브러리만을 의미한다고 가정해서는 안 됩니다. Alfresco 사이트에는 사이트 폴더 아래에 위키 페이지, 링크 및 기타 객체들이 포함될 수도 있습니다.
프로덕션 애플리케이션에서 이 수집 단계는 보통 매번 전체 저장소에 대해 실행되어서는 안 됩니다. 일반적인 방식은 새로 추가되거나 변경된 문서에 대해서만 실행하고 영구 벡터 스토어를 사용하는 것입니다.
Alfresco 메타데이터 유지하기
ECM 콘텐츠에서 메타데이터는 장식이 아닙니다. 그것은 데모와 실제로 사용 가능한 애플리케이션을 가르는 차이점인 경우가 많습니다.
OpenDMA를 통해 로드된 문서는 텍스트 청크만을 담고 있지 않습니다. 또한 OpenDMA 메타데이터, Alfresco 메타데이터, 그리고 통합 메타데이터도 함께 가지고 있습니다. 여기에는 다음과 같은 값들이 포함됩니다:
opendma:Titleopendma:CheckedOutalfresco:Sitealfresco:Pathalfresco:cm:namealfresco:cm:creatoralfresco:cm:accessedcontent_state
문서를 인덱스에 삽입하기 전에 메타데이터를 검사할 수 있습니다:
for doc in documents[:3]:
print(doc.id_)
print(doc.metadata.get("opendma:Title"))
...
이것은 중요합니다. 실제 Alfresco 리포지토리는 작고 깨끗한 튜토리얼 파일 세트가 아니기 때문입니다. 수십만 개 또는 수백만 개의 문서, 여러 팀의 회의록, 계약서, 합의서, 제품 사양, 작업 초안, 그리고 유사한 어휘를 가진 프로젝트 폴더들을 포함할 수 있습니다.
모든 인덱싱된 리포지토리 콘텐츠에 걸쳐 단순한 유사성 검색(similarity search)을 수행하면 관련 없는 청크가 반환될 수 있습니다. 만약 질문이 특정 프로젝트나 팀 사이트에 관한 것이라면, alfresco:Site와 alfresco:Path는 유용한 신호입니다. 체크아웃된 콘텐츠를 제외해야 한다면, opendma:CheckedOut가 검색 로직의 일부가 될 수 있습니다.
메타데이터 인식 검색 튜토리얼에서 이를 더 명시적으로 보여줍니다. 이 튜토리얼은 먼저 Alfresco 샘플 사이트를 인덱싱한 다음, 두 번째 사이트의 유사한 콘텐츠를 추가하고 모든 청크가 하나의 평평한 풀(flat pool)로 처리될 때 검색 품질이 어떻게 저하되는지 시연합니다.
왜 작은 Alfresco REST 리더만 작성하지 않을까요?
프로토타입의 경우, 작고 사용자 정의된 리더(reader)가 매력적입니다. Alfresco에서 콘텐츠를 다운로드하고, 이를 텍스트로 변환한 다음, LlamaIndex에 전달하는 방식이죠.
이 방법은 리더가 리포지토리에 대해 더 많이 알아야 할 때까지는 작동합니다.
코드는 단순히 "이 노드의 콘텐츠 다운로드"에서 출발하여 사이트 검색(site discovery), 폴더 순회(folder traversal), 메타데이터 추출, 콘텐츠 유형 처리, 측면 및 속성(aspects and properties), 경로 재구성(path reconstruction), 체크아웃 상태(checked-out state), 전체 텍스트 검색(full-text search), MIME별 파싱(MIME-specific parsing), 그리고 접근 제어 인식 배포 선택지까지 확장됩니다.
OpenDMA는 이러한 관심사들을 ECM 추상화 뒤에 숨깁니다. LlamaIndex 애플리케이션은 여전히 순수 Python일 수 있지만, Alfresco 통합이 조각조각 재구축되는 장소가 되지는 않습니다.
이는 콘텐츠 변환에도 영향을 미칩니다. OpenDMA 리더는 일반 텍스트를 직접 디코딩하고, 더 풍부한 형식(richer formats)은 MIME 유형 매핑을 통해 LlamaIndex 파일 리더에 위임합니다. 위의 예시에서 레거시 Word 파일은 Docling으로 명시적으로 매핑됩니다. 저장소 렌디션(repository renditions)이 OpenDMA/adaptor 배포의 일부인 경우, 이는 각 애플리케이션마다 별도로 재구현되기보다는 저장소 통합 계층에 속합니다.
벡터 스토어를 원하지 않을 때 AlfrescoRetriever 사용하기
때로는 벡터 스토어가 적절한 선택일 수 있습니다. 큐레이션된 코퍼스(corpus)에 대한 의미론적 검색(semantic retrieval)이 필요하다면, AlfrescoReader와 LlamaIndex 인덱스를 결합하는 것이 좋은 조합입니다.
하지만 벡터 스토어를 구축하는 데는 비용이 따릅니다. 콘텐츠를 수집하고(ingest), 텍스트를 추출하며, 청크로 나누고(chunk), 임베딩을 계산하고, 결과를 저장하며, Alfresco와 동기화 상태를 유지해야 합니다. 엔터프라이즈 저장소에서는 접근 권한 및 규정 준수 경계가 종종 더 어려운 부분입니다.
AlfrescoRetriever는 다른 선택지입니다. 이는 LlamaIndex 리트리버 API를 구현하고 OpenDMA를 통해 Alfresco에 대한 실시간 전체 텍스트 검색을 수행합니다.
from llama_index.core.node_parser import SentenceSplitter
from llama_index.readers.docling import DoclingReader
from llama_index.retrievers.opendma import AlfrescoRetriever
...
이 리트리버는 입력 문자열을 Alfresco AFTS TEXT 쿼리로 변환합니다. 만약 sites가 설정되면, 사이트 제한(site restrictions)을 추가합니다. 그 결과는 LlamaIndex 노드로 변환되어 NodeWithScore로 반환됩니다.
이 점을 유의해야 합니다: AlfrescoRetriever는 의미론적 벡터 검색(semantic vector search)이 아니라 전체 텍스트 검색(full-text retrieval)입니다. similarity_top_k 매개변수는 문서 로딩 및 노드 파싱 후 반환되는 LlamaIndex 노드의 개수를 제한하는 것입니다. 이는 벡터 유사도 점수가 아닙니다.
장점은 모든 검색 호출이 OpenDMA를 통해 Alfresco를 거친다는 것입니다. 전체 리포지토리를 미리 수집(ingestion)할 필요가 없고, 모든 콘텐츠에 대한 임베딩을 생성할 필요도 없으며, 동기화해야 할 별도의 리포지토리 텍스트 복사본도 없습니다.
효과적인 사용자 인증 또는 ID 포워딩(identity forwarding)을 사용하면, Alfresco는 여전히 검색어에 포함될 수 있는 내용, 즉 Alfresco/OpenDMA 경로에서 적용되는 리포지토리 권한 및 거버넌스/보안 마킹을 결정하는 시스템으로 남아 있습니다. 만약 OpenDMA 엔드포인트가 공유 기술 계정 또는 관리자 계정으로 호출된다면, 애플리케이션은 여전히 사용자 수준의 인증(authorization)을 처리해야 합니다. 이 부분은 사라지지 않습니다.
벡터 스토어 없이 에이전트 기반 검색 (Agentic retrieval without a vector store)
실시간 전체 텍스트 검색기는 에이전트가 여러 번의 검색 시도를 할 수 있도록 허용될 때 특히 잘 작동합니다.
첫 번째 검색어는 너무 구체적일 수 있습니다:
localisation of new website design
다음 검색어는 더 적은 용어를 사용할 수 있습니다:
website design
또는 문서에 실제로 나타나는 도메인 단어에 초점을 맞출 수도 있습니다:
localisation
이것이 Alfresco 전체 텍스트 검색을 의미론적 검색으로 바꾸지는 않습니다. 벡터 스토어는 사용자의 단어가 문서 텍스트와 일치하지 않을 때 종종 더 나은 결과를 검색합니다. 그러나 에이전트 워크플로우는 검색 용어를 변경하고 검색 범위를 관련 사이트로 제한함으로써 많은 실제 사례에서 보상할 수 있습니다.
OpenDMA Retriever를 사용한 에이전트 기반 RAG 튜토리얼은 search_content 도구 내에서 AlfrescoRetriever를 사용하는 에이전트로 이 패턴을 보여줍니다.
에이전트가 탐색(browse)해야 할 때는 AlfrescoToolSpec 사용
<code>AlfrescoRetriever</code>는 검색(retrieval)을 위한 것이고, <code>AlfrescoToolSpec</code>은 저장소(repository)를 검사해야 하는 에이전트(agent)를 위한 것입니다.
이는 다른 작업입니다. 때로는 최적의 텍스트 청크(text chunks)를 검색하는 것만으로는 답변을 찾을 수 없습니다. 에이전트는 먼저 사이트를 나열하거나, 폴더를 탐색하고, 메타데이터를 검사하거나, 후보 문서를 찾은 다음, 비로소 그 텍스트를 읽어야 할 수도 있습니다.
<code>AlfrescoToolSpec</code>은 다음과 같은 도구(tool)들을 노출합니다:
alfresco_list_sitesopendma_list_childrenopendma_get_metadataopendma_describe_classopendma_searchopendma_read_text
이 도구들은 고정된 OpenDMA 엔드포인트, 계정 및 저장소에 대해 구성됩니다. 이는 임의의 자격 증명(arbitrary credentials)을 가진 일반적인 HTTP 클라이언트보다 에이전트에게 더 나은 인터페이스를 제공합니다.
from llama_index.core.agent import FunctionAgent
from llama_index.llms.openai import OpenAI
from llama_index.tools.opendma import AlfrescoToolSpec
...
프롬프트(prompt)가 중요합니다. 문서 텍스트를 읽는 것은 자식 노드를 나열하거나 메타데이터를 가져오는 것보다 비용이 많이 듭니다. 유용한 에이전트는 먼저 탐색하고, 메타데이터를 검사한 다음, 후보 문서를 가질 때만 텍스트를 읽어야 합니다.
텍스트 읽기 도구는 계속 토큰(continuation tokens)을 가진 청크를 반환합니다. 이는 긴 문서와 대규모 저장소에 중요합니다. 에이전트는 메타데이터가 이미 질문에 답하고 있을 경우 전체 문서를 요청해서는 안 됩니다.
tool-calling agent 튜토리얼에서는 에이전트가 먼저 문서를 찾고, 메타데이터를 검사한 다음, 필요할 때만 텍스트를 읽는 과정을 보여줍니다.
인터페이스 선택하기 (Choosing the surface)
제어된 인덱싱 코퍼스(controlled indexed corpus)에 대한 의미론적 검색(semantic search)이 필요한 경우 <code>AlfrescoReader</code>부터 시작하세요.
벡터 유사성(vector similarity)보다 Alfresco 내에서 검색을 활성화하는 것이 더 중요한 경우 <code>AlfrescoRetriever</code>부터 시작하세요.
에이전트가 저장소 탐색, 메타데이터 검사 및 선택적 읽기가 필요한 경우에는 <code>AlfrescoToolSpec</code>을 사용하세요.
직접 예제를 실행해 보세요
AlfrescoReader, AlfrescoRetriever, 그리고 AlfrescoToolSpec에 대한 전체 실행 예제는 GitHub 샘플 프로젝트에서 확인할 수 있습니다.
저장소(repository)를 클론하여 자신만의 환경에서 다양한 통합 접근 방식을 실험해 보세요.
전체 실행 흐름을 보려면 기존 튜토리얼을 참고하세요:
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기