터미널 AI 에이전트 구축 (v10)
터미널에서 작동하는 AI 에이전트를 직접 구축하는 것은 개발자에게 매우 실용적인 도구입니다. 이 가이드에서는 로컬 LLM을 활용한 터미널 AI 에이전트를 구축하고, 실제 개발 워크플로우에 적용하는 방법을 단계별로 안내합니다.
1. CLI AI 에이전트 생태계
현재 CLI AI 에이전트 생태계는 여러 도구로 구성되어 있습니다:
주요 도구 비교
Aider: GitHub Copilot처럼 파일 편집 기능 제공
pip install aider
aider --help
Continue.dev: VS Code 확장으로 개발자 경험 최적화
npm install -g continue
OpenCode: 오픈소스, 로컬 실행 가능한 에이전트
git clone https://github.com/open-code/open-code.git
cd open-code && python -m pip install -e .
사용자 정의 스크립트: 최대한의 커스터마이징이 가능
2. 로컬 LLM API 엔드포인트 설정
로컬 LLM을 위한 API 서버를 구축하여 비용과 보안 문제를 해결합니다.
LM Studio 설치
# macOS
brew install lm-studio
# 또는 직접 다운로드
curl -L https://github.com/lm-s Studio/lm-studio/releases/latest/download/LM-Studio-Mac.dmg -o lm-studio.dmg
LocalAI 설치 (대안)
git clone https://github.com/go-skynet/LocalAI.git
cd LocalAI
docker build -t localai .
docker run -p 8080:8080 -v $(pwd)/models:/models localai
테스트 명령
curl http://localhost:8080/v1/models
curl http://localhost:8080/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "llama3",
"prompt": "Hello, how are you?",
"max_tokens": 100
}'
3. 간단한 Python CLI 에이전트 구축
다음은 기능 호출을 사용하는 간단한 CLI 에이전트입니다:
# ai_agent.py
import openai
import subprocess
import json
import os
from typing import List, Dict, Any
class TerminalAgent:
def __init__(self, api_key: str = None):
self.client = openai.OpenAI(
base_url="http://localhost:8080/v1",
api_key="none"
)
self.tools = [
{
"type": "function",
"function": {
"name": "execute_shell",
"description": "Shell 명령어 실행",
"parameters": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "실행할 명령어"
}
},
"required": ["command"]
}
}
}
]
def execute_shell(self, command: str) -> str:
"""Shell 명령어 실행"""
try:
result = subprocess.run(
command,
shell=True,
capture_output=True,
text=True,
timeout=30
)
return result.stdout + result.stderr
except Exception as e:
return f"Error: {str(e)}"
def run(self, prompt: str) -> str:
"""AI 에이전트 실행"""
messages = [
{
"role": "user",
"content": prompt
}
]
# 함수 호출
response = self.client.chat.completions.create(
model="llama3",
messages=messages,
tools=self.tools,
tool_choice="auto"
)
# 결과 처리
tool_calls = response.choices[0].message.tool_calls
if tool_calls:
for tool_call in tool_calls:
if tool_call.function.name == "execute_shell":
args = json.loads(tool_call.function.arguments)
output = self.execute_shell(args["command"])
messages.append({
"role": "tool",
"content": output,
"tool_call_id": tool_call.id
})
# 최종 응답 요청
final_response = self.client.chat.completions.create(
model="llama3",
messages=messages
)
return final_response.choices[0].message.content
return response.choices[0].message.content
# 사용법
if __name__ == "__main__":
agent = TerminalAgent()
result = agent.run("시스템 정보를 확인해주세요")
print(result)
4. tmux와 통합
터미널 multiplexer와 통합하여 에이전트를 더 효율적으로 사용합니다:
# tmux 세션 생성
tmux new-session -d -s ai_agent
# 에이전트 실행
tmux send-keys -t ai_agent "python ai_agent.py" Enter
# 세션 연결
tmux attach -t ai_agent
Python 스크립트에서 tmux 통합:
# tmux_integration.py
import subprocess
import json
class TmuxAgent(TerminalAgent):
def __init__(self, session_name: str = "ai_agent"):
super().__init__()
self.session_name = session_name
def create_session(self):
"""tmux 세션 생성"""
subprocess.run(["tmux", "new-session", "-d", "-s", self.session_name])
def send_command(self, command: str):
"""tmux 세션에 명령어 전송"""
subprocess.run([
"tmux", "send-keys", "-t", self.session_name, command, "Enter"
])
def get_session_output(self):
"""세션 출력 가져오기"""
result = subprocess.run([
"tmux", "capture-pane", "-p", "-t", self.session_name
], capture_output=True, text=True)
return result.stdout
# 사용법
agent = TmuxAgent("my_ai")
agent.create_session()
agent.send_command("ls -la")
5. 사용자 정의 도구 개발
코드 검색 도구
# code_search.py
import os
import re
from pathlib import Path
class CodeSearcher:
def __init__(self, root_dir: str = "."):
self.root_dir = Path(root_dir)
self.supported_extensions = {'.py', '.js', '.ts', '.java', '.cpp', '.h'}
def search_patterns(self, pattern: str, file_pattern: str = "*") -> List[Dict]:
"""정규식 패턴으로 코드 검색"""
results = []
for file_path in self.root_dir.rglob(file_pattern):
if file_path.suffix in self.supported_extensions:
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
matches = re.finditer(pattern, content)
for match in matches:
results.append({
'file': str(file_path),
'line': content[:match.start()].count('\n') + 1,
'content': match.group()
})
except Exception:
continue
return results
def search_function(self, function_name: str) -> List[Dict]:
"""함수 정의 검색"""
pattern = rf'def\s+{function_name}\s*\('
return self.search_patterns(pattern)
Git 통합 도구
# git_tools.py
import subprocess
import json
from typing import List, Dict
class GitTools:
@staticmethod
def get_git_status() -> str:
"""Git 상태 확인"""
try:
result = subprocess.run(
['git', 'status', '--porcelain'],
capture_output=True, text=True
)
return result.stdout.strip()
except:
return "Git repository not found"
@staticmethod
def get_recent_commits(limit: int = 5) -> List[Dict]:
"""최근 커밋 정보"""
try:
result = subprocess.run([
'git', 'log', '--oneline', f'-{limit}'
], capture_output=True, text=True)
commits = []
for line in result.stdout.strip().split('\n'):
if line.strip():
parts = line.split(' ', 1)
commits.append({
'hash': parts[0],
'message': parts[1] if len(parts) > 1 else ''
})
return commits
except:
return []
@staticmethod
def get_changed_files() -> List[str]:
"""변경된 파일 목록"""
try:
result = subprocess.run([
'git', 'diff', '--name-only', 'HEAD~1'
], capture_output=True, text=True)
return result.stdout.strip().split('\n')
except:
return []
6. 컨텍스트 윈도우 관리
대규모 코드
📥 Get the full guide on Gumroad: https://gumroad.com/l/auto ($5)
Top comments (0)