경량 에이전트의 엣지 배포
낮은 지연 시간으로 응답하기 위해 Raspberry Pi와 엣지 장치에서 소형 모델을 실행합니다.
경량 에이전트의 엣지 배포은(는) CoddyKit의 무료 AI Agents 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Agents 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.
엣지 AI Agent
엣지 Agent는 클라우드가 아니라 IoT 장치나 로컬 게이트웨이(라즈베리 파이, 젯슨 나노 또는 산업용 PC)에서 직접 실행됩니다. 장점은 낮은 지연 시간(왕복 통신이 필요 없음), 오프라인 작동, 낮은 대역폭 비용입니다. 대신 연산 능력과 RAM이 제한되어 더 작고 효율적인 모델이 필요합니다.
엣지 배포를 위한 모델 선택
엣지 장치에서는 GPT-4o나 클로드 오퍼스를 실행할 수 없습니다. 라즈베리 파이 5(8GB RAM)에 맞는 소형 모델로는 파이-3-미니(38억 개 매개변수), 젬마-2B, TinyLlama-1.1B가 있습니다. 이러한 모델을 4비트로 양자화하면 1~3GB RAM이 필요하며 CPU에서 초당 5~15개 토큰을 처리합니다.
# Model size reference for edge selection:
EDGE_MODELS = {
'tinyllama-1.1b-q4': {
'params': '1.1B', 'quantization': 'Q4_K_M',
'ram_gb': 0.8, 'tokens_per_sec_cpu': 15,
'use_case': 'simple classification, keyword detection'
},
'phi-3-mini-q4': {
'params': '3.8B', 'quantization': 'Q4_K_M',
'ram_gb': 2.5, 'tokens_per_sec_cpu': 8,
'use_case': 'reasoning, multi-step decisions'
},
'gemma-2b-q4': {
'params': '2B', 'quantization': 'Q4_K_M',
'ram_gb': 1.5, 'tokens_per_sec_cpu': 10,
'use_case': 'general assistant tasks'
}
}
for name, info in EDGE_MODELS.items():
print(f'{name}: {info["ram_gb"]}GB RAM, '
f'{info["tokens_per_sec_cpu"]} tok/s — {info["use_case"]}')라즈베리 파이에 올라마 설치
올라마는 로컬 하드웨어에서 소형 LLM을 실행하는 가장 쉬운 방법입니다. 모델 다운로드와 양자화, OpenAI SDK와 호환되는 로컬 REST 방식의 프로그래밍 인터페이스를 관리합니다. 한 명령으로 설치하고, 다른 명령으로 모델을 가져와 시작할 수 있습니다.
# Install Ollama (run on the Raspberry Pi terminal):
# curl -fsSL https://ollama.ai/install.sh | sh
# Pull and run a model:
# ollama pull phi3:mini
# ollama serve (starts API on localhost:11434)
# Python client — uses the OpenAI-compatible endpoint:
from openai import OpenAI
local_client = OpenAI(
base_url='http://localhost:11434/v1',
api_key='ollama' # Ollama ignores this but it is required by the SDK
)
def local_inference(prompt: str, model: str = 'phi3:mini') -> str:
response = local_client.chat.completions.create(
model=model,
messages=[{'role': 'user', 'content': prompt}],
max_tokens=256,
temperature=0.1
)
return response.choices[0].message.content
result = local_inference('Is temperature 45C dangerous for a server room?')
print(result)4비트 GGUF 양자화
GGUF(GPT가 생성한 통합 형식)는 llama.cpp와 올라마가 양자화된 모델에 사용하는 파일 형식입니다. Q4_K_M은 4비트 혼합 양자화를 의미합니다. fp32보다 약 75% 작으면서도 엣지 추론 작업에서 품질 손실이 거의 없습니다.
# Understanding quantisation quality levels:
QUANTISATION_GUIDE = {
'Q2_K': {'size_multiplier': 0.25, 'quality': 'poor', 'ram': 'minimal'},
'Q4_K_M': {'size_multiplier': 0.45, 'quality': 'good', 'ram': 'low'},
'Q5_K_M': {'size_multiplier': 0.55, 'quality': 'better', 'ram': 'medium'},
'Q8_0': {'size_multiplier': 0.75, 'quality': 'near-original', 'ram': 'high'},
'F16': {'size_multiplier': 1.0, 'quality': 'original', 'ram': 'full'}
}
# For edge: Q4_K_M is the sweet spot
# 7B model: 7B * 4bit/8 = 3.5 GB in Q4 vs 14 GB in F16
def estimate_vram_gb(param_billions: float, quant: str) -> float:
multiplier = QUANT_GUIDE = {
'Q4_K_M': 0.45, 'Q8_0': 0.75, 'F16': 1.0
}
return round(param_billions * multiplier.get(quant, 0.5), 2)
print(f'Phi-3-mini Q4_K_M: {estimate_vram_gb(3.8, "Q4_K_M")} GB')
print(f'Phi-3-mini F16: {estimate_vram_gb(3.8, "F16")} GB')CPU에서 추론 속도 최적화
CPU만 사용하는 엣지 장치에서 추론 속도는 스레드 수와 프롬프트 캐싱에 따라 달라집니다. 스레드 수를 CPU 코어 수에 맞추고, 시스템 프롬프트를 짧게 유지하십시오. 캐시되지 않으면 호출할 때마다 시스템 프롬프트를 다시 처리하기 때문입니다. 가능하면 반복되는 질의를 묶어서 처리하십시오.
import os
import time
# Ollama environment variables for performance tuning
# Set before starting the Ollama service:
# OLLAMA_NUM_PARALLEL=1 (single request at a time on small devices)
# OLLAMA_MAX_LOADED_MODELS=1 (only keep one model in RAM)
def timed_inference(prompt: str, client, model: str = 'phi3:mini') -> dict:
start = time.time()
response = client.chat.completions.create(
model=model,
messages=[{'role': 'user', 'content': prompt}],
max_tokens=128
)
elapsed = time.time() - start
text = response.choices[0].message.content
tokens = len(text.split()) # approximate
return {
'text': text,
'elapsed_s': round(elapsed, 2),
'approx_tps': round(tokens / elapsed, 1)
}
result = timed_inference('Classify: temperature=45C, normal range 18-30C. Action?',
local_client)
print(result)하이브리드 엣지-클라우드 아키텍처
최적의 아키텍처는 빠르고 위험도가 낮은 판단(분류, 임계값 논리)에 엣지 모델을 사용하고, 복잡하거나 드물게 발생하거나 중요한 판단에는 클라우드 모델과 동기화합니다. 엣지 에이전트는 복잡한 질의를 대기열에 넣었다가 연결이 가능해지면 전송합니다.
import anthropic
import time
class HybridAgent:
def __init__(self, edge_client, cloud_api_key: str):
self.edge = edge_client # Ollama local client
self.cloud = anthropic.Anthropic(api_key=cloud_api_key)
self.pending_cloud_queries = []
def decide(self, context: dict) -> str:
# Fast path: edge model for simple binary decisions
simple_prompt = (
f'Sensor: {context}. '
'Respond with exactly one word: NORMAL or ALERT.'
)
edge_result = self.edge.chat.completions.create(
model='phi3:mini',
messages=[{'role': 'user', 'content': simple_prompt}],
max_tokens=5
).choices[0].message.content.strip()
if edge_result == 'ALERT':
# Queue complex analysis for cloud
self.pending_cloud_queries.append(context)
return edge_result
def sync_to_cloud(self):
"""Call when online connectivity is available."""
for ctx in self.pending_cloud_queries:
result = self.cloud.messages.create(
model='claude-opus-4-5', max_tokens=512,
messages=[{'role': 'user', 'content':
f'Full analysis of: {ctx}'}]
)
print('Cloud analysis:', result.content[0].text[:100])
self.pending_cloud_queries.clear()클라우드 동기화를 위한 오프라인 대기열
엣지 에이전트는 연결이 간헐적으로 끊기는 환경에서 작동하는 경우가 많습니다. 질의, 센서 측정값, 작업 로그를 로컬에 버퍼링한 다음 연결이 복구되면 클라우드로 전송합니다. 로컬 버퍼로 SQLite 데이터베이스를 사용합니다.
import sqlite3
import json
from datetime import datetime
DB_PATH = '/home/pi/agent_buffer.db'
def init_buffer_db():
conn = sqlite3.connect(DB_PATH)
conn.execute("""
CREATE TABLE IF NOT EXISTS sync_queue (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type TEXT NOT NULL,
payload TEXT NOT NULL,
created_at TEXT NOT NULL,
synced INTEGER DEFAULT 0
)
""")
conn.commit()
conn.close()
def buffer_for_sync(record_type: str, payload: dict):
conn = sqlite3.connect(DB_PATH)
conn.execute(
'INSERT INTO sync_queue (type, payload, created_at) VALUES (?, ?, ?)',
(record_type, json.dumps(payload), datetime.utcnow().isoformat())
)
conn.commit()
conn.close()
def flush_to_cloud(cloud_fn):
conn = sqlite3.connect(DB_PATH)
rows = conn.execute(
'SELECT id, type, payload FROM sync_queue WHERE synced=0 LIMIT 100'
).fetchall()
for row_id, r_type, payload in rows:
cloud_fn(r_type, json.loads(payload))
conn.execute('UPDATE sync_queue SET synced=1 WHERE id=?', (row_id,))
conn.commit()
conn.close()
print(f'Synced {len(rows)} records to cloud')
if __name__ == '__main__':
import os, tempfile
DB_PATH = os.path.join(tempfile.gettempdir(), 'agent_buffer_demo.db')
init_buffer_db()
buffer_for_sync('sensor_reading', {'temp': 22.5})
flush_to_cloud(lambda t, p: print(f'Synced to cloud: {t} -> {p}'))
엣지 에이전트 상태 모니터링
엣지 장치는 과열되거나 RAM이 부족해지거나 모델 추론이 멈출 수 있습니다. CPU 온도, 사용 가능한 RAM, 추론 지연 시간을 확인하고 상태 지표를 클라우드에 게시하는 상태 모니터를 구현합니다.
import subprocess
import psutil # pip install psutil
def get_edge_health() -> dict:
cpu_percent = psutil.cpu_percent(interval=1)
ram = psutil.virtual_memory()
disk = psutil.disk_usage('/')
# Read CPU temperature (Raspberry Pi specific)
try:
temp_output = subprocess.check_output(
['vcgencmd', 'measure_temp'], text=True
)
cpu_temp = float(temp_output.strip().replace("temp=", "").replace("'C", ""))
except Exception:
cpu_temp = -1.0 # not available on non-Pi hardware
return {
'cpu_percent': cpu_percent,
'cpu_temp_c': cpu_temp,
'ram_used_pct': ram.percent,
'ram_available_mb': round(ram.available / 1024 / 1024),
'disk_used_pct': disk.percent,
'timestamp': datetime.utcnow().isoformat()
}
health = get_edge_health()
print('Edge health:', health)엣지 에이전트를 위한 추론 캐싱
엣지 모델은 느리므로 동일한 입력에 대한 응답을 캐시합니다. 센서 분류 작업에서는 동일한 프롬프트(예: "온도=23.5, 분류")가 반복되는 경우가 많습니다. TTL이 적용된 간단한 딕셔너리 캐시는 중복 추론 호출을 방지합니다.
from datetime import datetime, timedelta
import hashlib
class InferenceCache:
def __init__(self, ttl_seconds: int = 60):
self.ttl = timedelta(seconds=ttl_seconds)
self._cache: dict = {} # hash -> {'result', 'expires'}
def _key(self, prompt: str) -> str:
return hashlib.md5(prompt.encode()).hexdigest()
def get(self, prompt: str):
key = self._key(prompt)
entry = self._cache.get(key)
if entry and datetime.utcnow() < entry['expires']:
return entry['result']
return None
def set(self, prompt: str, result: str):
key = self._key(prompt)
self._cache[key] = {
'result': result,
'expires': datetime.utcnow() + self.ttl
}
cache = InferenceCache(ttl_seconds=60)
def cached_edge_inference(prompt: str, client) -> str:
cached = cache.get(prompt)
if cached:
print('Cache hit')
return cached
result = local_inference(prompt, client)
cache.set(prompt, result)
return result배포 체크리스트
엣지 에이전트를 운영 환경에 배포하기 전에 다음을 확인합니다. 모델이 20%의 여유 공간을 확보한 상태로 사용 가능한 RAM에 들어가는지, 추론 지연 시간이 이벤트 응답 요구 사항을 충족하는지, 오프라인 버퍼가 테스트되었는지, 상태 모니터링 결과가 게시되고 있는지, 충돌 시 자동 재시작이 구성되었는지를 확인합니다.
# systemd service file for auto-restart (save as /etc/systemd/system/edge-agent.service)
SYSTEMD_SERVICE = '''
[Unit]
Description=IoT Edge Agent
After=network.target ollama.service
Requires=ollama.service
[Service]
User=pi
WorkingDirectory=/home/pi/edge-agent
ExecStart=/usr/bin/python3 /home/pi/edge-agent/agent.py
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
'''
# Enable:
# sudo systemctl enable edge-agent
# sudo systemctl start edge-agent
# sudo journalctl -u edge-agent -f (follow logs)
print('Deployment checklist:')
checklist = [
'Model RAM fits with 20% headroom',
'Inference latency < response time requirement',
'Offline SQLite buffer tested',
'Health metrics publishing to cloud',
'systemd auto-restart configured'
]
for item in checklist:
print(f' [ ] {item}')Raspberry Pi 하드웨어 설정
소프트웨어를 배포하기 전에 하드웨어를 준비합니다. Phi-3-mini를 실행하려면 8GB RAM이 장착된 Raspberry Pi 5가 최저 권장 사양입니다. GPU 메모리 분할을 활성화하고, 플래시 저장 장치의 성능을 저하시키는 스왑을 비활성화하며, 안정적인 원격 액세스를 위해 고정 IP를 구성합니다.
# Raspberry Pi setup notes (run manually over SSH):
# sudo raspi-config -> System -> GPU Memory -> 256
# Disable swap to protect SD card:
# sudo dphys-swapfile swapoff && sudo dphys-swapfile uninstall
def check_available_ram_mb():
try:
with open('/proc/meminfo') as f:
for line in f:
if line.startswith('MemAvailable'):
return int(line.split()[1]) // 1024
except FileNotFoundError:
return None
ram_mb = check_available_ram_mb()
if ram_mb is None:
print('Could not read /proc/meminfo on this OS — simulated Pi reading: MemAvailable ~ 850 MB')
else:
print(f'Available RAM: {ram_mb} MB')지식 확인
언어 모델에서 Q4_K_M 양자화는 무엇을 의미합니까?
복습: 경량 에이전트의 엣지 배포
이 레슨에서 학습한 내용:
- 모델 선택: 엣지용 Phi-3-mini, Gemma-2B, TinyLlama와 Q4_K_M 양자화
- Ollama: 포트 11434에서 OpenAI 호환 API를 제공하는 로컬 LLM 서버
- 하이브리드 아키텍처: 빠른 판단에는 엣지 모델을, 복잡한 분석에는 클라우드를 사용
- 오프라인 버퍼: 다시 연결되면 클라우드로 전송되는 SQLite 대기열
- 추론 캐시: TTL 캐시로 동일한 프롬프트에 대한 반복 추론을 방지
- 배포: 충돌 시 자동 재시작을 위한 systemd 서비스
다음 코스: 에이전트 마켓플레이스와 플러그인 시스템
AI 튜터와 함께 AI Agents을(를) 배우세요 — 무료
브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.
- 코스
- 60
- 레슨
- 239
자주 묻는 질문
“경량 에이전트의 엣지 배포” 강의는 무료인가요?
네 — “경량 에이전트의 엣지 배포” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Agents 강의 전체를 잠금 해제할 수 있습니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.
“경량 에이전트의 엣지 배포”에서 뭘 배우나요?
낮은 지연 시간으로 응답하기 위해 Raspberry Pi와 엣지 장치에서 소형 모델을 실행합니다. 브라우저에서 직접 실행하는 실습 코드로 AI Agents을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
AI Agents을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 AI Agents은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“경량 에이전트의 엣지 배포” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 AI Agents 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 AI Agents 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 에이전트 통합을 위한 MQTT 프로토콜
- 에이전트의 시계열 데이터 처리
- 센서 이벤트에 대한 자동 응답
- 경량 에이전트의 엣지 배포