우분투(Ubuntu) 서버 환경에서 Mistral LLM을 구축하고 파이썬 API 서버(FastAPI)로 띄우는 전체 과정을 순서대로 정리해 드립니다. 하드웨어(GPU 유무, RAM 용량)에 구애받지 않고 가장 안정적으로 동작하는 **표준 라이브러리(`transformers`) 기준**으로 작성되었습니다. --- ## 1단계: 가상환경 및 필수 라이브러리 설치 시스템 파이썬을 보호하고 의존성 충돌을 막기 위해 가상환경(Conda)을 세팅합니다. **1. Conda 가상환경 생성 및 활성화** ```bash conda create -n mistral-env python=3.10 -y conda activate mistral-env ``` **2. 필수 파이썬 패키지 설치** AI 구동 커널, 웹 서버 라이브러리, 허깅페이스 통신 모듈을 한 번에 설치합니다. ```bash pip install torch transformers accelerate fastapi uvicorn huggingface_hub ``` ## 2단계: Hugging Face 인증 및 모델 다운로드 Mistral 7B 모델은 허깅페이스(Hugging Face)를 통해 배포되므로 토큰 인증이 필요합니다. **1. 토큰 로그인** ```bash python -m huggingface_hub.cli login ``` * `Token:` 프롬프트가 뜨면 허깅페이스 사이트(Settings -> Access Tokens)에서 발급받은 토큰을 붙여넣고 엔터를 칩니다. (보안상 화면에 글자가 보이지 않습니다.) * `Add token as git credential? (y/n)` 질문에는 `n`을 입력합니다. **2. 모델 다운로드 경로 준비** ```bash mkdir -p ~/mistral_models/7B-Instruct-v0.3 ``` **3. 모델 다운로드 실행 (약 15GB)** ```bash python -m huggingface_hub.cli download mistralai/Mistral-7B-Instruct-v0.3 --local-dir ~/mistral_models/7B-Instruct-v0.3 --local-dir-use-symlinks False ``` ## 3단계: 파이썬 웹 서버 코드 작성 (`serve_mistral.py`) FastAPI를 사용하여 외부에서 API로 LLM에 질문을 던질 수 있도록 서버 코드를 작성합니다. **1. 파이썬 파일 생성** ```bash nano serve_mistral.py ``` **2. 서버 코드 붙여넣기** 메모리 부족(Killed)이나 GPU(CUDA) 에러를 방지하기 위해 용량을 절반으로 줄이는 `float16` 옵션과 자동 디스크 오프로딩이 적용된 코드입니다. ```python import warnings warnings.filterwarnings("ignore") from fastapi import FastAPI from fastapi.responses import JSONResponse from pydantic import BaseModel import uvicorn import torch import os from transformers import AutoModelForCausalLM, AutoTokenizer import time # ========================================================= # [시스템] AI 모델 로드 # ========================================================= model_path = os.path.expanduser("~/mistral_models/7B-Instruct-v0.3") print("=== AI 모델 로딩 중... ===") try: tokenizer = AutoTokenizer.from_pretrained(model_path) # 메모리 최적화 및 장치 자동 할당 model = AutoModelForCausalLM.from_pretrained( model_path, device_map="auto", # GPU가 없으면 자동으로 CPU/RAM 사용 torch_dtype=torch.float16, # 메모리 사용량 절반 감소 low_cpu_mem_usage=True ) print("=== AI 준비 완료 ===") except Exception as e: print(f"!!! 모델 로드 실패: {e}") exit() app = FastAPI() class ChatRequest(BaseModel): prompt: str # ========================================================= # [API] 메인 엔드포인트 # ========================================================= @app.post("/chat") async def chat_endpoint(request: ChatRequest): try: user_input = request.prompt print(f"\n>> 질문: {user_input}") # 메시지 템플릿 적용 messages = [{"role": "user", "content": user_input}] prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) # 모델 장치(CPU/GPU)에 맞게 입력값 전달 inputs = tokenizer(prompt, return_tensors="pt").to(model.device) start_time = time.time() print(" (AI 연산 시작...)") # 텍스트 생성 with torch.no_grad(): outputs = model.generate( **inputs, max_new_tokens=512, temperature=0.1, do_sample=True, pad_token_id=tokenizer.eos_token_id ) print(f" (연산 완료: {time.time() - start_time:.2f}초)") # 결과 디코딩 (입력된 프롬프트 제외) generated_text = tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=True) return JSONResponse(content={"response": generated_text.strip()}) except Exception as e: print(f"Server Error: {e}") return JSONResponse(content={"response": "시스템 오류가 발생했습니다."}, status_code=500) if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000) ``` * 저장 후 종료: `Ctrl + O` -> `Enter` -> `Ctrl + X` ## 4단계: 무중단 백그라운드 실행 (`tmux`) SSH 터미널 접속을 끊어도 서버가 계속 켜져 있도록 가상 화면(`tmux`)을 활용합니다. **1. 백그라운드 세션 생성** ```bash tmux new -s aiserver ``` **2. 환경 활성화 및 서버 실행** 새로 열린 가상 화면에서 서버를 켭니다. ```bash conda activate mistral-env python serve_mistral.py ``` **3. 가상 화면 빠져나오기 (서버 유지)** 서버가 정상적으로 켜진 것을 확인한 뒤, 키보드에서 `Ctrl + B`를 누르고 손을 뗀 다음 `D`를 누릅니다. 이제 터미널 프로그램을 종료해도 백그라운드에서 AI 서버가 정상적으로 요청을 대기합니다. --- > **운영 팁:** 프로세스가 램 용량을 초과해 강제 종료(Killed)되는 현상이 발생한다면, 우분투 하드디스크 공간을 램처럼 활용하는 **스왑 메모리(Swap Memory)**를 16GB 이상 할당해 주어야 모델이 죽지 않고 연산을 완료할 수 있습니다.