LangChain으로 Neo4j DB 활용하기

LangChain Docs를 참고했다.

LangChain Docs 링크


Neo4j란?

Neo4j는 open-source database management system그래프 데이터베이스 기술을 전문으로 하는 회사이다.

즉, Neo4j는 벡터 유사성 검색을 위한 통합 지원 기능을 갖춘 오픈 소스 그래프 데이터베이스라고 볼 수 있다.

  • 특징
    • Neo4j를 사용하면 노드와 에지에 데이터를 표현하고 저장할 수 있으므로 연결된 데이터와 관계를 처리하는 데 이상적이다.
    • Cypher Query Language그래프 데이터와 쉽게 상호작용하고 쿼리할 수 있는 기능을 제공한다.
    • graph traversals and queriesNeo4j를 사용하면 프로덕션 수준 시스템에 적합한 고성능을 구현할 수 있다.

지원 기능

다음과 같은 기능을 지원한다.

  • 근사 최근접 이웃 검색
  • 유클리드 유사성과 코사인 유사성
  • 벡터 검색과 키워드 검색을 결합한 하이브리드 검색

Setup

url = "bolt://localhost:7687"
username = "neo4j"
password = "password"

.env에 필요한 환경변수들을 넣어줬다.

password는 neo4j 홈페이지에서 instance 생성할 때 받은 패스워드이다.

로컬에서 실행하려면 bash에 따로 깔아줘야 한다.

brew install neo4j
neo4j start

neo4j start 명령어 실행 시 터미널창에 나오는 로컬 url에서 DB를 확인할 수 있다.

protocol, username, password를 입력해서 connect해주면 연결이 된다.

기본 requirements 설치는 다음과 같다.

pip install neo4j langchain-neo4j

벡터스토어

Neo4j 벡터 인덱스는 의미 검색이나 예제 선택을 위한 벡터 저장소로 사용된다.

from langchain_neo4j import Neo4jVector로 임포트해서 사용한다.

from langchain_community.document_loaders import TextLoader
from langchain_core.documents import Document
from langchain_neo4j import Neo4jVector
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import CharacterTextSplitter

# DB에 저장을 원하는 문서를 불러옴
loader = TextLoader("문서경로")

documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(documents)

embeddings = OpenAIEmbeddings()

url = os.getenv("NEO4J_URI")
username = os.getenv("NEO4J_USERNAME")
password = os.getenv("NEO4J_PASSWORD")

db = Neo4jVector.from_documents(
    docs,
    embedding=embeddings,
    url=os.getenv("NEO4J_URI"),
    username=os.getenv("NEO4J_USERNAME"),
    password=os.getenv("NEO4J_PASSWORD"),)

이제 DB를 연결해주면 되는데, 여기서 Error가 떴다.

NEO4J_URI 문제였다.

내가 사용하고 있는 URI로 맞게 넣어주기 ..!

그럼 기본적인 유사도 검색, 코사인 거리를 사용한 유사성 검색(기본값)을 먼저 해보자.

query = "애니카 보험은 차사고로 죽으면 최대 보상 금액이 어떻게 돼?"
docs_with_score = db.similarity_search_with_score(query, k=2)

답변은 잘 한 것을 볼 수 있다.

LLM 사용하지 않고, 그냥 쿼리와 DB index간의 유사도로 답변을 얻은 것이다.

그럼 이제 .invoke로 LLM을 호출해서 DB를 참고하여 답하게 해보자.

답은 잘 하는 것을 확인 가능하다.

하지만 DB에서 확인해 보면,

노드들 간의 연결 관계는 없이 엔티티들만 존재하는 것을 확인할 수 있다.

굳이 neo4j를 쓸 필요가 없는 것이다.

심지어 latency, token 사용 수도 Chroma보다 더 길고 많다.

Chroma vs Neo4j

구분 Chroma Neo4j
핵심 구조 순수 벡터 데이터베이스 그래프 DB + 벡터 확장 기능
주요 목적 빠른 유사도 검색 (RAG 전용) 관계 기반 질의 + 의미 검색
속도/Latency 빠름 (메모리 기반, 단순 벡터 검색) 상대적으로 느림 (Cypher 쿼리, 네트워크 I/O)
Token 사용량 적음 (context 바로 반환) 많을 수 있음 (context 추가 전처리, 그래프 정보 포함 시)
적합한 상황 단순 문서검색, Q&A 엔티티 관계 중심 분석, 지식 그래프 기반 질의
데이터 연결성 단순 문서 단위 노드/엣지 기반 연결 (예: 보험상품-보장항목-제외항목 관계)
확장성 (데이터 양) 중간 (in-memory 중심) 매우 높음 (트랜잭션 기반, 수백만 노드 가능)
쿼리 유연성 제한적 (KNN만 가능) 강력 (Cypher, graph traversal 가능)
통합성 (외부 시스템) 간단 (로컬 or 클라우드) 기업 환경에서 강력 (API, BI 툴 연동 등)

즉, 요약하자면,

속도, 단순 RAG, 저비용 → Chroma

관계형 질의, 엔터프라이즈 데이터 분석, 지식 그래프 기반 검색 → Neo4j

인데

크게 메리트가 없어 보이는데 Neo4j를 정말 언제 유용하게 쓸 수 있을까?

relation들을 실제로 연결하고 사용하고자 할 때,

다음과 같은 확장&활용 가능성을 고려해볼 수 있다.

사용 케이스 Neo4j만의 강점
보험 도메인 RAG “삼성화재의 ‘운전자보험’과 관련된 보장 항목 중 ‘교통사고처리지원금’이 포함된 상품만 보여줘” 같은 관계형 질의 가능
RAG + GraphQA 하이브리드 문서 검색 후, 관련 노드(상품-보장항목-고객후기 등) 자동 탐색
FAQ 자동 연결 비슷한 질문들을 그래프 간선으로 연결해서 문맥 유지형 QA 구현
엔티티 기반 Summarization ‘상품명’, ‘특약명’, ‘제외항목’ 같은 노드를 추출해서 구조적 요약 생성
Multi-hop 질의 (Graph Traversal) “A 보험에 포함된 특약 중 B 보험에도 있는 항목”처럼 두 노드 간 교차검색

Neo4j는 속도보다 ‘의미 연결성(semantic graph)’이 주 목적이라 단순 QA 챗봇 단계에서는 오버스펙이지만,

복잡한 추론이 필요한 질문이 들어오면 압도적으로 좋지 않을까?

흠, 그럼 LangGraph를 활용해서 각각 벡터DB, 그래프DB .. 등등을 사용하는 각각의 에이전트를 만들어놓고

  1. 사용자(고객)의 질문 수준이나 난이도,
  2. 혹은 사용자가 쓸 것 인지, 임직원이 쓸 것인지

상황에 따라 특정 에이전트를 활성화하도록 설계하면 리소스도 아낄 수 있고,

필요한 순간에 고수준 추론이 가능한 Neo4j의 장점을 딱 뽑아서 써먹을 수 있지 않을까..

Adaptive Multi-Agent Graph-RAG? 로 아래와 같은 파이프라인처럼.

사용자 입력  [질문 분석 노드]  [에이전트 라우터 노드] ─┬─> [Chroma_RAG_Agent]
                                              ├─> [Neo4j_GraphQA_Agent]
                                              ├─> [Hybrid_Agent]
                                              └─> [Fallback_SimpleLLM]

자, 그럼 아까

” 하지만 DB에서 확인해 보면,

노드들 간의 연결 관계는 없이 엔티티들만 존재하는 것을 확인할 수 있다. “

이 얘기에 대해서 다시 생각해보자.

LLM을 사용하여 비정형 텍스트를 지식 그래프로 변환하는 방법

위의 링크를 참고해서 정말 지식 그래프를 구축해보고자 한다. (근데 만약, 도메인에 대한 이해가 확실하고 이미 데이터 설계자가 원하는 관계 설정이 있다면 LLM을 통하지 않고 직접 해도됨.)