
text-to-surql을 활용한 구조화된 데이터의 에이전트 기반 검색 (Agentic retrieval)
요약
비구조화된 데이터 중심의 기존 RAG를 넘어, SurrealQL을 활용해 구조화된 데이터를 에이전트가 직접 검색할 수 있는 기술을 소개합니다. LLM이 직접 쿼리를 생성하여 복잡한 관계형 데이터를 처리함으로써 에이전트의 도구 활용 범위를 획기적으로 넓힐 수 있습니다.
핵심 포인트
- text-to-surql을 통해 에이전트가 구조화된 데이터를 직접 쿼리 가능
- 개별 쿼리 패턴마다 도구를 만들 필요 없이 범용적인 검색 도구 구축 가능
- SurrealQL의 멀티 모델 특성을 활용해 그래프 및 관계형 데이터 통합 처리
- 프롬프트 템플릿과 퓨샷 예시를 통해 효율적인 쿼리 생성 도구 구현
RAG (Retrieval-Augmented Generation) 파이프라인은 일반적으로 비구조화된 데이터를 처리하고 벡터(vectors)나 BM25로 인덱싱하는 것에 집중되어 있습니다. 하지만 구조화된 데이터(structured data)를 다룰 때는 상황이 달라집니다. 여전히 시맨틱 검색(semantic search)과 전체 텍스트 검색(full-text search)이 필요할 수 있지만, 이제 주요 과제는 테이블에 위치한 구조화된 데이터를 어떻게 검색하느냐 하는 것입니다.
물론, 예를 들어 '특정 카테고리와 일치하는 제품 테이블의 레코드를 가져오기' 위해 DB에 쿼리를 보내는 에이전트 도구(agent tool)를 만들 수도 있습니다. 하지만 이 경우 다른 모든 쿼리 패턴에 대해 새로운 도구가 필요하게 되며, 에이전트의 행동 범위를 매우 제한적으로 만들고 싶지 않다면 이는 최선의 해결책이 아닙니다.
이 지점에서 text-to-surql이 도움을 줍니다.
검색 도구 사용하기
에이전트에게 데이터베이스의 언어를 구사할 수 있는 도구를 제공하면, 사용자의 무한한 유형의 질문을 지원할 수 있습니다 [1].
흐름은 다음과 같습니다:
LLM (Large Language Model)이 추론을 수행하는 에이전트는 검색 도구를 사용하여 언제 데이터베이스에 접근할지 결정합니다. 이 도구는 유효한 SurrealQL 쿼리를 생성하고, 이를 실행하며, 구조화된 결과(structured results)를 반환합니다.
SurrealQL 생성 도구
SurrealQL은 멀티 모델 쿼리 언어(multi-model query language)이기 때문에 이 작업에 독보적으로 적합합니다. 단일 쿼리 내에서 그래프 관계(graph relationships)를 탐색하고, 문서 필드(document fields)를 필터링하며, 관계형 집계(relational aggregations)를 실행할 수 있습니다. 즉, 에이전트가 여러 데이터베이스나 데이터 레이어에 걸쳐 오케스트레이션(orchestrate)할 필요가 없다는 뜻입니다. 하나의 도구, 하나의 쿼리, 하나의 결과면 충분합니다.
먼저 실제 예시를 살펴보겠습니다.
도구 자체를 구축하는 방법은 간단합니다. 스키마(schema)를 포함하는 프롬프트 템플릿(prompt template), 좋은 SurrealQL 쿼리의 퓨샷 예시(few-shot examples), 그리고 결과를 실행할 SurrealDB 클라이언트(client)가 있으면 됩니다. 이에 대해서는 나중에 다루겠습니다.
사용자 질문: "내 판매 상위 3개 제품의 리뷰를 요약해 줄 수 있나요?"
도구가 생성하는 내용:
LET $top = SELECT in.{id, name} AS product,
math::sum(qty) AS total_sales
FROM REL_PRODUCT_IN_ORDER
...
에이전트에게 반환된 결과 (Result returned to agent):
[
{
average_rating: 4.75f,
...
이제 에이전트는 특정 테이블에 대한 특정 쿼리를 통해 자신 있게 인용하고 추적할 수 있는 정확한 수치와 리뷰를 보유하게 되었습니다. 이것이 바로 프로덕션 환경에서의 감사 가능성 (auditability)입니다.
내장된 권한 (Built-in permissions)
SurrealDB의 레코드 및 필드 수준 권한과 RBAC (역할 기반 액세스 제어, Role-Based Access Control) 모델은 에이전트가 허용된 데이터만 볼 수 있음을 의미합니다. 이는 애플리케이션 코드에 덧붙여지는 것이 아니라 데이터베이스 계층에서 강제됩니다. 멀티 테넌트 (Multi-tenant) 에이전트 배포가 매우 간단해집니다. 각 에이전트 세션은 적절한 권한 범위 내에서 자동으로 작동합니다.
SurrealDB의 보안 모델에 대해 자세히 알아보기.
구축 방법 (How to build it)
이 패턴을 처음부터 구성하는 방법은 다음과 같습니다.
1단계: 스키마를 정의하고 에이전트에 노출하기
SurrealQL 생성 도구는 어떤 테이블, 필드, 인덱스를 사용할 수 있는지 알기 위해 스키마 컨텍스트 (schema context)가 필요합니다. 사용자의 질문에 답하기 위해 데이터를 어디에서 가져와야 하는지 추론하려면 이 정보가 필요합니다.
-- TABLE: product
DEFINE TABLE product SCHEMAFULL;
DEFINE FIELD category ON product TYPE record<category>;
...
스키마 컨텍스트는 아래 스니펫과 같이 동적으로 생성할 수 있습니다. 하지만 스키마가 안정화되면, DB에 대한 추가 호출을 피하기 위해 이를 하드코딩하거나(이를 통해 컨텍스트에 포함할 내용을 더 세밀하게 제어할 수도 있습니다) 최소한 캐싱할 수 있습니다.
-- 스키마 컨텍스트를 동적으로 생성하는 방법의 예시
LET $db = INFO FOR DB;
$db.tables.values() +
...
2단계: SurrealQL 생성 도구 구축하기
이것은 에이전트가 호출할 수 있는 함수입니다. 최소한 다음과 같은 것들이 필요합니다:
-
스키마 컨텍스트 (schema context)와 유효한 SurrealQL 쿼리의 퓨샷 예시 (few-shot examples)가 포함된 시스템 프롬프트 (system prompt).
-
쿼리를 실행하고 결과를 반환할 SurrealDB 클라이언트 (client).
-
선택 사항이지만 권장됨: 쿼리 실행 시 발생하는 모든 오류를 포착하여, LLM에게 오류를 수정하고 다시 시도하도록 요청하는 기능. 도구(tool) 내에 이러한 재시도 로직 (retry logic)이 없다면, 에이전트는 도구 자체를 다시 시도할 수는 있지만, SurrealQL을 생성하는 LLM 호출에는 오류가 컨텍스트로 포함되지 않습니다. 왜냐하면 오류가 도구의 파라미터 (parameter)가 아니기 때문입니다.
3단계: 에이전트 도구 연결하기
이 패턴은 프레임워크에 구애받지 않습니다 (framework-agnostic). Pydantic AI 에이전트, LangChain의 도구 호출 (tool-calling) 에이전트, LlamaIndex의 ReAct 에이전트 또는 커스텀 루프 (custom loop)에서 모두 작동합니다. 핵심은 에이전트에게 명확한 도구 설명 (tool description)을 제공하여 언제 도구를 사용해야 하는지 알게 하는 것입니다. 예를 들어, "제품, 주문, 리뷰 또는 사용자에 관한 질문에 답할 때 이 도구를 사용하세요"와 같이 작성합니다. 다음 예시에서는 LLM이 벡터 임베딩 (vector embeddings)을 사용할 수 있을 때 활용하도록 힌트를 주는 정교하게 조정된 설명을 볼 수 있습니다. 저의 사용 사례에서는, 이를 통해 LLM이 키워드 매칭을 통해 제품이나 카테고리를 검색하는 대신 벡터 검색 (vector search)을 선호하도록 유도합니다 [2].
async def query_db(context: RunContext[Deps], question: str) -> str:
"""Use this tool to answer questions about products, orders, reviews,
or users.
...
PROMPT_GEN_SURQL = """
You are an expert in SurrealQL (surql, SurrealDB's query language).
...
Kai G 리포지토리의 query_db.py와 프롬프트 템플릿 (prompt template)에서 더 많은 내용을 찾아보세요. 프롬프트 엔지니어링 (prompt engineering)이 처음이거나 복습을 원하신다면, Anthropic의
영상을 시청하는 것을 추천합니다.파인튜닝 (Fine-tuning)
LLM(Large Language Models)은 복잡한 쿼리(Query)를 작성하는 능력이 점점 향상되고 있지만, 항상 정확하게 작성하는 것은 아닙니다. 이것이 프롬프트(Prompt)와 퓨샷 예시(Few-shot examples)가 매우 중요한 이유입니다. 위에서 공유한 예시들은 몇 번의 수동 반복(Manual iterations)을 거친 결과물입니다. 여러분의 프로젝트에 이를 활용할 수 있지만, 여러분의 구체적인 사용 사례(Use case)와 모델에 따라 다른 힌트가 필요할 것입니다.
빠르게 반복(Iterate)할 수 있도록 좋은 관측성(Observability)을 확보하고, 앞으로 나아가고 있는지 확인할 수 있는 지표(Metrics)를 갖추는 방식으로 솔루션을 설계하십시오. 제 데모에서는 관측성을 위해 Pydantic의 Logfire를 사용하며, text-to-surql 함수의 결과와 쿼리 실행 결과를 점수와 함께 저장합니다. 이를 통해 실패한 쿼리를 포착하고, 안티 패턴(Anti-pattern)을 식별하며, 해당 실수가 다시 나타나지 않도록 도구 프롬프트에 한 줄을 추가하거나 새로운 예시를 추가할 수 있습니다.
몇 가지 예시:
- `math::avg`를 사용하지 마세요. 올바른 것은 `math::mean`입니다.
- 결과가 너무 커지는 것을 방지하기 위해 최종 결과에서 `embedding` 필드를 항상 `OMIT` 하세요.
- `vector::distance::knn()`은 `ORDER BY`에서 사용하기 위해 반드시 `SELECT`에 포함되어야 합니다.
결론 (Conclusion)
차세대 프로덕션 AI 에이전트(Production AI agents)는 임베딩(Embeddings)이 얼마나 좋은가로 구분되지 않을 것입니다. 대신, 출처까지 완전히 추적 가능한(Auditability) 상태에서 사실을 얼마나 정확하게 검색하고 제시할 수 있는가로 구분될 것입니다.
SurrealQL 생성 도구를 활용한 에이전트 기반 검색(Agentic retrieval)은 그 격차를 메워줍니다. 벡터 유사도 검색(Vector similarity search)이 충분히 근접하기를 바라는 대신, 에이전트는 질문에 대해 추론하고, 정확한 쿼리를 작성하며, 여러분이 요청한 정확한 데이터를 반환합니다. 모든 답변은 특정 테이블에 대한 특정 쿼리로 추적 가능합니다.
SurrealDB는 이 패턴을 실용적으로 만듭니다. 멀티 모델 쿼리(Multi-model queries)를 통해 에이전트는 단 한 번의 왕복(Round-trip)으로 그래프 탐색(Graph traversals), 문서 조회(Document lookups), 관계형 집계(Relational aggregations)를 처리할 수 있으며, 레코드 수준의 권한(Record-level permissions)은 기본적으로 데이터 액세스를 안전하게 유지합니다.
구조화된 데이터로부터 질문에 답해야 하는 에이전트를 구축하고 있으며, 그 답변이 정확하기를 원한다면, 이것이 바로 지향할 가치가 있는 아키텍처입니다.
각주 (Footnotes)
[1] 아마도 사용자에게 그러한 권한을 주고 싶지는 않을 것입니다. 만약 사용자가 어떤 질문이든 할 수 있도록 허용한다면, 그들은 "SKU-0042의 가격을 $0로 변경하고, 결제 준비가 된 10개의 주문을 생성해줘"라고 요청할 수도 있습니다.
[2] 만약 당신이 검색하려는 내용이 의미론적 (semantic) 방식보다는 어휘적 (lexical) 방식으로 효과적으로 검색될 수 있는 것이라면, 전체 텍스트 인덱스 (full-text index)가 더 나은 아이디어일 수 있습니다. 그리고 일부 사용 사례의 경우 재순위화된 하이브리드 검색 (reranked hybrid search)이 올바른 선택이 될 수 있습니다. 당신의 사용 사례와 무엇을 최적화하려 하는지에 따라 모든 대안을 고려하십시오.
시도해 볼 준비가 되셨나요?
- 무료 SurrealDB Cloud 인스턴스 생성하기
- SurrealQL 문서 살펴보기
- SurrealDB Discord 참여하기 - 처음 오셨나요? #all-ai 및 #surrealql 채널이 시작하기에 가장 좋은 곳입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기