Agent Builder는 현재 기술 미리보기 버전으로 제공됩니다. Elastic Cloud 체험판으로 시작한 뒤, Agent Builder 문서를 여기에서 확인하세요.
요즘 다른 모든 사람들과 마찬가지로 Elastic도 Chat, 에이전트, RAG에 올인하고 있습니다. 검색 부서에서는 최근 에이전트 빌더와 도구 레지스트리를 개발 중이며, 모두 Elasticsearch에서 데이터와 '채팅'하는 것을 간단하게 만들기 위한 것입니다.
이러한 노력의 '큰 그림'에 대해 자세히 알아보려면 Elasticsearch로 AI 에이전트 워크플로우 구축 블로그 또는 첫 번째 Elastic 에이전트를 읽어보세요: 단일 쿼리에서 AI 기반 채팅까지에서 보다 실용적인 입문서를 읽어보세요.
하지만 이 블로그에서는 채팅을 시작할 때 가장 먼저 일어나는 일 중 하나를 조금 더 자세히 살펴보고 최근 개선된 몇 가지 사항을 안내해드리려고 합니다.
여기서 무슨 일이 일어나고 있나요?

Elasticsearch 데이터와 채팅할 때 기본 AI 에이전트가 이 표준 플로우를 안내합니다:
- 프롬프트를 확인합니다.
- 해당 프롬프트에 대한 답변이 포함되어 있을 가능성이 높은 인덱스를 식별합니다.
- 프롬프트에 따라 해당 인덱스에 대한 쿼리를 생성합니다.
- 해당 쿼리로 해당 인덱스를 검색합니다.
- 결과를 종합합니다.
- 결과가 프롬프트를 해결할 수 있나요? 그렇다면 응답하세요. 그렇지 않다면 반복하되 다른 것을 시도하세요.
검색 증강 세대(RAG)에 불과하기 때문에 너무 새롭지 않을 것입니다. 예상대로 응답의 품질은 초기 검색 결과의 관련성에 따라 크게 달라집니다. 따라서 응답 품질을 개선하기 위해 노력하면서 3단계에서 생성하고 4단계에서 실행하는 쿼리에 매우 세심한 주의를 기울이고 있습니다. 그리고 흥미로운 패턴을 발견했습니다.
첫 번째 응답이 '나쁨'인 경우가 종종 있었는데, 이는 쿼리를 잘못 실행했기 때문이 아니었습니다. 쿼리할 인덱스를 잘못 선택했기 때문입니다. 3단계와 4단계는 보통 2단계가 문제가 되지 않았습니다.
우리가 뭘 하고 있었나요?
초기 구현은 간단했습니다. 저희는 _cat/indices 을 통해 사용 가능한 모든 인덱스를 나열한 다음, 이 인덱스 중 사용자의 메시지/질문/프롬프트에 가장 적합한 인덱스를 식별하도록 LLM에 요청하는 도구(index_explorer라고 함)를 구축했습니다. 이 원본 구현은 여기에서 확인할 수 있습니다.
얼마나 잘 작동했나요? 확실하지 않았습니다! 잘 작동하지 않는 사례는 분명 있었지만, 현재 상태를 정량화하는 것이 첫 번째 과제였습니다.
기준선 설정
데이터에서 시작됩니다.
우리에게 필요했던 것은 사용자 프롬프트와 기존 인덱스 세트가 주어졌을 때 올바른 인덱스를 선택하는 도구의 효율성을 측정하기 위한 골든 데이터 세트였습니다. 그런 데이터 세트가 없었기 때문에 저희가 직접 생성했습니다.
인정합니다: 이것이 '모범 사례'는 아니라는 것을 알고 있습니다. 하지만 때로는 자전거를 타는 것보다 앞으로 나아가는 것이 더 나을 때도 있습니다. 진행, 심플한 완벽함.
이 프롬프트를 사용하여 여러 다른 도메인에 대한 시드 인덱스를 생성했습니다. 그런 다음 생성된 각 도메인에 대해 이 프롬프트를 사용하여 몇 가지 인덱스를 더 생성했습니다(여기서 목표는 하드 네거티브와 분류하기 어려운 예시로 LLM에 혼란을 심어주는 것입니다). 다음으로, 생성된 각 인덱스와 그 설명을 수동으로 편집했습니다. 마지막으로 이 프롬프트를 사용하여 테스트 쿼리를 생성했는데, 다음과 같은 샘플 데이터가 남았습니다:

와 같은 테스트 사례:

테스트 하네스 제작하기
여기서부터의 과정은 매우 간단했습니다. 가능한 도구를 스크립트로 작성하세요:
- 대상 Elasticsearch 클러스터로 클린 슬레이트를 설정하세요.
- 대상 데이터 세트에 정의된 모든 인덱스를 생성합니다.
- 각 테스트 시나리오에 대해 i
ndex_explorer도구를 실행합니다(편리하게도 도구 실행 API가 있습니다). - 결과 인덱스와 예상 인덱스를 비교하고 결과를 캡처합니다.
- 모든 테스트 시나리오를 완료한 후 결과를 표로 작성합니다.
설문조사에 따르면...
초기 결과는 당연히 평범했습니다.

전반적으로 77.14% 올바른 인덱스를 식별하는 데 정확합니다. 그리고 이것은 모든 인덱스에 의미적으로 의미 있는 좋은 이름이 있는 '최상의 경우'의 시나리오입니다. PUT test2/_doc/foo {...}`를 해본 사람이라면 누구나 인덱스에 항상 의미 있는 이름이 있는 것은 아니라는 것을 알고 있습니다.
따라서 우리는 기준선을 가지고 있으며 개선의 여지가 많이 있음을 보여줍니다. 이제 과학이 필요한 시간입니다! 🧪
실험
가설 1: 매핑이 도움이 될 것입니다.
여기서 목표는 원래 프롬프트와 관련된 데이터를 포함할 인덱스를 식별하는 것입니다. 그리고 인덱스에 포함된 데이터를 가장 잘 설명하는 부분은 인덱스의 매핑입니다. 인덱스 콘텐츠의 샘플을 가져오지 않더라도 인덱스에 double 유형의 가격 필드가 있다는 것은 데이터가 판매할 상품을 나타낸다는 것을 의미합니다. 텍스트 유형의 작성자 필드는 일부 구조화되지 않은 언어 데이터를 의미합니다. 이 두 가지를 합치면 데이터가 책/이야기/시라는 것을 암시할 수 있습니다. 인덱스의 속성을 아는 것만으로도 많은 의미론적 단서를 얻을 수 있습니다. 그래서 로컬 브랜치에서 '.index_explorer`를 조정했습니다. 도구를 사용하여 인덱스의 전체 매핑(이름과 함께)을 LLM에 전송하여 결정을 내릴 수 있습니다.
결과(Kibana 로그에서 가져온):
이 도구의 초기 개발자는 이러한 문제를 예상하고 있었습니다. 인덱스의 매핑은 정보를 얻을 수 있는 금광이지만, 상당히 장황한 JSON 블록이기도 합니다. 그리고 수많은 인덱스(평가 데이터 세트는 20개를 정의함)를 비교하는 현실적인 시나리오에서는 이러한 JSON 블롭이 합쳐집니다. 따라서 모든 옵션에 대한 인덱스 이름뿐만 아니라 각 옵션의 전체 매핑이 아닌 더 많은 컨텍스트를 LLM에 제공하여 결정에 도움을 주고자 합니다.
가설 2: 절충안으로 '플랫화' 매핑(필드 목록) 사용
우리는 인덱스 작성자가 의미론적으로 의미 있는 인덱스 이름을 사용한다는 가정에서 시작했습니다. 이 가정을 필드 이름으로도 확장하면 어떨까요? 이전 실험은 실패했는데, 그 이유는 JSON 매핑에 복잡한 메타데이터와 상용구가 많이 포함되어 있었기 때문입니다.
예를 들어, 위의 블록은 236자이며 Elasticsearch 매핑에서 단 하나의 필드만 정의합니다. 반면 "description_text" 문자열은 16자에 불과합니다. 이는 문자 수가 거의 15배 증가한 것이지만, 해당 필드가 사용 가능한 데이터에 대해 의미하는 바를 설명하는 데 있어 의미 있는 의미 개선은 없습니다. 모든 인덱스에 대한 매핑을 가져오되, LLM으로 보내기 전에 필드 이름 목록으로만 '플랫화'하면 어떨까요?
저희도 사용해 보았습니다.

정말 멋지네요! 전반적으로 개선되었습니다. 하지만 더 잘할 수 있을까요?
가설 3: 매핑 _meta의 설명
추가 컨텍스트 없이 필드 이름만으로 그렇게 많은 점프가 발생했다면, 아마도 상당한 컨텍스트를 추가하는 것이 더 좋을 것입니다! 모든 인덱스에 반드시 설명을 첨부해야 하는 것은 아니지만, 매핑의 _meta 객체에 모든 종류의 인덱스 수준 메타데이터를 추가할 수 있습니다. 생성된 인덱스로 돌아가서 데이터 세트의 모든 인덱스에 대한 설명을 추가했습니다. 설명이 지나치게 길지 않다면 전체 매핑보다 적은 토큰을 사용하고 인덱스에 포함된 데이터에 대한 훨씬 더 나은 인사이트를 제공해야 합니다. 실험을 통해 이 가설을 검증했습니다.

소폭의 개선으로 이제 >90% 전반적으로 정확해졌습니다.
가설 4: 합이 부분보다 큼
필드 이름을 사용하면 결과가 향상되었습니다. 설명을 통해 결과가 향상되었습니다. 따라서 설명과 필드 이름을 모두 활용하면 더 나은 결과를 얻을 수 있겠죠?

데이터는 "아니오"라고 응답했습니다(이전 실험에서 변경 사항 없음). 여기서 유력한 이론은 설명이 처음부터 인덱스 필드/매핑에서 생성되었기 때문에 이 두 컨텍스트 간에 서로 다른 정보가 충분하지 않아 결합할 때 '새로운' 것을 추가하는 데 도움이 되지 않는다는 것입니다. 또한 20개의 테스트 지수에 대해 전송하는 페이로드가 상당히 커지고 있습니다. 지금까지 우리가 따라온 사고방식은 확장할 수 없습니다. 사실, 지금까지의 실험 중 어떤 것도 수백, 수천 개의 인덱스가 있는 Elasticsearch 클러스터에서는 작동하지 않을 것이라고 믿을 만한 충분한 이유가 있습니다. 인덱스의 총 수가 증가함에 따라 LLM으로 전송되는 메시지 크기를 선형적으로 증가시키는 접근 방식은 일반화할 수 있는 전략이 아닐 수 있습니다.
우리에게 정말 필요한 것은 수많은 후보를 가장 관련성이 높은 옵션으로 좁히는 데 도움이 되는 접근 방식입니다....
여기에는 검색 문제가 있습니다.
가설 5: 시맨틱 검색을 통한 선택
인덱스 이름에 의미론적 의미가 있는 경우, 벡터로 저장하여 의미론적으로 검색할 수 있습니다.
인덱스의 필드 이름에 의미론적 의미가 있는 경우, 이를 벡터로 저장하고 의미론적으로 검색할 수 있습니다.
인덱스에 의미론적 의미가 있는 설명이 있는 경우, 이 역시 벡터로 저장하고 의미론적으로 검색할 수 있습니다.
오늘날 Elasticsearch 인덱스는 이러한 정보를 검색할 수 없지만(어쩌면 그렇게 해야 할지도 모릅니다!), 그 차이를 해결할 수 있는 무언가를 함께 해킹하는 것은 꽤나 사소한 일이었습니다. Elastic의 커넥터 프레임워크를 사용해 클러스터의 모든 인덱스에 대한 문서를 출력하는 커넥터를 구축했습니다. 출력 문서는 다음과 같은 형태가 됩니다:
저는 이 문서들을 수동으로 매핑을 정의한 새 인덱스로 보냈습니다:
이렇게 하면 의미론적 의미를 가진 다른 모든 필드가 청크업되어 색인되는 단일 semantic_content 필드가 생성됩니다. 이 인덱스를 검색하는 것은 사소한 일이 됩니다:
수정된 index_explorer 도구는 이제 LLM에 요청할 필요 없이 주어진 쿼리에 대해 단일 임베딩을 요청하고 효율적인 벡터 검색 작업을 수행할 수 있으므로 훨씬 더 빨라졌습니다. 상위 히트를 선택한 지표로 삼은 결과 다음과 같은 결과를 얻었습니다:

이 접근 방식은 확장 가능합니다. 이 접근 방식은 효율적입니다. 하지만 이 접근 방식은 기준선보다 겨우 나은 수준입니다. 하지만 이는 놀라운 일이 아닙니다. 검색 접근 방식이 매우 순진하기 때문입니다. 뉘앙스가 없습니다. 인덱스의 이름과 설명이 인덱스에 포함된 임의의 필드 이름보다 더 많은 가중치를 가져야 한다는 인식이 없습니다. 동의어 일치보다 정확한 어휘 일치에 가중치를 부여하는 어포던스는 없습니다. 그러나 고도로 미묘한 쿼리를 작성하려면 현재 데이터에 대해 많은 것을 가정해야 합니다. 지금까지 인덱스와 필드 이름에 의미론적 의미가 있다는 큰 가정을 해 보았지만, 한 걸음 더 나아가서 얼마나 많은 의미를 가지고 있으며 서로 어떻게 연관되어 있는지 가정해 볼 필요가 있습니다. 이렇게 하지 않으면 최상의 일치 항목을 최고의 결과로 확실하게 식별할 수는 없지만, 상위 N개의 결과 중 어딘가에 최상의 일치 항목이 있다고 말할 수 있습니다. 우리는 의미론적 정보가 존재하는 맥락에서 의미론적 정보를 소비하고, 의미론적으로 구별되는 방식으로 자신을 표현할 수 있는 다른 개체와 비교하여 그 둘을 판단할 수 있는 무언가가 필요합니다. LLM처럼요.
가설 6: 후보 세트 감소
이 외에도 여러 가지 실험이 있었지만, 핵심적인 돌파구는 시맨틱 검색만으로 최적의 일치 항목을 고르려는 욕구를 버리고 대신 시맨틱 검색을 필터로 활용하여 LLM의 고려 대상에서 관련 없는 인덱스를 걸러내는 것이었습니다. 검색을 위해 선형 검색기, 하이브리드 검색과 RRF, semantic_text 를 결합하여 상위 5개 일치하는 인덱스로 결과를 제한했습니다.
그런 다음 각 일치 항목에 대해 인덱스의 이름, 설명 및 필드 이름을 LLM용 메시지에 추가했습니다. 결과는 환상적이었습니다:

역대 실험 중 가장 높은 정확도! 또한 이 접근 방식은 총 인덱스 수에 비례하여 메시지 크기가 증가하지 않기 때문에 훨씬 더 확장성이 뛰어납니다.
결과

첫 번째 분명한 결과는 우리의 기준선을 개선할 수 있다는 것이었습니다. 지금 생각하면 당연해 보이지만 실험을 시작하기 전에는 index_explorer 도구를 완전히 버리고 검색 공간을 제한하기 위해 사용자의 명시적 설정에 의존해야 하는지에 대해 진지한 논의가 있었습니다. 여전히 실행 가능하고 유효한 옵션이지만, 이 연구는 이러한 사용자 입력을 사용할 수 없는 경우 인덱스 선택을 자동화하는 방향으로 나아갈 수 있는 유망한 경로가 있음을 보여줍니다.
다음으로 분명한 결과는 문제에 더 많은 설명 문자를 던지는 것만으로는 수익이 줄어든다는 것이었습니다. 이 연구 이전에는 필드 수준 메타데이터를 저장하기 위해 Elasticsearch의 기능을 확장하는 데 투자해야 할지 고민하고 있었습니다. 현재 meta 값은 50자로 제한되어 있으며, 필드의 의미적 이해를 도출하기 위해서는 이 값을 늘려야 한다는 가정이 있었습니다. 이는 분명히 사실이 아니며, LLM은 필드 이름만으로 상당히 잘 작동하는 것 같습니다. 나중에 더 조사할 수 있지만 더 이상 시급하다고 생각하지 않습니다.
반대로, 이는 '검색 가능한' 인덱스 메타데이터의 중요성에 대한 명확한 증거가 되었습니다. 이 실험을 위해 저희는 인덱스 오브 인덱스를 해킹했습니다. 그러나 이것은 Elasticsearch에 직접 구축하거나, 관리할 API를 구축하거나, 최소한 관련 규칙을 수립하는 것을 검토할 수 있는 부분입니다. 여러 옵션을 검토하고 내부적으로 논의 중이니 계속 지켜봐 주시기 바랍니다.
마지막으로, 이러한 노력을 통해 시간을 들여 실험하고 데이터 기반 의사 결정을 내리는 것이 얼마나 가치 있는 일인지 확인했습니다. 실제로 에이전트 빌더 제품에 강력한 제품 내 평가 기능이 필요하다는 것을 재확인하는 데 도움이 되었습니다. 인덱스를 선택하는 도구만을 위한 전체 테스트 하네스를 구축해야 한다면, 고객은 반복적으로 조정할 때 사용자 지정 도구를 정성적으로 평가할 수 있는 방법이 반드시 필요합니다.
앞으로 무엇을 만들게 될지 기대가 되며, 여러분도 기대가 되시길 바랍니다!




