Neo4j GraphRAG Python 패키지 시리즈의 세 번째 기사에서는 전체 텍스트 인덱스를 사용하여 GraphRAG 애플리케이션을 향상시키는 방법을 살펴볼 거예요. 전체 텍스트 인덱스와 벡터 인덱스를 결합하면 벡터 검색만으로는 놓칠 수 있는 정보를 검색해서 검색 프로세스의 성능을 어떻게 향상시킬 수 있는지 보여드릴게요. 또한 Neo4j GraphRAG Python 라이브러리를 사용하여 전체 텍스트 인덱스와 벡터 인덱스를 모두 활용하는 GraphRAG 애플리케이션을 구축하는 방법을 살펴볼게요.
이전 블로그에서 사용된 사전 구성된 Neo4j 데모 데이터베이스 중 일부를 사용할 건데요 (GraphRAG Python 패키지 and GraphRAG Python 패키지를 사용하여 그래프 탐색으로 벡터 검색 강화 참고). 이 데이터베이스는 영화 추천 Knowledge Graph를 시뮬레이션해요. 데이터베이스에 대한 자세한 내용은 설정 섹션을 참조하세요. GraphRAG Python 패키지.
웹 브라우저를 통해 데이터베이스에 액세스할 수 있어요. 사용자 이름과 비밀번호로 "추천"을 사용하면 돼요. 다음 코드 조각을 사용하여 애플리케이션의 데이터베이스에 연결하세요.
from neo4j import GraphDatabase
# Demo database credentials
URI = "neo4j+s://demo.neo4jlabs.com"
AUTH = ("recommendations", "recommendations")
# Connect to Neo4j database
driver = GraphDatabase.driver(URI, auth=AUTH)
또한 OpenAI 키를 내보내야 해요.
import os
os.environ["OPENAI_API_KEY"] = "sk-…"
벡터 검색의 한계
Vector Search는 RAG 애플리케이션의 기본 구성 요소인 경우가 많아요. 이걸 통해 애플리케이션은 데이터베이스에서 사용자의 쿼리와 의미상 유사한 정보를 찾고, LLM이 응답을 생성할 수 있도록 해당 정보를 관련 컨텍스트로 제공할 수 있죠. 이전 시리즈 게시물에서는 GraphRAG 애플리케이션에서 Vector Search를 사용해서 의미 면에서 사용자 쿼리와 밀접하게 일치하는 플롯이 포함된 영화를 반환하고 영화에 대한 질문에 답했는데요. 예를 들어, 사용자가 "공룡 테마파크를 소재로 한 영화 제목이 뭐죠?"라고 물으면 Vector Search는 영화 Jurassic Park를 검색할 거예요. '미리보기 투어 중에 테마파크의 전력이 크게 중단되어 복제된 공룡 전시물이 날뛰게 됩니다'라는 줄거리가 사용자 쿼리와 의미가 유사하기 때문이죠.
하지만 의미론적 유사성이 항상 모든 쿼리에 대해 가장 관련성이 높은 정보를 검색하는 최고의 척도는 아닐 수 있어요. 예를 들어, 광범위한 의미가 부족하거나 더 넓은 맥락에서 다른 의미를 갖는 도메인별 용어를 검색할 때 Vector Search는 관련 정보를 검색하지 못하거나 관련 없는 정보를 반환할 수 있죠. 이는 이러한 용어가 Vector Search에 사용되는 임베딩 모델의 훈련 데이터에서 잘 표현되지 않을 수 있기 때문에 발생해요. 정확한 결과를 위해 정확히 일치해야 하는 이름이나 날짜와 같은 문자열이 사용자 쿼리에 포함된 경우에도 의미론적 유사성은 신뢰할 수 있는 측정이 아니에요. 이에 대한 예로, VectorRetriever를 사용해서 중국 제국의 1375년 영화 세트와 같이 특정 장소와 날짜를 배경으로 한 영화 세트의 이름을 묻는 경우를 들 수 있어요.
from neo4j import GraphDatabase
from neo4j-graphrag.embeddings.openai import OpenAIEmbeddings
from neo4j-graphrag.retrievers import VectorRetriever
driver = GraphDatabase.driver(URI, auth=AUTH)
embedder = OpenAIEmbeddings(model="text-embedding-ada-002")
retriever = VectorRetriever(
driver,
index_name="moviePlotsEmbedding",
embedder=embedder,
return_properties=["title", "plot"],
)
query_text = "What is the name of the movie set in 1375 in Imperial China?"
retriever_result = retriever.search(query_text=query_text, top_k=3)
print(retriever_result)
이걸 정확하게 일치시키려면 VectorRetriever 일치 알고리즘은 영화의 줄거리 설명 내에서 1375에 대한 정확한 날짜 참조를 찾아야 하지만, 현실적으로 불가능하죠. 결과적으로 VectorRetriever는 이 쿼리에 대한 올바른 영화(전사 무사)를 반환하지 못해요. 대신 중국을 배경으로 하거나 중국과 관련된 영화를 검색하지만, 1375년을 배경으로 한 영화는 없어요.
items = [
RetrieverResultItem(
content="{'title': 'Once Upon a Time in China (Wong Fei Hung)', 'plot': "Set in late 19th century Canton this martial arts film depicts the stance taken by the legendary martial arts hero Wong Fei-Hung (1847-1924) against foreign forces' (English, French and ..."}",
metadata={"score": 0.9209008812904358, "nodeLabels": None, "id": None},
),
RetrieverResultItem(
content="{'title': 'Once Upon a Time in China II (Wong Fei-hung Ji Yi: Naam yi dong ji keung)', 'plot': 'In the sequel to the Tsui Hark classic, Wong Fei-Hung faces The White Lotus society, a fanatical cult seeking to drive the Europeans out of China through violence, even attacking Chinese ...'}",
metadata={"score": 0.9179003834724426, "nodeLabels": None, "id": None},
),
RetrieverResultItem(
content="{'title': 'Red Cliff Part II (Chi Bi Xia: Jue Zhan Tian Xia)', 'plot': 'In this sequel to Red Cliff, Chancellor Cao Cao convinces Emperor Xian of the Han to initiate a battle against the two Kingdoms of Shu and Wu, who have become allied forces, against all ...'}",
metadata={"score": 0.91493159532547, "nodeLabels": None, "id": None},
),
]
metadata = {"__retriever": "VectorRetriever"}
Full-Text Indexes
다행히 이 문제에 대한 해결책이 있어요. 바로 Full-Text Indexes죠. 의미론적 유사성을 기준으로 문자열을 일치시키는 벡터 인덱스와 달리, Full-Text Indexes는 어휘 유사성을 기준으로 텍스트 조각을 일치시켜요. 즉, 정확한 단어 또는 텍스트 구조를 비교하는 거죠. 예를 들어, "The bat fly"와 "The bat broken"이라는 문장을 생각해 볼까요? 이 문장들은 단어 하나만 다르기 때문에 어휘적으로는 유사하지만 의미상으로는 달라요. 첫 번째는 날아다니는 동물을 묘사하고, 두 번째는 물체가 부서지는 것을 묘사하죠. Full-Text Index를 사용하면 날짜, 이름 등의 문자열을 정확하게 일치시킬 수 있어요.
하이브리드 리트리버
하이브리드 검색 프로세스
Neo4j GraphRAG Python 라이브러리의 HybridRetriever 클래스를 사용해서 GraphRAG 애플리케이션에 전체 텍스트 인덱스를 활용하는 방법을 알아볼게요. 이 Retriever는 하이브리드 검색이라는 방식으로 Vector Index와 전체 텍스트 인덱스를 모두 사용해요. 사용자 쿼리를 받아서 두 인덱스를 검색하고, `Node`와 점수를 얻어내죠. 각 결과 세트의 점수를 정규화한 다음 합쳐서 점수별로 순위를 매긴 후, 가장 적합한 결과를 반환해준답니다.
from neo4j import GraphDatabase
from neo4j-graphrag.embeddings.openai import OpenAIEmbeddings
from neo4j-graphrag.retrievers import HybridRetriever
driver = GraphDatabase.driver(URI, auth=AUTH)
embedder = OpenAIEmbeddings(model="text-embedding-ada-002")
retriever = HybridRetriever(
driver=driver,
vector_index_name="moviePlotsEmbedding",
fulltext_index_name="movieFulltext",
embedder=embedder,
return_properties=["title", "plot"],
)
query_text = "What is the name of the movie set in 1375 in Imperial China?"
retriever_result = retriever.search(query_text=query_text, top_k=3)
print(retriever_result)
여기서는 영화 줄거리용 Vector Index (moviePlotsEmbedding)와 각 영화의 제목과 줄거리가 합쳐진 전체 텍스트 인덱스 (movieFulltext)를 다시 사용하고 있어요. 이 Retriever를 사용하면 원하는 영화를 정확히 찾아낼 수 있죠!
items = [
RetrieverResultItem(
content="{'title': 'Musa the Warrior (Musa)', 'plot': '1375. Nine Koryo warriors, envoys exiled by Imperial China, battle to protect a Chinese Ming Princess from Mongolian troops.'}",
metadata={"score": 1.0},
),
RetrieverResultItem(
content="{'title': 'Once Upon a Time in China (Wong Fei Hung)', 'plot': "Set in late 19th century Canton this martial arts film depicts the stance taken by the legendary martial arts hero Wong Fei-Hung (1847-1924) against foreign forces' (English, French and ..."}",
metadata={"score": 1.0},
),
RetrieverResultItem(
content="{'title': 'Once Upon a Time in China II (Wong Fei-hung Ji Yi: Naam yi dong ji keung)', 'plot': 'In the sequel to the Tsui Hark classic, Wong Fei-Hung faces The White Lotus society, a fanatical cult seeking to drive the Europeans out of China through violence, even attacking Chinese ...'}",
metadata={"score": 0.9967417798386851},
),
]
metadata = {"__retriever": "HybridRetriever"}
이걸 전체 GraphRAG 파이프라인으로 만들려면, 다음 코드를 추가하기만 하면 돼요.
from neo4j-graphrag.llm import OpenAILLM
from neo4j-graphrag.generation import GraphRAG
# LLM
# Note: the OPENAI_API_KEY must be in the env vars
llm = OpenAILLM(model_name="gpt-4o", model_params={"temperature": 0})
# Initialize the RAG pipeline
rag = GraphRAG(retriever=retriever, llm=llm)
# Query the graph
query_text = "What is the name of the movie set in 1375 in Imperial China?"
response = rag.search(query_text=query_text, retriever_config={"top_k": 3})
print(response.answer)
우리가 기대하는 답변은 바로 이거죠!
The name of the movie set in 1375 in Imperial China is "Musa the Warrior (Musa)."
요약
neo4j-graphrag 패키지의 HybridRetriever 클래스를 사용해서 GraphRAG 애플리케이션을 구축하는 방법을 보여드렸어요. 이 클래스가 Vector Search와 전체 텍스트 검색을 결합해서, Vector Search만으로는 찾기 어려울 수 있는 사용자 쿼리에 대한 정확한 컨텍스트를 찾아내는 과정을 살펴봤죠.
패키지 코드는 오픈 소스이고 에서 확인할 수 있어요. 언제든지 이슈를 올려주세요.
GraphRAG
Python
에이치시스템즈의 LogTree는 Neo4j 기반 GraphRAG 플랫폼으로, 데이터를 자동으로 지식그래프화하고 자연어 질의로 즉시 답을 제공합니다.
이 기사에서는 정적 YAML 스키마 파일을 Neo4j 지식 그래프로 대체하여 토큰 사용량을 평균 20~30%(간단한 쿼리의 경우 최대 10배) 줄이는 동시에 복잡한 다중 테이블 질문의 정확도를 ~10% 포인트 향상시키는 방법을 보여 드리겠습니다. 모두 3분 안에 실행할 수 있는 라이브 데모에서 벤치마킹되었습니다.
중요한 이유
비즈니스 컨텍스트
데이터 기반 기업의 경우 데이터를 기반으로 주요 결정을 내려야 하므로 데이터에 대한 보편적인 액세스(정책 및 거버넌스 측면에서)는 선도하기 위한 필수 이니셔티브입니다.
그러나 대부분의 데이터는 데이터베이스에 상주하며 조직은 이 데이터를 지속적으로 대시보드로 전송하기 위해 IT 팀에 상당한 시간과 리소스를 투자합니다. 이러한 대시보드는 회사의 KPI를 기반으로 한 결정을 안내하는 중요한 자산이며 앞으로도 그럴 것입니다. 이제 비즈니스 사용자는 더 많은 것을 기대합니다. 그들은 숫자만 보고 싶어하는 것이 아닙니다. 그들은 조직 가치 사슬 전반에 걸쳐 데이터에 직접 액세스하여 '이유'를 이해하고 싶어합니다.
이러한 비즈니스 사용자에게 가장 쉬운 방법은 자연어를 사용하여 해당 산업에 특정한 뉘앙스와 기술 전문 용어를 사용하여 풍부한 맥락에 대한 생각을 전달하고 제공하는 것입니다. 이것이 사용자가 여러 데이터베이스의 데이터와 대화하고 탐색할 수 있도록 AI 에이전트가 개발되는 이유입니다.
오늘날 Text-to-SQL 에이전트의 문제점
데이터베이스와 대화한다는 것은 에이전트가 자연어 질문을 번역하고 PostgreSQL, Oracle, Snowflake, Databricks, BigQuery, Azure Fabric 등을 통해 SQL을 사용하여 데이터를 쿼리한다는 의미입니다.
표준 접근 방식: LLM에 모든 테이블/열 메타데이터가 포함된 포괄적인 YAML(또는 Markdown) 파일을 제공하거나 의미론적 유사성에 대한 벡터 기반의 동등한 파일, SKILL 및 쿼리를 안내하는 추가 비즈니스 설명을 제공합니다.
기본적인 질문에 효과가 있고 데모를 통해 쉽게 '와우' 효과를 제공할 수 있지만 몇 가지 문제점이 있습니다.
높은 토큰 비용: 요청마다 큰 부분 또는 전체 스키마가 전송됩니다.
상황에 따른 소음:관련 없는 테이블은 정확성을 저하시키고 환각을 유발합니다.
정적 제한사항:플랫 파일은 사용 패턴, 사전 또는 비즈니스 의미가 발전함에 따라 유지 관리하기가 어렵습니다. 지속적인 유지가 없으면 시간이 지남에 따라 에이전트의 성능이 저하됩니다.
Neo4j 의미 계층 접근 방식
Neo4j 의미 계층은 다음을 사용하여 GraphRAG 접근 방식을 도입합니다.동적 의미 계층으로서의 Neo4j. 선형 텍스트 파일에서 지식 그래프로 이동하면 에이전트는 모든 메타데이터 '읽기'를 중지하고 데이터 아키텍처를 지능적으로 '탐색'하기 시작합니다.
의미 계층의 스마트 그래프 모델
의미 계층에는 무엇이 저장되나요? 외과적 정밀도로 LLM을 기반으로 하고 유효한 SQL을 생성하기 위해 Neo4j 의미 계층은 다음을 저장합니다.
: 스키마, 테이블, 열, 유형.
: 외래 키 및 색인.
: 열의 특정 값 또는 몇 가지 예입니다.
: 도메인별 용어 및 정의와 기본 분류 구조
: 데이터베이스에서 외래 키로 지정되지 않은 RDBMS 트랜잭션 로그에서 조인합니다.
그리고 에이전트가 데이터베이스를 쿼리해야 할 때 에이전트는질문과 관련된 그래프 부분만, 의미 검색 + 그래프 순회(최단 경로)를 사용합니다.
구체적인 예
벤치마크 애플리케이션
인사(HR) 샘플 데이터가 포함된 Text2SQL 벤치마크 애플리케이션
In 이 응용 프로그램, 동일한 Streamlit 애플리케이션에서 두 에이전트를 나란히 사용하여 두 가지 접근 방식을 검토하고 시험해 볼 수 있습니다.
YAML 에이전트: 호출할 때마다 전체 Database_schema.yaml(44KB, 테이블 ~50개)을 읽습니다.
Neo4j 의미 계층 에이전트: 그래프를 쿼리하여 관련 컨텍스트만 검색합니다.
2개의 에이전트는 스키마 검색 도구의 유일한 차이점을 제외하고 완전히 동일한 LangChain 에이전트 체인 및 도구 세트를 사용하고 있습니다. 불공정한 비교를 피하기 위해 yaml 파일에는 사용자 행동을 기반으로 한 중요한 조인(아래 그래프에서 볼 수 있는 이메일 간의 "REFERENCES" 녹색 관계)과 같이 의미 계층에 저장된 모든 주요 정보가 포함되어 있습니다. 상담사에게 대화 내역이 전송되지 않으므로 세션을 삭제하지 않고도 쉽게 결과를 비교할 수 있습니다.
직원 급여 및 관련 만족도에 대한 질문에 대해 상담원에게 제공되는 컨텍스트 그래프
이 애플리케이션은 Neo4j 및 에이전트 로직에 저장된 의미 계층의 의미 유사성 검색을 위해 OpenAI GPT(gpt-5.4-mini + text-embedding-3-small)를 사용하여 PostgreSQL 데이터베이스에 저장된 인사 데이터(가짜 공개 데이터 세트)를 쿼리합니다.
상담원에게 질문하기
애플리케이션에는 예상되는 SQL 쿼리를 기반으로 답변의 정확성을 확인하고 증가하는 복잡성을 다룰 수 있도록 HR 데이터에 대한 3가지 질문이 사전 연결되어 있습니다.
단순 카운트, 단일 테이블(“후보자는 몇 명이에요?”)
다중 테이블 조인 및 집계(“남성과 여성의 평균 급여와 만족도는 얼마입니까?”)
공통 테이블 표현식(CTE) + 창 함수(ROW_NUMBER()), 그룹화(“현재 각 역할에서 가장 흔한 이름은 무엇입니까?”)
YAML 에이전트의 정확성 및 비용
데모 애플리케이션(아래 스크린샷 참조)에서 에이전트의 기본 구성을 사용하면YAML 설명 사용, 일반적인 결과는 다음과 같습니다.
간단한 질문에 대한 100% 완벽한 정확성
다중 조인을 사용한 질문의 정확도 ~90%
중간 보기(CTE)가 필요한 질문에 대한 정확도 ~85%
YAML 에이전트의 평균 정확도(각각 10회 실행)
복잡한 질문에 대한 YAML 에이전트의 평균 정확도(각각 10회 실행)
비용과 관련하여 컨텍스트로 제공된 YAML 파일의 크기를 반영하는 안정적인 토큰 사용량(18,000개 토큰)을 볼 수 있습니다. 에이전트가 환각을 느끼는 상황에서 질문을 하면 비용이 급격히 증가할 수 있습니다. 컨텍스트를 너무 많이 추가하면 잘못된 SQL 쿼리가 생성될 위험이 높아지고 에이전트가 오류를 수정하기 위해 루프를 반복하고 토큰 소비가 늘어날 위험이 있습니다.
YAML 에이전트에서 사용하는 토큰
Neo4j 의미 계층 에이전트의 정확성 및 비용
데모 애플리케이션을 유지하면서 설정에서 Neo4j 의미 계층 에이전트로 전환하면 일반적으로 정확도가 향상됩니다.
간단한 질문의 경우 100% 정확도
다중 조인을 사용한 질문의 정확도 ~98%
중간 보기(CTE)가 필요한 질문에 대한 정확도 ~94%
의미 계층의 평균 정확도(각각 10회 실행)
비용과 관련하여 YAML 에이전트는 환각이 아닌 답변에 대해 거의 일정한 수의 토큰을 사용하는 반면 Neo4j 의미 계층은 질문의 복잡성에 따라 달라집니다.
간단한 질문에 토큰 최대 1,800개
다중 조인 관련 질문에 최대 5,000개의 토큰
중간 보기(CTE)가 필요한 질문에 대한 토큰 최대 7,300개
최단 경로를 사용하여 긴 테이블 조인 체인을 보여주는 컨텍스트 그래프
결과 분석 및 그래프가 복잡한 질문에 적합한 이유
간단한 질문의 경우 두 에이전트 모두 비슷한 성능을 발휘하지만 사용되는 토큰은 확실히 줄어듭니다. 평균적으로, 그리고 이 접근 방식을 사용하는 프로젝트 현장에서 수집한 내용을 통해 우리는 최소한의 결과를 확인했습니다.토큰 20~30% 감소YAML 파일(또는 다중 에이전트로 분산된 여러 YAML 파일)을 사용하는 정적 접근 방식과 비교됩니다.
복잡한 다중 테이블 쿼리의 경우Neo4j 에이전트는 훨씬 더 높은 정확도를 보여줍니다(이 데모에서는 +10% 포인트).컨텍스트 그래프의 관련 부분에만 초점을 맞추기 때문입니다. 이 이점은 더 큰 스키마(50~100개 이상의 테이블)와 쿼리에 여러 테이블 간의 조인이 포함될 때 증가합니다. 비즈니스 용어집, 관련 분류 및 예제 값을 사용하면 특히 업계의 특정 용어 및 비즈니스 복잡성을 정의할 때 의미 계층 신뢰성이 향상됩니다.
제공된 정보에는 조인 경로가 포함됩니다. 이러한 조인 경로는 데이터베이스(외래 키)의 기술 메타데이터를 사용합니다.또한 데이터 엔지니어/분석가의 행동에서 지속적으로 업데이트될 수 있는 외래 키로 선언되지 않은 사용 추론 조인도 있습니다.. 관계형 데이터베이스 트랜잭션 로그에서 추출된 이러한 행동 정보는 다음에서 가중치로 사용될 수 있습니다.경로 찾기 알고리즘가장 많이 사용되는 항목만 제안합니다.
이 조인("REFERENCES")은 PostgreSQL 트랜잭션 로그에서 2번 확인되었습니다.
Neo4j 의미 계층에 대한 심층 분석
토큰 감소와 정확성 향상은 LLM이 완벽한 SQL 쿼리를 생성하는 데 필요한 메타데이터를 찾는 것을 기반으로 합니다. 이는 3단계로 이루어집니다.
의미적 유사성을 사용하여 가장 유사한 용어와 열 및 관련 테이블을 찾습니다.
MATCH (column:Column)
SEARCH column IN (VECTOR INDEX column_similarity
FOR $userEmbedding LIMIT 10) SCORE as score
WHERE score>$threshold
RETURN DISTINCT column
UNION
MATCH (entryTerm:Term)
SEARCH entryTerm IN (VECTOR INDEX term_similarity FOR $userEmbedding LIMIT 10) SCORE as score
WHERE score>$threshold-0.1
MATCH (entryTerm)-[:HAS_TERM*0..]->(:Term)-[:DEFINES|HAS_COLUMN*1..2]->(column:Column)
RETURN DISTINCT column
2. 식별된 테이블 사이에서 가능한 모든 조인을 찾습니다.
WITH collect(DISTINCT column) as columns
UNWIND columns as sourceColumn
UNWIND columns as targetColumn
WITH sourceColumn, targetColumn
OPTIONAL MATCH links = SHORTEST 1
(sourceTable:Table {name:sourceColumn.tableName})
(()-[:HAS_COLUMN|HAS_FOREIGN_KEY|ON_COLUMN|REFERENCES]-(x)){0,16}
(targetTable:Table {name:targetColumn.tableName})
3. 추가 컨텍스트 수집
WITH DISTINCT sourceColumn as columnSimilarity, links
MATCH (table:Table)-[:HAS_COLUMN]->(columnSimilarity:Column)
MATCH p=(:Schema)-[:CONTAINS_TABLE]->(table)-[:HAS_COLUMN]->(column:Column)
OPTIONAL MATCH termCol = (:Term)-[:HAS_TERM*0..]->(:Term)-[:DEFINES]->(column)
OPTIONAL MATCH termTable = (:Term)-[:HAS_TERM*0..]->(:Term)-[:DEFINES]->(table)
OPTIONAL MATCH values = (column)-[:HAS_VALUE]->(:Value)
그러면 테이블 정보와 테이블 간의 가능한 조인이 포함된 결과가 JSON 형식으로 단 몇 ms 만에 상담사에게 제공될 수 있습니다.
코딩 에이전트(커서, VS Code…)에서 데모 코드 폴더를 열고 모든 작업을 수행하도록 요청합니다. Init는 인터넷에서 HR 데이터세트를 다운로드하고 PostgreSQL 및 Neo4j에 데이터를 로드합니다.
Can you look at the README.md and run this application in a virtual python 3.13.3 environment ?
The application must reach openAI api on the internet, so don't configure proxy blocking internet access.
* I have installed locally PostgreSQL with database postgres and no password
* I have installed locally Neo4j with password text2sql
* You should have the openAI key in your env context
내장된 예시를 뛰어넘으세요
미리 연결된 세 가지 질문은 증가하는 SQL 복잡성을 다루지만 이에 국한되지는 않습니다. 설정 옆에 있는 버튼을 사용하여 다음을 입력할 수 있는 대화상자를 열어 자신만의 테스트 사례를 정의할 수 있습니다.
자연어 관련 질문
예상되는 정답을 나타내는 참조 SQL
비교 지침(검사기가 결과를 확인하기 위해 사용하는 열)
귀하의 질문이 목록에 나타나고 정확성 검사가 자동으로 실행됩니다. 이를 통해 자신의 시나리오에서 나온 질문에 대해 두 상담원을 모두 벤치마킹할 수 있습니다.
더 나아가기: 그래프 데이터 과학, 플러그 앤 플레이 MCP
Neo4j 의미 계층의 주요 장점 중 하나는 기본 설정으로도 견고한 결과를 제공하는 동시에 특히 그래프 데이터 과학(GDS)을 통해 상당한 개선 여지를 남겨둔다는 것입니다.
가중치를 사용한 경로 찾기: 트랜잭션 로그에서 조인이 실행된 횟수를 'REFERENCES' 에지에 대한 가중치로 사용하여 트래픽이 많은 조인을 선호합니다.경로 찾기 알고리즘
엔터티 해결: use 약하게 연결된 구성요소(WCC) and K-최근접이웃(KNN)구조화되지 않은 비즈니스 문서에서 추출된 항목에 대해 동의어를 비즈니스 용어집 용어에 자동 연결합니다.
: 각 비즈니스 사용자가 액세스할 수 있는 데이터만 그래프 컨텍스트에 반영되도록 사용자 그룹 액세스 제어를 포함합니다.
비즈니스 프로세스 강화: 데이터 흐름을 그래프 경로로 모델링하여 프로세스 수준 질문에 답합니다.
: 에이전트는 의미 계층에서 대화 기록과 사용자 피드백을 캡처하여 시간이 지남에 따라 더 높은 품질의 SQL 쿼리를 생성할 수 있습니다. (에이전트 지속적인 개선)
가속기로서 의미 체계 계층은 플러그 앤 플레이 MCP 서버를 갖춘 프로젝트 Neocarta에서 사용할 수 있습니다.
관계형 데이터베이스에 대한 자연어 쿼리는 이제 주요 플랫폼 전반에 걸쳐 표준이 되었습니다. 데모와 프로덕션 시스템을 구분하는 것은 제공하는 컨텍스트입니다.
전통적인 플랫 파일 또는 벡터 기반 접근 방식은 스키마 문서를 컨텍스트 창에 덤프할 텍스트 덩어리로 취급합니다. 이로 인해 프롬프트가 지나치게 커지고, API 비용이 높아지며, 의미 있는 추론이 시작되기도 전에 관련 없는 테이블 정의로 인해 LLM의 부담이 커집니다.
Neo4j 의미 계층은 접근 방식을 근본적으로 바꿉니다. 에이전트에게 모든 것을 제공하고 에이전트가 알아낼 것이라고 기대하는 대신, 질문에 답하는 데 필요한 것, 즉 관련 테이블, 열, 조인 경로 및 비즈니스 용어에 대한 정확한 실시간 하위 그래프만 제공합니다. 결과는 분명합니다. 특히 구조적 맥락과 비즈니스 맥락이 모두 필요한 복잡한 다중 테이블 질문의 경우 모든 쿼리에서 토큰 사용량이 낮아지고 정확도가 훨씬 높아졌습니다.
그래프는 또한 YAML 파일이 근본적으로 포착할 수 없는 것, 즉 데이터가 실제로 사용되는 방식을 포착합니다. 트랜잭션 로그에서 채굴된 패턴, 모호한 언어를 해결하는 비즈니스 용어집, 이론적인 경로보다 검증된 경로를 선호하는 사용량 가중치 관계 등을 조인하세요. 이는 데이터 생태계의 역동적이고 살아 있는 속성이며, 지식 그래프는 이를 모델링하는 데 적합한 도구입니다.
LLM에는 더 큰 컨텍스트 창이 필요하지 않습니다. 더 나은 지도, 즉 그래프 기반 지도가 필요합니다.
그래프RAG
텍스트-SQL
에이치시스템즈의 LogTree는 Neo4j 기반 GraphRAG 플랫폼으로, 데이터를 자동으로 지식그래프화하고 자연어 질의로 즉시 답을 제공합니다.
몇 년 동안 글로벌 제약 및 생명 과학 커뮤니티를 모아서 그래프 기술이 데이터 문제를 해결하는 데 어떻게 도움이 되는지 논의했는데요. 올해 행사는 실용화에 중점을 두었어요. Knowledge Graph, GraphRAG, 그리고 GenAI를 생명 과학 및 의료 분야에 적용하는 방법에 대해서 말이죠.
이번 행사에는 제약 및 생명공학 분야의 기술 리더, 개발자, 데이터 과학자들이 한자리에 모였답니다. 참석자들은 아이디어를 교환하고, 생산 가능한 그래프 아키텍처를 탐색하고, Neo4j를 사용해서 R&D 지식 관리부터 정밀 의학 및 신약 개발에 이르기까지 업계에서 가장 시급한 데이터 문제들을 해결하는 방법을 공유했어요.
혹시 이벤트를 놓치셨나요? 모든 세션을 지금 바로 보실 수 있어요.
실제 그래프 통찰의 하루
하루 종일 발표자들은 그래프 기반 접근 방식이 어떻게 복잡한 생물의학 데이터에 대한 구조화되고 설명 가능하며 확장 가능한 솔루션을 가능하게 하는지 강조했는데요. 볼만한 가치가 있는 4개의 뛰어난 세션이 있답니다.
Synaptix — 그래프 및 GenAI를 사용하여 R&D 지식 관리
Merck Group의 Natalie Romanov 님이 Synaptix 플랫폼이 전임상 연구, 임상 개발, 규제 운영 전반에 걸쳐 단편화된 지식을 연결하는 방법을 공유했어요. Neo4j를 사용해서 약물 용도 변경부터 경쟁력 있는 인텔리전스까지 분석 및 에이전트 GenAI 워크플로를 모두 지원하는 그래프 생태계를 구축했다고 해요. 구조화된 그래프 모델과 생성 인터페이스를 결합해서 상황에 맞는 AI 증강 통찰력을 제공하는 이중 플랫폼 전략의 대표적인 예시라고 할 수 있죠.
밤을 통해 빛으로: Noctis로 화학 반응 데이터 탐색
Syngenta의 Nataliya Lopanitsyna 님이 발표를 맡았는데요. 이 세션에서 Syngenta는 단 3줄의 Python 코드로 문헌, 특허, 고처리량 스크린의 데이터를 쿼리 가능한 Knowledge Graph로 바꾸는 오픈 소스 툴킷인 NOCTIS를 소개했어요. 실험실 벤치부터 데이터 레이크, 그래프까지 전체 파이프라인을 살펴보면서 그래프 기반 표현이 어떻게 합성 경로 계획을 가속화하고 기존 시스템이 종종 놓치는 패턴을 찾아내는지 보여주었답니다.
프로젝트 AMIGO: 유전적 발견을 표적 치료법으로 전환
LMU Klinikum의 Nicola Götzenberger 님과 Daniel Weiss 님이 발표를 맡았어요. 프로젝트 AMIGO는 희귀 질환을 앓고 있는 어린이의 진단 및 치료를 가속화하기 위한 야심 찬 연합 데이터 이니셔티브라고 해요. Care-for-Rare 재단은 소아과 진료소 전반의 Knowledge Graph와 보안 데이터 협업을 통해 어떻게 진단 일정을 단축하고 표적 치료를 활성화하며 질병 진행에 대한 실시간 통찰력을 지원할 수 있는지 보여주었는데요. 정밀 의학을 통해 삶을 개선하는 그래프 기술의 강력한 사용 사례라고 할 수 있겠죠?
그래프 접근법을 사용한 개인 수준 데이터 통합
바이엘 AG의 Mahmoud Ibrahim님이 발표자로 참여하여, 그래프 모델을 활용한 환자 중심 데이터 통합 접근 방식에 대해 이야기했어요. "환자 지도"를 구축해서 다양한 임상 및 분자 데이터 세트를 연결하고, 질병 메커니즘을 더 깊이 이해하고 새로운 치료 가설을 찾아내서 임상 시험 성공률을 높이는 거죠. R&D에서 더 현명한 의사 결정을 지원하기 위해 그래프 임베딩과 증거 체인을 사용하는 방법도 살펴봤다고 해요.
요약
RDF에서 LPG로의 마이그레이션, GraphRAG 인프라에 대한 논의, 그리고 제약 공급망 및 생물의학 발견 데모까지! GraphTalk 2025에서는 통합 그래프 기술이 생명과학 분야에서 어떻게 AI 기반 혁신으로 발전했는지 제대로 보여줬어요.
더 자세한 내용이 궁금하다면 필수 GraphRAG를 확인해보세요. GraphRAG 시스템을 처음부터 구축하는 방법에 대한 Manning의 종합 가이드랍니다.
GraphRAG
에이치시스템즈의 LogTree는 Neo4j 기반 GraphRAG 플랫폼으로, 데이터를 자동으로 지식그래프화하고 자연어 질의로 즉시 답을 제공합니다.
2021년 6월 24일, Gothamist의 George Joseph은 다음과 같은 제목의 작품을 발표했어요. "반복적으로 위법 행위로 기소된 뉴욕 경찰국(NYPD) 경찰관 집단을 매핑합니다."
독립 데이터 저널리스트인 EJ Fox와 함께 Joseph은 논란의 여지가 있는 경찰 행위가 집단 행동인 경우가 많다는 사실을 자세히 설명했는데요. 이 기사는 2010년 이후 불만 사항과 관련된 경찰관의 탐색 가능한 시각화 및 지도를 보여줬습니다.
전 75경찰서 로버트 마르티네즈 상사와 연결된 일부 officer `Node`의 클로즈업 이미지
이 글은 복잡한 사회 현상을 인사이트로 이끌어내고, 현실 세계에서 계속해서 일어나고 있는 숨겨진 패턴을 지적했다는 점에서 주목할 만해요. 위법 행위에 대해 불만을 제기하는 패턴이 있는 것으로 보이는 특정 주요 경찰관을 조사하면서 Joseph은 체포 시 금지된 목을 조르는 방법을 사용하는 것이 카메라에 포착된 후 최근 은퇴한 한 경찰관과 같은 많은 두드러진 사례를 발견했습니다.
여기서 그래프가 효과적인 이유
이 시점에서 이 분석에 Neo4j가 많이 사용되었다는 것은 놀라운 일이 아니죠? `Relationship`에서 패턴을 찾는 것은 그래프의 장점 중 하나이니까요. 그래프는 진정으로 "관계에 관한 모든 것"이며 이와 같은 사례는 경찰관, 불만 사항, 시민 등 간의 `Relationship`이 개별 불만 사항이나 경찰관 기록보다 더 중요한 상황이에요.
데이터의 연결은 데이터 자체만큼 가치가 있어요.
이 팀이 어떻게 작업을 수행했는지 궁금하시다면 EJ Fox가 분석에 대한 훌륭한 기술 분석을 작성했으니 한번 살펴볼까요? 여기에서 Fox는 다음과 같이 설명합니다.
그의 데이터는 무엇이었나요?
Cypher의 LOAD CSV 접근 방식을 사용하여 데이터를 가져오는 방법
그가 입증된 시민 불만을 경찰관과 연결한 방법
그가 officer들 사이의 `Relationship`을 구축한 방법.
기술적인 설명은 EJ의 탁월한 기술 분석에 맡기겠지만, 여기서 실제로 모든 것을 하나로 묶어주는 "비밀 소스"는 Neo4j의 Graph Data Science 라이브러리, 특히 EigenVector Centrality의 사용이었어요. 이 특정 알고리즘은 그래프에서 특정 Node의 영향을 측정하는데, EJ의 경우, 반복적으로 불만을 제기하는 경찰관과 밀접하게 관련된(또는 함께 협력하는) 반복적으로 불만을 제기하는 경찰관을 찾는 데 도움이 되죠.
Neo4j 그래프 데이터 과학은 요즘 그래프 작업에 대한 가장 흥미로운 것 중 하나인데요. EigenVector Centrality는 데이터 과학자, 분석가, 심지어 데이터 저널리스트가 데이터에서 통찰력을 끌어낼 수 있는 50개 이상의 "도구 상자에 포함된 도구" 중 하나일 뿐이에요. 이는 데이터 과학에 대한 "그래프 작성"을 주도하고 있으며 이미 많은 고객이 독일 당뇨병 연구 센터의 연구 데이터베이스를 연결하고 금융 사기를 적발하는 데 사용하고 있답니다.
Graphs4Good
Gothamist의 기사는 Neo4j가 이런 종류의 프로젝트에 사용된 것이 처음이 아니라는 것을 보여주죠. 몇 년 전 우리는 데이터로 작업하는 사람들을 연결하고 활성화하여 더 효과적으로 작업할 수 있도록 Graphs4Good 프로젝트를 시작했어요. 데이터 저널리즘 분야에서 Neo4j는 이전에 숨겨진 조세 피난처를 찾아내고, 소셜 미디어에서 선거 조작의 패턴을 탐지하고, NASA가 과거 임무에 대한 집단적 지식을 학습하도록 도움으로써 납세자의 세금을 절약하는 데 사용되었답니다.
Neo4j는 핑크 프로그래밍을 후원하고 커뮤니티에 참여하여 여성이 기술 부문에서 크게 소외된 그룹으로 발전할 수 있도록 돕습니다.
그리고 우리는 실제 데이터에서 연결을 발견하는 데 도움이 되는 프로젝트에 대해 열려 있어요. Neo4j 데이터 저널리즘 액셀러레이터 프로그램을 통해 EJ와 같은 데이터 저널리스트는 우리 주변에서 발견되는 실제 네트워크를 푸는 데 도움을 받을 수 있죠.
다음은 무엇일까요?
기술 전문가로서 저는 이 분석에 포함된 모든 사항과 이것이 기본 Graph Database인 Neo4j가 갖는 기술 강점과 어떻게 연결되는지 설명하고 싶어요. EJ Fox의 기사가 이 내용을 너무 잘 다루고 있기 때문에 이 게시물에서는 맛보기만 했을 뿐이죠.
그리고 기술 심층 분석에서는 나무 대신 숲을 잃을 위험이 항상 존재해요. 그래프 데이터 사이언스로 할 수 있는 강력하고 멋진 일이 많이 있지만, 이 게시물에서는 큰 그림에 주목하고 싶었어요. 그래프 기술은 근본적으로 저널리스트가 현실 세계에 대한 통찰력을 발견할 수 있도록 하며, 그래프 유틸리티는 우리가 세상을 더 잘 이해하는 데 기여하죠. 사람들이 이를 개선하기 위한 조치를 취하는 방법을 이해하는 데 도움이 될 수도 있고요.
그래프에 대해 궁금하신 점이 있으시면 알려주세요. 신용 카드 없이 클라우드에서 Neo4j AuraDB를 무료로 사용할 수 있어요. 또는 Neo4j 커뮤니티 사이트를 확인해 보세요. Cypher, GDS 및 모든 종류의 기타 기술을 사용하여 모든 산업 및 사용 사례에 걸쳐 여기에서 볼 수 있는 것과 동일한 작업을 수행하는 사람들로 구성된 크고 활발한 커뮤니티를 찾을 수 있을 거예요.
즐거운 그래프 해킹을 즐겨보세요!
EJ폭스
GraphsforGood
에이치시스템즈의 LogTree는 Neo4j 기반 GraphRAG 플랫폼으로, 데이터를 자동으로 지식그래프화하고 자연어 질의로 즉시 답을 제공합니다.
2000년에 저는 뭄바이행 비행기를 타고 있었어요. Peter, Johan과 저는 엔터프라이즈 콘텐츠 관리 시스템(ECM)을 구축하고 있었는데, 연결된 데이터를 `Query`하기 위해 RDBMS를 사용하는 문제에 계속 부딪혔죠.
그때 번뜩이는 아이디어가 떠올랐어요! 냅킨을 꺼내서 첫 번째 `Property Graph` 모델을 빠르게 스케치했죠. 저희는 함께 냅킨에 그린 아이디어를 바탕으로 세계 최초의 `Graph Database`인 Neo4j를 만들었어요.
제가 상상도 못 했던 건 냅킨 뒷면에 끄적거린 작은 스케치가 전 세계에 미칠 엄청난 영향력이었어요. 물론 비즈니스적으로도 큰 영향을 줬지만, 수익을 떠나 꾸준히 성장해 왔고, 지금도 조용히 영향력을 행사하고 있죠.
Neo4j 커뮤니티 전체적으로 보면, `Graph` 기술을 활용해서 기후 변화, 암 치료, 여성 역량 강화, 돈세탁 방지, 그리고 인간 지식의 한계를 넓히는 등 사회의 가장 시급한 문제들을 해결해 왔어요.
비영리 단체, 정부 기관, 뉴스룸, 연구소 등 어떤 곳에서 일하든, 세상을 더 나은 곳으로 만들기 위해 엄청난 시간을 쏟는 분들이 계세요. 때로는 개인이기도 하고, 서로 다른 글로벌 팀이기도 하지만, 모두 제한된 리소스와 빠듯한 예산 때문에 힘든 싸움을 하고 있죠.
그럼에도 불구하고, 그들은 그림자 속에 숨겨진 연결고리를 조사하고, 복잡하게 얽힌 불법 행위의 그물을 풀고, 인체에 큰 피해를 주는 분자를 모델링하고 (치료하는 분자와 함께!), 별까지의 경로를 매핑하는 등의 놀라운 일들을 계속 해내고 있어요.
여기저기서 그들의 프로젝트에 대한 이야기를 들어보셨을 수도 있지만, 전체적으로는 잘 알려지지 않았죠. 하지만 이제 변화가 있을 거예요.
Graphs4Good 소개
Neo4j의 회사 비전은 "세상이 데이터를 이해할 수 있도록 돕는 것"이에요. 하지만 `Graph Database` (및 기타 `Graph` 기술 제품)를 구축하는 건 그 비전을 현실로 만드는 과정의 일부일 뿐이죠.
저는 그 비전의 핵심은 데이터를 다루는 사람들을 연결하고 활성화해서 더 효과적으로 일할 수 있도록 돕는 거라고 믿어요. 그래서 저희가 그래프4굿 프로그램을 만들었어요.
이 새로운 프로그램의 목표는 긍정적인 사회 변화에 영향을 미치고, 민주주의 원칙을 지키며, 세계에서 가장 어려운 과제를 해결하는 그래프 기반 프로젝트를 소개하고, 다른 사람들을 지원하고 격려하며 연결하는 것이에요.
오늘 Graphs4Good을 공식적으로 출시하면서(GraphConnect 2018에서), 이러한 프로젝트의 성공과 Neo4j가 제공한 지원은 이미 수년 동안 진행되어 왔다는 것을 알 수 있었어요. 그들의 이야기를 한번 들어볼까요?
데이터 저널리즘의 Graphs4Good
이 모든 것은 국제탐사보도언론인협회(ICIJ)에서 시작돼요. 2015년에 그들은 Neo4j와 그래프 시각화 도구인 Linkurious를 사용하여 획기적인 작업을 시작했죠. 바로 스위스 누출 이야기인데요, 스위스 프라이빗 뱅킹의 비밀스럽고 그늘진 세계를 살펴보는 내용이었어요.
거기서부터 그들은 역사상 최대 규모의 데이터 유출로 세상을 뒤흔들었어요. 바로 파나마 페이퍼스죠! 파나마 법률 회사인 모색 폰세카(Mossack Fonseca)에서 약 2.6테라바이트에 달하는 1,150만 개의 문서가 유출되면서 40년 동안의 거래, 계정 및 세계 유명 기업의 페이퍼 컴퍼니의 복잡한 웹이 기록되었어요.
후속 보고에서는 45개 이상 국가의 국가 지도자와 유명인사들의 사기, 탈세, 돈세탁, 국제 제재 회피(기타 불법 활동 포함)가 드러났어요. 종합하면, 25개 언어로 활동하는 100개 언론 매체의 기자들은 유출된 문서를 이용해 부패를 폭로했답니다.
그들의 노력은 결국 그들에게 퓰리처상을 안겨주었죠. 하지만 이 중 어느 것도 불가능했을 거예요. 연결된 데이터에 대한 액세스 가능한 모델이 없었다면요.
1년 뒤 ICIJ는 파라다이스 페이퍼 보고서를 발표했어요. Appleby 및 Asiaciti Trust에서 1,350만 개의 문서, 1.4테라바이트가 유출되었죠. 380명이 넘는 언론인들이 이번 유출을 이용해 애플, 나이키, 페이스북 등 유명 기업과 엘리자베스 여왕, 트럼프 행정부 등 국가 원수들의 불법 행위(불법, 비윤리 또는 둘 다)를 폭로했답니다.
이와 같은 데이터 저널리즘 조사가 있었기에 계속되는 가짜뉴스 확산에 맞설 수 있었죠. 이는 Neo4j 팀이 Neo4j connected data 펠로우십을 통해 ICIJ에 대한 지원을 계속할 뿐만 아니라 Neo4j 데이터 저널리즘 액셀러레이터 프로그램을 만들게 된 계기가 되었어요.
이런 멋진 프로젝트 이후에도 ICIJ는 꾸준히 좋은 활동을 이어오고 있어요. 서아프리카 누출 사건이나, 파나마 페이퍼스의 두 번째 유출 (규모는 작았지만)에서 Mossack Fonseca를 파헤친 것도 정말 대단하죠.
데이터 저널리즘 분야에서 NBC News 팀이 러시아 트롤 트윗 20만 건 사이의 복잡한 연결 관계를 매핑한 훌륭한 작업도 빼놓을 수 없어요.
이런 작업들이 바로 Graphs4Good 프로그램이 계속해서 소개하고 지원하고 싶은 활동의 핵심이에요. 하지만 데이터 저널리즘만이 그래프 기술이 긍정적인 영향을 미치는 유일한 분야는 아니랍니다.
다른 분야의 Graphs4Good
제가 그래프 기술 기반의 영향력 있는 프로젝트들을 전부 다 요약할 수 있을까요? 당연히 불가능하죠! 여기 소개하는 건 여러분이 알 만한 몇 가지 주요 사례일 뿐이에요. 더 많은 내용은 Graphs4Good 프로그램 페이지에서 확인해 보세요.
인류 역사가 시작된 이래로 우리는 질병과 싸워왔고, 이미 꽤 많은 치명적인 질병들을 이겨냈죠. 하지만 특히 암과의 싸움은 아직 갈 길이 멀어요. 저는 개인적으로 암 치료법을 연구하는 다양한 그래프 기반 프로젝트를 **8개**나 알고 있답니다. 그중에서도 정말 인상적인 이야기는 Candiolo 암 연구소 사례인데요, 꼭 한번 읽어보시길 추천드려요.
비슷한 맥락에서 독일 당뇨병 연구 센터(DZD)가 Neo4j를 사용해서 현재 당뇨병 환자들을 돕고, 이 질병을 완전히 없애기 위한 복잡한 연구를 진행하고 있다는 소식도 정말 기뻤어요.
전혀 다른 분야로 눈을 돌려볼까요? NASA는 Neo4j Knowledge Graph를 사용해서 화성 탐사 임무를 진행하고 있다고 해요.
NASA의 수석 지식 설계자인 David Meza는 이렇게 말했어요. 특히 Orion 우주선 임무와 관련해서 "Neo4j는 2년 이상의 작업 시간과 백만 달러의 세금을 절약해 줬습니다." 이 정도면 정말 *good*을 넘어선 훌륭한 성과라고 생각하지 않으세요?
과학적 탐구와 같은 맥락에서 국제 연어 데이터 연구소(2018년 10월 공식 출범)도 Graphs4Good 프로그램에 참여하게 되어 정말 기뻐요. 이들은 전 세계 연어 서식지에 대한 전체적인 분석과 생태학적 영향 연구를 지원하고 있답니다.
마지막으로, 긍정적인 영향을 미치는 그래프 프로젝트에 대한 *아주 간략한* 요약에서 지금은 사소해 보일 수 있지만 앞으로 몇 년 동안 그 파급력이 느껴질 만한 이야기를 빼놓을 수 없죠.
지난 여름 Neo4j 팀원들은 데이터 과학 캠프를 후원하고 이끌었어요. Pink Programming이라는, 기술 분야에서 여성의 역할을 발전시키는 것을 목표로 하는 단체를 통해서요. 올해 캠프는 규모가 작았지만(여성 20명), 참가자들은 그래프 기술을 사용해서 데이터 과학 기술을 키우는 방법을 배울 수 있었답니다. 20년 후, 이 여성들이 앞으로 수십 년 동안 기술 생태계에 어떤 긍정적인 영향을 미치게 될지 정말 기대돼요.
결론
그래프는 세상을 바라보는 새로운(사실은 오래된) 방식이고, 이 새로운 관점은 우리 사회를 더 나은 방향으로 변화시킬 수 있는 엄청난 힘을 가지고 있어요.
저는 매일 긍정적인 변화를 만들기 위해 그래프 기술이 어떻게 활용되고 있는지에 대한 이야기를 듣고 있어요. 그리고 Neo4j 커뮤니티가 세상을 변화시키는 모습에 늘 놀라움과 겸손함을 느껴요. Graphs4Good 프로그램의 많은 프로젝트는 커뮤니티 주도의 오픈 소스 프로젝트로 시작되었고, 또 계속해서 생겨나고 있답니다.
저는 이 점을 아무리 강조해도 지나치지 않다고 생각해요. Neo4j 커뮤니티는 여러분이 전 세계에 긍정적인 영향을 미칠 수 있도록 돕고 있거든요. 이 커뮤니티는 목적이 무엇이든, 그래프 기반 프로젝트를 시작하고 실행하는 데 (또는 원활하게 유지하는 데) 시간과 노력을 아낌없이 쏟는 친절하고 헌신적인 사람들로 이루어진 그래프 그 자체라고 할 수 있죠.
오늘 우리는 연결된 데이터를 사용하여 긍정적인 영향을 미치는 수백 가지 이야기를 담은 Graphs4Good 프로젝트를 시작해요. 내년에는 그 수가 수천 개가 되도록 만들어봐요.
우리 팀의 영향력은 냅킨에서 시작되었어요. 여러분의 작업은 그래프 플랫폼에서 시작될 거고요. 이걸로 무엇을 하시겠어요?
그래프4굿
icij
nasa
Neo4j 커뮤니티
에이치시스템즈의 LogTree는 Neo4j 기반 GraphRAG 플랫폼으로, 데이터를 자동으로 지식그래프화하고 자연어 질의로 즉시 답을 제공합니다.
편집자 주: 이 프레젠테이션은 Alexander Jarasch가 GraphConnect San Francisco 2016년 10월에 발표한 내용이에요.
프레젠테이션 요약
Alexander Jarasch는 독일 당뇨병 연구 센터의 데이터 및 지식 관리 책임자예요. Jarasch는 다양한 분석가들의 연구 결과를 통합하고, 이 정보를 활용해서 당뇨병을 더 효과적으로 예방하고 치료하는 데 힘쓰고 있다고 해요.
이번 프레젠테이션에서 Jarasch는 인간 당뇨병의 진화에 대해 이야기하는데요. 먼저 “당뇨병이 뭐죠?”라는 질문에 간단하게 답하고, 독일 당뇨병 연구 센터의 목표를 설명해요.
그리고 당뇨병 예방과 당뇨병에 효과적으로 대처하는 방법에 대해 소개하면서 데이터 문제를 짚어주죠.
독일 당뇨병 연구 센터가 가진 특별한 과제는 수많은 과학자와 연구자들이 각기 다른 관점에서 데이터를 바라본다는 점인데요. 이 모든 정보를 효율적으로 연결하고 통합해야 하죠. 이 데이터 수집에는 동종 데이터와 이종 데이터, 메타데이터 등이 포함돼요. 그래서 Graph Database를 선택한 건 정말 합리적인 결정이었죠.
프레젠테이션에서는 실제 사례를 통해 당뇨병의 대사적 특성을 설명하기도 해요.
마지막으로 Jarasch는 센터 연구에서 Graph Database의 미래에 대한 전망을 제시하며 마무리해요.
전체 프레젠테이션
안녕하세요, 저는 Alexander Jarasch입니다. 독일 당뇨병 연구 센터 뮌헨 본부에서 왔어요. 오늘은 저희가 어떻게 Graph Database와 그래프를 이용해서 당뇨병과 싸우고 있는지 이야기해 보려고 해요.
진화
공룡 시대, 슈퍼마켓이 없던 시절에는 에너지를 저장하는 유전적 이점이 있었어요. 음식이 부족할 때를 대비해서 에너지를 지방으로 저장했던 거죠.
하지만 이런 과거의 장점은 현대에는 단점이 되어버렸어요. 지금은 어디든 슈퍼마켓이 있고, 음식도 풍족하죠. 그런데도 우리는 여전히 많이 먹고, 지방은 계속 쌓여서 과체중이나 비만이 되기 쉬워요. 비만은 당뇨병을 유발하기 때문에 문제가 되는 거죠.
당뇨병이란 무엇입니까?
당뇨병은 대사 질환이에요. 어떤 경우에는 췌장에서 인슐린 생산이 급격히 줄어들기도 하고, 또 다른 경우에는 몸이 인슐린에 제대로 반응하지 못하기도 해요.
인슐린은 혈액에서 당분을 제거하는 데 필요한 호르몬이자 단백질인데요. 혈액에 당분이 많으면 근육 세포나 간 세포로 흡수되는 양이 줄어들어요. 혈관에 당분이 계속 남아있는 상태를 저혈당증이라고 부르죠.
당뇨병은 정말 무서운 합병증을 동반하고, 안타깝게도 현재로서는 완치가 불가능해요. 치료만 가능하다는 점이 아쉽죠.
당뇨병의 종류를 이야기할 때, 크게 네 가지 주요 유형이 있어요:
제1형 당뇨병
제2형 당뇨병
임신성 당뇨병 (임산부에게 나타나는 당뇨병)
현재 연구 중인 추가 형태
아래 오른쪽 그림은 건강한 신체의 모습이에요. 췌장에는 작은 녹색 점으로 표시된 인슐린을 생산하는 세포가 있죠. 위를 보면 설탕이 혈관으로 들어가는 걸 볼 수 있어요. 그러면 인슐린이 작용하게 되는데요. 모든 것이 제대로 작동하면 설탕이 간이나 근육 세포로 전달된답니다.
환자의 약 5%를 차지하는 제1형 당뇨병의 경우에는, 이 인슐린 생산 세포가 면역 체계에 의해 파괴돼요. 이 과정에는 대략 20개의 유전자가 관여한다고 해요. 이건 생활 방식과는 무관한 유전자 결함이라서, 환자들은 평생 동안 외부 인슐린 공급원에 의존해야 하죠.
제2형 당뇨병은 국가에 따라 환자의 약 90~95%를 차지할 정도로 흔해요. 세포는 인슐린을 생산하지만, 어떤 이유에서인지 인슐린 저항성이 생기는 거죠. 생산은 되지만 신체가 제대로 반응하지 않는 거예요. 일반적으로 사람들은 자신이 당뇨병을 앓고 있다는 사실을 잘 모르는 경우가 많아요. 이 과정에는 150개 이상의 유전자가 관여하며, 이는 당뇨병에 걸릴 위험을 증가시킨다고 해요.
당뇨병 진단을 부추기는 안 좋은 조합들이 있어요.
유전적 소인을 가지고 있는 경우
적절한 신체 활동이 부족한 경우
전 세계적으로 당뇨병을 앓고 있는 사람은 4억 명이 넘는다고 해요. 예전에는 노년층의 질병이라고 생각했지만, 실제로는 전체 환자의 3분의 2가 근로 연령대에 속해 있다는 사실!
게다가 진단을 받지 못한 당뇨병 환자가 2억 명이나 더 있다고 하니, 정말 심각한 문제죠. 당뇨병(대부분 1형 당뇨병)을 앓고 있는 어린이도 백만 명이 넘는다고 해요. 전체 의료 비용의 12%가 당뇨병으로 인해 발생한다니, 우리가 꼭 해결해야 할 심각한 문제임에 틀림없어요.
미국만 놓고 봐도 당뇨병 환자가 3천만 명이나 된다고 해요. 이 숫자는 매년 증가하고 있다니 걱정이에요. 당뇨병 전증 환자는 무려 8,500만 명에 달하며, 이로 인해 고통받는 사람들의 생산성 감소로 연간 900억 달러의 손실이 발생한다고 하네요.
1985년부터 2009년까지의 데이터를 요약한 차트인데요. 시간이 지날수록 점점 숫자가 늘어나고 있어서, 당뇨병에 걸리거나 비만으로 고통받는 사람들이 점점 더 많아지고 있다는 걸 알 수 있어요.
사실 당뇨병 자체보다는 합병증이 더 큰 문제예요. 사람들은 합병증 때문에 목숨을 잃는 경우가 많거든요. 뇌졸중이나 심장마비 같은 것들이죠. 모든 심장마비의 3분의 1은 당뇨병 때문에 발생한다고 해요. 사지의 신경이나 혈관이 손상되거나, 신장 문제, 심지어 당뇨병 때문에 발을 절단해야 하는 경우도 모두 당뇨병으로 인한 합병증이에요.
당뇨병은 정말 복잡한 질병이에요. 신진대사에 영향을 미치고, 췌장에도 영향을 주죠. 또한 환경이나 생활 방식, 유전학 또는 후생유전학에 따라서도 달라지는 세포 과정이기도 해요.
가장 큰 문제 중 하나는 환경과 생활 방식이에요. 여러분의 생활 방식은 다음 세대에게도 영향을 미치거든요. 쥐 실험이나 인간 쌍둥이 연구를 보면, 유전적으로 동일하더라도 DNA에 있는 후성유전학적 표지 때문에 차이가 나타나는 걸 알 수 있어요. 이로 인해 당뇨병이 발생하고, 심지어 다음 세대로까지 전이될 수 있다는 점이 정말 심각하죠.
저희 연구팀이 쥐를 대상으로 실험을 진행했어요. 일부 쥐에게는 정상적인 식단을, 다른 쥐에게는 고지방 식단을 제공했죠. 그런 다음 교배를 진행하고 그들의 자손을 관찰했는데요. 다음 세대는 과체중이 되었고, 이 과체중으로 인해 당뇨병 위험이 급격히 증가하는 것을 확인했어요.
우리는 누구인가
저희는 독일 당뇨병 연구 센터에요. 연방 기관이자 학술/비영리 조직이고요. 연방 교육 연구부와 주정부로부터 자금을 지원받고 있어요.
뮌헨, 튀빙겐, 뒤셀도르프, 베를린, 포츠담, 드레스덴에 5개의 주요 파트너가 있고, 관련 파트너를 포함해서 기초 연구부터 대학 병원까지 다양한 분야에서 약 400명의 연구원이 함께하고 있어요.
저희 연구 분야는 영양, 예방, 유전학, 집단 연구 및 기초 연구인데요. 주요 목표는 당뇨병을 예방하고 당뇨병을 더 잘 치료하며 합병증을 예방하는 것이에요.
당뇨병 예방
저희는 1형, 2형 또는 현재 조사 중인 다른 새로운 유형의 당뇨병을 예방하고자 해요. 더 나아가 지능적인 알고리즘으로 환자를 식별하고 개별화된 방식으로 치료하고 싶어요.
당뇨병과 싸우는 방법
일반적인 연구원의 경우 조직 내의 정보와 데이터를 찾는 데 어려움을 겪는데요. 마치 건초 더미에서 바늘을 찾는 것과 같죠. 안타깝게도 저희 병원과 기초 연구에는 건초 더미가 너무 많아요.
데이터 문제
일반적으로 "어떤 혈액 샘플을 가지고 있나요?" 또는 "간에서 무엇을 측정했나요?"와 같은 간단한 질문에서부터 시작하는데요. 이러한 질문에 답하기가 점점 더 어려워지고 있고, 쿼리도 더욱 복잡해지고 있어요.
이러한 데이터 문제는 원래 서로 다른 기술을 가진 세 개의 조직이었기 때문에 발생했어요. 하지만 저희는 모두 같은 고객, 즉 당뇨병 환자를 위해 일하고 있었죠.
하지만 모두 이 당뇨병 환자를 조금씩 다르게 바라봤어요. 동물 모델로 보는 사람도 있고, 현미경 사진으로 보는 사람도 있고, 대사 산물을 보는 사람도 있었죠.
이제는 고객을 새로운 방식으로 바라보고 다양한 유형의 데이터를 결합해야 해요. 게다가 이는 데이터를 공유해야 함을 의미하죠.
이제 최대한 다양한 관점에서 고객을 바라봐야 하고, 이는 데이터를 하나로 연결해야 한다는 것을 의미해요.
두 가지 옵션이 있는데요. 한 가지 옵션은 모든 데이터베이스를 별도로 개발하는 것이에요.
별도의 데이터베이스를 사용하는 것은 좋은 생각이 아니에요. 그래서 저희는 새로운 레이어를 만들고 싶었고, 연결된 데이터를 선택했어요.
이것이 바로 우리가 DZDConnect라고 부르는 거예요. 이건 Graph Database인데, 이 Graph Database가 우리와 연구자들이 생물의학적 질문에 답하는 데 도움을 주고 있어요. 이런 질문들은 여러 위치에서 답변될 수 있죠. 말씀드린 것처럼, 독일에는 10개 이상의 지점이 있고, 학문 분야와 종을 넘나들며 질문에 답할 수 있답니다.
이 데이터베이스는 확장 가능해야 해요. 우리가 Graph Database를 좋아하는 주된 이유 중 하나는 데이터 시각화 기능 때문이기도 하고요.
동종 및 이종 데이터
우리는 이질적인 데이터와 동질적인 데이터를 다루고 있어요. 데이터 보안상의 이유로 원시 데이터는 건드리지 않죠. 다양한 위치의 데이터를 분류하고 라벨을 붙인 다음, 환자 데이터를 연결해서 서로 연결되도록 해요. 결국 이걸 단일 레이블로 줄이면 데이터가 그래프 모델과 비슷해지기 시작한답니다.
왜 그래프인가?
우리가 그래프를 좋아하는 첫 번째 이유는, 어쨌든 생물학 자체가 연결되어 있기 때문이에요. 모든 데이터와 생물학은 연결되어 있죠. 우리 연구원들은 이해하기 쉬워서 그래프를 좋아해요. 데이터 모델이 컴퓨터 과학자가 아니더라도 사람이 읽을 수 있을 정도로 직관적이거든요. 게다가 쿼리도 쉬워요. 일반 SQL보다 쿼리하기가 훨씬 쉬운 것 같아요.
그래프는 확장성과 적응력도 뛰어나요. 새로운 분야, 새로운 영역, 새로운 위치가 생기면 그래프 모델을 쉽게 적용할 수 있죠. 이렇게 확장하면 정말 멋진 시각화를 얻을 수 있답니다.
데이터에 대해 이야기할 때, 현재는 메타데이터를 포함하고 있어요.
위에 보이는 건 예비 데이터 모델이에요. 아주 큰 홉(hop)은 실험이죠. 우리는 연구자들이라서 실험을 많이 하거든요. 이 실험에서는 다양한 기술이나 장치를 사용해서 여러 매개변수를 측정해요. 어떤 실험에서는 혈액이나 소변 같은 생체 샘플을 수집하기도 하고요. 전문가들이 검토한 과학 출판물 같은 데이터도 포함하고 있답니다. 이런 것들이 모두 우리 데이터 모델에 연결되어 있어요.
메타데이터의 예로는 미세한 이미지가 있을 수 있겠네요. 치수를 설정하고, 매개변수 이름, 단위, 측정 방법 등을 설정하는 거죠. 우리는 액체 질소에 바이오 샘플을 저장하는 바이오 샘플 데이터베이스도 가지고 있어요.
우리는 이 그래프를 확장하고 싶어요.
그래프를 확장하는 방법은 여러 가지가 있어요. 한 가지 옵션은 심혈관 질환이나 알츠하이머병 같은 다른 질병으로 확장하는 거죠. 공개적으로 이용 가능한 문헌 데이터베이스도 많이 있고요. 우리는 전자 연구 노트 데이터, 단백질 데이터베이스 데이터 등을 포함할 거예요. 또한 유전자, 단백질, 대사산물의 세계로 들어가는 특별한 사례 섹션도 만들 거고요.
Rush의 아주 멋진 포스터네요.
여기 보시는 건 신체의 모든 대사 경로를 요약한 거예요. 이제 우리는 파란색 상자에만 집중해 볼게요.
확대해서 보면 점점 복잡해지는 걸 알 수 있어요. 효소에 의해 대사되는 대사산물이 있고, 다른 대사산물 등에 의해 조절되죠. 이 데이터베이스는 정말 풍부하고 거대해요.
Knowing Health라는 뮌헨 Helmer Center의 스타트업 회사도 이와 동일한 문제를 다루고 있어요. 그들의 데이터 모델 역시 Neo4j를 사용해서 이러한 다양한 유전자, 전사물 및 단백질 세계를 연결하죠. Neo4j 데이터베이스는 엄청 커서 8억 개의 Nodes와 Relationships로 구성되어 있어요. 우리는 이 데이터베이스를 우리 데이터베이스에 포함시킬 수 있어요.
요약하자면, 우리는 그래프 기술을 사용해서 서로 다른 분야, 서로 다른 위치를 가지며 서로 연결되는 메타 데이터베이스를 구축하고 있어요.
예시
많은 의사들이 묻는 질문 중 하나는 "우리 임상 연구의 17차 방문에서 얼마나 많은 생체 시료를 확보했습니까?"에요.
이 임상 연구를 당뇨병 전단계 생활습관 중재 연구라고 해요. 우리는 이 생체 시료에 관심이 있어요. 우리는 그들이 그것을 어떻게 측정했는지 알고 싶고요. 이 질문은 대답하기가 쉽지 않아요.
이를 위해 우리는 특별한 데이터 모델을 구축했어요.
우리는 임상 연구를 진행하고 있고 환자들은 다양한 방문을 받아요. 이러한 방문에서 의사는 다양한 실험을 수행하고 매개변수를 측정하죠. 일부 방문에서는 저장되어 있는 생체 시료를 수집하고 그에 대한 데이터를 측정해요.
우리 의사들은 Neo4j Graph Database로 이동해요. 그들은 임상 연구를 받고 그것을 확장하고 여기 방문을 봅니다. 그런 다음 17번 방문을 찾아볼 수 있어요.
이제 상황이 복잡해지고 있음을 알 수 있어요. 분홍색으로 다양한 실험이 있고 회색으로 매개변수가 있고 노란색으로 바이오샘플이 있어요. 그렇기 때문에 이 질문에 대답하는 것이 너무 복잡한 거죠.
두 번째 예는 완전히 다른 것이에요.
여기서 우리는 다양한 종, 즉 인간과 당뇨병 전증 돼지 모델의 데이터를 연결하려고 해요. 우리는 인간의 제2형 당뇨병 유전자를 동물 모델에서 연구할 수 있는지 질문하는 거죠.
이 질문에 답하기 위해서는 여기 있는 모든 분야가 많은 사람들이 연구하는 서로 다른 연구 분야라는 것을 알아야 하고, 이들을 연결해야 해요.
이러한 유전자는 공개적으로 이용 가능한 다양한 데이터베이스를 통해 충족돼요. 이들은 효소로 변하고, 이 효소는 다양한 화합물을 대사하죠. 이는 데이터의 인간 부분이에요.
이제 당뇨병 전증 돼지에 대한 표적 대사체학 에세이가 생겼어요. 우리는 16개의 서로 다른 대사산물을 측정하고, 공개 데이터베이스에서는 이 16개의 대사산물이 31개의 식별자예요. 그런 다음 우리는 이러한 세트의 결합을 갖고 동물 모델과 인간 데이터 사이에서 7가지 화합물을 식별할 수 있다는 결과를 얻었어요.
이제 우리 연구원들은 당뇨병에 대한 새로운 통찰력을 얻기 위해 이러한 대사산물을 조사하고 있어요.
전망
전망은 어떨까요? 우리는 공개적으로 이용 가능한 문헌 데이터로 그래프를 확장하고 싶어요. Pubnet이라는 매우 큰 데이터베이스에 동료가 검토한 아래 기사가 있어요.
Pubnet에는 3천만 개의 텍스트가 있어요. 이 텍스트는 다양한 기본 연구 분야에 관한 것이며 누구도 더 이상 모든 텍스트를 읽을 수 없죠. 당뇨병을 찾을 때 읽을 수 있는 것은 병목 현상이에요. 우리는 유전자 이름을 배우거나 질병 또는 그에 대한 특정 용어를 배우기 위해 이러한 텍스트에 그래프 알고리즘을 적용함으로써 자동으로 이를 수행하고자 해요.
결국 우리는 많은 텍스트에 대해 이를 수행하고 텍스트 사이의 연결이 무엇인지 확인하고 싶어요.
여기 보라색 `Node`들은 Graphaware의 Natural Language Processing 절차를 거쳐 분석된 텍스트들이에요. 이걸 통해 서로 다른 연구 텍스트 간의 중복을 확인할 수 있죠.
저희는 이런 연관성을 찾고 싶어요.
심혈관 영향, 알츠하이머, 암, 전염병, 폐 질환 사이의 연관성도 찾고 싶고요.
여기 주황색 점들은 독일 당뇨병 연구 센터처럼 저희와 같은 기관들이에요. 당뇨병이나 다른 질병과 싸우기 위해 서로 연결되기를 바라고 있죠.
당뇨병이나 다른 질병의 다양한 하위 유형을 가진 사람들이 있고, 연구원, 의사, 진료소도 있어서 전문 지식을 갖추고 있어요. 이제 이걸 그래프 기술과 결합해서 더 잘 식별하거나 당뇨병의 새로운 하위 유형을 클러스터링해서 개별화된 치료나 예방을 제공하려고 해요.
이 센터는 곧 디지털 당뇨병 예방 센터(Digital Diabetes Prevention Center)라는 새로운 센터가 될 거예요.
저희는 사회의 사람들이 제공하는 엄청난 양의 데이터에서 패턴을 인식하고 싶어요. 데이터를 제공한 사람들에게 이익을 돌려주고, 사회 전체에도 이익을 주기 위해 지도 또는 비지도 Machine Learning 기술을 사용하려고 하죠.
제 생각에는 그래프 기술을 통해 당뇨병 예방과 치료에 새로운 차원이 열렸어요.
관계형 데이터베이스에서는 볼 수 없었던 이벤트들을 보게 돼요. 다양한 분야, 위치, 종을 연결하기 때문이죠.
자금 제공자, 연방 교육 연구부, 주정부에 감사를 표하고 싶어요. DZD의 모든 과학자들과 여기 주최측에도 감사의 말씀을 전하고 싶습니다. 그래프커넥트, 이렇게 좋은 회의를 열어주셔서 정말 감사해요.
그래프 기술이 처음이신가요?
무료 사본을 받아보세요. 초보자를 위한 그래프 데이터베이스 eBook을 통해 그래프 데이터베이스 기술의 기본 사항에 대한 이해하기 쉬운 가이드를 받아보세요. 사전 지식이 필요하지 않아요.
에이치시스템즈의 LogTree는 Neo4j 기반 GraphRAG 플랫폼으로, 데이터를 자동으로 지식그래프화하고 자연어 질의로 즉시 답을 제공합니다.
지난 몇 달 동안 유럽 전역에서 "그래프 입문" 강연을 많이 했어요. 우리 회사에서 아이디어로 시작된 것이 런던 사용자 그룹이 되었는데, 이제는 정말 많은 분들이 참석해주시는 월간 소개 행사가 되었답니다. 여기서 끝이 아니에요! 다른 도시에서도 이런 세션을 시작하고 싶어 하는 분들이 많으시더라고요.
강연을 하면서 정말 현명하고 중요한 질문들을 많이 받았어요. 그래서 여러분과 답변을 공유하고자 짧은 스크린캐스트를 만들어봤습니다. 한번 보실까요?
각 질문에 대한 추가 정보가 필요하시면 아래 링크들을 참고해주세요.
Graph Database란 무엇일까요?
자세한 내용은 Neo4j.org의 학습 섹션을 참고하세요.
제가 쓴 beer 게시물을 보시면 기술적인 지식이 없는 분들도 Graph Database를 쉽게 시작할 수 있는 방법을 알 수 있을 거예요.
Graph Database는 어떻게 작동하나요?
순회(traversal)에 대한 자세한 내용은 Cypher 입문 튜토리얼을 참고하세요.
Graph Database는 어떤 경우에 유용할까요?
훌륭한 사용 사례들을 한번 읽어보세요.
Graph Database의 단점은 무엇일까요?
Graph Database는 어떻게 작동하나요?
Neo4j 매뉴얼에 좋은 팁들이 많이 있어요.
Graph Database는 어떻게 확장될까요?
를 참고해보세요. 정말 유용할 거예요.
Jim Webber의 캐시 샤딩 페이지도 살펴보시고요.
Graph Database는 어떻게 모델링해야 할까요?
이 예제들을 한번 보세요.
Alistair의 Skillsmatter 강연도 참고하시면 좋을 것 같아요.
Graph Database에서 데이터 무결성을 어떻게 보장할 수 있을까요?
Graph Database를 엔터프라이즈 아키텍처에 어떻게 통합해야 할까요?
GraphConnect 패널에서 어떻게 하는지 한번 살펴보세요.
Graph Database를 다른 DB 기술과 어떻게 통합할 수 있을까요?
NoSQL 환경에서 어떻게 활용되는지 살펴보세요.
일반적으로 neo4j.com을 출발점으로 활용하시면 좋을 것 같아요. 유럽을 비롯해 여러 지역에서 멋진 밋업 그룹도 운영하고 있답니다.
이 내용이 여러분 모두에게 도움이 되었으면 좋겠어요. 슬라이드를 보고 싶으시다면 저에게 연락 주세요! 혹시 관심 있으시다면 여러분이 계신 도시나 회사에서 이 강연을 진행하거나, 아니면 진행을 도와드릴 수도 있어요.
Graph Database에 대해 더 자세히 알고 싶으신가요? 아래를 클릭해서 O'Reilly의 무료 전자책을 다운로드하고, 지금 바로 여러분의 애플리케이션에 그래프 기술을 사용하는 방법을 알아보세요.
faq
에이치시스템즈의 LogTree는 Neo4j 기반 GraphRAG 플랫폼으로, 데이터를 자동으로 지식그래프화하고 자연어 질의로 즉시 답을 제공합니다.
편집자 주: 이 프레젠테이션은 2015년 10월 GraphConnect San Francisco에서 Tim Williamson이 진행했어요. 다음은 그가 다룬 내용에 대한 간략한 검토입니다.
증가하는 인구의 요구
과학 연구의 도약
Graph Database로 작물 수확량 늘리기
몬산토에서 Graph Database 구축하기
단순한 혈통 데이터 이상의 추적
몬산토의 그래프 기술의 미래
–
몬산토는 전 세계 160개국에서 판매되는 생산성 제품(주로 종자)을 개발하는 글로벌 농산물 회사에요. 몬산토는 지난 6년 동안 유전체학 파이프라인 데이터에서 더 나은 추론을 얻을 수 있는 새로운 방법을 찾기 위해 노력해 왔습니다.
인구 증가
Monsanto에서 근무하기 전에 저는 세인트루이스에 있는 워싱턴 대학교 환경공학과에서 과학자로 재직했어요. 저는 2050년까지 95억 명으로 늘어날 것으로 예상되는 인구를 먹여 살리는 문제를 해결하기 위해 학계를 떠나 몬산토로 갔습니다.
이렇게 많은 인구는 생산적인 농지를 희생하면서 도시 면적을 크게 확장할 거예요. 더 많은 사람들이 농촌 지역을 떠나 도시에 살기 때문에 이전에 농업에 사용되었던 토지가 도시 목적으로 더 많이 사용될 것입니다. 실제로 인구가 95억 명에 도달할 때쯤에는 1인당 먹을 수 있는 농지가 3분의 1에이커도 채 남지 않을 것으로 예상됩니다.
이렇게 증가하는 도시 인구는 중산층일 가능성이 훨씬 높으며, 이는 더 많은 동물성 단백질 공급원(고기, 계란 및 유제품)을 더 많이 사용하는 방향으로 전환하게 됩니다. 이것들은 모두 생산에 더 많은 자원 집약적이며, 이는 농업 생산 시스템을 더욱 강조합니다.
마지막으로, 글로벌 기후 변화는 우리의 일상 생활에 극적인 영향을 미치고 있으며, 특히 악천후 패턴이 더 자주 발생하고 예측하기 어렵습니다.
2014년 12월, NASA 과학자 그룹은 캘리포니아 가뭄을 완전히 해소하려면 주 전체에 11조 갤런의 물이 고르게 퍼져야 한다는 예측을 담은 광범위한 계산 모델을 발표했어요. 이는 세계에서 가장 큰 저수지보다도 더 큰 규모죠.
놀랍게도 이는 같은 해 10월, 노스캐롤라이나와 사우스캐롤라이나에 5일 동안 쏟아진 물의 양과 정확히 같아요. 이 폭우로 수확 시기에 엄청난 홍수가 발생했죠. 캘리포니아에 필요한 물은 분명히 지구 어딘가에 있었지만, 정작 필요한 곳에는 없었던 거예요.
과학 연구의 도약
다행히 인류는 이러한 문제를 해결할 수 있는 도구를 가지고 있어요. 그중 하나가 주요 작물의 유전학을 개선하는 것이죠. 사실 이건 우리가 수천 년 동안 해오던 일이기도 해요. 약 10,000년 전, 최초의 농부들은 변화의 여정을 시작했답니다. 테오신테(Teosinte), 즉 현대 옥수수의 조상인 야생초를 오늘날 우리가 알고 있는 최적화된 태양열 발전 공장으로 만들어낸 거죠.
이들은 두 가지 중요한 관찰 덕분에 이런 일을 해낼 수 있었어요. 첫째, 테오신테 밭을 살펴보니 어떤 식물은 다른 식물보다 더 많은 종자를 생산하는 등 더 나은 특성을 보이는 걸 발견했죠. 둘째, 다음 해에 그 식물을 다시 심고 수분시키면 시간이 지남에 따라 바람직한 특성을 가진 식물의 빈도가 높아진다는 걸 알게 된 거예요.
이걸 인공 선택 또는 선택적 번식이라고 부르는데요. 이런 과정이 수세대에 걸쳐 축적되면 사람들에게 더 효과적으로 식량을 제공할 수 있는 새롭거나 최적화된 작물 품종을 개발할 수 있게 되는 거죠.
1800년대 중반에 미국 농무부는 옥수수와 같은 주요 작물에 대한 전국 수확량 통계를 정기적으로 수집하기 시작했어요.
에이커당 부셸(Bushels per acre)은 옥수수와 같은 작물의 곡물 생산량을 측정하는 단위예요. 옥수수 1부셸은 약 56파운드의 옥수수 종자에 해당하고, 1에이커는 미식축구 경기장 면적의 약 90% 정도 된답니다.
1860년대부터 1930년대까지 옥수수 개선은 대체로 정체 상태였어요. 하지만 현대 트랜지스터 제조 기술의 발전으로 CPU 처리 속도가 무어의 법칙(Moore's Law)을 따라잡을 수 있게 되면서, 유전학에 대한 이해가 높아져 인구 증가에 맞춰 곡물 생산량을 늘릴 수 있게 되었죠.
1930년대에 우리는 특정 작물을 교배하여 새로운 품종을 만드는 방법을 알아냈어요. 그리고 분자 생물학을 발견하고 성능과 직접적으로 연관된 특정 DNA 조각을 분리하는 방법도 찾아냈죠. 지난 10~15년 동안에는 작물에서 정확히 원하는 것을 얻기 위해 DNA에 표적화된 변형을 가하는 데 매우 능숙해졌답니다.
Graph Database로 작물 수확량 늘리기
이제 곡선이 가파르게 상승하는 다음 단계는 더 많은 데이터를 수집하는 능력이 아니라, 그 데이터를 더 빠르고 의미 있는 방식으로 이해하는 능력이 될 거예요. 현재 우리는 몇 가지 중요한 발전을 활용하기 위해 8가지 상품 작물과 18가지 채소 작물군에 걸쳐 있는 모든 글로벌 작물 곡물 파이프라인을 재구성하고 있답니다.
유전자 곡물을 생산하는 방법은 무엇일까요? 대학에 있든 기업 연구실에 있든 더 나은 작물을 개발하는 것은 번식 주기를 중심으로 이루어져요.
발견 육종가가 질병 저항성과 같은 바람직한 특성 때문에 각각 선택되는 두 부모, 즉 수컷과 암컷을 선택하면 주기가 시작돼요. 우리는 또한 식물에 바람직하지 않은 특성이 없는지도 확인하고요.
다음으로, 우리는 그 두 부모를 교배해서 수십만에서 수백만의 자손을 얻은 다음, 고도로 집중된 번식 주기를 거치게 돼요. 주기의 모든 단계에서 우리는 특정한 바람직한 특성만을 가진 식물을 선별하죠. 우리는 최선의 것을 선택하고 나머지는 버려요. 그런 다음 이 단계에서 "승자"를 심고 서로 수분을 공급해서 주기의 다음 라운드로 자손을 전진시켜요.
주기의 마지막에 우리의 목표는 부모로부터 바람직한 특성을 모두 나타내는 새로운 식물을 갖는 것이에요. 이를 미래 교배에 사용하거나 세계 어딘가의 농부에게 판매하기도 하고요.
주기의 모든 단계에서 우리는 두 가지 종류의 데이터를 사용해서 어떤 종자를 보관하고 어떤 종자를 폐기할지에 대한 결정을 내리는데요. 하나의 데이터 세트인 유전자형 데이터는 실험실에서 저렴하게 생성되며 식물이 어떻게 작동할지에 대한 예측 정보를 제공해요.
다음 데이터 세트는 현장 시험에서 나오는데, 이 과정에서 씨앗을 심고 그 성능을 측정하죠. 불행하게도 임상시험의 규모 때문에 임상시험을 심고, 데이터를 수집하고, 모니터링하는 과정은 비용이 꽤 많이 들어요. 예를 들어, 우리는 수천 개의 교배를 만들고 5개 위치에 수십 개의 자손을 심을 수 있는데, 이는 수백만 달러의 비용이 들 수 있어요.
각 주기에서 더 좋은 식물을 얻을 수 있는 세 가지 방법이 있어요.
교차할 두 부모를 더 잘 선택할 수 있어요. 수십만 명의 부모가 있는데, Data Science를 사용해서 어떤 부모가 교배하기에 가장 좋은지 결정하려면 어떻게 해야 할까요?
우리는 선택 파이프라인의 모든 경로에서 최선의 결정을 내릴 수 있도록 보장할 수 있어요.
우리는 더 많은 플랜트를 테스트해서 파이프라인을 확장하려고 노력할 수 있어요. 우리는 현장 시험을 위해 사용 가능한 토지를 거의 모두 사용했기 때문에 이것은 어려운 일이죠.
이 슬라이드에서 C는 번식 주기를 거쳐 나온 한 식물을 나타내요. 이것은 생산을 시작하기 위해 원래 교배되었던 두 부모에게 다시 연결되는 자가 자손 세대(회색)를 포함하는 깨지지 않은 조상 나무를 가지고 있어요.
가능한 최상의 부모와 결과를 찾는 데 가까워짐에 따라 해당 체인의 길이는 1년에 약 4홉까지 늘어날 수 있어요. 해당 라인에서 나오는 최종 부모가 수백 또는 수천 개의 자체 교배에 사용되는 경우 이는 더욱 복잡해지죠. 게다가 우리는 식물을 육종한 지 20년이 되었고 그 이전에는 60년의 데이터가 있어요. 그 부모 A와 B 각각은 그것을 낳기 위해 교배된 풍부한 조상의 역사를 가지고 있고요. 시간이 지남에 따라 이것이 실제로 어떻게 형성되는지 쉽게 알 수 있을 거예요.
이 실제 데이터 세트의 중심에 있는 상위 C는 연구 개발 파이프라인에서 중요한 옥수수 계통의 가장 오래된 소스라고 해요. 이 그래프에는 최소 300,000개 이상의 식물이 표시되는데, 중앙에 있는 부모 식물의 유전적 영향이 파이프라인 전체에서 느껴진다는 점이 흥미롭죠.
위의 세 가지 영역에서 획기적인 변화를 만들려면 복잡하고 의미 있는 유전적 특징에 대해 이 정도 크기의 데이터 세트를 실시간으로 마이닝할 수 있어야 해요. 바로 그게 저희가 해결해야 할 문제였죠.
이전에는 Graph Database가 없었기 때문에, 어쩔 수 없이 관계형 데이터 구조를 사용해서 이 작업을 처리했어요. 기존 관계형 저장소에는 9억 행의 데이터를 나타내는 약 11개의 조인 테이블이 있었죠. 여러분이 상상하시는 것처럼, 이 시스템에서 뭔가를 읽어오는 건 사전 연결, 대규모 재귀 조인 때문에 꽤나 고통스러운 작업이었답니다.
우리의 목표는 단일 식물의 전체 조상 트리를 제공할 수 있는 도구를 찾는 거였어요. 이를 위해 가능한 최고의 최적화 테이블과 재귀 `JOIN` 쿼리를 작성하고 프로덕션 캐싱을 통해 속도를 최적화했죠. 하지만 우리의 성과 곡선을 보면 "실시간"이라는 목표는 달성되지 않았음이 분명해요.
이 그래프에서 깊이는 "트리 위로 뛰어오르기", 즉 조상 깊이의 한 수준을 나타내요. 응답 시간은 데이터 세트를 반환하는 실행 시간을 측정한 것이고요. 이는 데이터세트의 조상 수가 폭발적으로 증가하기 시작하는 시점과 정확히 관련이 있죠.
우리는 여전히 이 문제를 해결해야 했어요. 다행스럽게도 우리는 유전적 조상이 자연스럽게 발생하는 그래프를 형성한다는 것을 깨달았죠. 이는 실시간으로 데이터를 가져오는 과정에서 직면한 문제를 실제로 어떻게 처리했는지 보여주는 다소 작고 사소한 스냅샷이에요.
모든 씨앗 봉지에는 `Node`가 있어요. 새로운 `Node`를 사용하면 `Node`를 심을 때마다, 수확할 때마다 추적하므로 부모에서 자손까지 원하는 만큼 추상화 계층을 구축할 수 있죠. 이 그래프의 최종 테스터를 처음 구축했을 때 그래프에는 7억 개의 `Node`, 12억 개의 `Relationship`, 20억 개의 속성이 있었어요.
우리가 시작한 곳으로 돌아가서 동일한 프로덕션 속편을 사용하고 다음을 사용하여 동일한 알고리즘을 다시 만들어요.의 순회 프레임워크를 사용하고 동일한 조건과 데이터 세트를 사용하고 `Query`를 다시 실행하세요.
이제 거의 스케일 프리 성능에 가까운 수준으로 임의 깊이의 트리를 처리할 수 있어요. 이제 우리는 이 일을 신속하게 할 수 있을 뿐만 아니라, 성능만 추적하는 게 아니라 식물의 기능을 파악하기 위한 추상화를 구축할 수 있다니 정말 흥미롭죠? 또한 이제 단 몇 분 만에 단 하나의 식물이 아닌 백만 개의 식물의 조상을 분석할 수 있다니 놀랍지 않나요?
Graph Database 구축
이제부터 우리는 "무엇이었는지"의 세계를 뒤로하고 추상화를 어떻게 구축했는지 한번 살펴볼까요?
우리 그룹에서 데이터 과학 제품을 제공하는 것에 대한 우리의 철학은 REST 또는 우리가 원하는 프로그래밍 언어에서 액세스할 수 있는 일반적인 생물학적 문법을 사용하여 데이터 세트를 캡슐화하는 방법을 결정하는 거예요. 그렇게 하면 누구에게도 방법을 가르치지 않고도 복잡한 알고리즘을 실행할 수 있어요.
예를 들면 다음과 같은 기본 트리가 있다고 가정해 볼게요. 개체군 1에는 단일 연결 조상이 하나 있고 교배로 분리되며, 각 교배에는 고유한 단일 연결 조상이 있어요. 우리 문법에서는 간단한 REST 리소스를 사용하여 전체 트리를 반환하는 것을 캡슐화했어요. 인구 1이 있고 트리의 설득력 있는 JSON 표현으로 모든 조상을 반환하려고 해요. 모든 Node와 Relationship이 표시되죠.
이를 통해 누구나 실시간으로 Neo의 전체 하위 그래프를 얻을 수 있으며, 전체 데이터베이스를 자신의 컴퓨터에 복사하지 않고도 거대한 그래프의 기능을 효과적으로 활용할 수 있어요.
하지만 우리는 중요한 유전적 특징도 추적하고 싶어요. 유전학에는 혈통에서 얻는 정보를 이해하고 극대화하는 데 중요한 여러 가지 이정표가 있어요. 우리는 과학자들이 그것에 접근할 수 있도록 문법을 작성했답니다.
매우 기본적인 Query는 다음과 같아요. Plant One의 경우 해당 조상에서 가장 최근의 이진 교배를 표시합니다(예: 두 부모가 있는 경우). 이는 식물의 유전사에서 중요한 순간인데요, 왜냐하면 재조합 사건을 표시하기 때문이에요. 이는 계통에서 서로 다른 염색체를 가진 두 부모가 함께 교배되어 식물을 생산하는 시기입니다.이질적인 인구. 우리 시스템에서 사용자는 이진 교배만 요청하면 Plant One을 산출한 정확한 남성과 여성이 반환돼요.
특정 기능으로 이어진 계보를 추적하는 것도 가능해요. 예를 들어, 첫 번째 이진 교차까지만 인구 1의 조상을 요청할 수 있죠.
이 경우 동일한 트리 구조를 반환하지만, 이진 교차 수준으로 정리된 트리 구조를 얻게 돼요. 우리는 모든 의미 있는 유전적 요소를 고려하려고 노력했고, 그 주위에 문법을 구축했답니다. 2014년 9월에는 "Ancestry-as-a-Service"라는 내부 시스템을 가동하기 시작했어요.
우리 시스템은 파이프라인의 전체 유전적 이력을 포함하는 내장형 Neo4j 클러스터에 풍부한 RESTful 문법을 통합하고 있어요. REST 계층은 개별 데이터 과학자와 애플리케이션 개발자가 직접 액세스할 수 있는 계층이죠.
현재 우리 시스템에는 약 30개의 RESTful 문법 요소가 있어요. 이를 통해 우리는 가장 오래된 것으로 알려진 발견 교배부터 오늘날 현장에서 판매되는 가장 최근 작물까지 파이프라인을 추적할 수 있답니다. 우리 시스템을 사용하는 약 120명의 애플리케이션 개발자와 데이터 과학자가 있는데, 이들이 함께 6억 개가 넘는 REST 쿼리를 작성했어요.
이 도구의 개발은 우리에게 정말 큰 변화를 가져다 줬어요. 예를 들어, 우리가 개발한 애플리케이션 중 하나는 우리 파이프라인의 모든 시드에 적용되었죠. 우리는 이 애플리케이션에서 성능이 10배 증가한 것을 확인했고, 특정 데이터 과학자는 우리의 새로운 시스템을 사용하여 한 달 걸리던 분석 시간을 단 세 시간으로 단축할 수 있었어요.
실시간으로 데이터를 읽어오려면 당연히 실시간 데이터가 필요하겠죠? 그래프를 만드는 순간 데이터가 이미 낡았다면, 시스템을 실시간으로 활용하는 건 정확하지 않을 거예요. 그렇다고 모든 애플리케이션이 그래프에 데이터를 쓰도록 할 수도 없다는 걸 알고 있었죠. 그래서 저희는 Oracle의 기술인 GoldenGate를 사용해서 이 문제를 해결했어요. GoldenGate는 Exadata 인스턴스에서 나오는 리두 로그에서 변경 캡처 스트림을 생성해준답니다.
저희는 변경 스트림을 파이프하고, 이걸 Apache Kafka가 인식할 수 있는 형태로 변환하는 커스텀 어댑터를 만들었어요. 이 변경 스트림은 하루에 무려 1,000만 건의 쓰기를 그래프에 꾸준히 제공하고, 이 쓰기는 Oracle에 도달한 후 1초 안에 상위 계층에 반영돼요. 이걸 활용해서 전체 데이터 단일체를 조금씩 분할해서 AWS로 옮기고 있답니다.
이 방식이 저희처럼 규모가 크고 복잡한 상황에 놓인 회사들에게 정말 유용할 거라고 생각해요. 저희 어댑터에 대한 오픈 소스 액세스도 제공하고 있으니 참고해주세요.
가계 데이터 그 이상의 추적
저희가 가계 데이터 추적에만 관심 있는 건 아니에요. 이 다이어그램, Triforce는 현대 게놈 과학의 궁극적인 목표를 나타내죠. 이걸 통해 식물의 관찰 가능한 특성(표현형)을 식물의 성능을 예측하는 유전 정보, 그리고 해당 성능을 측정하는 환경에 대해 인덱싱할 수 있어요. 이건 현재 현대 과학에 존재하는 몇 가지 흥미로운 유전적 수수께끼를 풀 수 있는 문을 열어준답니다.
이러한 문제 중 하나는 조상 그래프에 유전자형 데이터를 계층화하는 방법을 고려해서 접근할 수 있다는 점이에요.
유전자형 데이터 세트가 있는 모든 식물에 대해 간단한 node를 그 population과 연결해줄 수 있어요. 이 node는 게놈 데이터를 저장하는 외부 시스템(이 경우 HBase 환경)에 대한 포인터 역할을 하죠. 이걸 통해 특정 유전형 특징의 존재를 기반으로 조상 그래프를 구문 분석하는 알고리즘을 만들 수 있답니다.
이 그래프에는 연결된 게놈 데이터 세트가 있는 세 개의 엔터티가 각각 있어요. "마커 수"는 데이터 세트의 크기와 직접적인 상관관계가 있죠. 이 예시에서 60,000개의 마커는 60,000이 되고, 300개의 마커는 300개의 사실이 되는 거예요. 대규모 마커 데이터 세트를 수집하는 건 비용이 꽤 많이 들기 때문에, 부모로 사용할 식물에 대해서만 수집하게 돼요.
이제 모든 저밀도 및 고밀도 마커 데이터 세트의 위치와 해당 데이터 세트 간의 정확한 유전 경로가 있다면, 저해상도 데이터의 데이터 콘텐츠를 값비싼 데이터 세트를 측정할 때와 비슷하게 업샘플링할 수 있어요.
RESTful 문법을 사용해서 이걸 구축하려면, 가장 최근의 유전자형 조상 세트에 도달했을 때 데이터베이스에 트리를 "가지치기"하도록 요청하는 거예요. ID는 해당 데이터세트가 포함된 HBase 데이터 저장소에 연결되는 키를 나타내기 때문에, 트리에는 이러한 모집단에 대해 보유하고 있는 모든 게놈 데이터가 주석으로 추가되죠.
이제 Ancestry-as-a-Service에서 이러한 유전자형 주석이 달린 조상 트리를 뱉어낼 수 있게 되었어요. 그래서 해당 시스템에 Apache Spark 및 GraphX 기반 유전자형 추정 엔진을 구축했답니다.
유전자형 데이터 세트와 연결된 조상 트리를 사용해서 대상 자손의 고해상도 유전자형을 업샘플링(추정)하는 방식이에요.
이 추정을 할 때 연결된 키를 사용해서 HBase에서 필요한 데이터 세트를 가져오고, 추정된 유전자형을 HBase에 다시 쓰고, Kafka를 통해 그래프에 전달해서 향후 계산에서 이러한 새로운 데이터 세트를 활용할 수 있게 만들죠. 이 거대한 피드백 루프는 우리의 육종 파이프라인 중 하나를 통과하는 모든 단일 종자의 유전자형을 추정할 수 있는 힘을 제공해요.
이제 종자에 대한 고해상도 유전자형 데이터가 있으니, 가장 효과적인 자손을 위해 해당 유전자형을 추정하고 해당 데이터를 유전적으로 마이닝해서 현장 시험의 첫 번째 단계를 대체할 수 있어요. 이로 인해 전체 번식 주기에 걸쳐 더 나은 선택이 가능해지죠.
실험실에서 종자를 스크리닝하면 더 빠르고 비용 효율적이어야겠죠? 더 이상 현장 시험을 할 필요가 없으니 연간 수백만 달러를 절약하고 토지를 다른 목적으로 사용할 수 있어요. 우리는 데이터를 활용해서 파이프라인의 수평적 확장을 확장하는 거예요.
우리가 다음으로 갈 곳
유전학자들은 오랫동안 그래프 분석의 힘을 알고 있었어요. [슬라이드 30:11 삽입] 이 예는 가금류 육종, 분자 전 생물학에 관한 1921년 교과서에서 발췌한 것인데요. 역사상 현 시점에서는 특성의 유전성을 의미 있는 방식으로 설명할 방법이 없었어요. 그럼에도 불구하고 는 자손의 조상이 유전적으로 어떻게 기여했는지를 나타내는 그래프 구조를 그렸답니다.
그가 설명한 내용은 정말 강력한 게놈 선택 기술의 기초가 되는 공동 조상 분석이라는 알고리즘이었어요. 오른쪽에 보이는 2010년 논문에서는 공동 조상 분석을 사용해서 특정 유형의 자손을 위해 교배할 부모를 선택하는 데 유용한 그래프 기반 알고리즘을 설명하고 있죠. 이때는 아직 Graph Database에 접근할 수 있는 사람이 없었다는 점이 아쉬워요.
공동 조상의 경우, 특정 식물에 대해 각 조상의 유전적 기여도를 나타내는 축소된 표현인 공동 조상 행렬을 생성하는 데 거의 근접했어요. 그래프 이론가들에게 행렬 형태의 그래프는 낯선 개념이 아닐 거예요. 왜냐하면 계산 효율이 정말 좋거든요. 그리고 우리는 게놈 선택 알고리즘을 사용해서 우선 파이프라인에 올바른 식물을 배치하는 거죠.
더 자세한 논의를 원하시면 언제든지 저에게 연락해주세요. 지저귀다.
이와 같은 그래프 기반 앱을 만들고 싶으신가요? 무료 사본을 다운로드하려면 아래를 클릭하세요.Neo4j 배우기세계 최고의 Graph Database로 속도를 따라잡으세요.
Graph
GraphConnect
HBase
Kafka
Monsanto
Oracle
에이치시스템즈의 LogTree는 Neo4j 기반 GraphRAG 플랫폼으로, 데이터를 자동으로 지식그래프화하고 자연어 질의로 즉시 답을 제공합니다.
GraphRAG Python 패키지는 비정형 데이터에서 Knowledge Graph 생성, Knowledge Graph 검색, 그리고 전체 GraphRAG 파이프라인을 한 곳에 모아 제공하는 end-to-end 워크플로우를 제공해요. Python을 사용해서 지식 도우미, 검색 API, 챗봇, 또는 보고서 생성기를 구축하고 있다면, 이 패키지를 통해 Knowledge Graph를 쉽게 통합해서 Retrieval-Augmented Generation (RAG)의 관련성, 정확성, 설명 가능성을 개선할 수 있어요.
이번 포스팅에서는 GraphRAG Python 패키지를 사용해서 0에서 GraphRAG로 가는 방법과 다양한 Knowledge Graph 검색 패턴을 사용해서 GenAI 앱에서 다양한 동작을 얻는 방법을 보여드릴게요.
GraphRAG: GenAI에 지식 추가
Knowledge Graph와 RAG를 결합한 GraphRAG는 환각과 같은 Large Language Model (LLM)의 일반적인 문제를 해결하는 동시에 기존 RAG 접근 방식보다 향상된 품질과 효율성을 위해 도메인별 컨텍스트를 추가하는 데 도움이 돼요. Knowledge Graph는 LLM이 질문에 안정적으로 답변하고 복잡한 워크플로에서 신뢰할 수 있는 에이전트 역할을 하는 데 필요한 상황별 데이터를 제공하죠. 텍스트 데이터의 단편에만 액세스를 제공하는 대부분의 RAG 솔루션과 달리 GraphRAG는 구조화된 정보와 반구조화된 정보를 모두 검색 프로세스에 통합할 수 있다는 장점이 있어요.
GraphRAG Python 패키지는 Knowledge Graph를 생성하고 그래프 순회, text2Cypher를 사용한 쿼리 생성, 벡터 및 전체 텍스트 검색의 조합을 사용하는 Knowledge Graph 데이터 검색 패턴을 쉽게 구현하도록 도와줘요. 전체 RAG 파이프라인을 지원하는 추가 도구와 결합된 이 패키지를 사용하면 GenAI 애플리케이션 및 워크플로에서 GraphRAG를 원활하게 구현할 수 있어요.
빠른 개요: 몇 줄의 코드로 구성된 GraphRAG
다음은 전체 end-to-end 워크플로우를 위한 몇 줄의 코드인데요. 다음 섹션에서는 이 예제의 더 자세한 버전을 살펴보고 다음 GenAI 혁신을 시작하기 위한 추가 리소스를 제공할게요. 복제할 모든 코드는 이 GitHub 저장소에서 찾을 수 있어요.
import neo4j
from neo4j_graphrag.llm import OpenAILLM as LLM
from neo4j_graphrag.embeddings.openai import OpenAIEmbeddings as Embeddings
from neo4j_graphrag.experimental.pipeline.kg_builder import SimpleKGPipeline
from neo4j_graphrag.retrievers import VectorRetriever
from neo4j_graphrag.generation.graphrag import GraphRAG
neo4j_driver = neo4j.GraphDatabase.driver(NEO4J_URI,
auth=(NEO4J_USERNAME, NEO4J_PASSWORD))
ex_llm=LLM(
model_name="gpt-4o-mini",
model_params={
"response_format": {"type": "json_object"},
"temperature": 0
})
embedder = Embeddings()
# 1. Build KG and Store in Neo4j Database
kg_builder_pdf = SimpleKGPipeline(
llm=ex_llm,
driver=neo4j_driver,
embedder=embedder,
from_pdf=True
)
await kg_builder_pdf.run_async(file_path='precision-med-for-lupus.pdf')
# 2. KG Retriever
vector_retriever = VectorRetriever(
neo4j_driver,
index_name="text_embeddings",
embedder=embedder
)
# 3. GraphRAG Class
llm = LLM(model_name="gpt-4o")
rag = GraphRAG(llm=llm, retriever=vector_retriever)
# 4. Run
response = rag.search( "How is precision medicine applied to Lupus?")
print(response.answer)
#output
Precision medicine in systemic lupus erythematosus (SLE) is an evolving approach that aims to tailor treatment based on individual genetic, epigenetic, and pathophysiological characteristics…
0. Neo4j 데이터베이스 생성
RAG 예제를 시작하려면 검색에 사용할 데이터베이스를 만들어야 해요. Neo4j를 사용하면 무료 Neo4j Graph Database를 빠르게 시작할 수 있는데, AuraDB를 사용하면 돼요. 더 높은 수집 및 검색 성능을 위해 AuraDB Free를 사용하거나 AuraDB Professional(Pro) 무료 평가판을 시작할 수도 있고요. Pro 인스턴스에는 RAM이 조금 더 많아서 최고의 사용자 경험을 위해 권장된답니다.
인스턴스를 생성한 후에는 다음 코드에서 사용할 자격 증명을 다운로드하고 저장할 수 있어요.
1. Knowledge Graph 구축
문서를 Knowledge Graph로 변환해서 Neo4j 데이터베이스에 저장해볼게요. 루푸스에 관한 의학 연구 논문이 포함된 몇 가지 PDF 문서를 통해 보여드릴게요. 이런 문서에는 전문적인 정보가 많이 들어있는데, Knowledge Graph는 이 복잡한 임상 데이터를 더 효과적으로 구성해서 AI 사용 사례를 향상시킬 수 있어요. 아래는 우리가 만들 그래프의 샘플이에요. 여기에는 몇 가지 주요 Node 유형(Node Label이라고도 함)이 포함되어 있죠.
Document: 문서 소스에 대한 메타데이터
Chunk: 강력한 Vector Embedding을 위한 임베딩이 포함된 문서의 텍스트 Chunk
__Entity__: 텍스트 Chunk에서 추출된 Entity
Entity 간의 Relationship과 Entity가 Chunk와 문서 간의 연결 경로를 생성하는 방법을 확인해보세요. 이게 바로 GraphRAG의 장점이고, 나중에 이게 얼마나 중요한지 살펴보게 될 거예요.
GraphRAG Python 패키지를 사용해서 Knowledge Graph를 만드는 건 Neo4j 전문가가 아니더라도 정말 간단해요.
The SimpleKGPipeline 클래스를 사용하면 다음과 같은 몇 가지 주요 입력으로 Knowledge Graph를 자동으로 구축할 수 있어요.
Neo4j에 연결하기 위한 Driver,
Entity 추출을 위한 LLM, 그리고
유사성 검색을 위해 텍스트 Chunk에 Vector를 생성하는 임베딩 모델이에요.
Neo4j Driver
Neo4j Driver를 사용하면 데이터베이스에 연결해서 읽기 및 쓰기 트랜잭션을 수행할 수 있어요. 데이터베이스를 생성할 때부터 URI, 사용자 이름 및 비밀번호 변수를 얻을 수 있는데, AuraDB에서 데이터베이스를 생성했다면 다운로드한 파일에 있을 거예요.
이번에는 OpenAI의 GPT-4o-mini를 사용해볼게요. 빠르고 저렴한 모델이거든요. GraphRAG Python 패키지는 모든 LLM 모델을 지원하는데, OpenAI, Google VertexAI, Anthropic, Cohere, Azure OpenAI, 로컬 Ollama 모델 및 LangChain과 작동하는 모든 채팅 모델의 모델을 포함해요. 다른 LLM에 대한 사용자 정의 인터페이스를 구현할 수도 있고요.
마찬가지로 OpenAI의 기본값인 text-embedding-ada-002를 임베딩 모델로 사용할 건데요, 다른 임베더도 다른 공급자로부터 사용할 수 있어요.
import neo4j
from neo4j_graphrag.llm import OpenAILLM
from neo4j_graphrag.embeddings.openai import OpenAIEmbeddings
llm=OpenAILLM(
model_name="gpt-4o-mini",
model_params={
"response_format": {"type": "json_object"}, # use json_object formatting for best results
"temperature": 0 # turning temperature down for more deterministic results
}
)
#create text embedder
embedder = OpenAIEmbeddings()
선택 입력: 스키마 & Prompt Template
필수 사항은 아니지만, Knowledge Graph의 품질을 높이고 싶다면 그래프 스키마를 추가하는 걸 추천해요. 엔티티 추출 중에 생성할 Node와 Relationship 유형에 대한 가이드라인을 제공하거든요.
전문가 팁: 어떤 스키마를 사용해야 할지 고민된다면, 먼저 스키마 없이 그래프를 만들어보고 가장 흔하게 생성되는 Node와 Relationship 유형을 살펴보는 것도 좋은 시작점이 될 수 있어요.
그래프 스키마는 추출하려는 엔티티(즉, Node Label)와 Relationship을 정의해요. 이 간단한 예시에서는 사용하지 않겠지만, potential_schema를 통해 어떤 Relationship이 어떤 Node에 연결되어야 하는지 안내할 수도 있답니다. 자세한 내용은 여기에서 확인해 보세요.
엔티티 추출을 위한 커스텀 Prompt도 추가할 수 있어요. GraphRAG Python 패키지에는 기본 Prompt가 내장되어 있지만, 사용 사례에 더 적합한 Prompt Engineering을 통해 더욱 유용한 Knowledge Graph를 만들 수 있는 경우가 많답니다. 아래 Prompt는 약간의 실험을 거쳐 만들어졌어요. 기본 Prompt와 동일한 일반 형식을 따라야 한다는 점, 잊지 마세요! 기본 Prompt를 참고하세요.
prompt_template = '''
You are a medical researcher tasks with extracting information from papers
and structuring it in a property graph to inform further medical and research Q&A.
Extract the entities (nodes) and specify their type from the following Input text.
Also extract the relationships between these nodes. the relationship direction goes from the start node to the end node.
Return result as JSON using the following format:
{{"nodes": [ {{"id": "0", "label": "the type of entity", "properties": {{"name": "name of entity" }} }}],
"relationships": [{{"type": "TYPE_OF_RELATIONSHIP", "start_node_id": "0", "end_node_id": "1", "properties": {{"details": "Description of the relationship"}} }}] }}
- Use only the information from the Input text. Do not add any additional information.
- If the input text is empty, return empty Json.
- Make sure to create as many nodes and relationships as needed to offer rich medical context for further research.
- An AI knowledge assistant must be able to read this graph and immediately understand the context to inform detailed research questions.
- Multiple documents will be ingested from different sources and we are using this property graph to connect information, so make sure entity types are fairly general.
Use only fhe following nodes and relationships (if provided):
{schema}
Assign a unique ID (string) to each node, and reuse it to define relationships.
Do respect the source and target node types for relationship and
the relationship direction.
Do not return any additional information other than the JSON in it.
Examples:
{examples}
Input text:
{text}
'''
SimpleKGPipeline의 다른 선택적 입력으로는 문서 로더와 Knowledge Graph 빌더 컴포넌트가 있어요. 전체 문서는 여기에서 확인할 수 있습니다.
Knowledge Graph 빌더 실행
Knowledge Graph 빌더는 run_async 메서드를 사용해서 실행할 수 있어요. 아래에서는 3개의 PDF를 반복해서 처리할 거예요.
pdf_file_paths = ['truncated-pdfs/biomolecules-11-00928-v2-trunc.pdf',
'truncated-pdfs/GAP-between-patients-and-clinicians_2023_Best-Practice-trunc.pdf',
'truncated-pdfs/pgpm-13-39-trunc.pdf']
for path in pdf_file_paths:
print(f"Processing : {path}")
pdf_result = await kg_builder_pdf.run_async(file_path=path)
print(f"Result: {pdf_result}")
완료되면 통합 콘솔에서 결과 Knowledge Graph를 탐색할 수 있어요. 콘솔은 아주 훌륭한 인터페이스를 제공하죠.
쿼리 탭으로 이동해서 아래 쿼리를 입력하면 그래프 샘플을 볼 수 있습니다.
MATCH p=()-->() RETURN p LIMIT 1000;
Document, Chunk, 그리고 __Entity__ 노드들이 어떻게 연결되어 있는지 확인할 수 있을 거예요.
“어휘적” 그래프 부분을 보려면, 다음을 포함하는 Document 와 Chunk node에서 다음을 실행해 보세요.
일치 p=(:Chunk)--(:!__Entity__) RETURN p;
이 쿼리는 우리가 수집한 각 문서에 대해 하나씩 연결이 끊긴 컴포넌트들을 보여줘요. 각 Chunk에 추가된 Vector Embedding도 확인할 수 있죠.
이번에는 그래프를 살펴볼까요? __Entity__ node에서 다음 쿼리를 실행해 보세요.
일치 p=(:!Chunk)-->(:!Chunk) RETURN p;
다양한 개념들이 어떻게 추출되었고, 서로 어떻게 연결되는지 확인할 수 있을 거예요. 이 도메인 그래프는 문서들 사이의 정보를 연결해 준답니다.
맞춤형 및 상세 Knowledge Graph 구축에 대한 참고사항
후드 아래에서 SimpleKGPipeline은 아래 나열된 구성 요소를 실행해요. GraphRAG 패키지는 낮은 수준의 파이프라인 API를 제공해서, Knowledge Graph 구축 프로세스를 꽤 많이 커스터마이징할 수 있다는 점! 자세한 내용은 선적 서류 비치를 참고하세요.
문서 파서: PDF 같은 문서에서 텍스트를 추출해요.
텍스트 분할기: LLM 컨텍스트 창에서 관리하기 쉽도록 텍스트를 작은 조각으로 분할하죠 (토큰 제한).
청크 임베더: 각 청크에 대한 텍스트 Vector Embedding을 계산해요.
스키마 빌더: 정확하고 쉽게 탐색할 수 있는 Knowledge Graph를 위해 LLM 엔터티 추출을 기반으로 하는 스키마를 제공합니다.
엔터티 및 관계 추출기: 텍스트에서 관련 엔터티 및 관계를 추출해요.
지식 정보 작성자: 식별된 엔터티 및 관계를 KG에 저장해요.
2. Knowledge Graph에서 데이터 검색
GraphRAG Python 패키지는 Knowledge Graph에서 데이터를 검색하기 위한 여러 클래스를 제공하는데요, 한번 살펴볼까요?
벡터 리트리버: Vector Embedding을 사용해서 유사성 검색을 수행해요.
벡터 사이퍼 리트리버: Neo4j의 그래프 쿼리 언어인 Cypher의 검색 쿼리와 벡터 검색을 결합해서 그래프를 탐색하고 추가 `Node`와 `Relationship`을 통합합니다.
하이브리드 리트리버: 벡터 검색과 전체 텍스트 검색을 결합합니다.
하이브리드 사이퍼 리트리버: 추가 그래프 탐색을 위해 벡터 및 전체 텍스트 검색을 Cypher 검색 쿼리와 결합합니다.
Text2Cypher: Neo4j에 대해 실행하기 위해 Natural Language 쿼리를 Cypher 쿼리로 변환합니다.
Weaviate 및 Pinecone Neo4j 리트리버: Weaviate 또는 Pinecone에 저장된 벡터를 검색하고 외부 ID 속성을 사용하여 Neo4j의 `Node`에 연결할 수 있어요.
: 특정 요구 사항에 따라 맞춤형 검색 방법을 허용합니다.
이러한 검색기를 사용하면 다양한 데이터 검색 패턴을 구현해서 RAG 파이프라인의 관련성과 정확성을 높일 수 있어요.
방금 만든 그래프에서 몇 가지를 살펴볼게요.
벡터 리트리버
벡터 리트리버는 ANN(Approximate Nearest Neighbor) 벡터 검색을 사용해서 Knowledge Graph에서 데이터를 검색합니다.
이 검색기가 청크 `Node`에서 정보를 가져올 수 있도록 Neo4j에서 벡터 `Index`를 생성할 수 있어요.
from neo4j_graphrag.indexes import create_vector_index
create_vector_index(driver, name="text_embeddings", label="Chunk",
embedding_property="embedding", dimensions=1536, similarity_fn="cosine")
이제 간단한 프롬프트로 이 검색기를 실행해 볼게요. 검색기는 텍스트 청크와 벡터 유사성 점수를 다시 가져와서 RAG의 질문에 답변하는 데 유용한 컨텍스트를 제공할 수 있답니다.
import json
vector_res = vector_retriever.get_search_results(query_text = "How is precision medicine applied to Lupus?",
top_k=3)
for i in vector_res.records: print("====n" + json.dumps(i.data(), indent=4))
# output text chunks
====
{
"node": {
"text": "precise and systematic fashion as suggested here.nFuture care will involve molecular diagnostics throughoutnthe patient timecourse to drive the least toxic combinationnof therapies. Recent evidence suggests a paradigm shift isnon the way but it is hard to predict how fast it will come.nDisclosurenThe authors report no con ufb02icts of interest in this work.nReferencesn1. Lisnevskaia L, Murphy G, Isenberg DA. Systemic lupusnerythematosus. Lancet .2014 ;384:1878 u20131888. doi:10.1016/S0140-n6736(14)60128"
},
"score": 0.9368438720703125
}
====
{
"node": {
"text": "d IS agents.nPrecision medicine consists of a tailored approach toneach patient, based on genetic and epigenetic singularities,nwhich in ufb02uence disease pathophysiology and drugnresponse. Precision medicine in SLE is trying to addressnthe need to assess SLE patients optimally, predict diseasencourse and treatment response at diagnosis. Ideally everynpatient would undergo an initial evaluation that wouldnproufb01le his/her disease, assessing the main pathophysiolo-ngic pathway through biomarkers, ther"
},
"score": 0.935699462890625
}
====
{
"node": {
"text": "REVIEWnT owards Precision Medicine in Systemic LupusnErythematosusnThis article was published in the following Dove Press journal:nPharmacogenomics and Personalized MedicinenElliott Lever1nMarta R Alves2nDavid A Isenberg1n1Centre for Rheumatology, Division ofnMedicine, University College HospitalnLondon, London, UK;2Internal Medicine,nDepartment of Medicine, CentronHospitalar do Porto, Porto, PortugalAbstract: Systemic lupus erythematosus (SLE) is a remarkable condition characterised byndiversit"
},
"score": 0.9312744140625
}
Vector Cypher Retriever
탐색해볼 만한 또 다른 유용한 검색기는 Vector Cypher Retriever에요. 이걸 사용하면 Neo4j의 그래프 쿼리 언어인 Cypher를 사용해서 Vector Search로 초기 Node 세트를 검색한 다음, 그래프 순회 로직을 통합할 수 있어요. 아래에서는 Vector Search를 통해 청크 Node를 얻은 다음, 최대 3홉 아웃까지 엔터티를 탐색하는 검색기를 만들어볼게요.
from neo4j_graphrag.retrievers import VectorCypherRetriever
vc_retriever = VectorCypherRetriever(
driver,
index_name="text_embeddings",
embedder=embedder,
retrieval_query="""
//1) Go out 2-3 hops in the entity graph and get relationships
WITH node AS chunk
MATCH (chunk)<-[:FROM_CHUNK]-()-[relList:!FROM_CHUNK]-{1,2}()
UNWIND relList AS rel
//2) collect relationships and text chunks
WITH collect(DISTINCT chunk) AS chunks,
collect(DISTINCT rel) AS rels
//3) format and return context
RETURN '=== text ===n' + apoc.text.join([c in chunks | c.text], 'n---n') + 'nn=== kg_rels ===n' +
apoc.text.join([r in rels | startNode(r).name + ' - ' + type(r) + '(' + coalesce(r.details, '') + ')' + ' -> ' + endNode(r).name ], 'n---n') AS info
"""
)
동일한 프롬프트를 제출하면 다음과 같은 컨텍스트가 반환될 거예요.
vc_res = vc_retriever.get_search_results(query_text = "How is precision medicine applied to Lupus?", top_k=3)
# print output
kg_rel_pos = vc_res.records[0]['info'].find('nn=== kg_rels ===n')
print("# Text Chunk Context:")
print(vc_res.records[0]['info'][:kg_rel_pos])
print("# KG Context From Relationships:")
print(vc_res.records[0]['info'][kg_rel_pos:])
# output
# Text Chunk Context:
=== text ===
precise and systematic fashion as suggested here.
Future care will involve molecular diagnostics throughout
the patient timecourse to drive the least toxic combination
of therapies. Recent evidence suggests a paradigm shift is
on the way but it is hard to predict how fast it will come.
Disclosure
The authors report no con flicts of interest in this work.
References
1. Lisnevskaia L, Murphy G, Isenberg DA. Systemic lupus
erythematosus. Lancet .2014 ;384:1878 –1888. doi:10.1016/S0140-
6736(14)60128
---
d IS agents.
Precision medicine consists of a tailored approach to
each patient, based on genetic and epigenetic singularities,
which in fluence disease pathophysiology and drug
response. Precision medicine in SLE is trying to address
the need to assess SLE patients optimally, predict disease
course and treatment response at diagnosis. Ideally every
patient would undergo an initial evaluation that would
profile his/her disease, assessing the main pathophysiolo-
gic pathway through biomarkers, ther
---
REVIEW
T owards Precision Medicine in Systemic Lupus
Erythematosus…
=== kg_rels ===
Systemic lupus erythematosus - AUTHORED(Published in) -> N. Engl. J. Med.
---
Lisnevskaia L - AUTHORED() -> Systemic lupus erythematosus
---
Murphy G - AUTHORED() -> Systemic lupus erythematosus
---
Isenberg DA - AUTHORED() -> Systemic lupus erythematosus
---
Systemic lupus erythematosus - CITES(Published in) -> Lancet
---
Systemic lupus erythematosus - CITES(Systemic lupus erythematosus is discussed in the Lancet publication.) -> Lancet
---
Systemic lupus erythematosus - ASSOCIATED_WITH(SLE is characterized by aberrant activity of the immune system) -> Aberrant activity of the immune system
---
Immunological biomarkers - USED_FOR(Immunological biomarkers could diagnose and monitor disease activity in SLE) -> Systemic lupus erythematosus
---
Novel SLE biomarkers - DESCRIBES(Novel SLE biomarkers have been discovered through omics research) -> Systemic lupus erythematosus
—
콘솔에 시각화하면 벡터 검색의 텍스트 청크와 엔터티, 그리고 연결된 Knowledge Graph 관계의 조합인 아래 하위 그래프가 반환되는 것을 확인할 수 있어요.
Vector Cypher Retriever는 관계 집합을 (Node)-[RELATION]->(Node) 형식으로 반환해서 엔티티 그래프를 텍스트화해요. 이는 데이터베이스의 다양한 부분에서 얻은 인사이트를 결합해서 여러 청크와 잠재적으로 여러 문서를 연결하죠. 개별 텍스트 덩어리를 보는 대신 엔티티 간의 관계를 통해 더 광범위하고 상호 연결된 정보를 공개할 수 있어서 나중에 더 복잡한 쿼리에 답할 수 있게 돼요. 관계의 명시적인 특성은 사실이 어떻게 도출되는지 정확하게 볼 수 있게 해주므로 설명 가능성을 높여줘요. 위에서 다룬 Knowledge Graph 구성을 조정해서 사용 사례에 더 잘 맞도록 이러한 관계의 품질을 반복할 수도 있고요.
다음 섹션에서는 다양한 검색기가 어떻게 작동하는지 확인하기 위해 호출할 수 있는 GraphRAG 객체를 만들어 볼 거예요.
3. GraphRAG 인스턴스화 및 실행
GraphRAG Python 패키지를 사용하면 GraphRAG 파이프라인을 쉽게 인스턴스화하고 실행할 수 있어요. 전용 GraphRAG 클래스를 사용할 수 있는데, 최소한 생성자에 LLM과 Retriever를 전달해야 해요. 선택적으로 사용자 정의 Prompt Template도 넣을 수 있죠. 여기서는 LLM이 데이터 소스의 정보를 잘 따르도록 좀 더 자세한 지침을 제공하기 위해 그렇게 할 거예요.
아래에서는 벡터 및 벡터 Cypher 검색기 모두에 대한 GraphRAG 객체를 만들 거예요.
from neo4j_graphrag.llm import OpenAILLM as LLM
from neo4j_graphrag.generation import RagTemplate
from neo4j_graphrag.generation.graphrag import GraphRAG
llm = LLM(model_name="gpt-4o", model_params={"temperature": 0.0})
rag_template = RagTemplate(template='''Answer the Question using the following Context. Only respond with information mentioned in the Context. Do not inject any speculative information not mentioned.
# Question:
{query_text}
# Context:
{context}
# Answer:
''', expected_inputs=['query_text', 'context'])
v_rag = GraphRAG(llm=llm, retriever=vector_retriever, prompt_template=rag_template)
vc_rag = GraphRAG(llm=llm, retriever=vc_retriever, prompt_template=rag_template)
이제 간단한 질문을 던져보고 다양한 Knowledge Graph 검색 패턴이 어떻게 비교되는지 확인해 볼까요?
q = "How is precision medicine applied to Lupus? provide in list format."
print(f"Vector Response: n{v_rag.search(q, retriever_config={'top_k':5}).answer}")
print("n===========================n")
print(f"Vector + Cypher Response: n{vc_rag.search(q, retriever_config={'top_k':5}).answer}")
벡터 RAG 응답
벡터 + Cypher RAG 응답
루푸스의 정밀의학은 유전적, 후생적 특이성에 기반한 맞춤형 접근 방식을 사용해요.
루푸스 환자를 최적으로 평가하고 진단 시 질병 경과 및 치료 반응을 예측하는 것을 목표로 하죠.
초기 평가에서는 바이오마커를 통해 주요 병태생리학적 경로를 평가하여 환자의 질병을 프로파일링해요.
루푸스의 정밀의학은 유전적 및 후생적 특이점을 기반으로 각 환자에 대한 맞춤형 접근 방식을 사용해요.
루푸스 환자를 최적으로 평가하고, 질병 경과 및 진단 시 치료 반응을 예측하는 것을 목표로 해요.
이상적으로 모든 환자는 바이오마커를 통해 주요 병리생리학적 경로를 평가하여 질병의 프로필을 작성하기 위한 초기 평가를 받게 돼요.
이와 같은 간단한 질문에 대한 답변은 다양한 Knowledge Graph 벡터 검색 접근 방식 간에 비슷할 수 있어요. 두 답변 모두 유사한 정보를 포함하고 있다는 걸 알 수 있죠. 다른 간단한 질문에 대해서는 응답이 약간 더 일반적이거나 더 광범위한 반면, 벡터 + Cypher 응답은 의학 연구를 위해 특별히 구성된 Knowledge Graph의 도메인/엔티티 부분을 가져오기 때문에 좀 더 도메인 특정적이거나 기술적이에요 (엔티티 추출 프롬프트 및 스키마를 다시 살펴보면 알 수 있어요).
물론 검색 방법을 조정하고 결합해서 이러한 응답을 더욱 향상시킬 수 있어요. 이건 단지 시작의 예일 뿐이에요. 여러 텍스트 덩어리에서 정보를 가져와야 하는 좀 더 복잡한 질문을 해볼게요.
q = "Can you summarize systemic lupus erythematosus (SLE)? including common effects, biomarkers, and treatments? Provide in detailed list format."
v_rag_result = v_rag.search(q, retriever_config={'top_k': 5}, return_context=True)
vc_rag_result = vc_rag.search(q, retriever_config={'top_k': 5}, return_context=True)
print(f"Vector Response: n{v_rag_result.answer}")
print("n===========================n")
print(f"Vector + Cypher Response: n{vc_rag_result.answer}")
산출:
벡터 RAG 응답
벡터 + Cypher RAG 응답
전신 홍반 루푸스 (Systemic Lupus Erythematosus, SLE) 개요:
SLE는 면역 체계의 비정상적인 활동을 특징으로 하는 전신 자가면역 질환이에요.
다양한 임상 증상을 나타내며 다양한 장기에 손상을 줄 수 있죠.
일반적인 효과:
SLE는 환자의 삶에 상당한 부담을 주며 HRQoL(건강 관련 삶의 질)에 영향을 미쳐요.
질병 활동 통제에 대한 의사의 초점과 삶의 질에 영향을 미치는 증상에 대한 환자의 초점 사이에는 차이가 있대요.
바이오마커:
SLE 진단 및 모니터링에는 다양한 기관의 면역 반응성과 염증을 반영하는 실험실 바이오마커가 포함돼요.
일반적인 바이오마커는 장기 특이적 손상 여부에 관계없이 질병 활동을 진단하고 모니터링하는 데 사용된대요.
'오믹스(omics)' 연구를 통해 새로운 바이오마커가 발견되었대요.
치료:
의사는 피해 발생을 방지하기 위해 질병 활동을 통제하는 것을 목표로 해요.
치료 접근법에는 임상 증상과 환자의 삶의 질에 미치는 영향을 모두 다루는 것이 포함된대요.
전신홍반루푸스(SLE) 요약:일반적인 효과:
다양한 증상을 보이는 복잡한 임상상
다양한 심각도와 예측할 수 없는 재발 및 완화 과정
만성 전신 염증
증상으로는 신장염, 관절염, 혈관염, 피로, 광범위한 신체 통증, 우울증, 불안, 인지 기능 장애, 수면 장애, 말라 발진, 미만성 탈모증, 근육통, 발열, 발진, 피부 혈관염, 신장 문제, 흉막염, 심낭염, 혈소판 감소증 및 용혈성 빈혈이 있어요.
바이오마커:
항핵항체(ANA)
항dsDNA 항체
항Sm 항체
항뉴클레오솜 항체(ANuA)
항-C1q 항체
높은 ESR 값과 낮은 CRP 수준
단백뇨, 뇨 원주, 망상적혈구증가증을 동반한 용혈성 빈혈, 백혈구 수
항인지질항체, 항카디오리핀, 루푸스항응고제
기능 장애가 있는 고밀도 지질단백질
IFI44L 메틸화 수준
치료:
항말라리아제
글루코코르티코이드 치료 (예: Prednisone)
면역억제제(IS)
아니프루맙
아타시셉트
수술, 물리치료, 비처방약, 스포츠, 가족 및 동료 지원, 식이요법, 심리적 측면, 운동을 포함한 다학제적 접근
관리 전략:
완화 또는 낮은 질병 활성도를 목표로 하는 치료 목표 전략
SLE 질병 활동 지수(SLEDAI)를 사용하여 질병 활동 모니터링
건강 관련 삶의 질(HRQoL)을 평가하기 위한 환자 보고 결과(PRO)
환자-의사 의사소통 격차 해소
메모: SLE는 치료할 수 없지만 증상을 조절할 수 있고 진행을 지연시킬 수 있대요.
이러한 답변은 더 중요한 차이를 보여주는데요. 그만큼Vector + Cypher 응답은 특히 바이오마커와 치료에 대해 더 자세하고 구체적이어서, 해당 주제에 대한 깊이를 추구하는 전문가에게 더 유용할 거예요. Vector 응답은 합리적으로 잘 구조화되어 있고 일반적인 효과에 대한 좋은 개요를 제공하지만, 기술적인 세부 사항이 완벽하지는 않아요. 문서에는 도메인별 관련 정보가 많이 포함되어 있지 않거든요.
이 경우 Vector + Cypher 응답은 여러 문서와 텍스트 청크의 정보를 연결하는 Knowledge Graph의 entities와 relationships를 사용하므로, 여러 소스의 정보를 요구하는 질문에 더 효과적이에요.
반환된 context를 비교하면 Vector 전용 검색기가 특정 단어 "biomarker"를 포함하는 시스템적으로 유사한 텍스트 덩어리를 반환했다는 것을 알 수 있어요. 하지만 특정 바이오마커와 같은 특정 기술적 세부 정보는 포함되어 있지 않죠.
for i in v_rag_result.retriever_result.items: print(json.dumps(eval(i.content), indent=1))
#output
{
"text": "ld be noted that nreproducibility and reliability may be affected by laboratory errors, specific techniques, nor changes in storage [13]. Because SLE can cause damage to various organs, has a complex pathogenesis, and displays heterogeneous clinical manifestations, one nparticular biomarker may only reflect one specific aspect of SLE but not be useful for nreflecting the state of the disease as a whole [14,15]. n nFigure 1. Common biomarkers for SLE and their measur ement sites in patients with "
}
{
"text": "agnosed and classified based on a patientu2019s clinical symptoms, signs, and nlaboratory biomarkers that reflect immune reactivity and inflammation in various norgans. It is necessary to develop consistent cl assification criteria of SLE for research and nclinical diagnosis. The most widely used classification criteria for SLE was established by the American College of Rheumatology (ACR) and contains laboratory biomarkers, nFigure 1. Common biomarkers for SLE and their measurement sites in patient"
}
{
"text": "s nElena Elefantea, Alain Cornetb, Jeanette Andersenb, Amy Somersb, Marta Moscaa,* naRheumatology Unit, Department of Clinical and Experimental Medicine, Azienda Ospedaliero-Universitaria Pisana, Italy nbLupus Europe, Brussels, Belgium nARTICLE INFO nKeywords: nSystemic Lupus Erythematosus nPatient-reported outcomes nPatient-clinician communication gap nHealth-related quality of life ABSTRACT nSystemic Lupus Erythematosus (SLE) imposes a great burden on the lives of patients. Patients u2019 and "
}
{
"text": "immunological biomarkers that could diagnose and monitor disease activity in SLE, with andnwithout organ-speciufb01c injury. In addition, novel SLE biomarkers that have been discovered throughnu201comicsu201d research are also reviewed.nKeywords: systemic lupus erythematosus; biomarkers; diagnosis; monitoring; omicsn1. IntroductionnSystemic lupus erythematosus (SLE) is a systemic autoimmune disease characterizednby aberrant activity of the immune system [ 1] and presents with a wide range of clinicalnmanife"
}
{
"text": "nSystemic Lupus Erythematosus (SLE) imposes a great burden on the lives of patients. Patients u2019 and nphysicians u2019 concerns about the disease diverge considerably. Physicians focus on controlling ndisease activity to prevent damage accrual, while patients focus on symptoms that impact on nHealth-Related Quality of Life (HRQoL). We explored the physicians u2019 and patients u2019 perspective nand the potential role of Patient Reported Outcomes (PROs). Physicians are aware of the theo-nretical usefulness o"
}
반면에, 반환된 컨텍스트에서 바이오마커를 검색하면 Vector + Cypher를 통해 도메인별 컨텍스트를 다루는 관계를 볼 수 있을 거예요. 다음은 출력의 샘플입니다.
vc_ls = vc_rag_result.retriever_result.items[0].content.split('\n---\n')
for i in vc_ls:
if "biomarker" in i: print(i)
#output (sample)
…
IP-10 - BIOMARKER_FOR(IP-10 is a biomarker for SLE) -> SLE
…
ANA - BIOMARKER_FOR(ANA is highly characteristic of SLE and can be used as a biomarker.) -> SLE
anti-Sm antibodies - BIOMARKER_FOR(Presence of anti-Sm antibodies serves as a biomarker for SLE classification) -> SLE
…
dysfunctional high-density lipoprotein - BIOMARKER_FOR(dysfunctional high-density lipoprotein is a key biomarker for SLE patients with CVD) -> SLE
Anti-dsDNA antibodies - ASSOCIATED_WITH(Anti-dsDNA antibodies are biomarkers associated with SLE.) -> SLE
…
치료법에 대해서도 똑같이 해보면 비슷한 패턴을 확인할 수 있어요.
궁극적으로 GraphRAG Python 패키지는 조정, 결합 및 사용자 정의할 수 있는 데이터 검색 방법과 여러 가지 다른 데이터 검색 방법을 제공해요. GenAI 애플리케이션에서 GraphRAG 파이프라인을 설계하기 위한 다양한 옵션이 있는 거죠.
초보자를 위한 GraphRAG
연결된 데이터를 기반으로 복잡한 질문에 답할 수 있는 GraphRAG 애플리케이션을 구축해 보세요. 세 가지 주요 검색 패턴을 알아볼까요?
GraphRAG 경험을 단순화하는 리소스
GraphRAG Python 패키지를 사용하면 문서에서 Knowledge Graph 생성 및 검색으로 전환하는 것이 훨씬 쉬워져요. Neo4j 전문가가 될 필요도 없고 많은 코드를 작성할 필요도 없죠. 또한 일반적인 GraphRAG 패턴을 특징으로 하고 개발 경험을 단순화하는 데 도움이 되는 가이드와 클래스를 준비했어요. 다음 리소스를 꼭 확인해 보세요.
이전 블로그에서는 4줄의 코드로 구성된 GenAI 기반 노래 찾기를 통해, 벡터 검색을 사용해서 노래 설명을 기반으로 노래를 찾았어요. 우리는 단순히 문서를 찾기 위해 Vector Embedding을 사용했지만, Retrieval-Augmented Generation(RAG)을 사용하면 검색 결과를 챗봇(예: ChatGPT)에 대한 컨텍스트로 활용해서 근거 있는 답변을 제공함으로써 환각을 피할 수 있고, 소스 참조를 제공하며, 챗봇이 모르는 것에 대해 질문할 수도 있죠.
표준 RAG에서는 벡터 검색을 사용해서 데이터 소스에서 관련 문서를 찾아요. 그런 다음 이를 챗봇에 제공해서 해당 문서의 내용을 기반으로 질문에 대한 답변을 요청하는 거죠.
GraphRAG를 사용하면 벡터 검색을 사용해서 문서를 찾을 수도 있지만, Knowledge Graph의 기능을 사용해서 이를 확장하고 제공할 더 관련성 높은 문서를 찾을 수 있어요.
영화 그래프
이를 입증하기 위해 2024년 2월 현재 영화, TV 시리즈, 비디오 게임 등의 그래프와 해당 작업에 종사하는 사람들을 구축했어요. 그래프에는 약 천만 개의 타이틀과 약 1,300만 명의 사람들이 포함되어 있고, 약 1억 6백만 개의 Relationships가 있죠. 그 중 약 130만 권에 시놉시스가 첨부되어 있어요. 이 그래프의 데이터 모델은 다음 이미지와 같아요.
그래프는 IMDB(인터넷 영화 데이터베이스) 및 TMDB(영화 데이터베이스)의 비상업적 공개 데이터 세트를 사용해서 생성되었어요. 데이터는 2024년 2월 22일에 가져왔고요.
이전 블로그 게시물과 마찬가지로 이번에는 제목의 시놉시스 속성에 대해 벡터 Index와 Vector Embedding을 수행할 거예요. Index 생성부터 시작해 볼까요?
CREATE VECTOR INDEX synopsis_embeddings IF NOT EXISTS
FOR (t:Title) ON (t.embedding)
OPTIONS {
indexConfig: {
`vector.dimensions`: 1536,
`vector.similarity_function`: 'cosine'
}
}
이제 임베딩을 수행할게요. 음악 블로그에서는 단순히 모든 속성을 일괄 임베딩에 제공할 수 있지만, OpenAI는 일괄 처리에서 2,048개의 속성만 지원하고 우리는 130만 개의 속성을 가지고 있잖아요. 그래서 0이 반환될 때까지 이 쿼리를 실행하는 스크립트를 만들었어요.
MATCH (title:Title)
WHERE title.synopsis IS NOT NULL AND title.embedding IS NULL
WITH title LIMIT 2048
WITH collect(title.synopsis) AS synopsis, collect(title) AS titles
CALL genai.vector.encodeBatch(synopsis, "OpenAI", {token: $apiKey}) YIELD index, resource, vector
CALL db.create.setNodeVectorProperty(titles[index], "embedding", vector)
RETURN COUNT(index) AS embedded
위의 쿼리와 이후의 모든 쿼리에는 매개변수로 설정할 수 있는 OpenAI의 API 키가 필요해요.
:params
{
apiKey: "*****"
}
질문
음악 블로그에서는 설명을 바탕으로 한 곡을 검색하기 위해 벡터 검색을 활용했죠. 하지만 이 경우에는 ChatGPT가 영화 데이터베이스의 시놉시스를 기반으로 답변하기를 원하는 질문을 표현하고, 답변을 찾은 위치에 대한 참조도 제공하려고 해요. 그래서 우리가 대답하고 싶은 질문은 다음과 같아요.
Robb Stark는 어떤 가족과 전쟁을 시작하나요?
우리 대부분은 이것이 왕좌의 게임에서 나온 것이라는 것을 알고 있다고 생각하지만, 우리가 모른다고 가정해 봅시다. 우리는 이 질문에 대한 답을 원해요. ChatGPT에는 130만 개의 시놉시스를 제공할 수 없으니까, 이 질문에 대한 답을 찾을 가능성이 가장 높은 곳을 찾아야겠죠.
질문을 매개변수로 설정하는 것부터 시작해 볼게요.
:params
{
question: "With what family does Robb Stark start a war?",
apiKey: "*****"
}
이제 음악 블로그에서 했던 것처럼 벡터 검색을 수행해 볼게요.
WITH genai.vector.encode($question, "OpenAI", {token: $apiKey}) AS embedding
CALL db.index.vector.queryNodes('synopsis_embeddings', 1, embedding) YIELD node AS title, score
RETURN title
이것은 우리에게 "The Watchers on the Wall" from 왕좌의 게임 시즌 4, 에피소드 9를 제공하네요. 130만 개의 타이틀 중에서 올바른 TV 시리즈를 찾았다는 게 정말 인상적이고, 1초도 안 돼서 찾아냈다는 점도 놀라워요. 하지만 이 에피소드의 개요는 ChatGPT가 다음 요청에 대한 답변을 찾는 데 도움이 되지 않아요.
Jon Snow와 Night's Watch는 큰 도전에 직면합니다.
여기서 우리는 Knowledge Graph의 힘을 활용할 거예요. Vector Search에서 제목을 반환할 뿐만 아니라, 제목이 TV 시리즈인 경우 모든 에피소드도 포함하고, 에피소드인 경우(이 경우처럼) 시리즈와 다른 모든 에피소드를 포함하도록 쿼리를 확장하죠.
WITH question, genai.vector.encode($question, "OpenAI", {token: $apiKey}) AS embedding
CALL db.index.vector.queryNodes('synopsis_embeddings', 1, embedding) YIELD node AS title, score
OPTIONAL MATCH (title)-[:EPISODE_OF]->(series:Title)
OPTIONAL MATCH (title)<-[:EPISODE_OF]-(other1:Title)
OPTIONAL MATCH (series)<-[:EPISODE_OF]-(other2:Title)
WITH collect(title)+collect(series)+collect(other1)+collect(other2) AS allTitles
UNWIND allTitles AS titles
RETURN DISTINCT titles
이는 다음과 같은 결과를 제공해줘요.
왕좌의 게임 및 모든 에피소드
RAG
이제 실제 RAG 부분이 나오는데요. 여기서는 모든 개요를 수집하고 ChatGPT에 이를 기반으로 질문에 대한 답변을 요청할 거예요. 이를 위해서는 OpenAI에 REST 호출을 수행해야 하죠. 이는 (현재) Neo4j에 내장된 절차가 아니므로 자체 애플리케이션에서 수행해야 하거나 Neo4j의 자체 인스턴스를 호스팅하고 APOC Extended를 실행할 수 있는 경우 거기에서 절차를 사용할 수 있어요. 저는 후자를 선택할 거예요.
ChatGPT에 물어볼 질문은 다음과 같아요.
Answer the following Question based on the Context only and provide a reference to where in the context you found it.
Only answer from the Context.
If you don't know the answer, say 'I don't know'.
The context is a list of titles followed by a synopsis, separated by colon.
Context: [All titles and synopsises separated by colon]
Question: [Our original question]
다음은 APOC 확장 프로시저를 통해 해당 질문이 처리되는 전체 Cypher 쿼리의 모습이에요.
WITH question, genai.vector.encode($question, "OpenAI", {token: $apiKey}) AS embedding
CALL db.index.vector.queryNodes('synopsis_embeddings', 1, embedding) YIELD node AS title, score
OPTIONAL MATCH (title)-[:EPISODE_OF]->(series:Title)
OPTIONAL MATCH (title)<-[:EPISODE_OF]-(other1:Title)
OPTIONAL MATCH (series)<-[:EPISODE_OF]-(other2:Title)
WITH collect(title.primaryTitle + ":" + title.synopsis)+collect(series.primaryTitle + ":" + series.synopsis)+collect(other1.primaryTitle + ":" + other1.synopsis)+collect(other2.primaryTitle + ":" + other2.synopsis) AS allTitles
UNWIND allTitles AS titles
WITH DISTINCT titles
WITH apoc.text.join(collect(titles), "n") AS context
CALL apoc.ml.openai.chat([
{role:"user", content:"Answer the following Question based on the Context only and provide a reference to where in the context you found it. Only answer from the Context. If you don't know the answer, say 'I don't know'. The context is a list of titles followed by a synopsis, separated by colon.nnContext: " + context + "nnQuestion: " + $question}
], $apiKey) yield value
RETURN value.choices[0].message.content AS Title
우리가 돌려받는 대답은 The Lannisters이에요. "북쪽은 기억합니다: Robb Stark와 그의 북부 군대가 Lannisters와의 전쟁을 계속하면서..." — 환각이 없으며 출처 참조가 제공되죠.
다음 레벨
제가 이것을 동료에게 보여주었을 때 그는 "멋지네요. 하지만 ChatGPT는 Game of Thrones에 대해 알고 있고 어쨌든 답변을 제공할 수 있었을 거예요. ChatGPT가 교육을 받았을 때 존재하지 않았던 타이틀로 어떻게 작동할 수 있었겠어요?"라고 말했어요.
당시 ChatGPT는 2023년 4월에 마지막 학습을 했어요. 그래서 2023년 4월부터 2024년 2월 사이에 출시된 것을 제가 본 적이 있는 것을 찾아서 이에 대한 질문을 할 수 있었죠. 제가 생각한 것은 영화 아가일이었어요. 제가 생각해낸 질문은 다음과 같아요.
엘리 콘웨이의 고양이 이름은 무엇인가요?
우선 RAG 없이 평범한 Prompt로 ChatGPT에 문의했더니 돌아온 대답은 "엘리 콘웨이의 고양이 이름은 루시입니다. 엘리 콘웨이는 'Big Little Lies', 'Nine Perfect Strangers' 등의 작품으로 유명한 호주 작가 Liane Moriarty의 가명입니다. Lucy는 작가와 관련된 인터뷰와 소셜 미디어 게시물에서 자주 언급됩니다." 였어요.
여기서 우리는 환각에 걸린 것 같아요. ChatGPT는 영화가 늦게 개봉해서 몰랐을 뿐만 아니라, “모른다”는 대신 거짓 답변을 내놓았어요. Elly Conway라는 가명을 사용하는 Liane Moriarty에 대한 정보는 전혀 찾을 수 없죠.
하지만 위에서 사용했던 것과 똑같은 RAG 쿼리를 실행하면, 이렇게 완벽하게 정확한 답변을 얻을 수 있어요. "Alfie (맥락: 은둔 작가 Elly Conway의 가상 스파이 소설 줄거리가 실제 스파이 조직의 은밀한 행동을 반영하기 시작하면서, 집에서 조용한 저녁 시간은 과거의 일이 됩니다. 그녀의 고양이 Alfie와 고양이 알레르기가 있는 스파이 Aiden과 함께…)."
짜잔! 거의 순수한 Cypher로 GraphRAG를 구현했어요.
추가 자료
앞서 말씀드렸듯이, Neo4j는 GraphRAG 애플리케이션을 더 쉽게 만들 수 있도록 다양한 AI 기술 스택과 통합되어 있어요. 관련해서 더 자세한 내용을 다루는 글들을 소개해 드릴게요.
LLM Knowledge Graph Builder: 5분 만에 0에서 GraphRAG까지
GenAI 생태계 – Neo4j Labs
GraphRAG
RAG
에이치시스템즈의 LogTree는 Neo4j 기반 GraphRAG 플랫폼으로, 데이터를 자동으로 지식그래프화하고 자연어 질의로 즉시 답을 제공합니다.