반응형

VectorCypher 검색 및 기타 GraphRAG 검색기로 MCP 도구 상자 확장

The 모델 컨텍스트 프로토콜(MCP)는 애플리케이션이 LLM에 컨텍스트를 제공하여 표준화된 도구를 통해 외부 데이터 및 기능에 액세스할 수 있도록 하는 방법을 정의하는 개방형 표준이에요.

그러한 MCP 서버 중 하나는 MCP Neo4j Cypher 서버인데, 이걸 통해 에이전트는 Neo4j 데이터베이스를 `query`할 수 있어요. 이 MCP 서버를 사용하면 데이터베이스 `schema` 정보를 검색하고 Cypher 구문을 직접 배울 필요 없이 LLM(Text2Cypher)에서 생성된 Cypher `query` 읽기 및 쓰기를 모두 실행할 수 있죠. 이런 방식으로 Text2Cypher 접근 방식은 자연어와 기존 그래프 `query` 사이에 투명하고 효과적인 연결을 제공한답니다.

하지만, 벡터 검색은 또 다른 도전을 제시해요. Text2Cypher와 달리 벡터 검색은 단순히 자연어를 Cypher `query`로 변환하는 게 아니거든요. 대신 데이터와 `query`에 대한 `Vector Embedding`을 생성한 다음 이를 벡터 `index`에서 비교해야 해요. 이 때문에 프로세스가 덜 투명해지죠. 결과를 의미 있게 해석하려면 `Vector Embedding`을 생성하는 데 사용된 텍스트 `Vector Embedding` 모델과 `query`가 해당 모델과 어떻게 일치하는지 아는 것이 중요해요. 효과적인 벡터 검색을 설계하려면 암호 생성뿐만 아니라 `Vector Embedding` 관리 및 신중한 `query` 공식화가 필요하답니다.

이걸 해결하기 위해 Neo4j는 GraphRAG를 제공하는데, 그중 하나가 VectorCypherRetriever에요. 이건 벡터 검색과 Cypher를 결합한 거죠. 이 블로그 게시물에서는 이 검색기를 MCP 서버로 노출해서 에이전트를 위한 추가 도구로 사용할 수 있도록 하는 방법을 살펴볼게요.

MCP 코드는 다음 에서 확인할 수 있어요.

GraphRAG 리트리버를 MCP 서버로 노출

언급했듯이 텍스트 `Vector Embedding`도 생성해야 하므로 사용자 정의 검색기가 필요해요. 왜 LLM에 `Vector Embedding` 모델을 도구로 제공하고 이를 Text2Cypher와 결합하지 않는지 궁금할 수도 있을 것 같아요. 그 이유는 오늘날 한 도구의 결과를 다른 도구로 전달하는 유일한 방법은 LLM 컨텍스트 자체를 통해서이기 때문이에요. 하지만 `Vector Embedding`은 고차원 벡터이므로 LLM을 통해 이를 라우팅하는 것은 토큰 및 지연 시간 측면에서 비효율적이고 비용이 많이 들죠.

VectorCypherRetriever를 MCP 도구로 노출

위에 표시된 것처럼 더 나은 접근 방식은 검색기가 전체 워크플로를 처리해서 `Vector Embedding`을 생성하고 벡터 검색을 수행하도록 하는 거예요. 이렇게 하면 `Vector Embedding`이 LLM을 통과하지 않고 모든 것이 단일 도구 인터페이스 뒤에서 깔끔하게 추상화되죠.

GraphRAG 벡터Cypher MCP

이제 검색기를 구현할 차례에요. 저는 MCP 프레임워크 전문가가 아니기 때문에 MCP 프레임워크의 구조를 복사하는 것부터 시작했어요. MCP Neo4j Cypher 서버를 참고해서 FastMCP로 구축했고, 이걸 적용했죠.

`Vector Embedding` 모델을 구현하려면 유연한 방법이 필요해요. 코드 수정 없이 VectorCypherRetriever MCP가 모든 모델과 호환되도록 만들기 위해 LangChain의 init_embeddings 기능을 사용했어요. 이 함수는 간단한 provider:model 문자열을 사용하면 다양한 `Vector Embedding` 모델 간을 매우 쉽게 전환할 수 있게 해주죠.

# Example
embedding_model = init_embeddings("openai:text-embedding-3-small")

검색기가 작동하려면 다음 구성 요소를 정의해야 해요.

  • The Neo4j 데이터베이스 연결
  • The 벡터 `index` 이름
  • The Cypher `query` 검색을 위해

이러한 설정을 구성한 후 서버를 구축하는 함수에 검색기 개체를 전달하면 돼요.

embedding_model = init_embeddings(embedding_model)
driver = GraphDatabase.driver(db_url, auth=(username, password))
retriever = VectorCypherRetriever(
    driver,
    index_name=index_name,
    embedder=embedding_model,
    retrieval_query=retrieval_query,
    neo4j_database=database
)

mcp = create_mcp_server(retriever, namespace)

MCP 서버는 LLM과 외부 기능 사이의 다리 역할을 하면서 형태로 노출돼요. 이런 도구를 정의해두면 서버는 LLM이 사용자 쿼리에 응답하는 데 도움이 되는 도구 실행을 요청할 수 있게 되죠.

여기서는 벡터 검색을 수행하는 함수, 즉 단일 도구를 노출해볼게요.

@mcp.tool(
    name=namespace_prefix + "neo4j_vector",
    annotations=ToolAnnotations(
        title="Neo4j vector",
        readOnlyHint=True,
        destructiveHint=False,
        idempotentHint=True,
        openWorldHint=True,
    ),
)
async def vector_search(
    query: str = Field(..., description="Natural language question to search for.")
) -> list[ToolResult]:
    """Find relevant documents based on natural language input"""

    try:

        result = vector_retriever.search(query_text=query, top_k=5)
        text = "\n".join(item.content for item in result.items)

        return ToolResult(content=[TextContent(type="text", text=text)])

    except Neo4jError as e:
        logger.error(f"Neo4j Error executing read query: {e}\n{query}")
        raise ToolError(f"Neo4j Error: {e}\n{query}")

    except Exception as e:
        logger.error(f"Error executing read query: {e}\n{query}")
        raise ToolError(f"Error: {e}\n{query}")

이 함수는 Neo4j 데이터베이스에 대한 Semantic Search 도구 역할을 하는 거예요. LLM이 이 도구를 사용하기로 결정하면 자연어 쿼리가 전달되죠. 그러면 함수는 벡터 검색기를 사용해서 데이터베이스에서 가장 관련성이 높은 문서 5개를 찾고, 결합된 텍스트 콘텐츠를 LLM에 반환한답니다.

@mcp.tool 데코레이터는 vector_search 함수를 사용 가능한 도구로 만들어줘요. 도구 설명은 해당 문서 문자열에서 자동으로 생성되어서 LLM에게 명확한 지침을 제공하죠. 도구 정보는 다음과 같아요:

  1. 도구의 목적 ("무엇"): 함수의 주요 독스트링은 도구의 전반적인 설명이 돼요. 이 요약 정보는 LLM에게 도구의 기능을 알려주고 언제 사용해야 할지 결정하는 데 도움을 줘요.
  2. 도구의 입력 ("방법"): 함수에 필요한 각 파라미터도 설명해야 해요. 이런 구체적인 설명은 LLM에게 각 입력에 대해 어떤 정보를 제공해야 하는지 정확하게 알려줘서 도구를 올바르게 호출하도록 도와주죠.

추가적으로 도구 주석을 정의할 수도 있어요.

  • name: 도구에 고유한 이름을 부여해요.
  • readOnlyHint=True: 이 도구는 데이터를 읽기만 하고 데이터베이스를 변경하지 않는다는 의미예요.
  • destructiveHint=False: 도구가 파괴적이지 않다는 것을 명시적으로 나타내죠.
  • idempotentHint=True: 정확히 동일한 쿼리로 도구를 여러 번 호출해도 추가적인 부작용 없이 동일한 결과를 얻을 수 있다는 의미에요. 예를 들어 "cats"를 두 번 검색하면 동일한 결과가 나오고 아무것도 변경되지 않죠.
  • openWorldHint=True: 도구의 지식 소스(Neo4j 데이터베이스)가 독립적으로 업데이트될 수 있다는 것을 LLM에 알려줘요. 새 데이터가 추가되면 오늘 얻는 답변이 내일 얻는 답변과 다를 수 있다는 거죠.

Claude Desktop에서 테스트하기

이제 Claude 데스크탑 애플리케이션에서 다음 구성을 사용해서 서버를 테스트할 수 있어요.

이 설정은 공개 읽기 전용 Neo4j 영화 추천 데이터베이스에 연결되도록 미리 구성되어 있어요. OPENAI_API_KEY만 입력하면 텍스트 임베딩 모델을 사용할 수 있답니다.

{
  "mcpServers": {
    "neo4j-dev": {
      "command": "uv",
      "args": ["--directory", "/path/to/servers/mcp-neo4j-vector-graphrag", "run", "mcp-neo4j-vector-graphrag", "--transport", "stdio", "--namespace", "dev"],
      "env": {
        "NEO4J_URI": "neo4j+s://demo.neo4jlabs.com:7687",
        "NEO4J_USERNAME": "recommendations",
        "NEO4J_PASSWORD": "recommendations",
        "NEO4J_DATABASE": "recommendations",
        "OPENAI_API_KEY": "sk-proj-",
        "INDEX_NAME": "moviePlotsEmbedding",
        "EMBEDDING_MODEL": "openai:text-embedding-ada-002",
        "RETRIEVAL_QUERY": "RETURN 'Title: ' + coalesce(node.title,'') + 'Plot: ' + coalesce(node.plot, '') AS text, {imdbRating: node.imdbRating} AS metadata, score"
      }
    }
  }
}

moviePlotsEmbedding index를 사용하면 포함된 영화 줄거리 데이터에서 Natural Language Processing 검색이 가능해요. 한번 테스트해 볼까요?

Claude Desktop의 샘플 흐름

요약

작년의 검색 시스템은 더 이상 쓸모 없어진 게 아니라, 새로운 형태로 진화한 거예요. 에이전트 시대에는 리트리버가 모듈식, 효율적, 표준화된 도구로 포장되죠. 깔끔한 MCP 인터페이스 뒤에 임베딩 생성 및 Vector Search의 복잡성을 숨김으로써, LLM이 데이터 검색의 하위 수준 메커니즘보다는 추론 및 조정에 집중할 수 있도록 도와주는 거예요.

에이전트는 복잡한 내용을 알 필요가 없어요. text-embedding-3-small이나 Vector Index의 구조 같은 것 말이죠. 그냥 호출할 수 있는 강력한 Semantic Search 도구가 있다는 것만 알면 돼요. 동일한 원칙을 적용해서 다른 항목들을 노출할 수도 있어요. GraphRAG 검색기나 맞춤 데이터 액세스 로직을 사용해서 에이전트를 위한 다양하고 강력한 도구 상자를 만들 수 있죠.

MCP 코드는 에서 확인할 수 있어요.

자원

  • Free 필수 GraphRAG book
  • 개발자가 모델 컨텍스트 프로토콜(MCP)에 대해 알아야 할 모든 것
  • GraphRAG란 무엇입니까?

  • Cypher
  • mcp 서버

에이치시스템즈LogTree는 Neo4j 기반 GraphRAG 플랫폼으로, 데이터를 자동으로 지식그래프화하고 자연어 질의로 즉시 답을 제공합니다.

👉 에이치시스템즈 홈페이지

반응형

+ Recent posts