Graph Database에서 검색된 정보를 바탕으로 답변을 제공하는 챗봇을 구현하는 방법을 알아볼까요?
Not so long ago, OpenAI added Chat API, which is optimized for generating conversations. The main difference between Chat and the older Completion APIs is that the Chat API allows specifying the conversation history. While the Completion API could be used for single-turn tasks like text generation, summarization, and similar, the Chat API is designed more for conversational tasks like chatbots or customer support. The ability to provide a dialogue history or the context of the conversation gives the model a better ability to answer additional or follow-up questions.
불과 한 달 전에 Knowledge Graph 기반 챗봇을 구현하는 방법에 대한 글을 썼었어요. 여기서는 Completion API, 특히 text-davinci-003 모델을 사용해서 사용자 프롬프트를 기반으로 Cypher 문을 생성했죠. 하지만 Completion API는 대화 기록을 인식하지 못하기 때문에, 관심 있는 개체에 대한 프롬프트에서 아주 구체적이어야 해요. 예를 들어 모델이 참조하는 내용에 대한 context가 없기 때문에 후속 질문에서는 it, they 또는 she와 같은 대명사를 사용할 수 없다는 거죠.
하지만 Chat API를 사용하면 이 문제를 해결할 수 있어요. 그래서 저는 새로운 GPT-4와 GPT-3.5 터보 모델을 시험해보고, Knowledge Graph에서 정보를 가져오는 챗봇에 어떻게 사용될 수 있는지 평가해보기로 결정했어요.
Knowledge Graph 기반 챗봇 설계
최근에 등장하는 수많은 애플리케이션에서 알 수 있듯이 챗봇은 다양한 애플리케이션에 사용될 수 있어요. ChatGPT와 같은 LLM의 한 가지 중요한 문제는 잘못된 정보를 제공하면서도 모든 질문에 자신 있게 답변할 수 있다는 것, 즉 환각 (Hallucination) 현상이에요.
환각 (Hallucination)은 일부 영역에서는 허용되지만, 다른 영역에서는 허용되지 않죠. 특정 정보를 환각 (Hallucination)하지 않도록 모델을 재교육하는 것도 어려운 일이에요. 하지만 Graph Database와 같은 지식 기반을 사용해서 챗봇의 답변을 뒷받침한다면, 챗봇이 제공할 수 있는 답변을 완전하고 총체적으로 제어할 수 있을 거예요.

모든 과정은 사용자가 프롬프트를 입력하는 것으로 시작돼요. 프롬프트와 대화 기록은 Cypher 구문을 생성하기 위해 GPT-4 엔드포인트로 전송되죠. 그런 다음 반환된 Cypher 구문은 Neo4j 데이터베이스를 쿼리하는 데 사용되고요. 데이터베이스 결과를 사용자에게 직접 반환할 수도 있지만, 데이터베이스 결과를 대화 컨텍스트와 함께 보내 자연어처럼 보이는 텍스트를 답변으로 생성하는 것이 훨씬 더 나은 사용자 경험을 제공할 수 있어요. 여기서는 GPT-3.5 터보 모델을 사용해서 답변을 만들어 볼 건데요, 이 모델이 GPT-4만큼 충분히 괜찮으면서 훨씬 저렴하거든요. 마지막으로 생성된 응답을 사용자에게 다시 보내면 끝!
정말 놀랍도록 쉬워 보이고, 실제로 구현하기도 꽤 간단해요. 코드는 에서 확인하실 수 있습니다.
Neo4j 환경 및 데이터 세트
가장 먼저 Neo4j 환경을 구성해 볼게요. 사용 가능한 데이터세트는 추천 프로젝트 Neo4j 샌드박스에서 제공하는 MovieLens 데이터 세트입니다. 가장 쉬운 방법은 이 링크를 통해 Neo4j Sandbox 인스턴스를 생성하는 거예요. 하지만 Neo4j의 로컬 인스턴스를 선호하신다면, GitHub에서 사용할 수 있는 데이터베이스 덤프를 이용하시면 됩니다.
Neo4j 데이터베이스가 인스턴스화되면, 다음 스키마로 채워진 그래프가 있어야 해요.

데이터베이스에는 영화, 배우, 감독, 장르에 대한 정보가 담겨 있어요. 영화에 대한 사용자 평가 정보도 포함되어 있고요. 다음 APOC 프로시저를 통해 데이터베이스 크기를 확인할 수 있습니다.
CALL apoc.meta.stats YIELD
nodeCount, relCount, labels

데이터베이스에는 거의 30,000개의 Node와 165,000개가 조금 넘는 Relationship이 있어요. **Label** 열은 Label당 Node 수를 보여주죠. 예를 들어, 거의 10,000편의 영화와 20,000명의 사람이 있네요. Person Node에는 Actor 또는 Director라는 보조 Label이 있을 수 있는 것 같아요. 데이터셋이나 Cypher에 대해 좀 더 먼저 알고 싶다면 Sandbox 환경에 포함된 브라우저 가이드를 따라가면 돼요.
GPT-4를 사용하는 English2Cypher
사용자 입력을 기반으로 Cypher 문을 생성하는 것은 챗봇에 정말 중요한 부분이에요. 쿼리가 작동하지 않으면 쿼리를 수정할 사람이 없기 때문에 유효한 Cypher 문을 안정적으로 생성할 수 있어야 하죠. 또한 모델은 대화 기록에서 맥락을 파악할 수 있어야 하고요.
OpenAI의 ChatCompletion 엔드포인트는 현재 **GPT-3.5-turbo**와 **GPT-4** 모델을 지원해요. 저는 처음에 GPT-3.5 터보 모델을 사용해봤는데, 결과를 사과하거나 설명하지 말라는 지시를 자주 무시해서 대화 기록을 기반으로 Cypher 문을 생성하는 데 적합하지 않다는 걸 금방 알게 됐어요. GPT-3.5-터보는 사과를 너무 좋아해서 캐나다산이라는 소문도 있다니까요! 게다가 GPT-4는 상황을 이해하고 훈련 예제를 통해 학습하는 데 훨씬 뛰어나요.
아직 GPT-4에 액세스할 수 없더라도 GPT-3.5-turbo를 사용할 수 있어요. 코드에는 원치 않는 사과와 설명을 정리하는 기능이 포함되어 있답니다.
먼저, 우리는 **Schema** 메시지를 정의해야 해요. 여기에서 모델의 역할을 Cypher 문 생성기로 정의하고, 모델이 설명하거나 사과해서는 안 되는 몇 가지 제약 조건을 설정하는 거죠. 또한 훈련 예제를 기반으로 추론할 수 없는 Cypher 문을 구성하는 것을 원하지 않아요.
system = f"""
You are an assistant with an ability to generate Cypher queries based off example Cypher queries.
Example Cypher queries are: n {examples} n
Do not response with any explanation or any other information except the Cypher query.
You do not ever apologize and strictly generate cypher statements based of the provided Cypher examples.
You need to update the database using an appropriate Cypher statement when a user mentions their likes or dislikes, or what they watched already.
Do not provide any Cypher statements that can't be inferred from Cypher examples.
Inform the user when you can't infer the cypher statement due to the lack of context of the conversation and state what is the missing context.
"""
예를 들어 훈련 예제의 정보만 사용해야 한다는 제약 조건을 두지 않는다고 가정해 볼까요? 이 경우, 아무리 부정확하더라도 모든 사용자 입력에 대해 Cypher 문을 생성할 수 있을 거예요.
저는 몇 가지 다른 데이터 세트에 대한 그래프 스키마 또는 샘플 Cypher 문 제공을 기반으로 ChatGPT의 기능을 평가해봤어요. 그런데 샘플 Cypher 문을 제공하는 게 항상 더 나은 옵션인 것 같아서, 이제 이게 GPT 모델을 사용해서 Cypher 문을 생성하는 기본 접근 방식이 되었죠.
다음 예를 사용해서 GPT-4에 피드해볼게요.
examples = """
# I have already watched Top Gun
MATCH (u:User {id: $userId}), (m:Movie {title:"Top Gun"})
MERGE (u)-[:WATCHED]->(m)
RETURN distinct {answer: 'noted'} AS result
# I like Top Gun
MATCH (u:User {id: $userId}), (m:Movie {title:"Top Gun"})
MERGE (u)-[:LIKE_MOVIE]->(m)
RETURN distinct {answer: 'noted'} AS result
# What is a good comedy?
MATCH (u:User {id:$userId}), (m:Movie)-[:IN_GENRE]->(:Genre {name:"Comedy"})
WHERE NOT EXISTS {(u)-[:WATCHED]->(m)}
RETURN {movie: m.title} AS result
ORDER BY m.imdbRating DESC LIMIT 1
# Who played in Top Gun?
MATCH (m:Movie)<-[:ACTED_IN]-(a)
RETURN {actor: a.name} AS result
# What is the plot of the Copycat movie?
MATCH (m:Movie {title: "Copycat"})
RETURN {plot: m.plot} AS result
# Did Luis Guzmán appear in any other movies?
MATCH (p:Person {name:"Luis Guzmán"})-[:ACTED_IN]->(movie)
RETURN {movie: movie.title} AS result
# Recommend a movie
MATCH (u:User {id: $userId})-[:LIKE_MOVIE]->(m:Movie)
MATCH (m)<-[r1:RATED]-()-[r2:RATED]->(otherMovie)
WHERE r1.rating > 3 AND r2.rating > 3 AND NOT EXISTS {(u)-[:WATCHED|LIKE_MOVIE|DISLIKE_MOVIE]->(otherMovie)}
WITH otherMovie, count(*) AS count
ORDER BY count DESC
LIMIT 1
RETURN {recommended_movie:otherMovie.title} AS result
"""
우리는 단 7개의 Cypher 예제만 제공했지만, GPT-4는 Cypher를 잘 이해하고 있어서 이런 예제를 사용해서 훈련 예제에 나타나지 않는 Cypher 문도 생성할 수 있어요. 대부분의 경우, 모델에게 `Node`를 탐색하거나 필터링할 때 사용할 `Relationship`과 `Property`를 가르치는 거죠.
이제 대화를 기반으로 Cypher 문을 생성하는 함수를 정의해볼 수 있어요.
@retry(tries=2, delay=5)
def generate_cypher(messages):
messages = [
{"role": "system", "content": system}
] + messages
# Make a request to OpenAI
completions = openai.ChatCompletion.create(
model="gpt-4",
messages=messages,
temperature=0.0
)
response = completions.choices[0].message.content
# Sometime the models bypasses system prompt and returns
# data based on previous dialogue history
if not "MATCH" in response and "{" in response:
raise Exception(
"""GPT bypassed system message and is returning response
based on previous conversation history""" + response)
# If the model apologized, remove the first line
if "apologi" in response:
response = " ".join(response.split("n")[1:])
# Sometime the model adds quotes around Cypher when it wants to explain stuff
if "`" in response:
response = response.split("```")[1].strip("`")
return response
모델이 사과하는 경우는 항상 응답의 첫 번째 줄이나 문장에 나타나죠. 추가적으로 원치 않는 추가 설명을 제공할 경우, Cypher 문 주위에 "`" 따옴표를 붙여주는 친절함도 보여주고요. 이 두 가지 데이터 정리 단계는 GPT-3.5 터보 모델과 더 관련이 깊어요.
모델이 시스템 메시지를 완전히 우회하고 이전 대화에서 메시지를 반환하는 경우에도 예외가 발생하는데요. 예를 통해 이 시나리오를 더 잘 이해할 수 있을 거예요.
print(generate_cypher([
{'role': 'user', 'content': 'What are some good cartoon?'},
{'role': 'assistant', 'content': 'Shrek 3'},
{'role': 'user', 'content': 'Which actors appeared in it?'}]))
# MATCH (m:Movie {title: "Shrek 3"})<-[:ACTED_IN]-(a:Person)
# RETURN {actor: a.name} AS result
이 예시에서는 모델에 대화 기록을 일부러 줘보는 거예요. 모델이 대화의 맥락을 학습하도록, 생성된 이전 Cypher 쿼리를 주지 않고, 해당 Cypher 쿼리를 사용해서 Neo4j에서 얻은 답변을 주는 거죠. GPT-3.5-turbo를 쓰면 이전 대화에서 Cypher 쿼리를 주지 말라고 5번이나 말해도, 안 준 것에 대해 사과할 거예요. 하지만 GPT-4는 안 그러죠. 하지만 제공된 대화 기록을 기반으로 학습하고, 가끔은 시스템 메시지를 완전히 우회해서 슈렉 3 결과를 내놓고, 결국 Cypher 쿼리를 생성해야 할 때도 있어요.
GPT에 독점 코드나 정보를 넣으면 안 된다는 생각은 당연한 거죠. 제 대화 기록은 커스텀으로 생성되고, 모델이 전달한 이전에 생성된 Cypher 쿼리는 포함되지 않기 때문에, 학습 과정이 얼마나 명확한지에 대한 뉴스가 나온 것도 당연하고요.
그리고 훈련 예제에서 추론할 수 없는 입력이 주어졌을 때 모델이 뭘 하는지 제한할 수도 있어요.
print(generate_cypher([
{'role': 'user', 'content': 'What are some good cartoon?'},
{'role': 'assistant', 'content': 'Shrek 3'},
{'role': 'user', 'content': 'Who was the first person on the moon?'}]))
# I can only provide Cypher queries based on the provided examples.
# Please ask a question related to the examples or provide a new Cypher query example.
하지만 제약 조건이 있어도 그걸 안 지킬 수도 있어요. 아마 GPT-4를 점검하기 위한 더 나은 Prompt Engineering 옵션이 있을 거예요.
Graph2Text
퍼즐의 두 번째 조각은 Graph Database에서 얻은 결과를 기반으로 자연스러운 텍스트를 생성하는 거예요. 이전처럼, 생성된 텍스트가 더 사실적으로 들리도록 대화 기록을 포함하려고 해요. 여기서는 훨씬 저렴하고 자연어 텍스트를 생성하는 데 충분하니까 GPT-3.5-turbo를 쓸 수 있어요.
몇 번의 시행착오를 거쳐서 다음과 같은 시스템 메시지를 만들었어요.
system = f"""
You are an assistant that helps to generate text to form nice and human understandable answers based.
The latest prompt contains the information, and you need to generate a human readable response based on the given information.
Make it sound like the information are coming from an AI assistant, but don't add any information.
Do not add any additional information that is not explicitly provided in the latest prompt.
I repeat, do not add any information that is not explicitly given.
"""
정보가 AI 비서로부터 오는 것처럼 들리게 하는 지침을 추가하면, 데이터베이스 결과를 요약하는 대신 봇과 대화하는 것처럼 들리게 돼요. 하지만 AI 비서처럼 행동하라고 지시하면 응답에 알고 있는 추가 정보를 추가하려고 하죠. 우리는 GPT-3.5 터보가 결과를 환각으로 만들 수 있고, 데이터베이스나 모델에서 나온 정보를 구별하는 게 불가능하기 때문에 이걸 막고 싶어요. 그래서 GPT-3.5-turbo는 한 번만 설명하는 내용을 따르면 좋지 않기 때문에, 추가 정보를 추가하지 않기 위해 세 문장을 추가했어요. 시스템 프롬프트에서는 사과하지 말라고 지시하는데, 제가 캐나다인이기 때문에 그렇게 안 할 수는 없네요.
데이터베이스 결과로부터 자연어를 생성하는 기능은 다음과 같아요.
def generate_response(messages):
messages = [
{"role": "system", "content": system}
] + messages
# Make a request to OpenAI
completions = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages,
temperature=0.0
)
response = completions.choices[0].message.content
# If the model apologized, remove the first line or sentence
if "apologi" in response:
if "n" in response:
response = " ".join(response.split("n")[1:])
else:
response = " ".join(response.split(".")[1:])
return response
여기서는 모델이 텍스트를 생성한 방법을 설명할 필요를 못 느껴서, 사과만 필터링하면 돼요.
다음 예제에서 함수를 테스트할 수 있어요.
data = [{'actor': 'Sigourney Weaver', 'role': "Witch"},
{'actor': 'Holly Hunter', "role": "Assassin"},
{'actor': 'Dermot Mulroney'},
{'actor': 'William McNamara'}]
print(generate_response([{'role': 'user', 'content': str(data)}]))
#The list contains four actors and their respective roles.
#Sigourney Weaver played the role of a witch, while Holly Hunter portrayed an assassin.
#The roles of Dermot Mulroney and William McNamara were not specified.
저는 JSON이나 사전 객체를 사용하는 게 데이터베이스 결과와 함께 일부 컨텍스트를 제공하는 가장 좋은 방법이라고 생각해요. 그런 식으로 사전 키를 사용해서 값 컨텍스트로 모델을 제시할 수 있죠. 예를 들어 모델은 이제 배우와 각자의 역할이 제공됐다는 걸 알게 되는 거예요.
Streamlit을 이용한 챗봇 구현
저희는 Streamlit Chat 패키지를 사용해서 챗봇의 사용자 인터페이스를 개발했어요. 사용하기 쉽고 간단한 데모에 딱 좋죠. 모든 코드를 다루진 않고, 제가 중요하다고 생각하는 부분만 짚어드릴게요. 챗봇 구현은 에서 언제든지 확인하실 수 있어요.

저희 챗봇에서 중요한 부분은 생성된 Cypher 문과 데이터베이스 결과에 대한 정보를 대화 기록과 함께 저장하는 거예요. Streamlit의 session_state 메서드를 사용해서 관련 정보를 저장하죠.
# Generated natural language
if 'generated' not in st.session_state:
st.session_state['generated'] = []
# Neo4j database results
if 'database_results' not in st.session_state:
st.session_state['database_results'] = []
# User input
if 'user_input' not in st.session_state:
st.session_state['user_input'] = []
# Generated Cypher statements
if 'cypher' not in st.session_state:
st.session_state['cypher'] = []
OpenAI의 ChatCompletion 엔드포인트가 예상하는 형식으로 대화 기록을 구성하는 함수도 정의해야 해요.
def generate_context(prompt, context_data='generated'):
context = []
# If any history exists
if st.session_state['generated']:
# Add the last three exchanges
size = len(st.session_state['generated'])
for i in range(max(size-3, 0), size):
context.append(
{'role': 'user', 'content': st.session_state['past'][i]})
context.append(
{'role': 'assistant', 'content': st.session_state[context_data][i]})
# Add the latest user prompt
context.append({'role': 'user', 'content': str(prompt)})
return context
이 예시에서는 사용자와 어시스턴트 간의 최대 3번의 대화만 사용해서 대화 컨텍스트를 구성해요. 그러니까 최대 6개의 메시지(사용자 3개, 어시스턴트 3개)를 보내는 거죠. 사용자 메시지는 항상 user_input 세션 상태를 사용하고, 어시스턴트 메시지에 대한 입력으로 사용해야 하는 세션 상태를 지정할 수 있어요. 기본적으로는 generated 세션 상태를 사용하고요.
마지막으로 사용자 입력을 처리하는 방법을 정의해야겠죠?
if user_input:
cypher = generate_cypher(generate_context(user_input, 'database_results'))
# If not a valid Cypher statement
if not "MATCH" in cypher:
print('No Cypher was returned')
st.session_state.user_input.append(user_input)
st.session_state.generated.append(
cypher)
st.session_state.cypher.append(
"No Cypher statement was generated")
st.session_state.database_results.append("")
else:
# Query the database, userID is hardcoded
results = run_query(cypher, {'userId': USER_ID})
# Harcode result limit to 10
results = results[:10]
# Graph2text
answer = generate_response(generate_context(
f"Question was {user_input} and the response should include only information that is given here: {str(results)}"))
st.session_state.database_results.append(str(results))
st.session_state.user_input.append(user_input)
st.session_state.generated.append(answer),
st.session_state.cypher.append(cypher)
생성된 모든 Cypher 구문에는 MATCH 절이 있어야 해요. 만약 없다면 GPT-4 모델이 우리에게 뭔가를 말하려 할 가능성이 높죠. 예를 들어, 컨텍스트가 제공되지 않아 프롬프트를 확인할 수 없는 경우 Cypher 구문을 반환하지 않을 거예요.

그렇지 않고 모델이 사용자 입력을 기반으로 유효한 Cypher 구문을 생성할 수 있다면, 해당 Cypher 구문을 사용해서 Neo4j 데이터베이스를 쿼리하고, 결과를 사용해서 자연어처럼 들리는 답변을 만들 거예요. 학습 예시의 대부분 Cypher 구문에는 LIMIT가 설정되어 있지 않아서, 각 쿼리에서 최대 10개의 결과를 표시하도록 수동으로 제한을 추가했어요.
또한 데이터베이스를 업데이트하는 쿼리에서는 userID가 모델이 아닌 애플리케이션에서 제공하는 파라미터라는 점도 기억해주세요.
예시 대화 흐름
이제 예시 흐름에서 챗봇을 테스트해 볼 수 있어요.

트레이닝 세트에는 제목을 기준으로 영화를 찾을 수 있는 예제가 포함되어 있어요. 이 예에서는 Pokémon 영화를 검색했는데요. 이제 모델에 후속 질문을 할 수 있죠.

대화의 맥락을 제공했기 때문에 모델은 어떤 영화가 참조되고 있는지 추론할 수 있어요. 하지만 아쉽게도 GPT-3.5-터보 모델은 세 번이나 그렇게 하지 말라고 명시적으로 밝혔음에도 영문판(영어로는 X라고도 함)에 대한 추가 정보를 추가하기로 결정했네요. 자연어 텍스트를 생성하는 GPT-4를 사용하여 동일한 흐름을 테스트해 봤어요.

GPT-4를 Natural Language Generation 모델로 사용해서 모델에 의해 원치 않는 추가 정보가 추가되는 것을 방지할 수 있었어요.
다음 예에서는 GPT-4를 텍스트 생성 모델로 사용할 건데요. 대화 흐름을 재현하고 싶을 때 약간 혼란스러워서 포기했답니다. 대부분의 경우 GPT-3.5 터보로 충분하지만, 가끔 아쉬운 순간이 있더라구요.
또 다른 후속 질문을 할 수도 있겠죠.

여기서 저는 꽤 흥분했는데요! 훈련 예제를 기반으로 새로운 Cypher 쿼리를 추론하는 GPT-4의 능력은 정말 놀라워요. Cypher 자체를 잘 이해하고 있고, 주어진 그래프 스키마를 파악했을 때 성능이 엄청 좋더라구요.
데이터베이스를 업데이트하는 Cypher 문을 생성하는 훈련 예제도 추가했답니다.

그리고 우리가 좋아하는 영화도 알려줄 수 있죠.

이제 우리가 어떤 영화를 좋아하는지 알게 됐으니, 이걸 활용해서 우리가 좋아할 만한 영화를 추천해 줄 수 있어요.

영화를 추천하기 위해 협업 필터링의 기본 변형을 사용하는 교육 예제에 간단한 추천 쿼리를 추가했어요. 간단히 말해서, 그래프에서 볼 수 있는 영화 등급을 활용하는 거죠. 사용자가 우리와 같은 영화를 좋아했다면 우리가 보지 않은 다른 영화가 무엇인지 조사해서 가장 자주 본 영화를 추천하는 방식이에요.
저는 다양한 흐름을 테스트하고 있었는데 챗봇이 어떻게 작동하는지 정말 흥미로웠어요. 예를 들어, 모델이 추천을 다시 추측하게 만들려고 노력했죠.

다음은 모델이 시스템 메시지를 완전히 재정의하는 또 다른 예시인데요. English2Cypher 부분에는 Cypher 구문만 생성하고 다른 건 만들지 않도록 명시적으로 지시했는데, 이 예시에서는 대화 기록에서 사용할 수 있는 권장 사항을 그냥 반복하고 Cypher 구문을 만들지 않았어요.
GPT-4와 GPT-3.5-turbo는 결정적이지 않다는 점! 즉, 결과가 달라질 수도 있다는 거죠.
하지만 대화 기록을 제공하고 데이터베이스에 정보를 유지하는 기능이 있다면, 정말 다양한 애플리케이션에서 훌륭한 사용자 경험을 만들 수 있을 거예요.

다중 언어 기능
자주 언급되지는 않지만 GPT-3.5-turbo와 GPT-4는 여러 언어를 이해한답니다. 저도 간단하게 테스트해 봤어요.

정말 놀랍지 않나요? 모델에 몇 가지 영어 예제를 줬는데, 이제 여러 언어로 사용이 가능하다니! 게다가 응답도 적절한 언어로 제공된다는 점이 포인트에요.
마지막으로, 플롯이 원래 영어로 되어있으니까, 자동으로 플롯을 번역하는지도 한번 테스트해보고 싶었어요.

GPT-4에 제공된 플롯 정보는 다음과 같아요.
"As students at the United States Navy's elite fighter weapons school compete
to be best in the class, one daring young pilot learns a few things from a
civilian instructor that are not taught in the classroom."
그리고 모델은 질문에 사용된 것과 동일한 언어로 답변을 번역해야 한다는 걸 알고 있어요. 번역에 대해 너무 걱정하지 않고, 전 세계적으로 정보나 콘텐츠를 가져올 수 있는 모든 가능성을 상상해 보세요!
요약
OpenAI의 Chat Completion 엔드포인트를 추가하면 더욱 사람과 비슷한 대화를 만들 수 있어요. 대화 기록에 제공된 정보에 의존하는 후속 질문에 답변하는 데 아주 유용해서 전체 토론을 훨씬 원활하게 만들어주죠. 사용자는 자신의 의미를 이해하는 사람과 대화하고 있는 것처럼 느낄 수 있을 거예요.
가능하면, 특히 Cypher 쿼리를 생성할 때 GPT-4를 사용하는 게 좋아요. 지침을 따르고 주어진 작업을 이해하는 데 더 뛰어나기 때문이죠. 하지만 현재로서는 모델이 이전 대화 기록을 모델의 훈련 사례로 사용하는 방법을 직접 봤기 때문에 비공개 또는 독점 데이터에 대해 GPT 모델을 사용하지 않을 거예요. Knowledge Graph 기반 챗봇을 사용하면 꽤 분명해졌는데요. 모델은 Cypher 쿼리만 반환해야 하지만, 시스템 지침을 무시하고 대화 컨텍스트를 이해하는 데 사용된 이전에 제공된 데이터베이스 결과를 반환하기로 몇 번 결정했거든요.
언제나 그렇듯이 모든 코드는 에서 확인할 수 있어요.
- 채팅GPT
- gpt-4
- 네오GPT
- NLP
에이치시스템즈의 LogTree는 Neo4j 기반 GraphRAG 플랫폼으로, 데이터를 자동으로 지식그래프화하고 자연어 질의로 즉시 답을 제공합니다.
'Agent AI' 카테고리의 다른 글
| AI 팀은 왜 프롬프트 엔지니어링에서 컨텍스트 엔지니어링으로 이동하고 있을까 (0) | 2026.04.06 |
|---|---|
| 에이전트 기반 AI 시스템을 위한 최적의 Context Engineering 도구 (0) | 2026.04.06 |
| Neo4j로 GraphAcademy 교육 챗봇 구축하기 (1) | 2026.04.05 |
| 바운더리 그래프: 그래프 렌즈로 IPL 탐험하기 (1) | 2026.04.05 |
| crewAI와 Neo4j로 자동 보고서 생성 에이전트 구현하기 (0) | 2026.04.04 |