본문 바로가기
AI 코딩

[로컬AI] Ollama모델의 Q4 양자화 모델 설치 및 실행

by 피크나인 2025. 7. 31.

홈 > AI활용 > 로컬AI > Q4양자화 > Ollama모델의 Q4 양자화 실행하기

관련글 먼저 읽어보기 : 2025.07.22 - [AI 활용] - [로컬AI] AI모델 Q4 양자화의 의미와 원리 이해하기

 

로컬AI를 구축하기 위해 제일 먼저 GPU서버의 마련과 관련된 부담감을 안고 시작하게 됩니다. 우리가 사용하는 일반적인 PC를 사용해서 간단하게 구축하는 일반적인 프로젝트와는 부담감의 차이가 있을 수 밖에 없습니다. 글로벌 AI전문 기업이면서 일반인들이 쉽게 접할 수 잇는 생성형 AI인 ChatGPT, Gemini, Claude등은 GPU가 수백만장씩 사용되고 여기서 발생되는 전기료, 발열과 관련된 이슈를 기사로 접하다 보면 저걸 우리가 할 수 있나 하면서 조기에 포기하는 현상들이 있을 수 밖에 없습니다.

 

초기의 개발 테스트와 마찬가지로 중소기업에서 로컬AI를 구축할 때도 GPU 1장에 1천만원이 넘는 높은 비용을 감수하면서 파일럿 프로젝트를 지행할 수 는 없습니다. 일단 NVIDIA GPU 4090에서도 Llama 32B정도는 시험 개발해 볼 수 있습니다. 그렇다 하더라도 실제로 학습과정에서는 더 많은 GPU 리소스를 요구하는 경우가 많습니다. 이럴 때 우리가 쉽게 알고 있는 압축으로 이해할 수 있는 "양자화" 과정을 거치면 보다 가벼운 모델 시험이 가능해지게 됩니다.

1.  Ollama에서 Q4 양자화 모델 설치 및 실행

# 1단계: Ollama 서버 시작
ollama serve

# 2단계: Q4 양자화된 Llama 3.3 70B 모델 다운로드
# 자동으로 Q4_K_M 양자화 버전이 다운로드됩니다
ollama pull llama3.3:70b-instruct

# 3단계: 모델 정보 확인 (양자화 레벨 확인)
ollama show llama3.3:70b-instruct

# 4단계: 특정 양자화 버전 지정 다운로드 (선택사항)
ollama pull llama3.3:70b-instruct-q4_k_m  # Q4_K_M 양자화
ollama pull llama3.3:70b-instruct-q4_k_s  # Q4_K_S 양자화 (더 작음)
ollama pull llama3.3:70b-instruct-q6_k    # Q6_K 양자화 (더 정확함)


이 bash 스크립트는 Ollama 플랫폼에서 양자화된 대형 언어 모델을 설치하고 관리하는 전체 과정을 담고 있습니다.

  • 첫 번째 단계인 ollama serve는 Ollama의 백그라운드 서비스를 시작하여 모델 다운로드와 추론을 위한 기반 환경을 구축합니다.
  • 두 번째 단계의 ollama pull 명령어는 허깅페이스나 Ollama 모델 레지스트리에서 지정된 모델을 로컬 시스템으로 다운로드하는데, 이때 자동으로 시스템에 최적화된 양자화 버전을 선택합니다.
  • 세 번째 단계의 ollama show 명령어는 다운로드된 모델의 상세 정보(크기, 양자화 레벨, 메모리 요구사항 등)를 확인할 수 있게 해주어 시스템 호환성을 사전에 점검할 수 있습니다.
  • 네 번째 단계는 특정 양자화 레벨을 명시적으로 지정하여 다운로드하는 방법을 보여주는데, 이는 사용자의 하드웨어 환경과 성능 요구사항에 따라 최적의 모델 버전을 선택할 수 있게 해줍니다.

2.  메모리 사용량 및 성능 비교

# 양자화별 메모리 요구사항 및 성능
quantization_specs = {
    'Q4_K_M': {
        'memory_gb': 42,        # VRAM 요구량
        'file_size_gb': 39,     # 모델 파일 크기
        'quality_score': 0.95,  # 원본 대비 품질 (상대값)
        'speed_multiplier': 1.0, # 추론 속도 배수
        'description': '품질과 속도의 최적 균형점'
    },
    'Q4_K_S': {
        'memory_gb': 38,
        'file_size_gb': 35,
        'quality_score': 0.92,
        'speed_multiplier': 1.1,
        'description': '메모리 절약 우선, 약간의 품질 타협'
    },
    'Q6_K': {
        'memory_gb': 58,
        'file_size_gb': 54,
        'quality_score': 0.98,
        'speed_multiplier': 0.85,
        'description': '고품질 우선, 더 많은 메모리 필요'
    },
    'Q8_0': {
        'memory_gb': 72,
        'file_size_gb': 68,
        'quality_score': 0.99,
        'speed_multiplier': 0.75,
        'description': '원본에 가까운 품질, 최대 메모리 요구'
    }
}

 

이 Python 딕셔너리는 서로 다른 양자화 레벨들의 성능과 자원 요구사항을 체계적으로 비교할 수 있는 참조 테이블을 제공합니다.

각 양자화 레벨은 메모리 사용량, 파일 크기, 품질 점수, 속도 배수라는 네 가지 핵심 지표로 평가되어 사용자가 자신의 환경에 가장 적합한 모델을 선택할 수 있도록 돕습니다.

  • Q4_K_M은 대부분의 사용 사례에서 권장되는 균형점으로, 원본 모델 대비 95%의 품질을 유지하면서도 메모리 사용량을 크게 줄인 최적화된 버전입니다.
  • Q4_K_S는 메모리가 제한된 환경에서 사용할 수 있는 더욱 압축된 버전으로, 약간의 품질 손실을 감수하고도 더 빠른 처리 속도를 얻을 수 있습니다.
  • Q6_K와 Q8_0은 고품질이 우선시되는 환경에서 사용되며, 더 많은 메모리를 요구하지만 원본 모델에 더 가까운 성능을 제공하여 정밀한 분석이 필요한 제조업 환경에 적합합니다.

3.  실행 환경별 최적 설정

# config/model_config.py
class ModelConfig:
    def __init__(self, hardware_profile: str):
        self.hardware_profile = hardware_profile
        self.model_settings = self._get_optimal_settings()
    
    def _get_optimal_settings(self):
        """하드웨어 프로필에 따른 최적 설정"""
        
        if self.hardware_profile == "budget":  # 24GB VRAM
            return {
                'model_name': 'llama3.3:70b-instruct-q4_k_s',
                'context_length': 4096,
                'batch_size': 1,
                'num_gpu': 1,
                'gpu_memory_fraction': 0.9,
                'cpu_threads': 8
            }
        
        elif self.hardware_profile == "standard":  # 40-48GB VRAM
            return {
                'model_name': 'llama3.3:70b-instruct-q4_k_m',
                'context_length': 8192,
                'batch_size': 2,
                'num_gpu': 1,
                'gpu_memory_fraction': 0.85,
                'cpu_threads': 12
            }
        
        elif self.hardware_profile == "high_end":  # 80GB+ VRAM
            return {
                'model_name': 'llama3.3:70b-instruct-q6_k',
                'context_length': 16384,
                'batch_size': 4,
                'num_gpu': 1,
                'gpu_memory_fraction': 0.8,
                'cpu_threads': 16
            }

 

이 Python 클래스는 다양한 하드웨어 환경에 따라 모델 실행 설정을 자동으로 최적화하는 설정 관리 시스템을 구현합니다.

  • ModelConfig 클래스는 사용자의 하드웨어 프로필을 입력받아 GPU 메모리 용량에 따라 가장 적합한 모델 버전과 실행 매개변수를 자동으로 선택하는 지능형 설정 시스템입니다.
  • budget 프로필은 24GB VRAM 환경을 대상으로 하며, 메모리 효율성을 최우선으로 하여 Q4_K_S 모델과 작은 컨텍스트 길이를 사용하여 안정적인 동작을 보장합니다.
  • standard 프로필은 일반적인 워크스테이션 환경(40-48GB VRAM)에 최적화되어 있으며, Q4_K_M 모델을 사용하여 성능과 안정성의 균형을 맞춘 실용적인 설정을 제공합니다.
  • high_end 프로필은 고성능 서버나 전문 워크스테이션을 위한 설정으로, 최대 성능을 위해 Q6_K 모델과 큰 배치 크기를 사용하여 대량 처리와 높은 정확도를 동시에 달성할 수 있습니다.

4.  Python에서 양자화 모델 사용

# ollama_quantized_client.py
import ollama
import json
import psutil
import GPUtil

class QuantizedLlamaClient:
    def __init__(self, model_name: str = "llama3.3:70b-instruct-q4_k_m"):
        self.model_name = model_name
        self.client = ollama.Client(host='http://localhost:11434')
        self.check_system_requirements()
        
    def check_system_requirements(self):
        """시스템 요구사항 검사"""
        # GPU 메모리 확인
        gpus = GPUtil.getGPUs()
        if gpus:
            total_gpu_memory = sum(gpu.memoryTotal for gpu in gpus)
            print(f"사용 가능한 GPU 메모리: {total_gpu_memory}MB")
            
            if "q4_k_s" in self.model_name and total_gpu_memory < 38000:
                print("⚠️ 경고: GPU 메모리 부족. 성능 저하 가능성")
            elif "q4_k_m" in self.model_name and total_gpu_memory < 42000:
                print("⚠️ 경고: GPU 메모리 부족. 성능 저하 가능성")
        
        # 시스템 RAM 확인
        ram_gb = psutil.virtual_memory().total / (1024**3)
        print(f"시스템 RAM: {ram_gb:.1f}GB")
        
        if ram_gb < 32:
            print("⚠️ 경고: 시스템 RAM 부족. 32GB 이상 권장")
    
    async def generate_response(self, prompt: str, temperature: float = 0.1) -> str:
        """Q4 양자화 모델로 응답 생성"""
        try:
            response = self.client.generate(
                model=self.model_name,
                prompt=prompt,
                stream=False,
                options={
                    'temperature': temperature,
                    'top_p': 0.9,
                    'top_k': 40,
                    'num_predict': 512,
                    'repeat_penalty': 1.1,
                    'num_ctx': 8192,  # 컨텍스트 길이
                    'num_batch': 2,   # 배치 크기
                    'num_gpu': -1,    # 모든 GPU 사용
                    'main_gpu': 0,    # 메인 GPU 지정
                    'low_vram': False # VRAM 최적화 끄기 (Q4에서는 불필요)
                }
            )
            return response['response']
            
        except Exception as e:
            print(f"응답 생성 오류: {e}")
            return "응답 생성에 실패했습니다."
    
    def analyze_cnc_with_quantized_model(self, sensor_data: dict) -> str:
        """Q4 양자화 모델로 CNC 상태 분석"""
        prompt = f"""
        다음 CNC 센서 데이터를 분석해주세요:
        
        온도: {sensor_data.get('temperature', 0):.2f}°C
        X축 진동: {sensor_data.get('vibration_x', 0):.3f}mm/s
        Y축 진동: {sensor_data.get('vibration_y', 0):.3f}mm/s
        Z축 진동: {sensor_data.get('vibration_z', 0):.3f}mm/s
        주축 전류: {sensor_data.get('spindle_current', 0):.2f}A
        주축 속도: {sensor_data.get('spindle_speed', 0):.0f}RPM
        
        분석 결과:
        1. 현재 상태 평가 (정상/주의/경고)
        2. 이상 징후 식별
        3. 권장 조치사항
        4. 예상 위험도 (1-10점)
        
        간결하고 실용적으로 분석해주세요.
        """
        
        return self.client.generate(
            model=self.model_name,
            prompt=prompt,
            stream=False,
            options={'temperature': 0.1, 'num_predict': 400}
        )['response']

 

이 Python 클래스는 양자화된 언어 모델을 실제 제조업 환경에서 사용하기 위한 완전한 클라이언트 인터페이스를 제공합니다.

  • QuantizedLlamaClient 클래스는 초기화 시 시스템의 하드웨어 사양을 자동으로 검사하여 선택된 모델이 현재 환경에서 안정적으로 실행될 수 있는지 사전 검증하는 안전장치를 포함하고 있습니다.
  • check_system_requirements 메서드는 GPU 메모리와 시스템 RAM을 실시간으로 모니터링하여 모델 실행 전에 잠재적인 메모리 부족 상황을 미리 경고함으로써 시스템 크래시를 방지합니다.
  • generate_response 메서드는 양자화 모델의 특성에 맞게 최적화된 추론 매개변수를 사용하여 일관되고 안정적인 텍스트 생성을 수행하며, 에러 처리 로직을 통해 예외 상황에서도 시스템이 중단되지 않도록 보장합니다.
  • analyze_cnc_with_quantized_model 메서드는 CNC 머신의 실시간 센서 데이터를 구조화된 형태로 모델에 전달하여 제조업 특화된 분석 결과를 얻는 실용적인 구현 예시를 보여줍니다.

5.  Docker 환경에서 Q4 양자화 모델 운영

# Dockerfile.ollama-q4
FROM ollama/ollama:latest

# 시스템 업데이트 및 필수 패키지 설치
RUN apt-get update && apt-get install -y \
    python3 \
    python3-pip \
    curl \
    && rm -rf /var/lib/apt/lists/*

# Python 의존성 설치
COPY requirements.txt .
RUN pip3 install -r requirements.txt

# Ollama 모델 다운로드 스크립트
COPY download_models.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/download_models.sh

# 애플리케이션 코드 복사
COPY . /app
WORKDIR /app

# 포트 노출
EXPOSE 11434 8000

# 시작 스크립트
CMD ["/usr/local/bin/download_models.sh"]
#!/bin/bash
# download_models.sh

echo "Ollama 서버 시작 중..."
ollama serve &
sleep 10

echo "Q4 양자화 모델 다운로드 중..."
ollama pull llama3.3:70b-instruct-q4_k_m
ollama pull bge-m3

echo "모델 다운로드 완료!"
ollama list

# 애플리케이션 시작
echo "🏃 CNC 모니터링 시스템 시작..."
python3 /app/cnc_monitor.py

 

이 Dockerfile과 bash 스크립트 조합은 양자화된 AI 모델을 컨테이너 환경에서 자동화된 방식으로 배포하고 운영하기 위한 완전한 솔루션을 제공합니다.

  • Dockerfile은 공식 Ollama 이미지를 베이스로 하여 Python 런타임과 필요한 시스템 도구들을 추가 설치하고, 애플리케이션 코드와 설정 파일들을 컨테이너 내부로 복사하는 멀티 스테이지 빌드 프로세스를 구현합니다.
  • download_models.sh 스크립트는 컨테이너 시작 시 Ollama 서버를 백그라운드에서 실행하고, 필요한 양자화 모델들을 자동으로 다운로드한 후 CNC 모니터링 애플리케이션을 시작하는 완전한 자동화 워크플로우를 제공합니다.
  • 포트 노출 설정(11434, 8000)을 통해 Ollama API 서버와 웹 대시보드에 외부에서 접근할 수 있도록 하여 마이크로서비스 아키텍처에서의 연동을 가능하게 합니다.

이러한 컨테이너화 접근법은 개발, 테스트, 프로덕션 환경 간의 일관성을 보장하고, 스케일링과 배포를 간소화하여 제조업 현장에서의 AI 시스템 운영을 크게 단순화합니다.


6.  성능 모니터링 및 최적화

# performance_monitor.py
import time
import psutil
import GPUtil
from typing import Dict, List

class QuantizedModelMonitor:
    def __init__(self):
        self.metrics_history = []
        
    def measure_inference_performance(self, client, test_prompts: List[str]) -> Dict:
        """추론 성능 측정"""
        results = {
            'avg_response_time': 0,
            'tokens_per_second': 0,
            'memory_usage': {},
            'gpu_utilization': []
        }
        
        total_time = 0
        total_tokens = 0
        
        for prompt in test_prompts:
            # GPU 상태 측정 전
            gpu_before = GPUtil.getGPUs()[0].load if GPUtil.getGPUs() else 0
            memory_before = psutil.virtual_memory().percent
            
            # 추론 실행
            start_time = time.time()
            response = client.generate(
                model=client.model_name,
                prompt=prompt,
                stream=False
            )
            end_time = time.time()
            
            # 메트릭 계산
            response_time = end_time - start_time
            token_count = len(response['response'].split())
            
            total_time += response_time
            total_tokens += token_count
            
            # GPU 상태 측정 후
            gpu_after = GPUtil.getGPUs()[0].load if GPUtil.getGPUs() else 0
            memory_after = psutil.virtual_memory().percent
            
            results['gpu_utilization'].append({
                'before': gpu_before,
                'after': gpu_after,
                'delta': gpu_after - gpu_before
            })
        
        # 평균 계산
        results['avg_response_time'] = total_time / len(test_prompts)
        results['tokens_per_second'] = total_tokens / total_time
        results['memory_usage'] = {
            'before': memory_before,
            'after': memory_after,
            'peak_delta': memory_after - memory_before
        }
        
        return results
    
    def optimize_model_settings(self, current_performance: Dict) -> Dict:
        """성능 기반 설정 최적화 제안"""
        recommendations = {}
        
        # 응답 시간이 너무 느린 경우
        if current_performance['avg_response_time'] > 30:
            recommendations['context_reduction'] = "컨텍스트 길이를 4096으로 감소 권장"
            recommendations['batch_size'] = "배치 크기를 1로 설정 권장"
            
        # GPU 사용률이 낮은 경우
        avg_gpu_util = sum(g['after'] for g in current_performance['gpu_utilization']) / len(current_performance['gpu_utilization'])
        if avg_gpu_util < 0.7:
            recommendations['batch_increase'] = "배치 크기 증가로 GPU 활용도 향상 가능"
            
        # 메모리 사용량이 높은 경우
        if current_performance['memory_usage']['peak_delta'] > 80:
            recommendations['memory_optimization'] = "더 작은 양자화 모델(Q4_K_S) 사용 권장"
            
        return recommendations

 

이 Python 클래스는 양자화된 모델의 실시간 성능을 종합적으로 모니터링하고 최적화 방안을 자동으로 제안하는 지능형 성능 관리 시스템을 구현합니다.

  • QuantizedModelMonitor 클래스는 추론 시간, 토큰 처리 속도, 메모리 사용량, GPU 활용도 등의 핵심 성능 지표들을 체계적으로 측정하여 시스템 운영 상태를 정량적으로 평가할 수 있게 해줍니다.
  • measure_inference_performance 메서드는 실제 사용 환경과 유사한 테스트 프롬프트들을 사용하여 모델의 실제 성능을 측정하고, 각 추론 과정에서 시스템 자원 사용량의 변화를 세밀하게 추적합니다.
  • optimize_model_settings 메서드는 측정된 성능 데이터를 분석하여 병목 지점을 자동으로 식별하고, 현재 하드웨어 환경에서 최적의 성능을 얻기 위한 구체적인 설정 변경 사항을 제안하는 자동화된 최적화 엔진 역할을 합니다.

이러한 성능 모니터링 시스템은 제조업 현장에서 AI 시스템이 24/7 안정적으로 운영될 수 있도록 지속적인 성능 관리와 예방적 최적화를 가능하게 하여 운영 비용 절감과 시스템 신뢰성 향상에 기여합니다.


양자화 모델의 적용에 따른 효율성 극대화를 보여주는 가상 이미지입니다.
양자화 모델의 적용에 따른 효율성 극대화 가상 이미지

 

관련글  : 2025.07.22 - [AI 활용] - [로컬AI] AI모델 Q4 양자화의 의미와 원리 이해하기