Retrieval 도구 사용해 보기 - Assistants API 베타 사용법
리트리벌 (Knowledge Retrieval)
retrieval 은 가져오다, 검색이라는 뜻이다.
Knowledge Retrieval은 모델 외부의 지식을 가져와서 생성할 때 활용할 수 있는 기술이다. 파일을 올리면 해당 파일의 내용을 지식으로 가지게 된다. 그리고 필요할 때 이를 가져와서 활용할 수 있다.
원리는 파일을 올리면 이를 임베딩할 수 있게 적절하게 자르고, 이를 임베딩한 후 벡터 데이터베이스에 저장하는 것이다. 이후 사용자가 질문을 할 때 사용자의 프롬프트를 임베딩으로 바꾸어 관련 정보를 벡터테이터베이스에서 가져온다. (벡터 검색) 그리고 이를 사용자의 질문에 문맥으로 첨부하여 대답한다. 이러한 과정을 RAG (Retrieval Augmented Generation) 이라고 한다.
나는 이 retrieval 이 인공지능 앱의 꽃이라고 생각한다. 이를 활용한 앱들이 많아질 것이다. (GPTs에서도 물론 사용할 수 있다.) 이 RAG 과정을 직접 구축할 수 도 있지만 OpenAI에서 이를 편하게 사용할 수 있게 도구로 준비해 놓았다.
임베딩
임베딩이란? 임베딩은 문장을 어떤 특징들을 가진 수치들로 바꾸는 것이다. 인공지능은 모든 데이터를 수치화하여 벡터로 만들어서 이해한다. 예를 들어 OpenAI의 임베딩은 1536차원의 벡터인데 값이 1536개인 배열이라고 보면 된다.
[1234, 2346, 345345, ... ,234234, 2342347]
이렇게 인공지능은 논리적 특성을 나름의 수치로 변환하여 저장을 하기 때문에 이를 통해 의미 검색을 할 수 있다. 어떤 문장과 다른 문장의 벡터 값이 비슷하다면 의미론적으로 비슷하다고 볼 수 있기 때문이다. 이를 통해 인공지능이 의미를 이해하고 일종의 추론을 진행할 수 있다.
검색도 마찬가지로 벡터 값이 비슷하다면 비슷한 의미를 가진다고 볼 수 있다. 일종의 시맨틱 검색이 가능해 진 것이다. 이를 기존의 검색과 다르게 구분하기 위해 인공지능에서는 이를 리트리벌이라고 부른다. 골든 리트리버라는 개가 사냥감을 가져온다는 특성이 있다는 것을 생각하면 외우기 쉽다.
참고 : https://platform.openai.com/docs/assistants/tools/knowledge-retrieval
작동방식
사용자의 메시지에 따라 필요할 때 자동으로 지식을 가져온다. 가져오는 방식은 다음과 같다.
짧은 문서의 경우 내용을 그냥 다 가져온다.
긴 문서에 대해서는 벡터 검색을 수행한다.
이런 식으로 하이브리드 방식이다. 현재는 좋은 결과를 위해 가져온 결과를 모두 첨부하지만 나중에는 이를 조정할 수 있을 것이라고 한다.
파일 업로드 하기
리트리벌을 하기 위해서 파일을 올려보자. 먼저 retrieval.py 를 만들고 다음 내용을 작성했다.
from openai import OpenAI
import time
client = OpenAI(api_key="YOUR_API_KEY")
file = client.files.create(
file=open("tilnote-how.md", "rb"),
purpose='assistants'
)
assistant = client.beta.assistants.create(
instructions="You are a customer support chatbot. Use your knowledge base to best respond to customer queries.",
model="gpt-4-1106-preview",
tools=[{"type": "retrieval"}],
file_ids=[file.id]
)
print(assistant)
지식 베이스 (Knowledge base)를 통해 고객 상담을 해주는 챗봇을 만들어 보자. 도구에 retrieval
을 전달하고 file_ids
에 file.id
를 전달하면 된다.
파일은 샘플로 틸노트 사용법을 마크다운 파일로 (md) 준비해 놓았다. 필요하면 여기에서 다운로드 받을 수 있다. tilnote-how.md 파일을 다운로드 받아 retrieval.py
와 같은 폴더에 저장한다.
이제 실행하고 여기서 나오는 assistant의 id를 잘 저장해 두자.
python retrieval.py
참고로 파일은 스레드 레벨에서도 업로드가 가능하다.
message = client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="I can not find in the PDF manual how to turn off this device.",
file_ids=[file.id]
)
파일은 최대 512MB 까지 가능하며 .pdf
, .md
, .docs
등 거의 대부분의 파일 형식을 지원한다. 전체 파일 형식은 여기에서 확인이 가능하다. 총 20개까지 업로드할 수 있으며 기관 당 최대 업로드 용량은 10GB이다.
retrieval 사용해 보기
이제 실제 리트리벌을 사용해 보자! 먼저 이전에 에이전트 생성 코드는 주석처리 하고, 다음과 같이 작성해 보자.
# Upload a file with an "assistants" purpose
# file = client.files.create(
# file=open("knowledge.md", "rb"),
# purpose='assistants'
# )
# Add the file to the assistant
# assistant = client.beta.assistants.create(
# instructions="You are a customer support chatbot. Use your knowledge base to best respond to customer queries.",
# model="gpt-4-1106-preview",
# tools=[{"type": "retrieval"}],
# file_ids=[file.id]
# )
# print(assistant)
# 위의 생성 코드는 에이전트 중복 생성이 될 수 있기 때문에 꼭 주석처리.
# 여러분의 어시스턴트 ID를 입력해 주세요.
assistant = client.beta.assistants.retrieve("YOUR_ASSISTANT_ID")
thread = client.beta.threads.create()
message = client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="틸노트의 사용법을 알려줘.",
)
run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant.id,
)
print("run을 실행합니다.")
while True:
if run.status == "completed":
break
run = client.beta.threads.runs.retrieve(thread_id=thread.id, run_id=run.id)
print(run)
print("실행 중...")
time.sleep(5)
messages = client.beta.threads.messages.list(thread_id=thread.id)
print(messages)
run의 상태를 출력하고 완료가 되면 메시지를 출력하는 코드이다. 먼저 run의 상태를 보자.
Run(id='run_VGSWdwcbkkYta2J1OzAjFmZF', assistant_id='asst_aKuUXx1R30tD0yPRvpMSvF0r', cancelled_at=None, completed_at=1700621853, created_at=1700621782, expires_at=None, failed_at=None, file_ids=['file-9OwMQWTPstvpp9i91T9lOtRO'], instructions='You are a customer support chatbot. Use your knowledge base to best respond to customer queries.', last_error=None, metadata={}, model='gpt-4-1106-preview', object='thread.run', required_action=None, started_at=1700621782, status='completed', thread_id='thread_6WPtTeXNNOu2yJakhkD0W3mD', tools=[ToolAssistantToolsRetrieval(type='retrieval')])
tools
에 retrieval
이 사용되고 있는 것을 알 수 있다.
그리고 마지막으로 메시지에 표시된 응답이다.
MessageContentText 객체에 응답이 잘 표시된 것을 확인할 수 있다. 이로써 나의 지식을 바탕으로 동작할 수 있는 에이전트를 완성해 보았다!