머신러닝&딥러닝

로컬 서버에 LLM 올리기 - Docker, Flask, LLM

코코로코코 2024. 4. 10. 16:44
반응형

이번 포스팅에서는 로컬서버에서 LLM을 Flask를 활용해서 API형태로 만들고 이를 Docker 컨테이너로 만드는 과정에 대해서 포스팅합니다.

 

LLM

커스텀 LLM이 아닌 기본 LLM을 사용합니다. 일반적으로 LLM을 불러오는 과정과 동일합니다.

# app.py

from transformers import GPT2LMHeadModel, GPT2Tokenizer

model_name = "gpt2"  # 예시는 GPT-2, 필요시 수정 할 부분
model = GPT2LMHeadModel.from_pretrained(model_name)
tokenizer = GPT2Tokenizer.from_pretrained(model_name)

 

 

Flask

endPoint는 predict 부분입니다. 로컬에서 API형태로 감싸서 호출할때 127.0.0.1:8000/predict로 호출하게 됩니다.

# app.py

from flask import Flask, request, jsonify


app = Flask(__name__)

@app.route('/predict', methods=['POST'])
def predict():
    data = request.json
    prompt = data['prompt']
    
    # 프롬프트를 토크나이즈하고 모델에 입력
    inputs = tokenizer.encode(prompt, return_tensors="pt")
    outputs = model.generate(inputs, max_length=50, num_return_sequences=1)
    
    # 생성된 텍스트를 디코딩
    text_generated = tokenizer.decode(outputs[0], skip_special_tokens=True)
    
    response = {"result": text_generated}
    
    return jsonify(response)

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=8000)

 

위 처럼 app.py를 구성했다면 터미널로 아래 명령어를 실행하여 Flask로 로컬 서버에 올려두시면 됩니다. 

python3 app.py

 

 

모델을 불러와 정상적으로 실행이 됐다면 curl를 통해 호출 하면 됩니다. 그러면 아래와 같은 결과를 받을 수 있습니다.

-X [호출 방식] [호출 주소]

-H 전달할 데이터 형식

-d 데이터

curl -X POST http://localhost:8000/predict -H "Content-Type: application/json" -d '{"prompt":"Hello, world!"}'

 

 

이제 이렇게 로컬서버에서 실행한 API를 도커 컨테이너로 만드는 과정을 진행해보겠습니다.

 

Docker

Docker컨테이너를 만드는데 구성은 간단합니다. 저는 아래와 같이 구성했습니다. 

1. app.py (실행할 py)

2. requirments.txt

3. Dockerfile

 

 

Dockerfile에 작성한 내용은 순차적으로 다음과 같은 명령을 실행합니다.

  1. Python 버전 설정: FROM python:3.8 명령어를 통해 Python의 특정 버전(여기서는 3.8)을 포함하는 베이스 이미지를 설정
  2. 작업 디렉토리 설정: WORKDIR /app 명령어를 통해 생성될 Docker 이미지 내에서의 작업 디렉토리를 /app으로 설정. 이후의 명령어들은 이 디렉토리를 기준으로 실행 됨.
  3. 의존성 파일 복사 및 설치: COPY requirements.txt ./ 명령어로 현재 빌드 컨텍스트(즉, Dockerfile이 위치한 디렉토리)에서 requirements.txt 파일을 Docker 이미지의 /app 디렉토리로 복사 및 설치
  4. 소스 코드 복사: COPY . . 명령어는 현재 디렉토리(빌드 컨텍스트)에 있는 모든 파일과 디렉토리를 Docker 이미지의 현재 작업 디렉토리(/app)로 복사.
  5. Flask 서버 실행 명령어 설정: CMD ["flask", "run", "--host=0.0.0.0", "--port=8000"] 명령어는 Docker 컨테이너가 시작될 때 실행될 기본 명령어를 설정.

이렇게 구성이 됐다면 터미널에서 아래 명령어를 실행하면 도커 이미지가 만들어집니다.

docker build -t flask-gpt2-app .

 

 

이후 아래 명렁어를 통해 실행중인 도커를 확인할 수 있습니다. 만약 실행중인 도커가 없다면 위에서 빌드한 도커 이미지의 이름을 run 명렁어로 실행시켜 주면 됩니다. 8000:8000은 로컬의 8000포트와 도커의 8000포트가 연결되는 것을 의미합니다.

# 실행중인 도커 확인
sudo docker ps

# 실행중이지 않은 도커 확인
# sudo docker ps -a

# 도커 실행
docker run -d -p 8000:8000 flask-gpt2-app

 

이후 호출 방식은 동일합니다. 이전에는 Flask가 로컬 8000포트를 통해 실행되고 있었지만 이제는 로컬의 8000포트로 내보내고 이게 도커의 8000포트로 들어가 답변을 받아오는 구조가 되었습니다.

curl -X POST http://localhost:8000/predict -H "Content-Type: application/json" -d '{"prompt":"Hello, world!"}'

 

 

도커 이미지 서버에올리고 접근하기

만약 해당 도커를 서버에 올리고 싶다면 도커이미지를 서버에서 올려서(pull) 실행(run)한다는 가정을 한다면 아래 명령어로 실행할 수 있습니다. 첫번째 5000은 외부에서 서버에 접근할 수 있는 포트이고 뒤에 8000은 Flask에서 접속할 포트를 의미합니다.

# 서버에서 실행
docker run -d -p 5000:8000 flask-gpt2-app

# 외부에서 서버에 요청시
curl -X POST http://[서버주소]:5000/predict -H "Content-Type: application/json" -d '{"prompt":"Hello, world!"}'
반응형