ks.dgoon.lee log

로컬에서 언어모델 사용하기: llama


2024/12/29 18:33:04 #dev #ai #productivity #linux #server #headless #AI #llama #openwebui #llm #playwright

몇년 전, 리얼리티 랩에서 하는 사업들 방향이나 파트너와의 협업 방향성에 뜨악하고(국내 어딘가에서 했던 개발자 행사에 가서 직접 들었다) 그날 밤에 메타 주식을 다 팔아버렸었다.

근래에 메타에서 llama3 를 발표할때 주커버그의 연설을 들으면서, "좀 나아졌나?" 싶은 생각이 들었다. 오픈소스 모델, 그리고 거대 장비로만 돌릴 수 있는 언어모델이 아닌 엣지 디바이스에서 실행할 수 있는 작은 언어모델에 대한 비전을 들으며 그럴싸하다고 느낀 것이다. 하지만 내가 "작은 언어모델을 직접 돌리는" 일이 생길것 같진 않다는 생각을 했는데, 인생은 모르는 일. 왠걸 정말 그런 일이 생겼다.


  • 사람이 손으로 모은 1만 7천개 정도의 데이터가 들어있는 엑셀 파일이 있다. 이 엑셀 파일은 특정 토픽에 대한 업체 정보 모음이다.
  • 눈으로 대강 훝어보며 랜덤하게 찍어서 확인해보는데, 가끔 전혀 관련 없는게 들어있다. 예를 들어서, 어떤 지역의 식당 리스트를 모아달라고 했는데, 보건소나 도서관이 끼어 있는 식이다.
  • 컬럼 중 하나는 구글지도 URL 이다.


이런 상황이다. 내가 1만 7천개의 항목을 모두 검수하는 것은 말도 안 된다. 시간도 시간이고 내가 이걸 정확하게 수행할 수 있을리가 없다. 그렇다고 이걸 다시 사람에게 의뢰해봤자 또 다른 오류가 중첩될 것 같다. 그래서 코드를 만들기 시작.


  • pandas로 엑셀 파일을 열어서 구글지도 URL 컬럼을 읽는다
  • Playwright 를 사용해서 브라우저에서 해당 URL 을 연다
  • 화면에서 업체 이름과 카테고리를 가져온다
  • 컬럼에 있는 업체명과 카테고리와 일치하는지 1차 검증
  • 업체명과 카테고리가 "내가 지정한 토픽" 에 속하는게 맞는지 2차 검증
  • 최종적으로 구글지도에서 가져온 업체명, 카테고리, 2차검증 결과를 새로운 컬럼으로 만들어서 저장


이런 일을 하는 코드를 만들었다. 여기서 2차 검증은 chatgpt 한테 물어보는걸로 해 두었다. 그리고 열댓개쯤 돌려 보니 의도대로 동작하는 것을 확인했다. 그런데, chatgpt 한테 1만 7천개를 모두 물어봐야 하나? 얼마지??? 생각이 든다. 이렇게 돈을 펑펑 써도 되나!?? 지금이야 몇만개 정도인데, 이거 갈수록 엄청 늘어날텐데...

1분간고민끝에, RTX 3090 이 설치된 서버니까 로컬에서 언어모델 돌릴 수 있지 않을까 해서 ollama API 를 써보기로 했다. 안그래도 OpenWebUI 설치해서 claude, chatgpt, gemini 등 연결해서도 쓰고 Local 에서도 이것저것 돌려보고 있어서 ollama 는 이미 설치되어 있다. localhost:11434 에 요청 보내고 응답 받기만 하면 되는 것이다. 


import requests
import json

# Ollama API URL
url = "http://localhost:11434/api/chat"

def is_related_to_topic(word, topic, model='llama3.2:3b'):
    """
    Check if the given word is related to a specific topic using the specified model.

    Args:
        word (str): The word to check.
        topic (str): The topic to check against.
        model (str): The model to use for the check (default is 'llama3.2:3b').

    Returns:
        str: 'Y' if related, 'N' if not, '?' if an error occurs.
    """
    data = {
        "model": model,
        "messages": [
            {
                'role': 'user',
                'content': f"The word '{word}' is related to {topic}? Answer in only 'Y' or 'N'.",
            },
        ],
        "temperature": 0.0,  # Deterministic response
        "max_tokens": 10     # Limit response length
    }

    try:
        response = requests.post(url, json=data)
        if response.status_code == 200:
            # Parse JSON response
            json_objects = response.content.decode().strip().split("\n")
            for obj in json_objects:
                item = json.loads(obj)
                return item['message']['content'].strip()[0]  # Extract and return first character ('Y' or 'N')
        else:
            return '?'
    except Exception as e:
        print(f"Error: {e}")
        return '?'


몇분 정도 디버깅 과정을 거쳐 위와 같은 함수를 만들었다. 속도도 매우 빠르고(llama3.1:8b 모델까지는 순식간이라고 부를만큼 빠르다), 정확도도 만족스럽다. 언어모델을 쓰지 않는 다른 방법도 찾아볼 수 있었겠지만, 들어가는 노력, 정확도, 성능, 비용 종합적으로 이만한게 있나 싶다.


In [7]: is_related_to_topic('food giant (식료품점)', 'medical')
Out[7]: 'N'

In [8]: is_related_to_topic('Walter C. Mackenzie Health Sciences Centre (종합병원)', 'medical')
Out[8]: 'Y'


이렇게 내가 필요한 일이 생기고, 이걸 풀기 위해 가져다가 써보고... 경험해보고 나니 Llama 를 엣디 디바이스서도 실행할 수 있다는 이야기가 확 와닿는다.

메타 주식 다시 살까...?


댓글 0개