Rough Experiments with Llamafile and LLaVA 1.5

Michael Lynch

Llamafile과 LLaVA 1.5로 해본 거친 실험

Simon Willison의 글을 읽었습니다. Llamafile을 이용해 오픈소스 챗봇/LLM을 실험하는 방법에 대한 글이었는데, 너무 쉬워 보여서 직접 한번 해보기로 했습니다.

오랫동안 취미로 운영해 온 프로젝트 중 하나는 라이브 코미디 공연을 찾아주는 사이트인 WanderJest입니다. 이 사이트의 어려운 점 중 하나는 다가오는 공연에 대한 가장 정확한 정보가 대체로 포스터에만 담겨 있다는 것입니다. 예를 들면 다음과 같습니다:

지금까지 이 정보를 일일이 수작업으로 모아 왔는데, 번거롭고 시간도 많이 듭니다.

Simon은 Llamafile을 이용하면 이미지에 대해 챗봇에게 질문할 수 있게 해주는 모델인 LLaVA 1.5를 쉽게 실행할 수 있다고 언급했습니다. 만약 LLaVA가 포스터에서 원하는 정보를 모두 뽑아낼 수 있다면 WanderJest에서 겪고 있는 문제를 자동화할 수 있을 것 같았습니다.

CPU 기반 LLaVA 1.5

먼저 Debian Bookworm을 실행하는 Scaleway PRO2-S VM 인스턴스를 하나 띄워 보았습니다. 어떤 VM을 써도 상관없지만, Scaleway 서버를 편리하게 띄울 수 있는 인프라를 갖추고 있어 이 인스턴스를 선택했습니다.

Llamafile의 웹 인터페이스에 접속할 수 있도록 포트 포워딩을 활성화한 상태로 서버에 SSH로 접속했습니다:

ssh mike@$MY_SCALEWAY_IP -L 8080:localhost:8080

Simon의 안내에 따라 서버를 실행하기 위한 바이너리를 다운로드했습니다:

curl -LO https://huggingface.co/jartine/llava-v1.5-7B-GGUF/resolve/main/llava-v1.5-7b-q4-server.llamafile && \
  chmod 755 llava-v1.5-7b-q4-server.llamafile

그리고 서버를 실행했습니다:

./llava-v1.5-7b-q4-server.llamafile --nobrowser

정상적으로 동작했고, 브라우저에서 웹 인터페이스를 확인할 수 있었습니다:

공연 포스터를 업로드해 보았는데 아무런 반응이 없었습니다. 포스터를 업로드하고 질문까지 입력해야 한다는 것을 알게 되었습니다.

시작부터 썩 매끄럽지는 않았습니다. 세 명의 이름이 모두 틀렸고, 실제 이름을 그럴듯하게 변형해 환각을 만들어 냈습니다.

User: 이 포스터에 나와 있는 출연자는 누구인가요?

Llama: 이 포스터에 나와 있는 출연자는 Ayeshah Mae, Jennifer Myskowski-Szynski, Ayisha Mae입니다.

이 답변을 생성하는 데 약 1분이 걸렸습니다. 표시된 통계는 다음과 같았습니다:

토큰당 130ms, 초당 7.67토큰

다른 질문도 해 보았습니다:

User: 이 공연은 어디에서 열리나요?

Llama: 이 코미디 쇼케이스는 펜실베이니아주 래스멜에 있는 Luthier’s Co-op에서 열릴 예정입니다.

이번에도 어느 정도는 맞추었지만 정확도는 70% 정도에 그쳤습니다.

정보를 JSON 형식으로 받을 수 있을지도 궁금해서 시도해 보았지만, LLaVA가 JSON으로 답하도록 만드는 것이 쉽지 않았습니다. “다음 질문에 JSON으로 답해 줘”라고 해도 지시를 무시하고 일반 영어로 답변했습니다.

논문에서 LLaVA 저자들은 LLaVA가 JSON으로 응답하도록 유도한 예시를 보여주었습니다:

논문에 나온 LLaVA에게 JSON으로 응답하도록 요청한 예시

논문에 나온 형식을 그대로 따라 해 보았지만 아무런 응답도 돌아오지 않았습니다:

User: 이 이미지의 텍스트를 읽고 다음 JSON 형식으로 정보를 반환해 주세요 (xxx는 자리표시자이며, 이미지에 정보가 없는 경우 “N/A”로 표기하세요). {“title”: xxx, “date”: xxx, “time”: xxx, “performers”: xxx, “hosts”: xxx, “location”: { “address”: xxx, “city”: xxx, “state”: xxx, “zipCode”: xxx}}

서버 로그를 보니 요청 처리는 끝났지만 아무 응답도 돌아오지 않았습니다.

다시 시도해 보니 이번에는 JSON을 성공적으로 생성했지만, 여전히 많은 정보를 환각으로 만들어 냈습니다:

User: 이 이미지의 텍스트를 읽고 다음 JSON 형식으로 정보를 반환해 주세요 (xxx는 자리표시자이며, 이미지에 정보가 없는 경우 “N/A”로 표기하세요). {“title”: xxx, “date”: xxx, “time”: xxx, “performers”: xxx, “hosts”: xxx, “location”: { “address”: xxx, “city”: xxx, “state”: xxx, “zipCode”: xxx}}

Llama: {“title”: “Luther’s Coop Comedy Showcase”, “date”: “December 2nd”, “time”: “7:00 PM - 9:30 PM”, “performers”: [“Ayisha M. Quinn”, “Jennifer Myskowski-Szczykowski”], “hosts”: [“Molly Hyne & Matt Woodland”], “location”: { “address”: “109 Court St, Framingham, MA”, “city”: “Framingham”, “state”: “MA”, “zipCode”: “01702”}}

맞춘 것도 몇 가지 있었습니다:

  • “Matt Woodland”라는 이름을 정확히 추출했습니다
  • 날짜가 12월 2일임을 정확히 파악했습니다
  • 주가 MA임을 정확히 파악했습니다

하지만 그 외 나머지는 크고 작게 모두 틀렸습니다. 흥미롭게도 01702는 매사추세츠주 프레이밍햄(Framingham)의 우편번호인데, 포스터에는 없는 정보이므로 다른 곳에서 끌어온 것이 분명합니다. 하지만 공연 장소는 프레이밍햄이 아닙니다.

CUDA를 이용한 GPU 기반 LLaVA 1.5 실행 실패

LLM 파라미터에 대해서는 아는 것이 없지만, 설정을 조정하면 더 나은 결과가 나올지 시도해 보고 싶었습니다. 문제는 CPU로 처리할 때 질문 하나에 답하는 데 약 1분이나 걸려서 이것저것 실험하기에는 너무 느리다는 점이었습니다.

Scaleway GPU-3070-S 인스턴스를 하나 띄워 보기로 했습니다. 이 인스턴스에는 8GB VRAM을 탑재한 NVIDIA 3070 GPU가 있어 제가 하던 CPU 기반 처리보다 훨씬 빠를 것으로 예상했습니다.

Llamafile이 GPU를 사용하도록 하려면 Linux에 CUDA를 설치해야 했는데, 생각보다 상당히 어려웠습니다. NVIDIA에서 공식 설치 안내를 제공하지만 내용이 매우 복잡했습니다.

여러 차례 실패한 끝에 NVIDIA의 안내를 다음과 같이 수정했고, 이를 통해 Scaleway의 Ubuntu 22.04 GPU 최적화 OS에 CUDA를 설치할 수 있었습니다:

sudo apt-get install linux-headers-$(uname -r) && \
  sudo apt-key del 7fa2af80 && \
  echo "deb [signed-by=/usr/share/keyrings/cudatools.gpg] https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/ /" | sudo tee /etc/apt/sources.list.d/cuda-ubuntu2204-x86_64.list && \
  wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-ubuntu2204.pin && \
  sudo mv cuda-ubuntu2204.pin /etc/apt/preferences.d/cuda-repository-pin-600 && \
  sudo apt-get update && \
 sudo apt-get install -y cuda-toolkit

그리고 다시 Llamafile을 다운로드했습니다:

curl -LO https://huggingface.co/jartine/llava-v1.5-7B-GGUF/resolve/main/llava-v1.5-7b-q4-server.llamafile && \
  chmod 755 llava-v1.5-7b-q4-server.llamafile

그리고 서버를 실행했습니다:

./llava-v1.5-7b-q4-server.llamafile --nobrowser

모든 과정이 정상적으로 진행되었고, 서버 로그에도 VM의 GPU를 사용하고 있다고 표시되었습니다. 이미지를 업로드하고 질문을 입력해 보니 서버가 다음과 같은 오류와 함께 다운되었습니다:

CUDA error 2 at /home/mike/.llamafile/ggml-cuda.cu:6006: out of memory

GPU VRAM이 두 배인 Scaleway의 더 고성능인 RENDER-S 인스턴스로 다시 시도해 보았지만 같은 오류로 다운되었습니다.

비슷해 보이는 llama.cpp GitHub 이슈가 하나 있었는데, “피닝(pinning)”을 비활성화하면 해결된다고 해서 다음과 같이 시도해 보았습니다:

export GGML_CUDA_NO_PINNED=1
./llava-v1.5-7b-q4-server.llamafile --nobrowser

여전히 다운되었습니다.

StackOverflow 글에서 CUDA가 배치 크기가 너무 크면 RAM이 부족해질 수 있다는 내용을 읽고, 다음과 같이 다시 실행해 보았습니다:

./llava-v1.5-7b-q4-server.llamafile --nobrowser --batch-size 1

하지만 결과는 마찬가지였습니다.

CUDA를 이용해 GPU 기반 LLaVA 1.5 실행에 성공하기

업데이트(2023-12-04): 마침내 동작시키는 데 성공했습니다.

Scaleway에 더 높은 사양의 GPU 사용 권한을 요청하는 지원 티켓을 제출해야 했습니다. 240GB RAM과 80GB VRAM을 갖춘 Scaleway H100-1-80G 인스턴스로 시도해 보니 모든 것이 정상적으로 동작했고, CPU에서 실행했을 때보다 10.6배 더 빨랐습니다.

GPU에서 LLaVA를 실행하는 것이 CPU에서 실행하는 것보다 10.6배 빨랐다

마무리

기본 설정의 LLaVA 1.5는 공연 포스터에서 정보를 파싱하려는 제 문제에는 맞지 않는 것 같습니다.

몇 시간 정도만 실험해 본 것이기 때문에, 설정을 조정하면 제대로 동작할 수도 있을 것 같습니다.

내년 한 해 동안 오픈소스 AI 모델이 계속 발전하고 더 접근하기 쉬워지기를 기대합니다.

원문은 Michael Lynch님이 에 게재했습니다.

이 글은 muse-spark-1.2-contributor 모델을 사용해 번역했습니다.