728x90
반응형
오늘은 2014년 8월 4일이에요. 대부분의 사람들에게는 별 의미 없는 날짜일 수 있지만, 유럽, 특히 독일, 벨기에, 영국, 프랑스, 그리고 중부/서부 유럽 국가 출신이라면 더욱 그렇죠. 전 세계적으로도 꽤 의미 있는 날일 텐데요. 왜냐하면 바로 이 해가 제1차 세계대전 발발 100주년이거든요. 독일이 벨기에를 침공하며 중립을 위반했고, 영국은 독일에 전쟁을 선포했죠. 제1차 세계대전 말이에요.
저는 전쟁을 겪어본 적이 없어요. 지난 40년간 앤트워프, 벨기에에서 아주 편안하고 안전한 삶을 살았죠. 하지만 가끔씩 Westvleteren의 성 식스투스 수도원에 가서 맥주도 마시고, 플랜더스 들판을 지나갈 뻔하기도 했어요.
네, 맞아요. 양귀비 추모 상징 말이에요. 적어도 오늘은 그렇죠. 사실 꽤 많은 의미가 담겨 있죠.
이런 전쟁 기념물들은 정말 감동적인 평화주의의 상징이기도 해요. 아이들을 데리고 타인 코트에 방문한 적이 있는데, 기억해야 할 날이었어요. 2만 개의 무덤을 보는 건 정말 잊을 수 없는 경험이죠.
올봄에는 아이들과 "죽음의 참호"에도 갔었고, Diksmuide의 전쟁 기념 박물관인 이세르강 박물관에도 방문했었죠. 저를 바보라고 불러도 좋지만, 이번 여름에는 아이들을 플랑드르 들판에 데려가고 싶어요. 아이들이 충격을 받을 거라는 걸 알면서도 미뤄왔지만, 전쟁은 절대 좋은 것이 아니라는 걸 아이들에게 알려줘야 한다고 생각해요.
특히 요즘처럼 우크라이나 불안이나 가자 지구의 잔혹한 전쟁 같은 소식을 접할 때면, 전쟁이 우리에게서 그리 멀리 떨어져 있지 않다는 생각이 들어요. 우리는 과연 배울 수 있을까요?
그래서 이번 달 초, 인터넷을 돌아다니다가 우연히 Correlates of War 웹사이트를 발견했어요. 이 프로젝트는 1963년 미시간 대학의 정치학자인 J. David Singer가 시작했는데, 다양한 전쟁(또는 그가 "분쟁"이라고 부르는)을 구조화된 방식으로 기록해 왔다고 해요. 바로 이 웹사이트에서 WarGraph라는 것을 알게 되었죠. 로 탐색해볼 만한 멋진 데이터 세트 같지 않나요?

데이터 작업

물론 저도 공개적으로 사용할 수 있는 자료들을 찾아봤어요. 먼저 전쟁 데이터세트의 상관관계 (Correlates of War dataset)를 살펴봤죠. 가져와야 할 데이터는 여러 개가 있었는데요. 국가 (State) 데이터, 분쟁 (Dispute) 데이터, 그리고 흥미로운 '메타데이터'인 종교 (Religion) 데이터 (국가별), 재료 능력 (Material Capabilities) 데이터 (국가별) 였어요. 이 데이터를 가지고 작업을 시작하기 위해, 먼저 모든 데이터를 하나의 큰 Google 스프레드시트에 모았답니다. 요즘 제가 애용하는 도구죠.

전쟁 모델의 그래프

의미 있는 작업을 하려면 먼저 데이터의 그래프 모델을 만들어야 했어요. 제가 완성한 모델은 다음과 같아요.
이 모델에 대해 좀 더 자세히 설명해 드릴게요.
  • 국가 `Node`에는 흥미로운 메타데이터가 많이 있어요. CoW에서는 국가의 경제적, 군사적 능력에 대한 많은 데이터를 수집했는데요. 1800년대 초반부터의 연간 데이터가 있지만, 간단하게 하기 위해 2007년 데이터만 가져왔어요.
    • 군비 지출 (GBP 또는 USD)
    • 군인 수 (천 명)
    • 국가 역량 점수 종합 지수: 위의 6개 역량 구성요소 각각에 대한 모든 관측치를 합산하고, 각 주의 절대 구성요소를 국제 시스템의 점유율로 변환한 다음, 6개 구성요소에 대한 평균을 계산하여 얻은 측정값이에요.
  • 모델을 좀 더 시각적으로 표현하고 정규화하기 위해, 몇 가지 메타데이터를 가져와서 다음과 같이 표현했어요.
    • 다양한 종류의 결과는 하위 그래프로 표시돼요.
    • 다양한 종류의 합의도 하위 그래프로 표시되구요.
    • 다양한 사망률 수준도 하위 그래프로 나타냈어요.
    • 분쟁 (HiAct)에서 다양한 종류의 "최고 수준의 조치"도 하위 그래프로 표현했죠.
    • '가장 높은 수준의 행동'과 관련된 다양한 종류의 적대감 수준도 하위 그래프로 표시하고 라벨을 붙였답니다.
  • 그래프에서 연도별로 작업하기 위해, 타임라인이라고도 불리는 "in-graph-index"에서 연도를 서로 연결했어요. 예전에 제 맥주 그래프에서도 비슷한 작업을 했었죠.
  • 종교 데이터도 가져왔어요. 1800년대 이후의 흥미로운 데이터가 많지만, 저는 2010년의 최신 데이터만 가져왔답니다.
다양한 데이터 요소의 의미에 대해 더 자세한 설명이 필요하다면, 언제든지 코드북 (Codebook)을 참고해 주세요. 자세한 내용을 확인할 수 있을 거예요.

WarGraph를 Neo4j로 가져오기

이제 데이터를 가져올 차례죠! 여기서는 두 가지 기술을 조합해서 사용했어요.
  • 저는 스프레드시트 방식을 사용해서 메타데이터를 가져왔어요. 작은 메타데이터 세트에 대해 굳이 CSV 파일을 준비하는 건 번거로우니까요.
  • 그리고 Google 스프레드시트에서 직접 `loadcsv`를 사용해서 실제 데이터를 가져왔답니다.
가져오기 프로세스에 대한 자세한 개요는 여기서 확인할 수 있어요. 전혀 어렵지 않아요!

WarGraph 쿼리하기

데이터가 Neo4j에 들어왔으니, Neo4j 브라우저를 사용해서 간단하게 데이터를 살펴볼 수 있어요. Cypher 쿼리를 사용하면 되죠!
이 데이터세트에서 미국 (`State`)을 찾을 수 있는지 한번 살펴볼까요?
MATCH (n:State {짧은:”미국”})-[r]-()
RETURN n,r
LIMIT 10
맞는 것 같아요. 이제 '전쟁' 관련 정보를 한번 살펴볼까요? 가장 많은 분쟁에 연루된 국가를 찾아볼게요.
MATCH (n:국가)-[r:PARTICIPATES_IN]->(d:분쟁)
RETURN n.이름, count(r)
ORDER BY count(r) DESC
LIMIT 10;

흥미롭네요! 미국과 영국이 보이네요. 하지만 독일, 프랑스, 그리고 (그때까지 존재하지 않았던 나라) 이스라엘도 있어요.

그럼, 이 데이터를 좀 더 세분화해볼 수 있겠죠? 인구 규모 대비 '1인당' 분쟁이 가장 많은 국가를 한번 살펴볼게요. 쿼리는 다음과 같아요:

MATCH (n:국가)-[r:PARTICIPATES_IN]->(d:분쟁)
WHERE n.totalpop IS NOT NULL
WITH n, count(r) AS NrOfDisputes
RETURN n.name, n.totalpop, NrOfDisputes, 1.0*NrOfDisputes/n.totalpop AS DisputesPerCapita
ORDER BY DisputesPerCapita DESC
LIMIT 10

쿼리의 "1.0*"에는 약간의 트릭이 숨어있어요. 이는 Cypher가 부동 소수점 연산을 수행하기 전에 부동 소수점 연산을 수행하도록 강제하는 것이죠. 나중에 수행하면 쿼리가 제대로 실행되지 않거든요. 이 팁을 알려준 Alistair에게 감사해요!

이제 그래프 내 연도 Index를 따라 실행해서 시간 차원을 한번 살펴볼게요. 20세기 전반의 논쟁을 알아볼까요?

MATCH (y1:연도 {이름:1900})-[:PRECEDES*..51]->(y2),
(d:분쟁)-[:STARTED_IN]->(y2)
RETURN DISTINCT d.name AS Dispute, y2.name AS StartYear

아니면 종교가 전쟁과 관련이 있는지 한번 살펴볼까요? 정말 그럴까요?
분쟁에 참여한 종교 신자가 가장 많은 상위 10개 국가는 다음과 같아요:
MATCH (n:종교)<-[r:HAS_ADHERENTS]-(c:국가)
WHERE n.name <> “비종교적”
WITH c.short AS country, r.number AS nrofadherents
ORDER BY nrofadherents DESC
LIMIT 10
WITH country
MATCH (c:국가 {짧은: country})-[:PARTICIPATES_IN]->(d:분쟁)
RETURN DISTINCT c.short, c.name, count(d);
그리고 마지막으로 몇 가지 경로를 탐색할 수 있는지 살펴볼게요. 예를 들어, 미국("USA")과 이스라엘("ISR")과 같은 두 국가 간의 링크를 살펴볼 수 있어요.
MATCH (u:국가 {짧은:”USA”}), (i:국가 {짧은:”ISR”}),
p = allShortestPaths((u)-[r*]-(i))
RETURN p;
이러한 쿼리에는 세계적으로 충격적인 데이터가 있는 건 아니지만, 그래도 가지고 놀 수 있는 매우 흥미로운 내용들이 있죠. 모든 쿼리는 여기서 요점을 확인해보세요.
평소와 마찬가지로 여러분의 의견을 환영해요. 이것이 도움이 되기를 바라면서, 우리 모두 전쟁이 아닌 그래프를 만들 수 있기를 바랍니다!

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

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

728x90
반응형
728x90
반응형

LLM 생성을 위한 텍스트 임베딩 검색의 단점 탐색

추상적인

외부 지식은 환각, 오래된 지식 등 LLM의 문제를 해결하는 열쇠이며, 이를 통해 LLM은 Retrieval-Augmented Generation(RAG)을 통해 보다 정확하고 신뢰할 수 있는 응답을 생성할 수 있어요. 하지만 LLM이 항상 예상대로 응답할 수는 없죠. 실제 사례를 분석함으로써 이 문서에서는 우려 사항의 여러 범주와 이러한 제한 사항이 나타나 LLM 생성 콘텐츠의 부정확성을 초래하는 사례를 보여줍니다.

배경

영화 그래프

Machine Learning 및 Large Language Model 초보자가 이를 쉽게 이해할 수 있도록 Neo4j에 저장된 영화 그래프를 사용하여 개념을 살펴볼게요.

아래 블로그 게시물에는 Movie Graph에 대한 더 완전한 지침과 Node 및 패턴에 대한 텍스트 임베딩을 생성하고 저장하는 방법이 나와 있어요. 주어진 질문에 대해 가장 유사한 텍스트를 검색합니다.

지식 그래프의 미래: 구조적 검색과 Semantic Search가 하나로 통합될 것인가?

경량 RAG 솔루션

다시 말하지만, LangChain 및 LlamaIndex와 같은 LLM/RAG 프레임워크의 학습 곡선을 더욱 줄이기 위해 Neo4j Graph Database Management System에서 제공하는 Cypher 및 APOC 절차만 사용하려 해요.

이전 게시물에서 RAG 애플리케이션 구축을 위한 이 경량 접근 방식에 대한 자세한 내용을 확인할 수 있습니다.

Neo4j를 사용하여 경량 RAG 애플리케이션 구축

LLM 모델

다음 테스트는 gpt-4–0613을 사용하여 수행되었는데, 가장 최근이자 가장 발전된 LLM이에요. 텍스트 임베딩 모델의 경우, 텍스트 임베딩-ada-002가 지식 내용과 질문 모두에 사용되었어요.

Query 결과의 예

모든 영화가 출연했어요(참조: 톰 행크스 영화):

╒════════════════════════╤══════════╕
│m.title                 │m.released│
╞════════════════════════╪══════════╡
│"Joe Versus the Volcano"│1990      │
├────────────────────────┼──────────┤
│"A League of Their Own" │1992      │
├────────────────────────┼──────────┤
│"Sleepless in Seattle"  │1993      │
├────────────────────────┼──────────┤
│"Apollo 13"             │1995      │
├────────────────────────┼──────────┤
│"That Thing You Do"     │1996      │
├────────────────────────┼──────────┤
│"You've Got Mail"       │1998      │
├────────────────────────┼──────────┤
│"The Green Mile"        │1999      │
├────────────────────────┼──────────┤
│"Cast Away"             │2000      │
├────────────────────────┼──────────┤
│"The Polar Express"     │2004      │
├────────────────────────┼──────────┤
│"The Da Vinci Code"     │2006      │
├────────────────────────┼──────────┤
│"Charlie Wilson's War"  │2007      │
├────────────────────────┼──────────┤
│"Cloud Atlas"           │2012      │
└────────────────────────┴──────────┘

그가 출연한 모든 영화 (이하 톰 크루즈 영화):


╒════════════════╤══════════╕
│m.title         │m.released│
╞════════════════╪══════════╡
│"Top Gun"       │1986      │
├────────────────┼──────────┤
│"A Few Good Men"│1992      │
├────────────────┼──────────┤
│"Jerry Maguire" │2000      │
└────────────────┴──────────┘

유사성이 결정되는 방식

Vector Search가 어떻게 작동하는지 알아보기 위해 간단한 질문부터 시작해 볼게요.

톰 행크스는 누구인가요?

여기는 Cypher를 사용해서 Neo4j의 vector index를 통해 텍스트 embedding 검색을 사용하여 답변을 생성하는 부분이에요. 충분한 콘텐츠를 검색하기 위해 top_k = 200을 사용해서 반환된 최상위 매칭 embeddings에 대해 검색을 수행하죠.

:param question=>'Who is Tom Hanks?';
:param top_k=>200;

// 1. Get text embedding for the question
CALL apoc.ml.openai.embedding([$question],NULL , {}) 
YIELD index, text, embedding 
// 2. Search for similar embeddings via vector index
WITH text, embedding
CALL db.index.vector.queryNodes($vector_index, $top_k, embedding) YIELD node, score
WITH node, score
RETURN $question, node.text AS context, score;

텍스트 embedding similarity search 결과는 다음과 같아요:

╒═══════════════════╤══════════════════════════════════════════════════════════════════════╤══════════════════╕
│$question          │context                                                               │score             │
╞═══════════════════╪══════════════════════════════════════════════════════════════════════╪══════════════════╡
│"Who is Tom Hanks?"│"Person  name Tom Hanks born 1956 "                                   │0.955516517162323 │
├───────────────────┼──────────────────────────────────────────────────────────────────────┼──────────────────┤
│"Who is Tom Hanks?"│"Person [Tom Hanks] ACTED_IN Movie [You've Got Mail]"                 │0.9315997362136841│
├───────────────────┼──────────────────────────────────────────────────────────────────────┼──────────────────┤
│"Who is Tom Hanks?"│"Person [Tom Hanks] ACTED_IN Movie [That Thing You Do]"               │0.9315773248672485│
├───────────────────┼──────────────────────────────────────────────────────────────────────┼──────────────────┤
│"Who is Tom Hanks?"│"Person [Tom Hanks] ACTED_IN Movie [Cast Away]"                       │0.9312677383422852│
├───────────────────┼──────────────────────────────────────────────────────────────────────┼──────────────────┤
│"Who is Tom Hanks?"│"Person [Tom Hanks] ACTED_IN Movie [Apollo 13]"                       │0.9302988052368164│
├───────────────────┼──────────────────────────────────────────────────────────────────────┼──────────────────┤
│"Who is Tom Hanks?"│"Person [Tom Hanks] DIRECTED Movie [That Thing You Do]"               │0.9302213788032532│
├───────────────────┼──────────────────────────────────────────────────────────────────────┼──────────────────┤
│"Who is Tom Hanks?"│"Person [Tom Hanks] ACTED_IN Movie [A League of Their Own]"           │0.9287475347518921│
├───────────────────┼──────────────────────────────────────────────────────────────────────┼──────────────────┤
│"Who is Tom Hanks?"│"Person [Tom Hanks] ACTED_IN Movie [The Polar Express]"               │0.9279540181159973│
├───────────────────┼──────────────────────────────────────────────────────────────────────┼──────────────────┤
... ... (192 more rows to follow) 

텍스트 삽입 검색은 Person node를 잘 찾아주는 것 같아요.

여기서 흥미로운 점은 "Person [Tom Hanks] DIRECTED Movie [That Thing You Do]" 행인데, 출연한 영화에 대한 행보다 약간 더 높은 유사성 점수를 가지고 있다는 거예요. 왜 그럴까요? 제 생각에는 사전 학습 단계에서 사용된 데이터에서 이 감독의 영화에 대한 언급이 더 많았기 때문인 것 같아요. 그렇지만 이게 답변을 크게 바꾸지는 않으니 다음으로 넘어가도록 하죠.

Tom Hanks와 관련된 모든 레코드가 나열되면, 그와 관련된 레코드(유사성 점수 > 0.91)가 나오네요. 처음 4개는 이름에 Tom이 들어가서 어느 정도 이해가 되죠.

그런데 "Person name Bill Paxton born 1955"라는 행은 톰 행크스와는 전혀 관련이 없는 것 같아서 언뜻 보기에는 조금 이상했어요. 목록을 계속 내려가다 보면 사실 <영화의 또 다른 배우>라는 것을 알 수 있어요 (Apollo 13의 공동 배우).

... ... (14 records upfront) 

│"Who is Tom Hanks?"│"Person  name Tom Cruise born 1962 "                                  │0.9114127159118652│
├───────────────────┼──────────────────────────────────────────────────────────────────────┼──────────────────┤
│"Who is Tom Hanks?"│"Person  name Tom Skerritt born 1933 "                                │0.910643458366394 │
├───────────────────┼──────────────────────────────────────────────────────────────────────┼──────────────────┤
│"Who is Tom Hanks?"│"Person  name Tom Tykwer born 1965 "                                  │0.9104374647140503│
├───────────────────┼──────────────────────────────────────────────────────────────────────┼──────────────────┤
│"Who is Tom Hanks?"│"Person [Tom Cruise] ACTED_IN Movie [A Few Good Men]"                 │0.902335524559021 │
├───────────────────┼──────────────────────────────────────────────────────────────────────┼──────────────────┤
│"Who is Tom Hanks?"│"Person  name Bill Paxton born 1955 "                                 │0.9013911485671997│
├───────────────────┼──────────────────────────────────────────────────────────────────────┼──────────────────┤
│"Who is Tom Hanks?"│"Person [Meg Ryan] ACTED_IN Movie [You've Got Mail]"                  │0.9006932973861694│

분명히 이건 gpt-4가 사전 훈련 과정에서 방대한 데이터로부터 배운 내용일 거예요. 아폴로 13호는 꽤 중요한 영화이고, 공동 배우도 마찬가지고요. 이건 상식/공공 지식 영역에서 이미 충분한 지식을 갖고 있는 LLM 기반의 Semantic Search의 위력이기도 하죠.

생성 결과

검색과 생성을 결합하는 Cypher 쿼리는 다음과 같아요. 또한 향후 평가를 위해 질문과 일치하는 Vector Embedding `NODE` ID를 생성된 답변과 함께 Graph Database에 저장했어요.

// 1. Get text embedding for the question
CALL apoc.ml.openai.embedding([$question],NULL , {}) 
YIELD index, text, embedding 
// 2. Search for similar embeddings via vector index
WITH text, embedding
CALL db.index.vector.queryNodes($vector_index, $top_k, embedding) YIELD node, score
// 3. Retrieve text
WITH node, score
WITH collect(node.text) AS sentences, collect(id(node)) AS nodeIds, collect(score) AS scores
CREATE (q:Question) SET q.text = $question, q.ids = nodeIds, q.scores = scores
// 4. Prepare context by concatenating texts
WITH q, sentences
WITH reduce(text='', x IN sentences | text + x + 'n') + 'n----n' AS context, q
// 5. Let LLM generate answers for the prompt
WITH "You are a customer service agent that helps a customer with answering questions about movies. Use the following context to answer the question at the end. Make sure not to make any changes to the context if possible when prepare answers so as to provide accuate responses. If the answer can't be found in context, just say that I don't know, don't try to make up an answer.nn----Contextn"
  AS system_message,
  "n----nQuestion:" AS user_message, context, q
CALL apoc.ml.openai.chat([
      {role:"system", content:system_message + context},
      {role:"user", content:$question}
    ], NULL, {model:'gpt-4'}) YIELD value
WITH q, context, value
SET q.answer = value.choices[0].message.content, q.created = value.created, q.finish_reason = value.choices[0].finish_reason
RETURN $question, context, value;

gpt-4는 검색된 컨텍스트를 사용해서 아래 답변을 생성했네요.

톰 행크스는 1956년생으로 'You've Got Mail', 'That Thing You Do', 'Cast Away', 'Apollo 13', 'A League of their Own', 'The Polar Express', 'Joe Versus the Volcano', 'Cloud Atlas', 'Sleepless in Seattle', 'Charlie Wilson's War', 'The Green Mile' 등 여러 영화에 출연했습니다. 그는 또한 영화 '당신이 하는 일'을 감독했습니다.

솔직히 말씀드리면, 정답은... 꽤 정확해요. 요약도 잘 되어 있고 개인 정보, 주연 영화, 감독 영화에서 얻은 지식을 다루고 있어서 완전하다고 볼 수 있죠.

관련 없는 소음

위의 샘플에서 검색 프로세스는 필연적으로 관련성이 낮은 콘텐츠를 많이 가져올 수밖에 없다는 걸 알 수 있을 거예요. 결과적으로 LLM이 정확한 답변을 생성하려면 강력한 소음 견고성이 필요하죠.

노이즈 견고성은 모델이 노이즈가 있는 문서에서 유용한 정보를 추출할 수 있다는 의미에요. 여기서 노이즈 문서는 질문과 관련은 있지만 답변 정보가 전혀 포함되지 않은 콘텐츠를 말해요. 위 샘플의 경우 노이즈가 있는 레코드는 14행 이후부터 200행까지의 레코드인데, 이는 top_k에 의해 제한되죠. 무려 92% 이상이에요!

하지만 그래프 속 레코드가 몇 개나 관련되어 있는지에 대한 사전 지식이 없기 때문에 Fine-tuning은 top_k를 실행 가능한 접근 방식으로 만들지 못할 거예요. 문서의 청크 크기를 조정하는 것도 마찬가지고요.

불행히도, 노이즈가 있는 내용이 있을 때 GPT-4가 항상 올바르게 작동하는 건 아니에요. 다른 질문을 테스트해 볼게요.

1995년 이전에 톰 행크스는 몇 편의 영화에 출연했으며, 그 영화는 무엇인가요?

연결 후 검색된 컨텍스트:

"Person  name Tom Hanks born 1956 
Person [Tom Hanks] ACTED_IN Movie [That Thing You Do]
Person [Tom Hanks] ACTED_IN Movie [A League of Their Own]
Person [Tom Hanks] ACTED_IN Movie [You've Got Mail]
Person [Tom Hanks] ACTED_IN Movie [Sleepless in Seattle]
... ... ... ...
(row #93)
Movie  title Sleepless in Seattle tagline What if someone you never met, someone you never saw, someone you never knew was the only someone for you? released 1993 
... ... ... ...
(row #162)
Movie  title A League of Their Own tagline Once in a lifetime you get a chance to do something different. released 1992 
... ... ... ... 
(200 rows in total)

생성된 답변:

문맥상 톰 행크스가 출연한 모든 영화에 대한 구체적인 개봉 날짜가 나와 있지 않아요. 따라서 1995년 이전에 그가 출연한 영화가 무엇인지 정확하게 판단할 수 없어요.

정답: 위의 TOM-HANKS-MOVIES를 확인해 보세요. 영화가 3개 이상 있어야 해요.

╒════════════════════════╤══════════╕
│m.title                 │m.released│
╞════════════════════════╪══════════╡
│"Joe Versus the Volcano"│1990      │
├────────────────────────┼──────────┤
│"A League of Their Own" │1992      │
├────────────────────────┼──────────┤
│"Sleepless in Seattle"  │1993      │
├────────────────────────┼──────────┤

GPT-4가 컨텍스트 중간에 뭐가 있는지 잊어버린 것 같아요. 이와 관련된 논문 ()에서 소위 Lost in the Middle 현상을 다루고 있는데, 꽤 흥미로운 정보를 얻을 수 있을 거예요.

간단한 수학 추론

LLM은 일반적으로 논리적 추론에서는 좋은 결과를 보여주지만, 간단한 수학 관련 문제에서는 형편없는 경우가 많아요.

질문:

2000년 이전에 톰 행크스는 몇 편의 영화에 출연했으며, 그 영화는 무엇인가요?

생성된 답변:

Tom Hanks는 2000년 이전에 9편의 영화에 출연했어요. 여기에는 'That Thing You Do', 'A League of their Own', 'You've Got Mail', 'Sleepless in Seattle', 'Joe Versus the Volcano', 'Apollo 13', 'The Green Mile', 'The Polar Express', 'The Da Vinci Code'가 있어요.

'The Da Vinci Code'는 2004년에 출시되었으므로 답변에 포함되면 안 되겠죠.

정보 통합

정보 통합은 모델이 여러 문서의 정보를 통합해야 하는 복잡한 질문에 답할 수 있는지 평가하는 거예요. Retrieval-Augmented Generation(RAG)의 경우, 문제는 검색 프로세스에서 나타나요. 즉, 검색된 콘텐츠가 얼마나 충분한지 확인하는 과정에서 문제가 생기는 거죠. 생성 단계에서도 문제가 발생할 수 있고요.

질문:

40~50세에 톰 행크스와 톰 크루즈가 출연한 영화는 무엇인가요?

생성된 답변:

톰 행크스는 1956년생이니 40~50세는 1996–2006년이 되겠네요. 이 기간 동안 그는 'That Thing You Do', '라이언 일병 구하기', '찰리 윌슨의 전쟁', '다빈치 코드', '유브 갓 메일', '캐스트 어웨이', '클라우드 아틀라스', '그린 마일', '폴라 익스프레스' 등의 영화에 출연했어요.

톰 크루즈는 1962년생이므로 40~50세라면 2002~2012년이 되죠. 하지만 제공된 맥락에 따르면 이 기간 동안 톰 크루즈가 출연한 영화는 나열되어 있지 않아요.

답변은 거의 정확한 결과를 제공했을 뿐만 아니라 결과를 얻기 위한 논리적인 단계도 제시했어요. 정말 놀랍죠! 하지만 '클라우드 아틀라스'는 2012년에 출시되었으므로 답변에 포함되면 안 돼요. LLM이 자체 추론에 대해 생성된 답변을 검증할 수 있는 방법이 필요하겠어요.

부정적 거부

부정적 거부란 검색된 컨텍스트에 필요한 지식이 없을 때 LLM이 질문에 대한 답변을 거부해야 한다는 의미에요. LLM은 "정보 부족" 또는 기타 거부 신호를 나타낼 것으로 예상되죠. RAG 구현을 위해 일반적으로 을 에 추가하는데, 예를 들면 이런 식이에요.

당신은 고객이 영화에 대한 질문에 답변하도록 돕는 고객 서비스 상담원입니다. 마지막 질문에 답하려면 다음 컨텍스트를 사용하세요. 답변을 작성할 때에는 가능한 한 문맥을 변경하지 않도록 하여 정확한 답변을 제공하시기 바랍니다.문맥상 답변을 찾을 수 없는 경우 모른다고 말씀해 주세요. 답을 만들어내려고 하지 마세요.

질문:

톰 행크스가 영화 반지의 제왕을 감독한 해는 언제입니까?

생성된 답변:

모르겠습니다.

이는 위 지침의 내용과 일치하네요.

상충되는 지식 감지

LLM(Large Language Model)에서 충돌하는 지식 검색은 답변 생성을 위해 주어진 컨텍스트 내에서 모순되는 정보가 발견되는 인스턴스를 식별하고 처리하는 모델의 능력을 나타내요. 효과적인 상충되는 지식 감지를 통해 LLM은 이러한 불일치를 인식하고 가장 신뢰할 수 있는 정보를 선택하거나, 다양한 관점을 제공하거나, 응답을 생성할 때 상충을 인정할 수 있어요. 이는 LLM에서 제공하는 정보의 정확성과 신뢰성에 기여하죠.

나에게검색된 컨텍스트의 시작 부분에 충돌하는 텍스트 조각:

"Person [Tom Hanks] did not DIRECT Movie [That Thing You Do] 
Person [Tom Hanks] DIRECTED Movie [That Thing You Do]
Person [Tom Hanks] ACTED_IN Movie [You've Got Mail]
Person [Tom Hanks] ACTED_IN Movie [A League of Their Own]
Person [Tom Hanks] ACTED_IN Movie [That Thing You Do]
... ... (196 more rows to come)

질문:

톰행크스가 감독한 영화는 무엇인가요?

생성된 답변:

톰 행크스 감독의 영화는 'That Thing You Do'입니다.

상충되는 텍스트를 어디에 삽입했든 처음이든 끝이든 결과는 같았어요. 왠지 GPT-4는 갈등을 무시하고 영화를 연출한 것이 굳건하다고 믿었던 것 같아요.

반사실적 견고성

반사실적 견고성은 모델이 명령을 통해 검색된 컨텍스트에서 알려진 사실 오류의 위험을 식별할 수 있는지 여부를 평가해요. 테스트를 위해 LLM이 직접 답변할 수 있는 질문을 할 수 있지만 검색된 컨텍스트에는 사실적 오류가 포함되어 있죠.

여기서는 검색된 컨텍스트의 시작 부분에 잘못된 사실을 삽입할게요.

"Person [Tom Hanks] DIRECTED Movie [Lord of the Rings] 
Person [Tom Hanks] DIRECTED Movie [That Thing You Do]
Person [Tom Hanks] ACTED_IN Movie [You've Got Mail]
Person [Tom Hanks] ACTED_IN Movie [A League of Their Own]
Person [Tom Hanks] ACTED_IN Movie [That Thing You Do]
Person  name Tom Hanks born 1956 
... .. (195 more rows to come)

질문:

톰행크스가 감독한 영화는 무엇인가요?

생성된 답변:

톰 행크스는 영화 '반지의 제왕'과 'That Thing You Do'를 감독했습니다.

이 경우 GPT-4와 같은 고급 LLM도 명백히 잘못된 사실에 대해 어떠한 경고도 제공하지 못했어요.

요약

의미론적 의미를 포착하는 데 혁신적이기는 하지만 텍스트 임베딩은 종종 상황 민감성, 상황적 의미 및 진화하는 언어 사용으로 인해 어려움을 겪어요(원본 논문). Retrieval-Augmented Generation(RAG)과 같은 솔루션에 적용되는 동안 임베딩 기반 유사성 검색 방법을 기반으로 검색된 콘텐츠는 결과적으로 Large Language Model(LLM) 생성의 정확성과 정확성에 영향을 미칠 수 있죠.

RAG가 LLM의 응답 정확도를 향상시킬 수 있음에도 불구하고 위에서 언급한 문제로 인해 여전히 심각한 어려움을 겪고 있어요.

  • 상충되는 지식 감지

도메인별 임베딩 모델을 Fine-tuning하면 일부 문제를 해결하고 개선할 수 있어요.더욱 발전된 검색 전략벡터 검색을 다른 검색 기술과 결합합니다.

이에 대한 블로그 게시물은 다음에서 확인할 수 있어요.

지식 그래프에 대한 협업 필터링을 통해 텍스트 임베딩의 의미 체계 검색 향상

고급도 있고Neo4j RAG 전략LangChain에서 사용하려면:

마스터의 langchain/templates/neo4j-advanced-rag · langchain-ai/langchain

RAG 솔루션을 구현할 때 이러한 제한 사항과 관련된 시나리오에 대해 정의된 특정 테스트 사례 및 평가 지표가 있어야 해요.


  • gpt-4
  • RAG
  • 벡터 유사성 검색

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

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

728x90
반응형
728x90
반응형

이는 그래프 알고리즘에 관한 5부작 시리즈 중 5부입니다.

  1. 르브론 제임스가 당신의 추천을 이끌어서는 안 되는 이유
  2. 카페테리아 파벌에서 그래프 커뮤니티까지: 루뱅 알고리즘 이해
  3. 누구의 서명이 정말 중요한가요? 연감 서명을 통한 PageRank 이해
  4. 가장 빠른 탈출구 찾기: Dijkstra 알고리즘이 최단 경로를 찾는 방법
  5. 기계에 임베딩이 필요한 이유: 그래프 구조를 기능으로 전환

축하해요. 우리는 해냈습니다. 우리는 직관적인 시각적 요소와 이해하기 쉬운 은유를 사용하여 네 가지 알고리즘을 통해 작업했습니다. 그러나 우리는 마침내 장애물에 부딪혔습니다. 이제 임베딩에 대해 논의해야 하는데 은유가 부족합니다.

아시다시피 그래프는 놀랍도록 직관적입니다. 노드와 관계의 그림을 한눈에 보고 클러스터, 허브 및 패턴을 즉시 찾아낼 수 있습니다. 하지만 그와 똑같은 시각적 매력이 바로 기계에게 그래프를 어색하게 만드는 이유입니다.

기계는 그림을 '보는' 것이 아니라 숫자를 처리합니다. 그리고 원시 형태의 그래프는 전혀 숫자가 아닙니다.

따라서 이상적으로는 그래프를 모델이 처리할 수 있는 행렬로 변환할 수 있는 방법이 있습니다.

그리고 실제로, 우리는 이미 인접 행렬을 가지고 있습니다. 각 행과 열은 노드를 나타내고, 각 셀은 두 노드가 연결되어 있는지 또는 얼마나 강하게 연결되어 있는지를 알려주는 거대한 격자입니다.

그래프를 기계 친화적으로 만들기 위한 훌륭한 첫 번째 시도입니다. 그래프가 충분히 커져 매트릭스가 1000페이지짜리 스프레드시트에 해당하는 디지털 크기로 부풀릴 때까지 말입니다. 그리고 바로 여기서 임베딩이 빛을 발하기 시작합니다.

FastRP 내부 살펴보기

100개의 다양한 미디어 인물을 얼마나 좋아하는지에 대한 설문조사에 참여한 1,000명의 사람들을 비교하여 각 사람이 100가지 차원의 미디어 인물 선호도를 갖고 있다고 상상해 보십시오. 누가 가장 비슷한 취향을 가지고 있는지 알아보기 위해 각 설문조사를 서로 비교하는 것은 정말 시간이 많이 걸릴 것입니다.

실제로 이 사람들이 서로 얼마나 유사한지 측정하려면 이 100D 공간에 있는 1,000개 지점 모두 사이의 거리를 계산해야 하는데, 이는 계산 비용이 많이 듭니다.

대신 결과를 1,000개의 "행"(각 사람당 하나씩)과 100개의 열(각 미디어 수치당 하나씩)이 있는 행렬로 표현할 수 있습니다. 이 행렬에 100개의 행과 10개의 열이 있는 무작위로 생성된 행렬을 곱하면 각 사람의 데이터를 단 10개의 숫자로 압축하는 새로운 행렬이 생성됩니다.

이 변환은 난수를 사용하더라도 모든 사람에게 적용되는 동일한 무작위 투영 행렬이므로 사람들 간의 관계가 보존됩니다. 실제로 차원 수를 줄였음에도 불구하고 사람들 사이의 상대적인 거리는 거의 그대로 유지됩니다. 이는 임의의 숫자를 곱할 때 발생하는 임의의 변동이 모든 차원에 걸쳐 충분히 곱할 때 평균이 0이 되는 경향이 있기 때문입니다.

이 예에서는 매우 작은 숫자로 작업할 것입니다. 그래프는 위에서 본 것과 같을 것입니다!

1단계: 원-핫-랜덤 투영

먼저, 그래프의 각 노드를 숫자로 변환하는 간단한 방법이 필요합니다. 한 가지 쉬운 방법은 원-핫 벡터입니다. 노드가 3개뿐이므로 각 노드는 자체 자리에 1이 하나 있는 짧은 3자리 숫자 목록을 얻습니다. 이 목록은 행렬로도 표현될 수 있습니다.

이는 작동하지만 대부분 0이므로 매우 작거나 효율적이지 않습니다. 이를 축소하려면 난수로 구성된 작은 테이블인 난수 투영 행렬을 곱합니다.

세 개의 노드가 있으므로 이 행렬에는 세 개의 행이 필요합니다. 그리고 모든 것을 노드당 두 개의 숫자로 줄이고 싶기 때문에 두 개의 열을 사용합니다.

두 행렬을 곱한 후 각 노드는 두 개의 숫자로 표시되어 동일한 아이디어를 훨씬 더 작은 형태로 포착합니다.

그럼 행렬의 첫 번째 행에 해당하는 노드 A부터 살펴보겠습니다. 기본적으로 H의 맨 위 행에 R의 각 행을 곱하고 모든 값을 더합니다.

각 행에 대해 이 작업을 수행하면 아래와 같은 결과가 나타납니다. 재미있는 점을 발견할 수 있습니다. 이 출력은 무작위 투영 행렬과 동일합니다. 그것은 우연이 아닙니다. 원-핫 행렬의 각 행에는 단일 1이 있습니다. 이는 단순히 투영 행렬에서 해당 행을 "선택"한다는 의미입니다. 모든 0은 다른 모든 것을 지웁니다.

이 때문에 FastRP는 원-핫 행렬을 구축하거나 이러한 곱셈을 전혀 수행하지 않습니다. 추가 단계 없이 각 노드에 임의의 밀집 벡터를 직접 할당합니다. 결과는 동일합니다.

그러나 이것이 바로 알고리즘이 개념적으로 작동하는 방식이므로 이웃 집계와 같은 더 복잡한 단계로 이동하기 전에 논리를 이해하는 것이 중요합니다.

2단계: 단일 홉 네이버후드 집계

어떤 노드가 어떤 노드에 연결되어 있는지 보여주는 인접 행렬이라는 것을 사용하여 이전 그래프의 연결을 나타낼 수 있습니다. 인접 행렬을 살펴보겠습니다.

행렬에서 1은 행 노드에서 열 노드까지의 가장자리가 있음을 의미합니다. 모서리가 방향이 지정되어 있으므로 A -> B는 B -> A를 의미하지 않습니다.

이를 사용하여 1단계의 초기 임베딩과 곱하여 이웃 임베딩을 집계합니다.

아웃바운드 관계가 가장 많은 노드 A부터 시작하겠습니다. 비록 정확한 표기법이 아니더라도 최대한 명확하게 설명하기 위해 모든 것을 적어보겠습니다.

이는 [-0.6, 1.0]과 같습니다.

[0,1,1]의 각 열을 행렬의 해당 행과 곱한다는 것을 기억하세요. 이는 최종 임베딩을 얻기 위해 함께 추가해야 하는 세 개의 벡터를 제공합니다. 이것이 어떻게 3개의 숫자를 2로 줄이는지 주목하세요.

다음으로 노드 B를 해보겠습니다.

노드 C에는 아웃바운드 관계가 없으므로 아래 결과 매트릭스의 마지막 "행"에 대해 모두 0을 얻습니다.

그렇다면 여기에 정확히 무엇이 있습니까? 첫 번째 행은 노드 A의 아웃바운드 관계를 나타내고, 두 번째 행은 노드 B를 나타내고, 세 번째 행은 노드 C를 나타내는 행렬이 있습니다.

3단계: 재투영 및 가중합

노드 벡터에 인접 행렬을 곱하면 미묘한 일이 발생합니다. 많은 벡터가 동일한 이웃에서 만들어지기 때문에 동일하게 보이기 시작합니다. 이는 세 가지 다른 색상의 페인트를 동일한 두 가지 새로운 색상과 혼합하는 것과 같습니다. 곧 모든 것이 비슷한 색상으로 변합니다.

재투영은 색상이 하나의 흐릿한 혼합으로 혼합되는 것을 방지하는 방법입니다.

기본적으로 우리는 각 노드의 각 벡터를 충분히 구별하기 위해 행렬에 또 다른 임의 행렬을 곱할 것입니다.

하지만 이 새로운 무작위 행렬의 크기는 얼마나 커야 할까요? 행렬을 곱할 때 첫 번째 행렬의 열 개수는 두 번째 행렬의 행 개수와 일치해야 합니다. 따라서 새로운 무작위 행렬에는 2개의 행이 있어야 합니다. 출력을 동일한 2D 공간에 유지하려면 다음과 같이 2 × 2 무작위 투영 행렬이 필요합니다.

그런 다음 이 행렬에 2단계의 결과 행렬을 곱해야 합니다. 그렇게 하면 다음이 생성됩니다.

이는 각 노드의 단일 홉 환경에 대한 임베딩을 나타냅니다. 그런 다음 가중치 합계를 사용하여 이를 원래 임베딩 세트와 결합할 수 있습니다. 노드의 원래 위치를 나타내는 첫 번째 임베딩 세트에 가중치 1을 할당하고, 직접 이웃을 나타내는 두 번째 임베딩 세트에 가중치 0.8을 할당합니다.

이는 우리에게 다음을 제공할 것입니다:

노드 A:

노드 B:

노드 C:

그리고, 짜잔! 이제 우리는 각 노드의 ID뿐만 아니라 바로 이웃한 노드도 인코딩하는 세련된 임베딩 세트를 갖게 되었습니다.

동일한 단계를 수행하여 이 경로를 계속 따라갈 수 있지만 1홉 이웃을 보는 대신 2홉 이웃을 볼 수 있습니다. 그러나 이 시점에서는 대체로 동일한 관행이 될 것입니다. 실제로 떨어져 있는 이웃의 수는 실제로 조정할 수 있는 매개변수입니다.

원래 임무로 돌아가 보겠습니다. 그래프처럼 복잡한 것을 가져와서 더 적은 차원으로 줄이는 것입니다. 무작위 투영을 통해 우리는 각 노드의 위치에 숫자 값을 할당하고 이웃 노드의 위치를 ​​추가로 인코딩할 수 있었습니다.

이제 이러한 간결한 표현을 통해 노드를 다른 특징 벡터처럼 처리할 수 있으므로 분류자, 회귀자 또는 클러스터링 알고리즘과 같은 표준 모델에 쉽게 연결할 수 있습니다.

  • 그래프 데이터 과학

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

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

728x90
반응형
728x90
반응형

회사 AI 비서와 대화하다 보면 답답할 때가 있죠. 챗봇이 질문에 제대로 답하지 못하고 뻔한 답변만 내놓아서 포기하게 만들기도 하고요.

하지만 꼭 그럴 필요는 없어요. 상세하고 정확한 답변을 제공하는 챗봇과 대화하는 상황을 상상해보세요. 마치 회사와 제품, 정책에 대한 깊은 지식을 가진 사람과 대화하는 것처럼 느껴질 거예요. 이런 챗봇은 정말 도움이 되겠죠?

이 두 번째 시나리오는 바로 *Retrieval-Augmented Generation(RAG)*이라는 Machine Learning 접근 방식을 통해 가능하답니다.

RAG는 외부 데이터 저장소에서 소스 정보를 검색해서 생성된 응답을 보강하여 Large Language Model(LLM)의 응답을 향상시키는 기술이에요.

데이터베이스, 문서, 웹사이트 등 다양한 데이터 저장소에는 LLM이 학습한 데이터 외에도 특정 상황 정보를 찾고 요약할 수 있는 도메인별 데이터가 담겨 있을 수 있어요.

RAG 애플리케이션은 더 스마트한 GenAI 애플리케이션을 원하는 조직에게 업계 표준이 되어가고 있어요. 이번 블로그 포스팅에서는 RAG 아키텍처, RAG 작동 방식, RAG 애플리케이션 사용의 주요 이점, 그리고 다양한 산업 분야의 사용 사례를 살펴볼게요.

RAG가 중요한 이유

OpenAI의 GPT 모델 같은 Large Language Model(LLM)은 일반적인 언어 작업에는 뛰어나지만, 몇 가지 이유 때문에 특정 질문에 답하는 데 어려움을 겪기도 해요.

  • LLM은 광범위한 지식 기반을 가지고 있지만, 깊이 있는 산업 또는 조직별 맥락이 부족한 경우가 많아요.
  • LLM은 '환각(hallucination)'이라고 알려진 잘못된 응답을 생성할 수 있어요.
  • LLM은 출처를 확인, 추적, 인용할 수 없기 때문에 설명력이 부족해요.
  • LLM의 지식은 실시간 정보로 업데이트되지 않는 정적인 학습 데이터를 기반으로 해요.

이러한 제한 사항을 해결하기 위해 기업들은 LLM을 강화하는 기술을 사용하는데요, 그 중 대표적인 것이 Fine-tuning과 RAG랍니다. Fine-tuning을 통해 LLM의 기본 데이터 세트를 추가로 학습시킬 수 있고, RAG 애플리케이션을 사용하면 다른 데이터 소스에 연결해서 각 Query에 대한 응답으로 가장 관련성이 높은 정보만 검색할 수 있어요. RAG를 사용하면 환각을 줄이고, 설명 가능성을 높이고, 최신 데이터를 활용하고, LLM이 답변할 수 있는 범위를 확장할 수 있죠. 응답의 품질과 특이성을 향상시키면 더 나은 사용자 경험을 만들 수도 있고요.

RAG는 어떻게 작동하나요?

RAG 아키텍처는 크게 Query 이해, 정보 검색, 응답 생성이라는 세 가지 주요 프로세스로 구성되어 있어요.

RAG 애플리케이션을 구현하기 전에, RAG 애플리케이션이 관련 정보를 빠르게 검색하고 가져올 수 있도록 데이터를 정리하는 게 중요해요. 이 과정을 데이터 인덱싱이라고 하죠.

LangChain 같은 프레임워크를 사용하면 API를 통해 LLM을 외부 데이터베이스에 연결하는 통합 인터페이스를 제공해서 RAG 애플리케이션을 쉽게 구축할 수 있어요. Neo4j Vector Index LangChain 라이브러리는 인덱싱 프로세스를 단순화하는 데 도움이 된답니다.

1. 사용자 쿼리 이해 (Understanding User Queries)

사용자가 질문을 하면 프로세스가 시작돼요. 쿼리는 LLM API를 통해 RAG 애플리케이션으로 전달되고, RAG 애플리케이션은 이를 분석해서 사용자의 의도를 이해하고 어떤 정보를 찾아야 할지 결정하죠.

2. 정보 검색 (Information Retrieval)

이 애플리케이션은 Vector Similarity Search 같은 고급 알고리즘을 사용해서 회사 데이터베이스에서 가장 관련성이 높은 정보를 찾으려고 해요. 이러한 알고리즘은 Semantic Search를 기반으로 Vector Embedding을 매칭시켜서 사용자의 질문에 가장 잘 답할 수 있는 정보를 식별하는 거죠.

3. 응답 생성 (Response Generation)

애플리케이션은 검색된 정보를 사용자의 원래 프롬프트와 결합해서 더 자세하고 맥락에 맞는 프롬프트를 생성해요. 그런 다음 새로운 프롬프트를 사용해서 조직의 내부 데이터에 맞는 응답을 생성한답니다.

RAG의 장점은 무엇일까요? (What are the benefits of RAG?)

바로 사용할 수 있는 GenAI 모델은 공개 데이터로 학습되었기 때문에 다양한 작업을 수행하고 여러 질문에 답변할 수 있도록 잘 갖춰져 있어요. LLM과 함께 RAG 애플리케이션을 사용하는 주요 장점은 AI를 훈련시켜 *여러분의* 데이터를 사용할 수 있다는 점이에요. 이 데이터는 가장 관련성이 높고 최신 내용에 따라 변경될 수 있죠. 어떤 데이터 저장소에 액세스하고 그 안에 있는 데이터를 얼마나 자주 새로 고치느냐가 중요해요. RAG를 사용하면 사용자 지정 데이터를 공개하지 않고도 액세스하고 사용할 수 있답니다.

전반적으로 RAG를 사용하면 독립 실행형 LLM의 한계를 해결하면서 업계 및 개별 비즈니스에 맞춤화된 생성적 AI 경험을 제공할 수 있어요.

  • 향상된 정확도 (Enhanced Accuracy): RAG 애플리케이션은 영역별 지식과 향상된 추론을 제공하여 환각의 위험을 크게 줄여줘요.
  • 상황에 따른 이해 (Contextual Understanding): RAG 애플리케이션은 고객 정보부터 제품 세부 정보, 판매 내역까지 조직 전체의 독점 내부 데이터를 기반으로 상황별 응답을 제공해요.
  • 설명 가능성 (Explainability): RAG 애플리케이션은 정보 소스에 기반한 응답을 기반으로 정보 소스를 추적하고 인용하여 투명성과 사용자 신뢰를 높일 수 있어요.
  • 최신 정보 (Up-to-date Information): Graph Database 또는 기타 문서 저장소를 최신 상태로 유지하는 한, RAG 애플리케이션은 최신 데이터에 실시간으로 액세스하여 지속적인 개선을 가능하게 한답니다.

일반적인 RAG 사용 사례는 무엇일까요? (What are common RAG use cases?)

RAG는 GenAI 애플리케이션을 강화해서 상황을 해석하고 정확한 정보를 제공하며 사용자 요구에 적응하도록 도와줘요. 이를 통해 광범위한 사용 사례가 가능해졌죠.

  • 고객 지원 Chatbot: RAG 챗봇은 제품 카탈로그, 회사 데이터 및 고객 정보를 손쉽게 활용해서 고객 질문에 유용하고 개인화된 답변을 제공할 수 있어요. 문제를 해결하고, 작업을 완료하고, 피드백을 수집하고, 고객 만족도를 높일 수 있죠.
  • 비즈니스 인텔리전스 및 분석: RAG 애플리케이션은 최신 시장 데이터, 동향 및 뉴스를 통합해서 기업에 통찰력, 보고서 및 실행 가능한 권장 사항을 제공할 수 있어요. 이는 전략적 의사 결정에 영향을 미치고 경쟁 우위를 유지하는 데 도움이 된답니다.
  • 의료 지원: 의료 전문가는 RAG를 사용해서 관련 환자 데이터, 의학 문헌 및 임상 지침을 바탕으로 정보에 입각한 결정을 내릴 수 있어요. 예를 들어 의사가 치료 계획을 고려할 때 앱은 환자의 현재 약물을 기반으로 잠재적인 약물 상호 작용을 보여주고 최신 연구를 기반으로 대체 치료법을 제안할 수 있죠. RAG는 또한 환자의 관련 병력을 요약해서 결정을 내리는 데 도움을 줄 수 있어요.
  • 법률 연구: RAG 애플리케이션은 법률 데이터베이스에서 관련 판례법, 법령 및 규정을 신속하게 검색하고 핵심 사항을 요약하거나 특정 법적 질문에 답변함으로써 정확성을 보장하면서 시간을 절약할 수 있어요.

기업이 계속해서 점점 더 많은 양의 데이터를 생성함에 따라 RAG는 정보에 기초한 응답을 제공하기 위해 데이터를 활용한답니다.

  • Fine-tuning
  • RAG
  • RAG AI
  • RAG Architecture
  • RAG Chatbot
  • RAG LLM
  • Retrieval-Augmented Generation
  • Retrieval-Augmented Generation RAG
  • Semantic Search
  • 벡터 검색
  • RAG가 뭐야?
  • Retrieval-Augmented Generation이란 무엇인가

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

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

728x90
반응형
728x90
반응형

GraphRAG는 성능을 향상시키는 강력한 검색 메커니즘이에요. GenAI 애플리케이션을 만들 때, 그래프 데이터 구조의 풍부한 컨텍스트를 활용할 수 있게 해주죠.

엔터프라이즈 GenAI 시스템은 신뢰할 수 있고 믿을 수 있는 결과를 내야 한다는 중요한 과제에 직면해 있어요. 순수한 LLM(Large Language Model) 기반 솔루션은 이 점에서 부족한 경우가 많죠. 왜냐하면, LLM은 사실성보다는 유용성을 우선시하도록 훈련되었고, 사전 훈련 데이터에는 중요한 최신 정보가 부족한 경우가 많거든요. 결과적으로 사실과 다른 설명을 만들어내는 경향이 있는데, 이는 특히 중요한 비즈니스 영역 및 사용 사례에 해로울 수 있어요.

이러한 문제를 해결하기 위해, Retrieval-Augmented Generation(RAG) 아키텍처가 솔루션으로 떠올랐어요. RAG는 LLM 답변이 기존 지식 소스의 정확한 정보만을 기반으로 하도록 보장해서 GenAI 구성 요소의 신뢰성을 높여준답니다.

기본적인 RAG 시스템은 격리된 텍스트 조각들을 검색하고 순위를 매기기 위해 Vector Database의 Semantic Search에만 의존해요. 이 접근 방식은 일부 관련 정보를 찾을 수는 있지만, 이러한 조각들을 연결하는 컨텍스트를 포착하는 데는 실패하죠. 그래서 기본적인 RAG 시스템은 복잡한 다중 홉 질문에 답하기에는 적합하지 않아요.

바로 이럴 때 GraphRAG가 등장하는 거죠! Knowledge Graph는 더 많은 데이터 포인트뿐만 아니라 그 관계도 포착하기 위해 정보를 표현하고 연결하거든요. 따라서 그래프 기반 검색기는 종종 명확하지 않지만 정보 상관 관계에 중요한 숨겨진 연결을 찾아내서, 더 정확하고 관련성이 높은 결과를 제공할 수 있어요.

이번 블로그 포스팅에서는 GraphRAG가 어떻게 작동하는지 자세히 알아보고, 다른 RAG 아키텍처와 비교했을 때 답변 품질과 설명 가능성을 향상시키는 장점을 살펴볼 거예요. 그리고 Neo4j 예제를 사용해서 실제 적용 사례를 보여드릴게요.

Retrieval-Augmented Generation(RAG) 소개

GraphRAG의 자세한 내용을 살펴보기 전에, RAG의 기본 개념을 이해하는 것이 중요해요. RAG의 세 가지 주요 단계를 자세히 살펴볼까요?

검색(Retrieval): 이 단계에서 RAG 시스템은 사용자의 Query를 기반으로 문서나 Database와 같은 외부 데이터 소스에서 관련 정보를 검색해요. 검색 프로세스에서는 유사성 검색이나 Database Query 등 가장 관련성이 높은 데이터를 식별하기 위해 다양한 기술을 사용할 수 있죠. 그런 다음 검색어와의 관련성을 기준으로 결과의 순위를 매기고 점수를 매긴답니다.

증강(Augmentation): 증강 단계에서는 검색된 정보가 추가 지침이나 컨텍스트와 함께 원래 사용자 질문과 결합돼요. 이렇게 증강된 Prompt는 Language Model이 응답을 생성하는 데 더 풍부한 컨텍스트를 제공하죠. 목표는 정확하고 유용한 출력을 생성하기 위해 모델이 관련 정보만 사용하도록 하는 거예요.

생성(Generation): 마지막 단계에서는 증강된 Prompt가 사전 훈련된 지식에 의존하지 않고 제공된 컨텍스트만을 사용하여 요청된 형식으로 답변을 생성하는 LLM에 의해 처리돼요. 응답은 소스 정보와 추가 메타데이터를 연결할 수도 있답니다.

외부 지식으로 Language Model을 강화하고 모델의 Natural Language Understanding 기능을 사용하여 이 정보를 검색하고 처리함으로써, RAG 시스템은 사전 훈련된 지식에만 의존하는 독립 실행형 Language Model에 비해 더 정확하고 유익한 응답을 생성할 수 있어요.

The retrieval-augmented generation process

Vector 전용 RAG의 한계

많은 기본적인 RAG 시스템은 Vector Search를 사용해서 정보 검색을 해요. 이때 텍스트의 의미를 숫자 벡터로 표현하는 Vector Embedding을 활용하죠. 소스 문서는 텍스트 조각의 의미를 정확하게 담기 위해 더 작은 단위로 쪼개진 다음, 검색, 인덱싱, 저장을 거치게 돼요.

하지만 이 방법에는 한계가 있어요. Vector Search에만 의존하면 답변 내용이 검색된 텍스트 조각에 갇히게 되거든요. 그래서 답변이 불완전하거나 단편적으로 보일 수 있죠.

예를 들어, 사용자가 특정 제품 기능에 대해 질문했을 때, 벡터 전용 RAG 시스템은 그 제품을 언급하는 텍스트 조각만 찾아낼 수 있어요. 더 포괄적인 답변을 줄 수 있는 다른 관련 정보는 놓칠 수 있다는 거죠.

게다가 Vector Embedding과 Vector Search는 블랙박스처럼 작동해서 정보를 어디서 가져왔는지 설명하기 어려워요. 사용자와 개발자는 특정 텍스트 조각이 왜 검색되었고, 생성된 답변에 어떻게 기여했는지 알기 힘들다는 뜻이죠. 투명성과 책임이 중요한 의료나 금융 분야에서는 이런 설명력 부족이 큰 단점이 될 수 있어요.

이런 단점을 극복하기 위해 RAG 프로세스(검색, 확대, 생성)의 여러 단계를 개선하는 새로운 기술들이 등장하고 있어요.

LLM에 제공되는 정보는 답변의 품질에 엄청난 영향을 주기 때문에, 검색 메커니즘을 개선하는 게 가장 중요할 때가 많아요. GraphRAG는 Knowledge Graph에 저장된 구조화된 도메인 지식을 활용해서 검색 성능을 끌어올리는 방법이에요. Knowledge Graph의 풍부한 연결과 의미론적 관계를 이용해서 Vector Search 기반 RAG의 한계를 극복하고, 더 정확하고 설명 가능한 답변을 제공하는 게 목표죠.

데이터 표현을 위한 Knowledge Graph

Knowledge Graph는 연결된 요소로 데이터를 구조화해서 표현하는 데 아주 효과적이에요. 기존 데이터베이스처럼 엄격한 스키마를 강요하지 않아서 데이터 모델이 훨씬 유연하죠. 그래프 모델을 사용하면 풍부한 실제 정보를 효율적으로 저장, 관리, 쿼리하고 처리할 수 있어요. RAG 시스템에서 Knowledge Graph는 요약, 번역, 추출 같은 LLM의 언어 능력을 유연하게 보완해주는 메모리 역할을 해요.

Knowledge Graph에서는 사실과 개체가 다음과 같이 표현돼요. Nodes는 속성을 가지고, 연결된 Relationships 또한 자격에 대한 속성을 가질 수 있죠. 이 그래프 모델은 단순한 가계도에서부터 수백만, 수십억 개의 연결을 통해 직원, 고객, 프로세스, 제품, 파트너십, 리소스를 포괄하는 회사의 완전한 디지털 트윈까지 확장될 수 있어요.

그래프 구조는 구조화된 비즈니스 도메인, (계층적) 문서 표현, 그래프 알고리즘으로 계산된 신호 등 다양한 소스에서 시작될 수 있답니다.

GraphRAG 검색기를 위한 Graph Querying

다음과 같은 간단한 패턴을 따라 그래프를 탐색할 수 있어요. (node:Type)-[relationship:TYPE]->(node:Type) 또는 Cypher나 GQL 같은 Graph Query Language로 표현된 더 복잡한 형태로도 가능하죠. 패턴 매칭을 사용하면 SQL과 같은 다른 Query Language에서처럼 Node, Relationship, Attribute를 필터링, 집계 및 정렬할 수 있는 경로가 생성돼요. 다음은 Vector Embedding 검색에서 이웃 정보를 반환하는 Graph Query의 예시입니다.

CALL db.index.vector.queryNodes(docs, 5, $embedding) yield node as doc, score
RETURN score, doc, COLLECT { 
MATCH path = (doc)-[rel]-(neighbor)
RETURN path
} as paths
ORDER BY score DESC LIMIT 10

GraphRAG가 검색을 향상시키는 방법

GraphRAG 검색을 통해 다음을 찾을 수 있어요. 은 Vector, 전체 텍스트, 공간 또는 기타 검색을 통해 찾고, 이 데이터 네트워크에서 관련 Relationship을 따라 사용자 Query를 만족시키기 위해 추가 정보를 수집하는 거죠. 관련성을 높이기 위해 사용자와 작업의 컨텍스트가 고려돼요. 캡처된 모든 Node, Relationship 및 해당 Attribute는 증강 단계에서 컨텍스트로 반환되기 전에 필터링되고 순위가 매겨질 수 있답니다.

이 접근 방식은 Vector 전용 RAG 시스템에 비해 다음과 같은 몇 가지 장점을 제공해요.

  1. 그래프 구조를 탐색하고 관련된 relationships을 따라가면서, GraphRAG는 검색된 chunk의 초기 세트에서 직접 언급되지 않은 정보까지 검색할 수 있어서 더 포괄적이고 맥락에 맞는 답변을 제공할 수 있어요.
  2. 사용자의 상황과 작업에 맞춰 검색된 정보를 필터링하고 순위를 매기는 기능 덕분에, GraphRAG는 가장 관련성이 높은 정보의 우선순위를 정해서 답변의 퀄리티를 높일 수 있죠.
  3. GraphRAG는 검색된 정보 간의 relationships을 캡처해서 더 나은 설명 가능성을 제공하고, 답변 뒤에 숨겨진 출처와 추론을 더 쉽게 추적할 수 있도록 도와줘요.
  4. GraphRAG는 계산된 신호뿐만 아니라 구조화된 데이터와 구조화되지 않은 데이터를 통합하는 Knowledge Graph의 기능을 사용해서, 더 넓은 범위의 정보 소스에서 얻어지는 더 많은 정보와 미묘한 답변을 제공할 수 있어요.

검색 단계가 이렇게 개선되면서 GraphRAG는 벡터 전용 RAG 시스템보다 더 정확하고 관련성 높으며 추적 가능한 답변을 만들어낼 수 있는 거죠.

GraphRAG Retriever 유형

실제 그래프 검색은 사용 사례와 도메인에 따라 달라져요. 다양한 유형의 retriever를 결합할 수 있고, 결과의 순위를 매기거나 결합하거나 순서를 지정할 수도 있죠. 에이전트 설정에서 retriever는 LLM이 선택하고 반복적으로 실행해서 질문에 답하는 데 필요한 정보가 수집될 때까지 parameter와 결과를 전달하는 도구가 될 수 있어요.

GraphRAG retriever 유형의 예시를 몇 가지 살펴볼까요?

  • 벡터(embedding), 전체 텍스트, 공간 또는 기타 검색 index: 사용자 질문의 정보와 함께 index 검색을 사용해서 추가 탐색을 위한 그래프의 시작점을 결정해요.
  • : 정보를 context에 추가하기 위해 Node의 직접 또는 간접적인 이웃에 접근해요.
  • : 시작 entity 사이의 경로를 찾고, 이웃과의 relationships을 확장하고, 추가 관련 문서, claim 및 기타 entity를 검색해요.
  • 글로벌 Query: 사전 계산된 주제 간 요약 및 통찰력에 대한 기타 글로벌 표현을 사용해서 일반적인 질문에 답변해요 (Query 중심 요약이 포함된 Microsoft의 GraphRAG를 참고하세요).
  • : 질문 category에 대한 사용 사례별 Query는 도메인 전문가가 제공하며, 동일한 시작점을 가질 수 있지만 다른 하위 그래프를 탐색할 수 있고, 질문을 분류해서 선택할 수 있어요.
  • (Text2Cypher): (Fine-tuning된) LLM은 사용자 질문과 그래프 Schema 설명에서 Cypher Query를 생성해서 구체적이고 구조적인 질문에 답해요.
  • : LLM은 다양한 retriever를 사용해서 계획된 순서에 따라 이를 선택하고 실행해서 질문에 답하기 위한 모든 정보를 수집해요.
  • : embedding을 사용해서 Node 주변의 "본질"을 표현하고 후보 embedding을 일치시켜 퍼지 토폴로지 검색을 허용해요.

GraphRAG 패턴 카탈로그에서 더 많은 예제를 찾아볼 수 있어요. graphrag.com.

Knowledge Graph 구축

GraphRAG가 제대로 작동하려면 데이터가 관련성이 높고 연결된 정보 조각을 정확하게 나타내는 모양을 가지고 있는지 확인해야 해요. 이 Knowledge Graph를 만들려면 두 단계를 수행해야 하고, 이를 반복해서 개선할 수 있죠.

  1. 도메인 데이터를 나타내기 위해 관련 Node와 Relationship을 모델링해요.
  2. 이 그래프 모델에 맞게 그래프 구조를 가져오거나 생성하거나 계산해요.

다양한 데이터 소스를 통합할 수 있다는 점이 매력적이죠.

  • 데이터베이스, 파일 또는 API에서 기존의 구조화된 데이터를 가져올 수 있어요.
  • 구조화되지 않은 데이터(텍스트, 오디오, 비디오)를 문서 구조/계층의 그래프 표현으로 변환하고, 청크에 대한 Vector Embedding 및 전체 텍스트 Index를 추가할 수 있어요.
  • 텍스트 정보로부터 구조화된 엔터티(선택적 임베딩 포함)와 해당 Relationships를 구성하거나 연결할 수 있어요.
  • 주제 클러스터링 요약(예: Microsoft Query Focused Summarization), 유사성 Relationship 및 개인화된 페이지 순위(PPR) 점수와 같은 추가 계산 또는 알고리즘을 사용하여 기존 그래프를 더욱 풍성하게 만들 수 있어요.

이러한 그래프 모델과 소스는 GraphRAG 패턴 카탈로그에도 자세히 설명되어 있답니다.

Neo4j를 사용한 GraphRAG 예시

GraphRAG의 흔한 사용 사례는 단순히 "PDF로 채팅"하는 것보다 훨씬 더 깊이 있는 정보 분석이에요. Vector 기반의 Semantic Search 방식에서는 검색기에서 반환된 데이터가 도메인이나 서로의 개념과 어떻게 연결되는지에 대한 정보가 거의 없는 텍스트 덩어리일 뿐이죠.

하지만 GraphRAG 방식을 사용하면 문서에 나타나는 사람, 조직, 기사, 논문, 생물학적 프로세스, 상태, 질병, 약물, 유전자, 표현, 노출 및 경로와 같은 엔터티를 추출해서 풍부한 정보 네트워크를 구축할 수 있어요.

이걸 보여드리기 위해 오픈 소스를 사용해서 Knowledge Graph를 구성하는 예시를 한번 살펴볼까요? neo4j-graphrag 패키지를 사용하면 된답니다. LangChain, LlamaIndex 등과의 도 지원하고 있어요.

이 예시에서는 여러 기본 설정을 제공하고 아래 설명된 단계를 실행하는 SimpleKGPipeline을 사용할 거예요.

이 추출을 실행하기 위해 다음 구성 요소로 파이프라인을 구성할 거예요.

  • LLM(예: OpenAI의 gpt-4‌‌‌o-mini)
  • Embedding 모델
  • Graph 스키마

구성이 완료되면 생물의학 연구 논문 데이터 세트에서 파이프라인을 실행할 수 있어요.

driver = neo4j.GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USERNAME, NEO4J_PASSWORD))

ex_llm=OpenAILLM(
    model_name="gpt-4o-mini",
    model_params={
        "response_format": {"type": "json_object"},
        "temperature": 0
    }
)
embedder = OpenAIEmbeddings()

node_labels = ["Anatomy", "BiologicalProcess", ...]
rel_types = ["ACTIVATES", "AFFECTS", "ASSESSES",..."TREATS", "USED_FOR"]

kg_builder_pdf = SimpleKGPipeline(
    llm=ex_llm,
    driver=driver,
    text_splitter=FixedSizeSplitter(chunk_size=500, chunk_overlap=100),
    embedder=embedder,
    entities=node_labels,
    relations=rel_types,
    prompt_template=prompt_template,
    from_pdf=True
)

pdf_file_paths = ['biomolecules-11-00928-v2.pdf', 'GAP-between-patients-and-clinicians_2023_Best-Practice.pdf','pgpm-13-39.pdf']

for path in pdf_file_paths:
    graph_data = await kg_builder_pdf.run_async(file_path=path)

청크된 문서 데이터와 그래프 데이터를 Neo4j에 저장한 후 쿼리 도구를 사용하여 시각화할 수 있죠.

이제 GraphRAG 검색기를 실행하고 그 결과를 Vector RAG 검색기와 비교해 볼 수 있어요.

이 검색기는 먼저 인덱싱된 텍스트 청크에 대한 벡터 검색을 실행한 다음 최대 2홉 아웃까지 청크가 아닌 관계를 따라가면서 직접 추출된 엔터티뿐만 아니라 해당 엔터티의 1차 및 2차 이웃도 검색해요. 프롬프트 확대 및 답변 생성의 최종 단계에서 사용할 컨텍스트로 청크 텍스트와 엔터티-관계-엔티티 쌍을 반환하는 거죠.

from neo4j_graphrag.retrievers import VectorCypherRetriever

graph_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]-(entity)-[relList:!FROM_CHUNK]-{1,2}(nb)
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 apoc.text.join([c in chunks | c.text], '\n') + 
  apoc.text.join([r in rels | 
  startNode(r).name+' - '+type(r)+' '+r.details+' -> '+endNode(r).name],  
  '\n') AS info
"""
)

다음으로, 적절한 LLM(여기서는 더 나은 OpenAI gpt-4‌‌o 사용)과 함께 각 검색기를 사용하여 벡터 및 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'])

vector_rag  = GraphRAG(llm=llm, retriever=vector_retriever, prompt_template=rag_template)

graph_rag = GraphRAG(llm=llm, retriever=graph_retriever, prompt_template=rag_template)

q = "Can you summarize systemic lupus erythematosus (SLE)? including common effects, biomarkers, and treatments? Provide in detailed list format."

vector_rag.search(q, retriever_config={'top_k':5}).answer
graph_rag.search(q, retriever_config={'top_k':5}).answer

답변을 비교해보면 GraphRAG 응답이 훨씬 더 포괄적이고 관련 컨텍스트를 더 많이 포함하고 있다는 것을 알 수 있어요.

더 자세한 내용은 다음을 참조하세요. GraphRAG Python 패키지: Knowledge Graph로 GenAI 가속화 리소스 섹션을 확인해 보세요.

일반적인 GraphRAG 사용 사례

GraphRAG는 출력이 중요한 비즈니스 의사 결정에 사용되기 때문에, 더 높은 수준의 신뢰가 필요한 애플리케이션 및 도메인에 적합해요. 몇 가지 예를 들어볼까요?

  • 법률 및 규정 준수: 계약, 판례, 법률, 규정 등을 검토하고 분석하는 데 활용돼요.
  • : 조직, 사람, 경쟁사, 시장 및 동향을 조사하는 데 쓰이죠.
  • : 약물 발견 및 용도 변경, 임상 시험 및 연구를 위한 Knowledge Graph에 액세스하는 데 사용돼요.
  • : 다양한 비즈니스 데이터 소스를 조직의 응집력 있는 관점으로 통합하는 데 활용돼요.
  • : 제품 및 생산 프로세스의 위험 평가, 규정 준수, 지속 가능성에 대한 조사를 수행하는 데 쓰여요.
  • : 자금세탁(AML), 보험 사기, 기타 사기 행위를 식별하고 예방하는 데 사용돼요.
  • : 뉴스 기사 및 조사를 위해 대규모 데이터 세트에서 연관성과 패턴을 찾아내는 데 활용돼요.
  • 자연어 검색 및 챗봇: 사용자 친화적인 인터페이스를 통해 기존 지식 기반에 대한 액세스를 민주화하는 데 쓰이죠.

GraphRAG: 엔터프라이즈급 AI 앱 활성화

RAG 아키텍처는 현재 신뢰할 수 있는 데이터 소스의 데이터를 사용하여 GenAI 비즈니스 애플리케이션에 안정적인 콘텐츠를 제공하는 가장 효과적인 방법이에요. GraphRAG는 여기서 한 단계 더 나아가 품질과 설명 가능성 모두에서 기본 벡터 기반 RAG를 개선하죠.

보다 관련성이 높은 컨텍스트를 고려하고 문서, 도메인 및 계산된 그래프 구조를 탐색하는 다양한 검색기를 사용함으로써 GraphRAG는 더욱 정확하고 신뢰할 수 있으며 추적 가능한 결과를 제공해요. 실제 정보를 풍부하게 표현하는 Knowledge Graph와 고급 언어 기술을 갖춘 LLM을 결합하여 기업 사용 사례를 위한 강력하고 안정적인 솔루션을 만드는 거죠.

점점 더 많은 조직이 GenAI를 채택함에 따라 GraphRAG는 이러한 시스템의 정확성, 신뢰성 및 투명성을 보장하고 더 나은 의사 결정과 향상된 비즈니스 결과를 위한 길을 닦는 데 필수적일 거예요.

 

GraphRAG에 대해 더 자세히 알고 싶으시다면, 다음 자료들을 확인해보세요!

  • GraphRAG 선언문
  • Knowledge Graph란 무엇일까요?
  • Neo4j를 사용한 생성적 AI
  • GraphRAG 패턴 카탈로그
  • 온라인 Neo4j LLM Knowledge Graph 빌더(LangChain 사용)
  • Neo4j GraphRAG Python 패키지
  • RAG 과정을 위한 DeepLearning.AI Knowledge Graph
  • 무료 GraphAcademy GenAI 강좌
  • GraphRAG
  • RAG

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

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

728x90
반응형
728x90
반응형

GraphRAG는 성능을 향상시키는 강력한 검색 메커니즘이에요. GenAI 애플리케이션을 만들 때, 그래프 데이터 구조의 풍부한 컨텍스트를 활용할 수 있게 해주죠.

엔터프라이즈 GenAI 시스템은 신뢰할 수 있고 믿을 수 있는 결과를 내야 한다는 중요한 과제에 직면해 있어요. 순수한 LLM(Large Language Model) 기반 솔루션은 이 점에서 부족한 경우가 많죠. 왜냐하면, LLM은 사실성보다는 유용성을 우선시하도록 훈련되었고, 사전 훈련 데이터에는 중요한 최신 정보가 부족한 경우가 많거든요. 결과적으로 사실과 다른 설명을 만들어내는 경향이 있는데, 이는 특히 중요한 비즈니스 영역 및 사용 사례에 해로울 수 있어요.

이러한 문제를 해결하기 위해, Retrieval-Augmented Generation(RAG) 아키텍처가 솔루션으로 떠올랐어요. RAG는 LLM 답변이 기존 지식 소스의 정확한 정보만을 기반으로 하도록 보장해서 GenAI 구성 요소의 신뢰성을 높여준답니다.

기본적인 RAG 시스템은 격리된 텍스트 조각들을 검색하고 순위를 매기기 위해 Vector Database의 Semantic Search에만 의존해요. 이 접근 방식은 일부 관련 정보를 찾을 수는 있지만, 이러한 조각들을 연결하는 컨텍스트를 포착하는 데는 실패하죠. 그래서 기본적인 RAG 시스템은 복잡한 다중 홉 질문에 답하기에는 적합하지 않아요.

바로 이럴 때 GraphRAG가 등장하는 거죠! Knowledge Graph는 더 많은 데이터 포인트뿐만 아니라 그 관계도 포착하기 위해 정보를 표현하고 연결하거든요. 따라서 그래프 기반 검색기는 종종 명확하지 않지만 정보 상관 관계에 중요한 숨겨진 연결을 찾아내서, 더 정확하고 관련성이 높은 결과를 제공할 수 있어요.

이번 블로그 포스팅에서는 GraphRAG가 어떻게 작동하는지 자세히 알아보고, 다른 RAG 아키텍처와 비교했을 때 답변 품질과 설명 가능성을 향상시키는 장점을 살펴볼 거예요. 그리고 Neo4j 예제를 사용해서 실제 적용 사례를 보여드릴게요.

Retrieval-Augmented Generation(RAG) 소개

GraphRAG의 자세한 내용을 살펴보기 전에, RAG의 기본 개념을 이해하는 것이 중요해요. RAG의 세 가지 주요 단계를 자세히 살펴볼까요?

검색(Retrieval): 이 단계에서 RAG 시스템은 사용자의 Query를 기반으로 문서나 Database와 같은 외부 데이터 소스에서 관련 정보를 검색해요. 검색 프로세스에서는 유사성 검색이나 Database Query 등 가장 관련성이 높은 데이터를 식별하기 위해 다양한 기술을 사용할 수 있죠. 그런 다음 검색어와의 관련성을 기준으로 결과의 순위를 매기고 점수를 매긴답니다.

증강(Augmentation): 증강 단계에서는 검색된 정보가 추가 지침이나 컨텍스트와 함께 원래 사용자 질문과 결합돼요. 이렇게 증강된 Prompt는 Language Model이 응답을 생성하는 데 더 풍부한 컨텍스트를 제공하죠. 목표는 정확하고 유용한 출력을 생성하기 위해 모델이 관련 정보만 사용하도록 하는 거예요.

생성(Generation): 마지막 단계에서는 증강된 Prompt가 사전 훈련된 지식에 의존하지 않고 제공된 컨텍스트만을 사용하여 요청된 형식으로 답변을 생성하는 LLM에 의해 처리돼요. 응답은 소스 정보와 추가 메타데이터를 연결할 수도 있답니다.

외부 지식으로 Language Model을 강화하고 모델의 Natural Language Understanding 기능을 사용하여 이 정보를 검색하고 처리함으로써, RAG 시스템은 사전 훈련된 지식에만 의존하는 독립 실행형 Language Model에 비해 더 정확하고 유익한 응답을 생성할 수 있어요.

The retrieval-augmented generation process

Vector 전용 RAG의 한계

많은 기본적인 RAG 시스템은 Vector Search를 사용해서 정보 검색을 해요. 이때 텍스트의 의미를 숫자 벡터로 표현하는 Vector Embedding을 활용하죠. 소스 문서는 텍스트 조각의 의미를 정확하게 담기 위해 더 작은 단위로 쪼개진 다음, 검색, 인덱싱, 저장을 거치게 돼요.

하지만 이 방법에는 한계가 있어요. Vector Search에만 의존하면 답변 내용이 검색된 텍스트 조각에 갇히게 되거든요. 그래서 답변이 불완전하거나 단편적으로 보일 수 있죠.

예를 들어, 사용자가 특정 제품 기능에 대해 질문했을 때, 벡터 전용 RAG 시스템은 그 제품을 언급하는 텍스트 조각만 찾아낼 수 있어요. 더 포괄적인 답변을 줄 수 있는 다른 관련 정보는 놓칠 수 있다는 거죠.

게다가 Vector Embedding과 Vector Search는 블랙박스처럼 작동해서 정보를 어디서 가져왔는지 설명하기 어려워요. 사용자와 개발자는 특정 텍스트 조각이 왜 검색되었고, 생성된 답변에 어떻게 기여했는지 알기 힘들다는 뜻이죠. 투명성과 책임이 중요한 의료나 금융 분야에서는 이런 설명력 부족이 큰 단점이 될 수 있어요.

이런 단점을 극복하기 위해 RAG 프로세스(검색, 확대, 생성)의 여러 단계를 개선하는 새로운 기술들이 등장하고 있어요.

LLM에 제공되는 정보는 답변의 품질에 엄청난 영향을 주기 때문에, 검색 메커니즘을 개선하는 게 가장 중요할 때가 많아요. GraphRAG는 Knowledge Graph에 저장된 구조화된 도메인 지식을 활용해서 검색 성능을 끌어올리는 방법이에요. Knowledge Graph의 풍부한 연결과 의미론적 관계를 이용해서 Vector Search 기반 RAG의 한계를 극복하고, 더 정확하고 설명 가능한 답변을 제공하는 게 목표죠.

데이터 표현을 위한 Knowledge Graph

Knowledge Graph는 연결된 요소로 데이터를 구조화해서 표현하는 데 아주 효과적이에요. 기존 데이터베이스처럼 엄격한 스키마를 강요하지 않아서 데이터 모델이 훨씬 유연하죠. 그래프 모델을 사용하면 풍부한 실제 정보를 효율적으로 저장, 관리, 쿼리하고 처리할 수 있어요. RAG 시스템에서 Knowledge Graph는 요약, 번역, 추출 같은 LLM의 언어 능력을 유연하게 보완해주는 메모리 역할을 해요.

Knowledge Graph에서는 사실과 개체가 다음과 같이 표현돼요. Nodes는 속성을 가지고, 연결된 Relationships 또한 자격에 대한 속성을 가질 수 있죠. 이 그래프 모델은 단순한 가계도에서부터 수백만, 수십억 개의 연결을 통해 직원, 고객, 프로세스, 제품, 파트너십, 리소스를 포괄하는 회사의 완전한 디지털 트윈까지 확장될 수 있어요.

그래프 구조는 구조화된 비즈니스 도메인, (계층적) 문서 표현, 그래프 알고리즘으로 계산된 신호 등 다양한 소스에서 시작될 수 있답니다.

GraphRAG 검색기를 위한 Graph Querying

다음과 같은 간단한 패턴을 따라 그래프를 탐색할 수 있어요. (node:Type)-[relationship:TYPE]->(node:Type) 또는 Cypher나 GQL 같은 Graph Query Language로 표현된 더 복잡한 형태로도 가능하죠. 패턴 매칭을 사용하면 SQL과 같은 다른 Query Language에서처럼 Node, Relationship, Attribute를 필터링, 집계 및 정렬할 수 있는 경로가 생성돼요. 다음은 Vector Embedding 검색에서 이웃 정보를 반환하는 Graph Query의 예시입니다.

CALL db.index.vector.queryNodes(docs, 5, $embedding) yield node as doc, score
RETURN score, doc, COLLECT { 
MATCH path = (doc)-[rel]-(neighbor)
RETURN path
} as paths
ORDER BY score DESC LIMIT 10

GraphRAG가 검색을 향상시키는 방법

GraphRAG 검색을 통해 다음을 찾을 수 있어요. 은 Vector, 전체 텍스트, 공간 또는 기타 검색을 통해 찾고, 이 데이터 네트워크에서 관련 Relationship을 따라 사용자 Query를 만족시키기 위해 추가 정보를 수집하는 거죠. 관련성을 높이기 위해 사용자와 작업의 컨텍스트가 고려돼요. 캡처된 모든 Node, Relationship 및 해당 Attribute는 증강 단계에서 컨텍스트로 반환되기 전에 필터링되고 순위가 매겨질 수 있답니다.

이 접근 방식은 Vector 전용 RAG 시스템에 비해 다음과 같은 몇 가지 장점을 제공해요.

  1. 그래프 구조를 탐색하고 관련된 relationships을 따라가면서, GraphRAG는 검색된 chunk의 초기 세트에서 직접 언급되지 않은 정보까지 검색할 수 있어서 더 포괄적이고 맥락에 맞는 답변을 제공할 수 있어요.
  2. 사용자의 상황과 작업에 맞춰 검색된 정보를 필터링하고 순위를 매기는 기능 덕분에, GraphRAG는 가장 관련성이 높은 정보의 우선순위를 정해서 답변의 퀄리티를 높일 수 있죠.
  3. GraphRAG는 검색된 정보 간의 relationships을 캡처해서 더 나은 설명 가능성을 제공하고, 답변 뒤에 숨겨진 출처와 추론을 더 쉽게 추적할 수 있도록 도와줘요.
  4. GraphRAG는 계산된 신호뿐만 아니라 구조화된 데이터와 구조화되지 않은 데이터를 통합하는 Knowledge Graph의 기능을 사용해서, 더 넓은 범위의 정보 소스에서 얻어지는 더 많은 정보와 미묘한 답변을 제공할 수 있어요.

검색 단계가 이렇게 개선되면서 GraphRAG는 벡터 전용 RAG 시스템보다 더 정확하고 관련성 높으며 추적 가능한 답변을 만들어낼 수 있는 거죠.

GraphRAG Retriever 유형

실제 그래프 검색은 사용 사례와 도메인에 따라 달라져요. 다양한 유형의 retriever를 결합할 수 있고, 결과의 순위를 매기거나 결합하거나 순서를 지정할 수도 있죠. 에이전트 설정에서 retriever는 LLM이 선택하고 반복적으로 실행해서 질문에 답하는 데 필요한 정보가 수집될 때까지 parameter와 결과를 전달하는 도구가 될 수 있어요.

GraphRAG retriever 유형의 예시를 몇 가지 살펴볼까요?

  • 벡터(embedding), 전체 텍스트, 공간 또는 기타 검색 index: 사용자 질문의 정보와 함께 index 검색을 사용해서 추가 탐색을 위한 그래프의 시작점을 결정해요.
  • : 정보를 context에 추가하기 위해 Node의 직접 또는 간접적인 이웃에 접근해요.
  • : 시작 entity 사이의 경로를 찾고, 이웃과의 relationships을 확장하고, 추가 관련 문서, claim 및 기타 entity를 검색해요.
  • 글로벌 Query: 사전 계산된 주제 간 요약 및 통찰력에 대한 기타 글로벌 표현을 사용해서 일반적인 질문에 답변해요 (Query 중심 요약이 포함된 Microsoft의 GraphRAG를 참고하세요).
  • : 질문 category에 대한 사용 사례별 Query는 도메인 전문가가 제공하며, 동일한 시작점을 가질 수 있지만 다른 하위 그래프를 탐색할 수 있고, 질문을 분류해서 선택할 수 있어요.
  • (Text2Cypher): (Fine-tuning된) LLM은 사용자 질문과 그래프 Schema 설명에서 Cypher Query를 생성해서 구체적이고 구조적인 질문에 답해요.
  • : LLM은 다양한 retriever를 사용해서 계획된 순서에 따라 이를 선택하고 실행해서 질문에 답하기 위한 모든 정보를 수집해요.
  • : embedding을 사용해서 Node 주변의 "본질"을 표현하고 후보 embedding을 일치시켜 퍼지 토폴로지 검색을 허용해요.

GraphRAG 패턴 카탈로그에서 더 많은 예제를 찾아볼 수 있어요. graphrag.com.

Knowledge Graph 구축

GraphRAG가 제대로 작동하려면 데이터가 관련성이 높고 연결된 정보 조각을 정확하게 나타내는 모양을 가지고 있는지 확인해야 해요. 이 Knowledge Graph를 만들려면 두 단계를 수행해야 하고, 이를 반복해서 개선할 수 있죠.

  1. 도메인 데이터를 나타내기 위해 관련 Node와 Relationship을 모델링해요.
  2. 이 그래프 모델에 맞게 그래프 구조를 가져오거나 생성하거나 계산해요.

다양한 데이터 소스를 통합할 수 있다는 점이 매력적이죠.

  • 데이터베이스, 파일 또는 API에서 기존의 구조화된 데이터를 가져올 수 있어요.
  • 구조화되지 않은 데이터(텍스트, 오디오, 비디오)를 문서 구조/계층의 그래프 표현으로 변환하고, 청크에 대한 Vector Embedding 및 전체 텍스트 Index를 추가할 수 있어요.
  • 텍스트 정보로부터 구조화된 엔터티(선택적 임베딩 포함)와 해당 Relationships를 구성하거나 연결할 수 있어요.
  • 주제 클러스터링 요약(예: Microsoft Query Focused Summarization), 유사성 Relationship 및 개인화된 페이지 순위(PPR) 점수와 같은 추가 계산 또는 알고리즘을 사용하여 기존 그래프를 더욱 풍성하게 만들 수 있어요.

이러한 그래프 모델과 소스는 GraphRAG 패턴 카탈로그에도 자세히 설명되어 있답니다.

Neo4j를 사용한 GraphRAG 예시

GraphRAG의 흔한 사용 사례는 단순히 "PDF로 채팅"하는 것보다 훨씬 더 깊이 있는 정보 분석이에요. Vector 기반의 Semantic Search 방식에서는 검색기에서 반환된 데이터가 도메인이나 서로의 개념과 어떻게 연결되는지에 대한 정보가 거의 없는 텍스트 덩어리일 뿐이죠.

하지만 GraphRAG 방식을 사용하면 문서에 나타나는 사람, 조직, 기사, 논문, 생물학적 프로세스, 상태, 질병, 약물, 유전자, 표현, 노출 및 경로와 같은 엔터티를 추출해서 풍부한 정보 네트워크를 구축할 수 있어요.

이걸 보여드리기 위해 오픈 소스를 사용해서 Knowledge Graph를 구성하는 예시를 한번 살펴볼까요? neo4j-graphrag 패키지를 사용하면 된답니다. LangChain, LlamaIndex 등과의 도 지원하고 있어요.

이 예시에서는 여러 기본 설정을 제공하고 아래 설명된 단계를 실행하는 SimpleKGPipeline을 사용할 거예요.

이 추출을 실행하기 위해 다음 구성 요소로 파이프라인을 구성할 거예요.

  • LLM(예: OpenAI의 gpt-4‌‌‌o-mini)
  • Embedding 모델
  • Graph 스키마

구성이 완료되면 생물의학 연구 논문 데이터 세트에서 파이프라인을 실행할 수 있어요.

driver = neo4j.GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USERNAME, NEO4J_PASSWORD))

ex_llm=OpenAILLM(
    model_name="gpt-4o-mini",
    model_params={
        "response_format": {"type": "json_object"},
        "temperature": 0
    }
)
embedder = OpenAIEmbeddings()

node_labels = ["Anatomy", "BiologicalProcess", ...]
rel_types = ["ACTIVATES", "AFFECTS", "ASSESSES",..."TREATS", "USED_FOR"]

kg_builder_pdf = SimpleKGPipeline(
    llm=ex_llm,
    driver=driver,
    text_splitter=FixedSizeSplitter(chunk_size=500, chunk_overlap=100),
    embedder=embedder,
    entities=node_labels,
    relations=rel_types,
    prompt_template=prompt_template,
    from_pdf=True
)

pdf_file_paths = ['biomolecules-11-00928-v2.pdf', 'GAP-between-patients-and-clinicians_2023_Best-Practice.pdf','pgpm-13-39.pdf']

for path in pdf_file_paths:
    graph_data = await kg_builder_pdf.run_async(file_path=path)

청크된 문서 데이터와 그래프 데이터를 Neo4j에 저장한 후 쿼리 도구를 사용하여 시각화할 수 있죠.

이제 GraphRAG 검색기를 실행하고 그 결과를 Vector RAG 검색기와 비교해 볼 수 있어요.

이 검색기는 먼저 인덱싱된 텍스트 청크에 대한 벡터 검색을 실행한 다음 최대 2홉 아웃까지 청크가 아닌 관계를 따라가면서 직접 추출된 엔터티뿐만 아니라 해당 엔터티의 1차 및 2차 이웃도 검색해요. 프롬프트 확대 및 답변 생성의 최종 단계에서 사용할 컨텍스트로 청크 텍스트와 엔터티-관계-엔티티 쌍을 반환하는 거죠.

from neo4j_graphrag.retrievers import VectorCypherRetriever

graph_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]-(entity)-[relList:!FROM_CHUNK]-{1,2}(nb)
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 apoc.text.join([c in chunks | c.text], '\n') + 
  apoc.text.join([r in rels | 
  startNode(r).name+' - '+type(r)+' '+r.details+' -> '+endNode(r).name],  
  '\n') AS info
"""
)

다음으로, 적절한 LLM(여기서는 더 나은 OpenAI gpt-4‌‌o 사용)과 함께 각 검색기를 사용하여 벡터 및 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'])

vector_rag  = GraphRAG(llm=llm, retriever=vector_retriever, prompt_template=rag_template)

graph_rag = GraphRAG(llm=llm, retriever=graph_retriever, prompt_template=rag_template)

q = "Can you summarize systemic lupus erythematosus (SLE)? including common effects, biomarkers, and treatments? Provide in detailed list format."

vector_rag.search(q, retriever_config={'top_k':5}).answer
graph_rag.search(q, retriever_config={'top_k':5}).answer

답변을 비교해보면 GraphRAG 응답이 훨씬 더 포괄적이고 관련 컨텍스트를 더 많이 포함하고 있다는 것을 알 수 있어요.

더 자세한 내용은 다음을 참조하세요. GraphRAG Python 패키지: Knowledge Graph로 GenAI 가속화 리소스 섹션을 확인해 보세요.

일반적인 GraphRAG 사용 사례

GraphRAG는 출력이 중요한 비즈니스 의사 결정에 사용되기 때문에, 더 높은 수준의 신뢰가 필요한 애플리케이션 및 도메인에 적합해요. 몇 가지 예를 들어볼까요?

  • 법률 및 규정 준수: 계약, 판례, 법률, 규정 등을 검토하고 분석하는 데 활용돼요.
  • : 조직, 사람, 경쟁사, 시장 및 동향을 조사하는 데 쓰이죠.
  • : 약물 발견 및 용도 변경, 임상 시험 및 연구를 위한 Knowledge Graph에 액세스하는 데 사용돼요.
  • : 다양한 비즈니스 데이터 소스를 조직의 응집력 있는 관점으로 통합하는 데 활용돼요.
  • : 제품 및 생산 프로세스의 위험 평가, 규정 준수, 지속 가능성에 대한 조사를 수행하는 데 쓰여요.
  • : 자금세탁(AML), 보험 사기, 기타 사기 행위를 식별하고 예방하는 데 사용돼요.
  • : 뉴스 기사 및 조사를 위해 대규모 데이터 세트에서 연관성과 패턴을 찾아내는 데 활용돼요.
  • 자연어 검색 및 챗봇: 사용자 친화적인 인터페이스를 통해 기존 지식 기반에 대한 액세스를 민주화하는 데 쓰이죠.

GraphRAG: 엔터프라이즈급 AI 앱 활성화

RAG 아키텍처는 현재 신뢰할 수 있는 데이터 소스의 데이터를 사용하여 GenAI 비즈니스 애플리케이션에 안정적인 콘텐츠를 제공하는 가장 효과적인 방법이에요. GraphRAG는 여기서 한 단계 더 나아가 품질과 설명 가능성 모두에서 기본 벡터 기반 RAG를 개선하죠.

보다 관련성이 높은 컨텍스트를 고려하고 문서, 도메인 및 계산된 그래프 구조를 탐색하는 다양한 검색기를 사용함으로써 GraphRAG는 더욱 정확하고 신뢰할 수 있으며 추적 가능한 결과를 제공해요. 실제 정보를 풍부하게 표현하는 Knowledge Graph와 고급 언어 기술을 갖춘 LLM을 결합하여 기업 사용 사례를 위한 강력하고 안정적인 솔루션을 만드는 거죠.

점점 더 많은 조직이 GenAI를 채택함에 따라 GraphRAG는 이러한 시스템의 정확성, 신뢰성 및 투명성을 보장하고 더 나은 의사 결정과 향상된 비즈니스 결과를 위한 길을 닦는 데 필수적일 거예요.

 

GraphRAG에 대해 더 자세히 알고 싶으시다면, 다음 자료들을 확인해보세요!

  • GraphRAG 선언문
  • Knowledge Graph란 무엇일까요?
  • Neo4j를 사용한 생성적 AI
  • GraphRAG 패턴 카탈로그
  • 온라인 Neo4j LLM Knowledge Graph 빌더(LangChain 사용)
  • Neo4j GraphRAG Python 패키지
  • RAG 과정을 위한 DeepLearning.AI Knowledge Graph
  • 무료 GraphAcademy GenAI 강좌
  • GraphRAG
  • RAG

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

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

728x90
반응형
728x90
반응형
  • News

분산 플랫폼의 Graph Database

TitanDB는 분산 클러스터 전체에서 확장되도록 설계되었어요. Cassandra에는 노드를 추가할 때 데이터베이스를 확장하는 분산 스토리지 엔진이 있죠. 이에 비해 선도적인 Graph Database인 Neo4j는 확장되고 마스터/슬레이브 아키텍처를 가지므로 확장을 위해서는 더 강력한 시스템이 필요해요. 클러스터 전반의 스토리지는 TitanDB의 장점이에요.

Neo4j와 Titan은 근본적으로 다른 접근 방식을 취하고 있다고 Neo4j의 창립자인 Emil Eifrem은 말했어요. 그는 성능과 신뢰성을 이유로 처음부터 Graph Database를 구축하기로 결정했다고 해요. 그래프용으로 구축되지 않은 데이터베이스 위에 Graph Database를 구축할 때 절충점이 발생하죠. Neo4j는 자체 관계형 데이터베이스 관리 시스템과 이를 위한 `Query` 언어를 구축했어요. 참고로 이 회사는 이번 주에 읽기 및 쓰기 확장성을 추가한 Neo4j 2.2를 발표했어요.

TitanDB는 다른 데이터베이스 위에 기본이 아닌 Graph Database를 구축하는 다른 접근 방식을 취해요. Eifrem은 Cassandra와 같은 데이터베이스가 대용량을 처리하고 많은 데이터를 수집하는 데 탁월하다고 말했어요. 그러나 그는 `Query`가 얼마나 빨리 실행되고 실시간 비즈니스 요구 사항을 얼마나 충족하는지에 대해 의문을 제기해요.

웹사이트에 따르면 OrientDB는 하이브리드 문서-그래프 엔진을 가지고 있어요. SQL을 기반으로 구축되었지만 트리 및 그래프 조작을 가능하게 하는 확장 기능을 추가하는 동시에 쓰기 작업에서 마스터-슬레이브 병목 현상을 극복하기 위해 다중 마스터 및 공유 아키텍처를 제공해요. 해당 사이트에는 Orient와 Neo4j의 차이점에 대한 자세한 비교 분석이 있어요.

여기에서 기사를 읽어보세요

Graph Database에 대해 더 자세히 알고 싶으신가요? 아래를 클릭하여 O'Reilly의 무료 전자책을 다운로드하고 지금 귀하의 애플리케이션에 그래프 기술을 사용하는 방법을 알아보세요.

  • Emil Eifrem
  • neo4j 2.2

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

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

728x90
반응형
728x90
반응형

Neo4j 그래프 데이터 과학 놀이터 애플리케이션 NEuler에서 그래프 임베딩 알고리즘 결과를 빠르게 검사합니다.

NEuler는 Neo4j에서 그래프 알고리즘을 실행하고 이해하는 데 도움을 주기 위해 설계된 그래프 데이터 과학 놀이터 애플리케이션이에요. 몇 번의 클릭만으로 예제 데이터를 가져오고, 다양한 그래프 알고리즘을 실행하고, 결과를 시각화할 수 있다니 정말 편리하죠? Neo4j 데스크탑의 확장 기능으로 사용할 수 있고, Neo4j 샌드박스와 함께 사용할 수도 있어요.

이번 블로그 포스팅에서는 영화 샌드박스 프로젝트를 사용해서 t-SNE 산점도를 통해 그래프 임베딩 결과를 빠르게 시각화하는 방법을 보여드릴게요.

Neo4j 샌드박스 환경 설정

이 링크를 따라가면 영화 샌드박스 프로젝트를 자동으로 생성할 수 있어요. 물론 다른 샌드박스 프로젝트를 선택해도 괜찮아요. Twitter, Open Street Map부터 접촉자 추적 프로젝트에 이르기까지 10개 이상의 샌드박스 프로젝트를 사용할 수 있답니다.

원하는 샌드박스 환경을 선택하고 생성한 후에는 드롭다운 메뉴에서 NEuler 애플리케이션을 선택해서 열어주세요.

Neo4j 샌드박스에서 NEuler 애플리케이션을 여는 방법

로그인 화면에 따라 온보딩 프로세스에서 기본 데이터베이스를 선택하세요.

온보딩 프로세스에서 기본 데이터베이스 선택

이제 NEuler 애플리케이션의 메인 화면에 도착해야 해요. 새로운 샘플 데이터세트를 가져오거나, 알고리즘 레시피를 실행하거나, 단일 알고리즘을 실행할 수 있죠.

이 블로그 포스팅을 따라 하려면 단일 알고리즘을 실행하도록 선택하세요.

단일 알고리즘 실행 옵션을 선택하세요.

이제 NEuler 애플리케이션에서 사용 가능한 모든 그래프 알고리즘을 볼 수 있어요.

NEuler에서 사용 가능한 그래프 알고리즘

30개 이상의 그래프 알고리즘을 사용할 수 있다니, 정말 많죠? 앞서 언급했듯이 여기에서는 그래프 임베딩 알고리즘을 실행하고 그 결과를 TSNE 산점도로 시각화하는 방법을 배울 거예요. 다음 중 하나를 선택하세요: Node2vec 또는 FastRP 연산. 둘 다 그래프 임베딩 알고리즘이에요. 그래프 임베딩 알고리즘은 그래프 구조 및 정보와 같은 속성을 최대한 유지하면서 그래프의 각 node에 대해 고정 길이 vector 표현을 계산해요. 이러한 임베딩은 그래프의 저차원 표현이며 그래프의 토폴로지를 보존한답니다.

그래프 임베딩 알고리즘에 대해 더 자세히 알고 싶다면 를 참고하세요.

이 예에서는 FastRP 알고리즘을 선택했어요. 기본 구성을 사용하거나 다양한 구성 매개변수를 테스트해서 결과에 어떤 영향을 미치는지 확인할 수 있어요. 저는 을 128로 설정하고 “표시할 행” 매개변수를 150으로 설정했어요.

FastRP 알고리즘 구성

이제 남은 일은 알고리즘을 실행하는 것뿐이에요!

FastRP 알고리즘의 결과

알고리즘이 완료되면 결과를 테이블 형식으로 볼 수 있어요. Each node has an embedding or a fixed-size vector assigned to it. 제 경우에는 임베딩 크기를 128로 사용했기 때문에 각 node의 vector 크기는 128이에요. 일반적으로 node 임베딩은 다운스트림 Machine Learning 워크플로에서 사용돼요. 임베딩 알고리즘 결과를 빠르게 검사하고 시각화하려면 왼쪽 메뉴에서 옵션을 클릭하세요.

그래프 임베딩 알고리즘 결과의 TSNE 산점도

NEuler 애플리케이션은 내부적으로 t-SNE 알고리즘을 사용해서 임베딩 차원을 2로 줄여요. 이렇게 벡터 차원을 2로 줄이면 산점도로 시각화하기 좋거든요. 다양한 알고리즘 구성을 실험하면서 임베딩 결과가 어떻게 달라지는지 확인해 보세요. NEuler 애플리케이션 외부에서 알고리즘을 실행하는 데 필요한 코드를 내보내고 싶다면, NEuler 애플리케이션의 Code 탭에서 생성된 코드를 복사하면 돼요.

Graph Embedding 알고리즘 FastRP를 실행하는 데 사용되는 생성된 코드

이 예제가 노드 임베딩 알고리즘을 시작하는 데 도움이 되었으면 좋겠네요. Neo4j Graph Data Science 플러그인을 사용하면 더욱 강력한 분석이 가능해요. Neo4j Desktop을 다운로드하거나, Neo4j Sandbox에서 네트워크 분석 및 그래프 알고리즘을 시작하는 프로젝트를 한번 사용해 보세요.

추신: NEuler는 네트워크 시각화도 지원한다는 사실! 애플리케이션에서 어떻게 사용하는지 자세히 알고 싶다면 를 참고하세요.

NEuler의 네트워크 시각화


  • Algorithm
  • Data Viz
  • Embedding

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

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

728x90
반응형
728x90
반응형

복잡하게 얽혀있는 정보를 이해하는 건 여러 분야에서 정말 중요한 과제인데요. 이 글에서는 이 문제를 해결하기 위한 새로운 AI 접근 방식을 소개하려고 해요. 기계가 데이터를 이해하고 탐색하는 방식을 개선하면, 법률 분석부터 과학 연구까지 다양한 분야에서 새로운 통찰력을 얻을 수 있는 가능성이 열린답니다. 특히, 대법원 판례 데이터 탐색을 통해 더욱 일관성 있는 그래프 구성을 위해 메타데이터 기반의 Ontology를 사용하는 새로운 방법을 소개해 드릴 거예요.

AI 시스템은 어떻게 추론할까요?

AI 추론은 계속 발전하고 있지만, 여전히 해결해야 할 과제들이 남아있어요. 어떻게 하면 정확하고 유연하게 추론할 수 있는 시스템을 만들 수 있을까요?

최근에는 Retrieval-Augmented Generation(RAG)과 같이 구조화된 지식 검색과 LLM의 생성 능력을 결합하여 이러한 격차를 해소하려는 시도가 이루어지고 있지만, 아직 갈 길이 멀답니다.

우리는 기계가 인간의 지능을 어떻게 시뮬레이션할 수 있을지에 대한 사고방식을 계속 발전시켜 나가고 있어요. 초기에는 추론을 논리와 규칙으로 풀어야 하는 수수께끼처럼 여겼죠. AI 시스템은 지식이 깔끔하게 정리된 전문가 시스템, 즉 Ontology (사실과 관계를 구조화해서 표현한 것)와 조건부 규칙으로 이루어져 있었어요. 예를 들어, MYCIN이라는 초기 AI는 의료 진단을 위해 설계되었는데, "if-then" 규칙을 적용해서 질병과 치료의 관계망을 탐색하고 정확하고 설명 가능한 결정을 내렸답니다.

하지만 이런 상징 체계는 결국 정해진 규칙만큼만 효과적이라는 문제가 있어요. 온톨로지랑 다르게, 실제 지식은 복잡하고 불확실하며 계속 변하잖아요. 이렇게 딱딱한 시스템은 새롭거나 예상치 못한 정보에 적응하기 어렵죠. AI가 좁은 영역을 벗어나려고 할수록, 추론이 엄격한 논리에만 갇혀 있을 수 없다는 게 분명해졌어요.

1990년대에는 또 다른 패러다임 전환이 있었는데, 바로 확률 모델의 등장이에요. 이런 시스템은 엄격한 규칙을 따르기보다는 통계를 사용해서 교육적인 추측을 하는 방식으로 불확실성을 받아들였어요. 예를 들어, 베이지안 네트워크를 사용하면 AI는 불완전한 정보를 바탕으로 다양한 결과가 나올 가능성을 확률적으로 추론할 수 있죠. 정말 중요한 발전이었어요! 이제 AI 시스템은 더 많은 모호성을 처리하고 데이터로부터 학습할 수 있게 되면서, 이전의 상징적인 시스템보다 훨씬 유연해졌으니까요.

하지만 이런 유연성에는 대가가 따랐어요. 확률 모델은 강력하지만, 상징 체계만큼 투명하지 않았거든요. 결정을 추적하고 설명하기가 더 복잡해졌죠. 추론 과정의 모든 단계를 볼 수 있었던 전문가 시스템의 해석 가능성은 일반화 및 확장 능력을 위해 희생된 셈이에요.

오늘날 AI 추론은 GPT-4, Llama 3 같은 Large Language Model(LLM)의 등장으로 계속 발전하고 있어요. 이런 모델들은 명시적인 규칙이나 확률보다는 엄청난 양의 데이터에서 학습된 패턴에 따라 추론하는 것처럼 보이거든요.

LLM은 인간 대화의 흐름을 흉내 내서 굉장히 상세하고 상황에 맞는 답변을 만들어내요. 연구자들은 LLM이 세상에 대한 "진짜" 이해를 나타내는 건지, 아니면 그냥 그런 "척"하는 건지에 대해 의견이 분분하죠. LLM이 실제로 추론 능력이 있든 없든, 이전에는 불가능했거나 자동화하기 매우 어려웠던 다양한 작업을 효과적으로 수행할 수 있다는 건 분명해요.

하지만 LLM은 강력한 만큼 단점도 있어요. 이전 시스템과 달리 구조화된 지식 기반이 부족해서 추론 과정이 불투명하죠. 설득력 있는 텍스트를 생성할 수는 있지만, 사실에 대한 확실한 근거가 없으면 엉뚱한 소리를 할 수도 있어요. 즉, 듣기에는 그럴듯하지만 실제로는 틀린 정보를 만들어내는 거죠. LLM의 이런 블랙박스 같은 특성은 AI의 근본적인 긴장, 즉 해석 가능성과 유연성 사이의 균형을 강조하고 있어요.

  1. LLM은 훈련 데이터에 의해 제한돼요.
  2. 환각 (Hallucination): LLM은 그럴듯하지만 잘못된 정보를 생성할 수 있어요.
  3. 최신 정보 부족: 실시간 또는 최근 업데이트된 데이터에 접근할 수 없어요.

Vector Database는 대부분의 Retrieval-Augmented Generation(RAG) 시스템의 핵심이에요. 문서 Vector Embedding을 효율적으로 저장하고 검색해서, 빠른 유사성 검색을 통해 관련 문서를 찾을 수 있게 해주죠. 이건 LLM에 정확하고 최신 정보를 제공하는 데 정말 중요해요.

GraphRAG: 한 단계 더 나아가기

RAG는 외부 지식에 접근하고 활용하는 AI 시스템의 능력을 크게 향상시켰지만, 한계가 없는 건 아니에요. RAG는 관련 문서를 찾는 데는 뛰어나지만, 서로 다른 정보 사이의 복잡한 관계망을 포착하고 활용하는 데는 어려움을 겪는 경우가 많아요.

GraphRAG는 Microsoft Research와 Neo4j 연구자들이 발표한 이후 업계에 등장한 새로운 개념이에요. Microsoft Research 와 에서 발표했죠. 지식을 그래프 구조로 표현해서 이런 단점을 해결하는 걸 목표로 해요. GraphRAG에 대한 접근 방식도 계속 발전하고 있어서, 앞으로 이 최첨단 분야에서 다양한 구현 방식을 보게 될 거예요.

이번 글에서는 LLM 중심 접근 방식(Microsoft GraphRAG 문서에서 설명하는 방식)과 그래프 구성 시 LLM에 대한 의존도를 줄이는 접근 방식을 비교해 볼 거예요.

LLM 중심 GraphRAG 접근 방식

GraphRAG는 그래프 기반 지식 표현을 도입해서 RAG를 기반으로 구축되었어요. 이 접근 방식을 사용하면 시스템은 다음과 같은 작업을 할 수 있어요.

  1. 지식을 그래프로 표현: GraphRAG는 문서를 고립된 단어 모음으로 취급하는 대신, 엔터티와 그 관계를 캡처해요. 이건 사람이 정보를 생각하고 연결하는 방식과 비슷하죠.
  2. 다중 홉 추론 활성화: GraphRAG는 관계 체인을 따라서 지식을 그래프로 표현함으로써 복잡한 Query에 답할 수 있어요. 이걸 통해 단순한 문서 검색을 뛰어넘는 더 정교한 추론이 가능해지죠.
  3. 더 상황에 맞는 결과 제공: 그래프 구조를 사용하면 시스템이 정보의 맥락을 더 잘 이해할 수 있어서, 더 미묘하고 관련성 높은 응답을 얻을 수 있어요.
  4. 구조화된 데이터와 구조화되지 않은 데이터를 결합: GraphRAG는 전통적인 지식 기반을 구조화되지 않은 텍스트와 통합해서 더 포괄적인 지식 표현을 만들 수 있어요.
  5. 설명 가능성 향상: 그래프 구조를 사용하면 추론 과정을 더 쉽게 추적할 수 있어서, 시스템의 투명성과 신뢰성을 높일 수 있죠.

GraphRAG 사용 사례

GraphRAG는 다음과 같은 다양한 사용 사례에 활용될 수 있어요.

  1. 의료 진단 및 치료 계획: GraphRAG는 증상, 질병, 치료 간의 관계를 네트워크로 표현해서 의료 진단을 향상시킬 수 있어요. 의사가 증상을 입력하면 관련 정보를 찾기 위해 의학 문헌을 검색하죠. 구조화된 의학 지식과 지능형 검색을 결합하면 의사가 놓칠 수 있는 복잡한 진단 경로, 희귀 질환, 예상치 못한 치료 상호 작용을 발견하는 데 도움이 될 수 있어요.
  2. : GraphRAG는 금융 생태계를 계정, 개인, 거래의 네트워크로 모델링할 수 있어요. 잠재적인 사기 행위를 조사할 때 관련 기록과 패턴을 검색하죠. 분석가는 구조화된 재무 데이터 표현과 AI 기반 Query 생성을 결합해서 자금 흐름을 추적하고, 페이퍼 컴퍼니를 식별하거나, 기존 분석에 숨겨져 있을 수 있는 조직화된 사기 활동을 찾아낼 수 있어요.
  3. : GraphRAG는 공급업체, 제조업체, 유통업체의 네트워크를 나타낼 수 있어요. 프로세스를 최적화할 때 관련 공급업체 정보와 시장 동향을 검색하죠. 이 접근 방식을 사용하면 병목 현상을 빠르게 식별하고, 경로를 최적화하거나, 중단 시 대체 공급업체를 찾을 수 있어요. 구조화된 공급망 표현과 유연한 분석을 통합하면 복잡한 글로벌 시장에서 더 탄력적이고 효율적인 운영에 대한 통찰력을 얻을 수 있답니다.

LLM 중심 GraphRAG 접근 방식의 한계

GraphRAG가 매우 유용할 수 있지만, 자체적인 문제점도 가지고 있어요.

  1. LLM 종속적인 그래프 구성: GraphRAG는 보통 LLM을 사용해서 Knowledge Graph를 구성하는데, 이 방식은 다음과 같은 결과를 초래할 수 있어요.
  • 그래프 구조의 불일치
  • 지식 표현의 LLM 편향 또는 오류 전파
  • 정보를 구성하는 데 사용되는 온톨로지에 대한 통제력 부족
  • : 그래프가 커지면 쿼리의 복잡성과 필요한 계산 리소스가 엄청나게 증가할 수 있어요.
  • 구조화된 데이터의 기반 부족: 그래프 구성 과정에서 기존의 구조화된 데이터(온톨로지나 메타데이터 등)를 제대로 활용하지 못할 수 있어요. 그래프 구성 작업을 LLM에 맡기면, 다중 홉 추론을 효과적으로 수행하기 어려울 정도로 가능한 Node 및 Edge 유형의 수가 폭발적으로 증가할 위험이 있죠.

이러한 제한 사항 때문에, 더 포괄적이고 통제된 지식 표현 및 검색 접근 방식이 필요하게 된답니다.

에이전트 그래프 탐색을 향한 길

데이터에 대한 추론은 여러 가지 형태로 나타날 수 있어요. RAG와 GraphRAG는 검색에 더 집중하는 반면, 저희는 Vector와 Graph Database를 함께 사용해서 구조화된 (그리고 궁극적으로는 자동화된) 데이터 탐색을 가능하게 하는 방법을 탐구하고 싶었어요. 기본적인 전제는 이렇습니다. Semantic Search를 사용해서 하위 그래프 필터링을 제한한 다음, 그래프 쿼리를 생성해서 ask and answer 상황에 맞는 질문을 던지는 거죠. 이 반복적인 탐색 과정은 수동으로 할 수도 있고, 에이전트 방식으로도 할 수 있어요.

이 접근 방식은 몇 가지 중요한 측면에서 GraphRAG와 다른데요, 이번 포스팅에서 자세히 살펴볼 거예요. 중요한 차이점 중 하나는, 그래프 구성을 위해 LLM에 의존하는 GraphRAG와는 달리, 저희는 메타데이터 데이터 세트 자체 (그리고 엔터티 및 관계에 대한 다른 "안정적인" 소스)에 내재된 정보를 활용한다는 점이에요. 이 메타데이터는 데이터의 기본적인 존재론적 구조를 형성하고, 이는 그래프에 그대로 반영된답니다.

앞으로 보여드리겠지만, 저희는 효과적으로 이 그래프에서 문맥상 관련 있고 유용한 답변을 얻을 가능성이 높은 쿼리를 만들 수 있어요. 이는 주로 그래프를 구성하는 제한된 방식 덕분이었죠.

잘 정의된 온톨로지에 따라 LLM이 생성할 수 있는 효과적인 쿼리의 수는, 엔터티 및 관계 유형에 부과된 제약에도 불구하고 실제로 증가해요. 이 접근 방식의 주요 이점은 다음과 같아요.

  1. : LLM은 엔터티 및 관계 유형을 제한함으로써 의미 있는 도메인별 연결에 집중하고 관련 없는 조합을 줄일 수 있어요.
  2. : 정의된 온톨로지는 도메인별 지식 구조에 맞춰 일관되고 상호 연결된 쿼리를 보장해 줘요.
  3. : 검색 공간이 좁아지면 뉘앙스에 대한 심층 분석이 가능해지고, 처리 속도가 빨라지며, 통찰력 있는 쿼리의 비율이 높아진답니다.

모든 데이터 세트가 이렇게 풍부한 메타데이터를 제공하는 건 아니에요. 그런 경우에는 온톨로지를 구성하고 적용하기 위한 대체 방법이 필요할 텐데요, 이 부분은 앞으로 다룰 포스팅에서 자세히 살펴볼 예정이에요. 하지만 지금은 그래프 구성을 안내하는 이러한 메타데이터 기반 방법에 집중해 볼게요.

 

저희 작업의 핵심은 다음과 같은 네 가지 주요 구성 요소를 결합하는 것이에요.

  1. 문서 데이터베이스(DDB): 문서, 기사 또는 기타 텍스트 기반 정보의 실제 콘텐츠와 같은 구조화되지 않은 원시 데이터를 저장하는 기반 역할을 해요.
  2. 벡터 데이터베이스(VDB): 문서의 고차원 Vector Embedding을 생성해서 Semantic Search를 가능하게 하고, 개념적으로 유사한 콘텐츠를 찾을 수 있게 해 줘요. (물론 Vector Database는 임베딩 모델의 사용에 의존하겠죠?)
  3. Graph Database(GDB): 이 유형의 데이터베이스는 엔터티(예: 사람, 장소 또는 기타 개념)를 Node로 나타내고, 이들 간의 관계를 Edge로 나타내기 때문에 상호 연결된 정보에 대한 복잡한 쿼리가 가능해요.
  4. LLM: LLM은 요약 및 그래프 쿼리 생성을 수행해요. 이 부분은 나중에 더 자세히 설명할게요.

시스템 흐름도를 한번 살펴볼까요?

의미 공간에서 그래프 쿼리까지

저희 작업 흐름은 에서 시작돼요. 문서, 문장, 단락 등 구조화되지 않은 원시 텍스트 데이터가 자연스러운 형태로 존재하는 곳이죠. 문제는 이 데이터를 도메인별 지식을 바탕으로 구조화되고 실행 가능한 데이터로 변환하는 것이에요.

저희 데이터는 두 개의 병렬 경로를 사용해요. 하나는 Vector Database로 이동하고, 다른 하나는 Graph Database로 이동하죠. 둘 다 원시 의미 데이터와 그래프를 구성하는 데 사용되는 메타데이터를 모두 포함하는 문서 저장소에서 시작된답니다.

  1. 그래프로 표시할 구조화된 문서: 저희는 문서의 구조를 분석하고, 문서로부터 개체와 관계를 추론하는 것부터 시작해요. 이는 데이터 세트의 온톨로지를 위한 기본 구성 요소를 제공하죠. 문서에서 발견된 모든 엔터티를 연결하는데, 문서 자체를 나타내는 Node를 포함해서요.
  2. 명명된 엔터티 인식(NER)을 통한 그래프 강화: 원시 데이터에서 보다 구조적으로 건전한 정보를 추출하기 위해, 저희는 구식 NER을 적용해서 텍스트에서 사람, 조직, 장소 등의 이름을 추출해요. 이 작업에 LLM을 사용하는 것과는 달리, 이 프로세스의 일부로 생성되는 관계 유형의 다양성은 상당히 제한적이어서 나중에 유용하게 사용될 거예요.
  3. 의미 공간에서 임베딩까지: 이 단계에서는 원시 텍스트를 고차원 벡터 표현, 즉 Vector Embedding으로 변환해요. 다른 RAG 프로세스와 마찬가지로 원시 텍스트 데이터를 더 작은 세그먼트로 나누어 포함하죠. 그런 다음 각 세그먼트가 포함되어 상위 문서를 가리키는 메타데이터와 함께 Pinecone에 저장돼요. 중요한 점은, 이 단계에서 사용된 문서 ID는 Graph Database에서 사용된 문서 ID와 일치한다는 거예요.
  4. RAG에 대한 Semantic Search: 다른 RAG 애플리케이션에서와 마찬가지로 검색된 일치 항목을 LLM의 컨텍스트로 사용해서 초기 쿼리와 관련된 요약을 생성해요. 이 요약 프로세스는 검색된 청크에서 주요 정보를 추출해서 사용자 쿼리에 대한 간결하고 관련성 높은 응답을 제공하는 데 도움이 되죠. 요약은 추가 탐색이나 보다 구체적인 후속 질문을 위한 출발점이 될 수도 있어요.
  5. 그래프 필터링으로서의 Semantic Search: 사용자가 쿼리를 수행하면 유사성 검색을 통해 청크를 찾아내요. 시스템은 일치하는 청크와 연관된 문서 ID를 반환하는데, 이는 Knowledge Graph의 Node ID에 해당하죠. 효과적으로 Semantic Search는 그래프를 필터링해서 초기 쿼리와 상황에 맞는 관련성을 갖는 Node와 Edge를 생성하는 거예요.
  6. 그래프 컨텍스트를 사용한 루프백: 이렇게 구조화된 그래프 컨텍스트를 가지고 시스템은 LLM으로 돌아가요. 이제 LLM은 이 그래프 기반 관점을 사용해서 더 정확하고 상황에 맞는 쿼리를 생성할 수 있죠. LLM은 맹목적으로 작동하는 대신 그래프로 정의된 관계와 제약 조건을 반영하는 쿼리를 작성해서 더 미묘하고 도메인 관련 질문을 할 수 있게 돼요.

데모 사용 사례: 대법원 사건 탐색

에이전트 그래프 탐색 접근 방식의 실제 적용을 보여주기 위해, 우리는 대법원 사건 탐색을 중심으로 한 예제를 개발했어요. 이 데모는 Semantic Search, Graph Database, 그리고 AI 기반 쿼리 생성 기능을 활용해서 우리 시스템이 어떻게 복잡한 법률 데이터에서 효과적으로 탐색하고 통찰력을 추출할 수 있는지 보여주죠.

우리가 선택한 대법원 사건 영역은 다음과 같은 여러 가지 이유로 이상적인 테스트 기반을 제공해요.

  • 사건, 판사, 법적 개념 간의 풍부한 상호 연결
  • 자연스럽게 그래프 표현에 적합한 구조화된 메타데이터
  • Semantic Search와 그래프 순회를 모두 활용하는 복잡한 쿼리

다음 섹션에서는 이 데이터를 처리하고 시스템을 활용해서 의미 있는 통찰력을 생성하는 방법에 대한 구체적인 내용을 설명할게요.

 

우리 파이프라인은 세 가지 주요 구성 요소에 걸쳐 원시 사례 데이터를 수집하고 처리하는 것으로 시작돼요.

  • 문서 데이터베이스(MongoDB): 각 사례의 전문과 메타데이터에 대한 기본 아카이브 역할을 해요.
  • 벡터 데이터베이스(솔방울): Vector Embedding을 통해 Semantic Search 기능을 활성화하죠.
  • Graph Database(Neo4j): 법률 영역 내의 복잡한 관계를 포착해서 Knowledge Graph의 기초를 형성해요.

파이프라인에 대한 자세한 분석은 다음과 같아요.

  1. 초기 수집 파이프라인:
    1. 에서 원시 데이터를 검색해요. Oyez API
    2. 검색된 HTML 데이터를 마크다운으로 변환하죠.
    3. Document DB에 데이터를 저장해요.

Raw → Document DB 파이프라인

  1. 우리는 각각에 내재된 메타데이터를 활용해서 온톨로지 기반 접근 방식을 적용해요.caseDocument DB에서:
  • 다음과 같은 주요 엔터티Case, Party, Justice, 그리고Advocate정의되죠 (처리 파이프라인– 셀 8)
  • 다음과 같은 관계advocated_by, decided_by , won_by데이터에서 파생돼요. (처리 파이프라인– 셀 14)
  • 데이터를 더욱 풍부하게 하기 위해 각 항목을 분석해요.opinion"좋은 구식" NER를 사용한 텍스트flair (처리 파이프라인– 셀 10).
  • All entities and relations다음과 같이 저장됩니다.nodes and edgesNeo4j에서.
  • 동시에 고급 Semantic Search를 준비해요.
  • 각 의견의 텍스트를 관리 가능한 덩어리로 나누죠.
  • 의미론적 본질을 포착하기 위해 각 청크를 Vector Embedding으로 변환해요.
  • 향후 의미론적 쿼리를 위해 이러한 임베딩을 벡터 데이터베이스에 저장하죠.

Document DB → Vector DB + GraphDB 파이프라인

 

Knowledge Graph와 임베딩을 적용한 후 데이터에서 통찰력 있는 쿼리를 생성하는 단계로 넘어갈게요.

프로세스는 포괄적인 맥락을 수집하는 것부터 시작해요(참조:graphStatsQueries.ts) :

  • : Node 수, 관계 유형 및 공통 속성에 대한 자세한 정보를 수집해서 데이터 환경에 대한 거시적인 보기를 제공해요.
  • : Node 및 관계 유형을 포함한 그래프 구조를 매핑하죠.

그런 다음 쿼리 생성기는 이 컨텍스트를 활용해서 Cypher 쿼리를 생성해요(참조: cypherQuestionsPromptBuilder.ts):

  • 타겟 분석을 위해 특정 관심 영역을 입력할 수 있어요.
  • 제로샷 학습 예시: 쿼리를 생성하는 방법에 대한 몇 가지 구체적인 예를 LLM에 제공하는 거죠. 이는 모델이 퍼지 일치, 선택적 일치 등을 활용하는 쿼리를 선호하는 데 도움이 돼요. 이 기술을 사용하면 쿼리 품질이 크게 향상된답니다.
  • Chain of Thought Prompting: 일반적으로 사용되는 Chain of Thought를 사용해서 생성된 쿼리의 품질을 향상시키는 일반적인 방법으로 문제에 접근하는 방법에 LLM을 집중시켜요.

Demo

 

AI 추론은 상당한 변화를 겪어왔고, 각 반복은 구조와 유연성 사이의 상충관계를 해결하기 위해 고심하고 있어요. 그래프 탐색에 대한 우리의 작업은 이러한 상충되는 요구 사항을 조정하기 위한 단계를 나타내죠. Semantic Search, Graph Database 및 LLM 기반 쿼리 생성을 통합함으로써 우리는 정밀성과 상황별 이해를 바탕으로 복잡한 데이터 세트를 탐색할 수 있는 시스템을 개발했어요.

우리의 대법원 사건 데모는 실제 애플리케이션에서 이러한 접근 방식의 잠재력을 보여주며, 메타데이터 기반 온톨로지가 복잡한 도메인에 대한 의미 있는 탐색을 어떻게 안내할 수 있는지 보여준답니다. 과제는 여전히 남아 있지만 이 방법은 AI 지원 지식 발견을 위한 새로운 길을 열어 잠재적으로 구조화된 시스템의 해석 가능성과 현대 언어 모델의 적응성 사이에 다리를 제공하는 것 같아요.

  • GenAI
  • RAG

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

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

728x90
반응형
728x90
반응형
  • 사이퍼 & GQL

Vector Search는 "가장 유사한 것이 무엇입니까?"에 대한 답을 찾는 데 효과적이에요. 하지만 실제 애플리케이션에서는 "가장 가까운 이웃"을 *모든 것*에서 찾고 싶어 하지는 않죠.

사용자들은 올바른 언어, 올바른 테넌트, 특정 기간 내, 재고가 있는, 보관되지 않은, 카테고리와 일치하는 가장 가까운 이웃을 보고 싶어 할 거예요.

Neo4j v2026.01에는 미리보기 기능으로 필터를 사용한 Vector Search가 도입되었어요. 조건자를 적용할 수 있는데, *Query 시 Vector Index 내부*에서 적용되죠. 따라서 Index는 기준과 일치하는 벡터만 포함하는 것처럼 동작해요. 이를 통해 초과 가져오기나 대규모 후보 스캔 및 사후 필터링에 의존하지 않고도 지연 시간을 낮게 유지하고 결과의 관련성을 유지할 수 있어요.

시사: Enterprise Edition, Community Edition 및 Neo4j Aura의 모든 계층에서 Cypher 25의 미리 보기 기능으로 Neo4j v2026.01에서 사용할 수 있어요. 미리 보기 기능은 평가 및 피드백을 위한 것이며 프로덕션 용도로는 지원되지 않아요. GA는 Neo4j v2026.02를 대상으로 해요. 전체 문서가 곧 공개될 예정이에요.

그리고 필터로 Vector Search를 보완하기 위해 다음도 출시합니다. 벡터 검색을 위한 기본 Cypher 구문. 이는 Query 작성을 간소화하고, Cypher 내부에서 고급 검색을 기본으로 만들고, 프로시저 호출의 필요성을 없애고, 고급 AI 및 GraphRAG 기능을 위해 데이터베이스를 준비하죠.

Vector Search 결과를 필터링하는 세 가지 방법

이제 필터링하는 대상과 보장해야 하는 대상에 따라 사용할 수 있는 세 가지 고유한 패턴이 있어요.

  1. 새로운 기능: 필터를 사용한 Vector Search(Index 필터링)
    검색 실행 중에 Vector Index 내부에 조건자를 적용해요.
  2. Vector Search 후 암호화(사후 필터링)
    필터 사용 여부에 관계없이 먼저 Vector Search를 실행한 다음 Cypher에서 결과를 구체화/확대해요.
  3. Vector Search 전 암호화(사전 필터링)
    Cypher를 사용하여 후보 하위 그래프를 정의한 다음 벡터 유사성을 기준으로 해당 후보에만 점수를 매겨요.

경험상 다음과 같아요.

  • Use 인덱스 내 필터링 필터가 단순한 속성에 대한 것이고 지연 시간이 짧은 일관된 검색이 필요한 경우.
  • Use 포함이 더 풍부한 그래프 논리에 따라 달라지거나 순회를 통해 결과를 확장하려는 경우.
  • Use 후보 세트를 제한적으로 정의할 수 있고 해당 세트 내에서 정확한 점수를 원하는 경우

Index 내 필터링을 사후 필터링과 결합하여 두 접근 방식의 이점을 모두 얻을 수 있어요.

1) 필터를 이용한 Vector Search(In-index 필터링)

이는 `index`가 필터 기준을 충족하는 `vector`만 포함하는 것처럼 동작해야 하는 경우에 이상적이에요. 테스트에서는 넓은(대부분의 데이터 포함) 필터와 좁은(대부분의 데이터 제외) 필터 모두에서 지연 시간이 낮게 유지되고 재현 정확도가 높게 유지되었어요. 가장 큰 단점은 `index` 생성 시 필터링된 속성을 식별해야 한다는 것이에요. 반면 `Cypher` 이후/이전 필터는 모든 `graph` 요소, 패턴 또는 속성을 기반으로 필터를 구성할 수 있는 `Cypher graph query`의 완전한 유연성을 제공하죠.

`Index` 만들기

`Vector index`를 생성할 때 `index`된 `node`/`relationship`에서 속성을 선택하여 각 `embedding`과 함께 메타데이터로 저장할 수 있어요. 아래 예에서는 문서의 작성자와 `published_year`가 `vector index`에 포함되어 있어요.

CYPHER 25

CREATE VECTOR INDEX documentIndex
  IF NOT EXISTS
  FOR (document:Document)
  ON document.embedding
  WITH [document.author, document.published_year]

`Index` 쿼리

`Query` 시 새로운 `SEARCH` 문의 `WHERE` 조건자는 일치할 수 있는 `index`화된 `vector`를 제한해요.

CYPHER 25

MATCH (document)
  SEARCH document IN (
    VECTOR INDEX documentIndex
    FOR $query_vec
    WHERE document.author = 'David'
    AND document.published_year >= 2020
    LIMIT $top_k
  ) SCORE AS score

RETURN document, score

`SEARCH` 문 내의 `WHERE` 절은 현재 `MATCH` 아래 `WHERE` 절의 하위 집합을 지원해요.

2) `Vector` 검색 후 `Cypher` (Post-filtering)

`SEARCH` 명령을 사용하여 `vector` 검색을 실행한 다음 `Cypher`를 사용하여 결과를 반환하기 전에 결과를 구체화, 검증 또는 확장할 수 있어요. 사후 필터링은 결과 포함 결정이 메타데이터로 표현될 수 있는 것보다 풍부한 `graph` 논리에 따라 달라지거나 `graph`를 탐색하여 관련 항목을 다시 가져오려는 경우에 특히 유용하죠.

필터링은 `vector` 검색 후에 발생하므로 속성을 `index`에 복사할 필요가 없지만 최종 결과 집합에는 요청된 k개보다 적은 결과가 포함될 수 있어요. 이를 보완하기 위해 원하는 결과 크기에 도달하기 위해 `query`를 과도하게 가져오거나 다시 `query`해야 할 수도 있어요.

CYPHER 25

MATCH (document)
  SEARCH document IN (
    VECTOR INDEX documentIndex
    FOR $query_vec
    LIMIT $ef_search
  ) SCORE AS score

MATCH (project:Project)<-[:WRITTEN_FOR]-(document)
      -[:WRITTEN_BY]->(author:Author)
  WHERE author.name = 'David'
    AND document.published_year >= 2020
    AND project.completed = true

RETURN document, project, author, score
  ORDER BY score DESC
  LIMIT $top_k

위의 `query`에서는 `$ef_search`를 사용하여 `vector index`에서 오버페치를 지정하고 `$top_k`를 사용하여 `query`에서 반환되는 결과 수를 제한했어요. 첫 번째 `SEARCH` 블록은 `WHERE` 필터를 사용할 수 있으므로 `Cypher`는 필터를 사용하여 `vector` 검색 결과를 확장하고 세분화할 수 있죠.

3) `Vector` 검색 전 `Cypher` (Pre-filtering)

사전 필터링에서 `Cypher`는 먼저 후보 하위 `graph`(예: 사용자가 볼 수 있는 모든 항목)를 식별해요. 그런 다음 `query`는 `query vector`와의 유사성을 기준으로 해당 후보의 순위를 매기죠. 이렇게 하면 일반적으로 `vector index`에서 반환되는 대략적인 결과(`ANN`)가 아니라 후보 세트에 대한 정확한 가장 가까운 이웃(`ENN`) 결과가 생성돼요.

사전 필터링은 `graph` 패턴 일치의 완전한 표현력을 제공하고 후보 세트에 대한 완벽한 재현을 보장할 수 있어요. 그러나 후보 세트가 매우 큰 경우(예: 수백만 개의 `vector`) `query`에서 직접 많은 `embedding` 점수를 매겨야 할 수 있으므로 성능이 확장되지 않을 수 있죠.

CYPHER 25

MATCH (project:Project)<-[:WRITTEN_FOR]-(document:Document)
      -[:WRITTEN_BY]->(author:Author)
  WHERE author.name = 'David'
    AND document.published_year >= 2020
    AND project.completed = true
  WITH document, project, author,
  vector.similarity.cosine(document.embedding, $query_vec) AS score

RETURN document, project, author, score
  ORDER BY score DESC
  LIMIT $top_k

성능

이러한 다양한 성능 특성을 보여주기 위해 간단한 `GraphRAG`에서 영감을 받은 데이터 모델을 만들고 10M `vector`를 로드했어요. 다음 단계는 `vector` 세트를 전체 데이터 세트의 다양한 비율(0.001% ~ 100%)로 제한하는 필터를 고안한 다음 위의 각 기술에 대한 `query`를 작성하는 것이었어요. 나는 `vector` 검색 후 `Cypher`에 대한 `query`를 두 번 테스트했어요. 한 번은 오버 페칭 없이, 또 한 번은 충분한 오버 페칭을 사용하여 일정한 리콜 정확도를 제공했죠.

예를 들어 위의 `query` 예는 내 데이터에서 실행될 때 동일한 `vector` 집합 또는 전체 `vector`의 약 0.1%로 제한돼요.

아래 차트는 필터 선택성(`X`축: 적합한 `vector`의 %)에 대한 `query` 대기 시간(ms)(`Y`축)을 표시해요. 각 포인트에는 % 재현율 정확도로 주석이 추가되어 있죠. 주요 시사점:

  • 검색 전 `Cypher`(녹색): `graph`를 사용하여 `vector`를 작은 세트로 빠르게 좁힐 수 있을 때 가장 좋은 성능을 발휘해요. 결과는 항상 100% 재현 정확도를 가지지만, 필터가 확장됨에 따라 철저한 검색은 계산 비용이 너무 많이 들고 대기 시간이 늘어나죠.
  • 검색 후 `Cypher`(파란색): 일관되게 수행되지만 필터의 범위가 좁아짐에 따라 점점 더 많은 결과가 필터링되어 재현율 정확도가 떨어져요.
  • 오버페치를 사용한 검색 후 암호화(노란색): 필터에 대응하기 위해 오버페치를 확장했더니, 90년대 수준의 높은 재현율 정확도를 꾸준히 얻을 수 있었어요. 하지만 필터가 좁아지면 오버페치가 증가해서 계산 비용이 너무 많이 들고 대기 시간이 늘어나는 문제가 생기죠.
  • 필터를 사용한 Vector Search(빨간색): HNSW 알고리즘은 인덱스 내부 속성을 필터링해서 벡터를 빠르게 필터링하고, 비교 비용을 절감하면서 가장 유망한 영역에서만 지능적으로 검색을 확장할 수 있어요. 지연 시간은 계속 낮게 유지되면서 재현 정확도는 높았답니다!

모든 기술은 동일한 인덱스 구성 및 쿼리 매개변수를 사용해서 동일한 머신 및 데이터세트(10M 벡터)에서 테스트했어요. 표시된 결과는 평균 대기 시간이고요. 재현율 정확도는 필터링된 후보 세트의 정확한 기준선을 기준으로 측정되었어요. 캐시가 예열된 상태에서 테스트를 10회 반복했답니다.

피드백

최근에 제품을 빠르게 출시하고 있는데, 이 기능은 그래프 + 검색을 최신 AI 및 RAG 스타일 워크로드를 위한 훌륭한 기반으로 만들기 위한 노력의 일환이에요.

저희 Vector Search 기능을 사용해 보셨다면, 어떤 점을 발견했는지 정말 듣고 싶어요! david.pond@neo4j.com으로 편하게 의견을 보내주세요. 무엇이 효과가 있었고 무엇이 효과가 없었는지, 그리고 무엇을 바꾸고 싶은지에 대한 솔직한 의견이 가장 도움이 될 것 같아요. 사용 사례와 가장 큰 장애물(있다면)에 대한 짧은 메모도 다음 단계의 우선순위를 정하는 데 큰 도움이 될 거예요.


  • 그래프RAG
  • Vector Search

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

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

728x90
반응형

+ Recent posts