그래프 검색 기반 생성 (Graph RAG)은 생성형 AI 애플리케이션이 도메인별 지식과 관련 정보를 활용할 수 있도록 하는 강력한 기법으로 부상하고 있습니다. 그래프 RAG는 벡터 데이터베이스를 사용하는 벡터 검색 방법의 대안입니다.
지식 그래프는 Neo4j 또는 Amazon Neptune과 같은 그래프 데이터베이스가 구조화된 데이터를 나타낼 수 있는 지식 시스템입니다. 지식 그래프에서는 데이터 포인트 간의 관계(엣지)가 데이터 포인트(버텍스 또는 노드라고도 함) 사이의 연결만큼이나 의미가 있습니다. 지식 그래프는 네트워크를 쉽게 탐색하고 연결된 데이터에 대한 복잡한 쿼리를 처리할 수 있게 해줍니다. 지식 그래프는 챗봇, ID 확인, 네트워크 분석, 추천 엔진, 고객 360도 및 사기 탐지와 관련된 사용 사례에 특히 적합합니다.
Graph RAG 방식은 그래프 데이터베이스의 구조적 특성을 활용하여, 네트워크나 복잡한 관계에 대한 검색 정보에 더 깊이 있는 통찰과 컨텍스트를 제공합니다. 그래프 데이터베이스가 대규모 언어 모델(LLM) 과 결합되면 개발자는 텍스트와 같은 비정형 데이터로부터 그래프 생성 프로세스의 상당 부분을 자동화할 수 있습니다. LLM은 텍스트 데이터를 처리하여 엔터티를 식별하고, 이들 간의 관계를 파악한 후 그래프 구조로 나타낼 수 있습니다.
Graph RAG 애플리케이션을 만드는 방법에는 Microsoft의 GraphRAG나 GPT-4와 LlamaIndex를 결합하는 등 여러 가지가 있습니다. 이 튜토리얼에서는 오픈 소스 그래프 데이터베이스인 Memgraph를 사용하여 watsonx에서 Meta의 Llama-3을 이용해 RAG 시스템을 구축합니다. Memgraph는 선언형 쿼리 언어인 Cypher를 사용합니다. Cypher는 SQL과 유사점이 있으나, 테이블과 행이 아닌 노드와 관계에 초점을 맞춥니다. Llama 3을 활용하여 비정형 텍스트로부터 그래프 데이터베이스를 생성하고 채우며, 데이터베이스 내 정보를 쿼리합니다.
여러 툴 중에서 선택할 수 있지만, 이 튜토리얼에서는 Jupyter Notebook을 사용하기 위해 IBM 계정을 설정하는 방법을 안내합니다.
IBM® Cloud 계정을 사용하여 watsonx.ai에 로그인합니다.
watsonx.ai 프로젝트를 생성합니다.
프로젝트 내에서 프로젝트 ID를 가져올 수 있습니다. 관리 탭을 클릭합니다. 그런 다음 일반 페이지의 세부 정보 섹션에서 프로젝트 ID를 복사합니다. 해당 튜토리얼에서는 이 프로젝트 ID가 필요합니다.
다음으로 프로젝트를 watsonx.ai Runtime과 연결합니다.
watsonx.ai Runtime 서비스 인스턴스를 만듭니다(무료 인스턴스인 Lite 요금제 선택).
b. watsonx.ai Runtime에서 API 키를 생성합니다. 이 튜토리얼에서 사용할 수 있도록 이 API 키를 저장하세요.
c. 프로젝트로 이동하여 관리 탭을 선택합니다.
d. 왼쪽 탭에서 서비스 및 통합을 선택합니다.
e. IBM 서비스를 선택합니다.
f. 서비스 연결을 선택하고 watsonx.ai Runtime을 선택하세요.
g. watsonx.ai에서 생성한 프로젝트에 watsonx.ai Runtime을 연결하세요.
이제 Docker를 설치해야 합니다.
Docker를 설치한 후에는 Docker 컨테이너를 사용하여 Memgraph를 설치합니다. OSX 또는 Linux에서는 터미널에서 다음 명령을 사용할 수 있습니다.
Windows 컴퓨터에서는 다음을 사용합니다.
설치 단계에 따라 Memgraph 엔진과 Memgraph 랩을 설치하고 실행합니다.
이 프로젝트를 위해 컴퓨터에서 새로운 가상 환경을 생성하세요.
노트북의 Python 환경에서 다음 Python 라이브러리를 설치합니다.
이제 Memgraph에 연결할 준비가 되었습니다.
Memgraph에서 사용자 이름과 비밀번호를 사용하도록 구성했다면 여기에서 해당 값을 입력하세요. 그렇지 않으면 둘 다 입력하지 않는 기본값을 사용할 수 있습니다. 운영 환경에서는 권장되지 않지만, 민감한 데이터를 저장하지 않는 로컬 개발 환경에서는 문제가 되지 않습니다.
이제 LLM 시스템의 그래프 생성 기능을 테스트하기 위해 관계 데이터 세트를 설명하는 샘플 문자열을 생성합니다. 더 복잡한 데이터 소스를 사용할 수도 있지만 이 간단한 예제가 알고리즘 시연에는 적합합니다.
첫 번째 단계에서 생성한 watsonx API 키를 입력하세요.
이제 텍스트를 생성하도록 WatsonxLLM 인스턴스를 구성합니다. temperature는 비교적 낮게 설정하고 토큰 수는 높게 지정해야 합니다. 이렇게 하면 모델이 실제로 존재하지 않는 엔터티나 관계를 환각 없이 가능한 한 많은 세부 정보를 생성할 수 있습니다.
LLMGraphTransformer를 사용하면 LLM에서 생성할 노드와 관계의 유형을 직접 지정할 수 있습니다. 사용자의 예시에서는 텍스트가 한 회사의 직원, 그들이 속한 그룹, 직함을 설명하고 있습니다. LLM이 이러한 엔터티로만 제한되도록 설정하면 그래프 내에서 지식을 더 정확하게 표현할 수 있습니다.
convert_to_graph_documents를 호출하면 LLMGraphTransformer가 텍스트로부터 지식 그래프를 생성합니다. 이 단계에서는 관련 컨텍스트와 엔터티를 표현하기 위해 해당 정보를 그래프 데이터베이스에 삽입할 Neo4j 쿼리 구문이 생성됩니다.
이제 Memgraph 데이터베이스의 기존 데이터를 모두 삭제하고 새로운 노드와 엣지를 삽입합니다.
생성된 Cypher 구문은 graph_documents 객체에 저장되며 문자열로 출력해 내용을 확인할 수 있습니다.
Cypher로 생성된 스키마와 데이터 유형은 그래프 'get_schema' 속성에서 확인할 수 있습니다.
다음과 같이 출력됩니다.
Memgraph Labs 뷰어에서도 그래프 구조를 확인할 수 있습니다.
LLM은 올바른 노드와 관계를 적절히 생성하는 데 성공했습니다. 이제 생성된 지식 그래프에 쿼리를 수행할 단계입니다.
LLM을 올바르게 프롬프트하려면 프롬프트 엔지니어링이 필요합니다. LangChain은 프롬프트에 여러 예시를 제공할 수 있는 FewShotPromptTemplate을 지원하여 LLM이 올바르고 간결한 Cypher 구문을 생성하도록 돕습니다. 다음 코드는 LLM이 사용해야 하는 질문 및 쿼리의 몇 가지 예를 제공합니다. 또한 모델의 아웃풋을 쿼리로만 제한하는 방법도 보여줍니다. 지나치게 대화형으로 응답하는 LLM은 불필요한 정보를 추가해 잘못된 Cypher 쿼리를 만들 수 있으므로 프롬프트 템플릿은 모델이 오직 쿼리만 출력하도록 지시합니다.
지시적인 접두어를 추가하면 모델의 동작을 제약하고, LLM이 올바른 Cypher 구문을 출력할 가능성을 높일 수 있습니다.
다음으로, Memgraph에서 반환된 정보로 LLM이 질문에 답하는 방법을 제어하는 프롬프트를 생성합니다. LLM이 그래프 데이터베이스에서 컨텍스트 정보를 가져온 후 응답하는 방법에 대한 몇 가지 예제와 지침을 제공합니다.
이제 질문 답변 체인을 만들 차례입니다. MemgraphQAChain을 통해 사용할 LLM, 적용할 그래프 스키마, 그리고 디버깅 관련 정보를 지정할 수 있습니다. temperature를 0으로 설정하고 length penalty를 적용하면 LLM이 Cypher 프롬프트를 간결하고 명확하게 유지하도록 유도할 수 있습니다.
이제 자연어 질문으로 체인을 실행할 수 있습니다. LLM은 완전히 결정론적으로 동작하지 않기 때문에 응답 결과는 다소 달라질 수 있습니다.
그러면 다음이 출력됩니다.
> Entering new MemgraphQAChain chain...
Generated Cypher:
MATCH (p:Person {id: 'John'})-[:TITLE]->(t:Title) RETURN t.id
Full Context:
[{'t.id': 'Director of the Digital Marketing Group'}]
> Finished chain.
{'query': 'What is Johns title?',
'result': ' \nAnswer: Director of the Digital Marketing Group.',
'intermediate_steps': [{'query': " MATCH (p:Person {id: 'John'})-[:TITLE]->(t:Title) RETURN t.id"},
{'context': [{'t.id': 'Director of the Digital Marketing Group'}]}]}
다음 질문에서는 체인에 조금 더 복잡한 질문을 합니다.
그러면 다음이 반환됩니다.
정답은 응답에 포함되어 있습니다. 경우에 따라 최종 사용자에게 답변을 반환하기 전에 제거하고 싶은 추가 텍스트가 있을 수 있습니다.
Memgraph 체인에 Group 관계에 대해 질문할 수 있습니다.
그러면 다음이 반환됩니다.
이것이 올바른 답변입니다.
마지막으로, 체인에 두 개의 결과를 반환하는 질문을 합니다.
그러면 다음과 같은 출력이 반환됩니다.
체인이 두 협력자를 모두 올바르게 식별합니다.
이 튜토리얼에서는 Memgraph와 watsonx를 활용하여 그래프 데이터 구조를 생성하고 쿼리하는 Graph RAG 애플리케이션을 구축했습니다. watsonx를 통한 LLM을 사용하여 자연어 소스 텍스트에서 노드 및 엣지 정보를 추출하고, 그래프 데이터베이스를 채우기 위한 Cypher 쿼리 구문을 생성했습니다. 그런 다음 watsonx를 사용하여 해당 소스 텍스트에 대한 자연어 질문을 Cypher 쿼리로 변환했습니다. 이 쿼리를 통해 그래프 데이터베이스에서 정보를 추출했습니다. 프롬프트 엔지니어링 기법을 통해 LLM이 Memgraph 데이터베이스의 결과를 자연어 응답으로 변환했습니다.