터미널 AI 에이전트 구축 (v46)
터미널에서 직접 작동하는 AI 에이전트를 구축해보는 실전 가이드입니다. 이 가이드는 로컬에서 작동하는 LLM을 활용한 개발자용 AI 에이전트를 구축하고 최적화하는 방법을 실습 중심으로 설명합니다.
1. CLI AI 에이전트 생태계
현재 CLI AI 에이전트 시장은 다음과 같은 주요 도구들로 구성되어 있습니다:
주요 도구 비교:
# Aider - 최신 인기 도구
# pip install aider
# aider --help
# Continue.dev - VSCode 확장이지만 CLI 지원
# npm install -g @continue-dev/cli
# OpenCode - 코드 생성 전용
# pip install opencode
현실적인 선택지: 로컬에서 작동하는 자체 에이전트가 가장 안정적입니다. 특히 회사 내부에서 사용할 경우.
2. 로컬 LLM API 엔드포인트 설정
로컬 LLM을 CLI에서 사용하기 위해 API 서버를 설정합니다:
# Ollama 설치 (가장 쉬운 방법)
curl -fsSL https://ollama.com/install.sh | sh
# 모델 다운로드
ollama pull llama3
ollama pull codellama:7b
# API 서버 시작
ollama serve
# 기본 포트: 11434
# 테스트
curl http://localhost:11434/api/generate -d '{
"model": "llama3",
"prompt": "Hello, how are you?",
"stream": false
}'
3. 간단한 Python CLI 에이전트 구축
기본적인 CLI 에이전트를 만들어보겠습니다:
# agent.py
import json
import requests
import sys
from typing import Dict, List
class LocalAI:
def __init__(self, base_url="http://localhost:11434"):
self.base_url = base_url
def chat(self, messages: List[Dict], model="llama3", temperature=0.7):
"""기본 채팅 API 호출"""
payload = {
"model": model,
"messages": messages,
"temperature": temperature,
"stream": False
}
response = requests.post(
f"{self.base_url}/api/chat",
json=payload,
timeout=30
)
if response.status_code == 200:
return response.json()['message']['content']
else:
raise Exception(f"API Error: {response.text}")
def main():
if len(sys.argv) < 2:
print("사용법: python agent.py <질문>")
return
question = " ".join(sys.argv[1:])
ai = LocalAI()
messages = [
{"role": "system", "content": "You are a helpful coding assistant. Respond in concise markdown."},
{"role": "user", "content": question}
]
try:
response = ai.chat(messages)
print(response)
except Exception as e:
print(f"에러 발생: {e}")
if __name__ == "__main__":
main()
실행 방법:
python agent.py "Python으로 factorial 함수를 작성해주세요"
4. tmux와 통합
터미널을 분할해서 사용할 수 있도록 tmux 통합:
# tmux_agent.py
import subprocess
import os
import time
import json
class TmuxAgent:
def __init__(self, session_name="ai_session"):
self.session_name = session_name
self._setup_session()
def _setup_session(self):
"""tmux 세션 생성"""
subprocess.run([
"tmux", "new-session", "-d", "-s", self.session_name
], check=True)
def create_window(self, name):
"""새 창 생성"""
subprocess.run([
"tmux", "new-window", "-t", f"{self.session_name}:{name}"
], check=True)
def send_command(self, window, command):
"""명령어 전송"""
subprocess.run([
"tmux", "send-keys", "-t", f"{self.session_name}:{window}",
command, "Enter"
], check=True)
def get_window_output(self, window):
"""창의 출력 가져오기"""
result = subprocess.run([
"tmux", "capture-pane", "-p", "-t", f"{self.session_name}:{window}"
], capture_output=True, text=True)
return result.stdout
# 사용 예시
agent = TmuxAgent("coding_session")
agent.create_window("editor")
agent.send_command("editor", "vim main.py")
5. 맞춤형 도구 개발
코드 검색 도구:
# search_tool.py
import subprocess
import os
import re
class CodeSearchTool:
def __init__(self, project_root="."):
self.project_root = project_root
def search_patterns(self, pattern, file_extensions=None):
"""정규식 패턴으로 코드 검색"""
if file_extensions is None:
file_extensions = ["*.py", "*.js", "*.ts", "*.java"]
cmd = ["find", self.project_root]
cmd.extend(["-name", f"*.{file_extensions[0]}"])
try:
result = subprocess.run(
cmd, capture_output=True, text=True, check=True
)
files = result.stdout.strip().split('\n')
matches = []
for file in files:
if file.strip():
with open(file, 'r') as f:
content = f.read()
if re.search(pattern, content):
matches.append(file)
return matches
except subprocess.CalledProcessError:
return []
# 사용 예시
searcher = CodeSearchTool()
results = searcher.search_patterns(r"def\s+\w+\s*\(")
print("함수 정의 찾기:", results)
Git 통합 도구:
# git_tool.py
import subprocess
import json
class GitTool:
def __init__(self, repo_path="."):
self.repo_path = repo_path
def get_diff(self, commit_range="HEAD~1..HEAD"):
"""Git diff 가져오기"""
try:
result = subprocess.run([
"git", "-C", self.repo_path, "diff", commit_range
], capture_output=True, text=True, check=True)
return result.stdout
except subprocess.CalledProcessError:
return ""
def get_staged_files(self):
"""스테이징된 파일들 가져오기"""
try:
result = subprocess.run([
"git", "-C", self.repo_path, "diff", "--cached", "--name-only"
], capture_output=True, text=True, check=True)
return result.stdout.strip().split('\n')
except subprocess.CalledProcessError:
return []
# 사용 예시
git_tool = GitTool()
diff = git_tool.get_diff()
staged = git_tool.get_staged_files()
6. 컨텍스트 윈도우 관리
대용량 코드베이스에서 컨텍스트 윈도우를 최적화:
# context_manager.py
class ContextManager:
def __init__(self, max_tokens=4096):
self.max_tokens = max_tokens
self.context = []
def add_message(self, role, content):
"""메시지 추가 (토큰 제한 고려)"""
message = {"role": role, "content": content}
# 간단한 토큰 추정 (실제 구현은 tokenizer 사용)
token_count = len(content.split())
if token_count > self.max_tokens:
# 너무 긴 내용은 자르기
content = " ".join(content.split()[:self.max_tokens])
message["content"] = content
self.context.append(message)
return self._trim_context()
def _trim_context(self):
"""컨텍스트 트리밍"""
total_tokens = sum(len(msg["content"].split()) for msg in self.context)
while total_tokens > self.max_tokens:
if len(self.context) > 2: # 최소 2개 유지
self.context.pop(1) # 중간 메시지 제거
total_tokens = sum(len(msg["content"].split()) for msg in self.context)
else:
break
return self.context
# 사용 예시
cm = ContextManager(max_tokens=2048)
cm.add_message("system", "You are a helpful AI assistant")
cm.add_message("user", "Write a function that does something complex with large data structures...")
7. 비용/성능 최적화
로컬 vs API 모델 비교:
python
# optimization.py
import time
from typing import Optional
class ModelOptimizer:
def __init__(self):
self.models = {
"llama3": {"local": True, "speed": "fast", "cost": "free"},
"codellama": {"local": True, "speed": "fast
---
📥 **Get the full guide on Gumroad**: https://gumroad.com/l/auto ($5)
Top comments (0)