DEV Community

matias yoon
matias yoon

Posted on

터미널 AI 에이전트 구축 (v26)

터미널 AI 에이전트 구축 (v26)

터미널에서 직접 작동하는 AI 에이전트를 구축하면, 코드 작성과 디버깅을 더 효율적으로 할 수 있습니다. 이 가이드는 터미널 내에서 작동하는 AI 에이전트를 구축하는 실전 가이드입니다.

1. CLI AI 에이전트 환경 분석

현재 CLI AI 에이전트 시장은 다양한 솔루션으로 구성되어 있습니다:

  • Aider: GitHub Copilot과 유사한 기능을 터미널에서 제공
  • Continue.dev: VSCode 확장 프로그램을 기반으로 한 터미널 기반 에이전트
  • OpenCode: 오픈소스 기반의 코드 생성 도구
  • 사용자 정의 스크립트: 직접 제작한 에이전트
# Aider 설치
pip install aider
# Continue.dev 설치
pip install continue
Enter fullscreen mode Exit fullscreen mode

2. 로컬 LLM API 엔드포인트 설정

로컬 LLM을 터미널에서 사용하려면 API 엔드포인트를 설정해야 합니다:

# llama-cpp-python을 사용한 로컬 서버 실행
pip install llama-cpp-python

# 모델 다운로드 및 서버 실행
llama-server --model ./models/llama-2-7b-chat.Q4_K_M.gguf \
  --port 8080 \
  --ctx-size 2048 \
  --n-gpu-layers 100
Enter fullscreen mode Exit fullscreen mode

3. 간단한 Python CLI 에이전트 구축

다음은 간단한 CLI 에이전트 구현 예제입니다:

# aider_agent.py
import os
import json
import subprocess
from openai import OpenAI

class AiderAgent:
    def __init__(self, api_key=None, model="llama2"):
        self.client = OpenAI(
            base_url="http://localhost:8080/v1",
            api_key="EMPTY"
        )
        self.model = model

    def code_completion(self, prompt, context=""):
        messages = [
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": f"{prompt}\n\nContext: {context}"}
        ]

        response = self.client.chat.completions.create(
            model=self.model,
            messages=messages,
            max_tokens=500,
            temperature=0.7
        )
        return response.choices[0].message.content

    def execute_command(self, command):
        try:
            result = subprocess.run(
                command, 
                shell=True, 
                capture_output=True, 
                text=True
            )
            return result.stdout, result.stderr
        except Exception as e:
            return "", str(e)

# 사용 예시
if __name__ == "__main__":
    agent = AiderAgent()
    response = agent.code_completion(
        "Write a Python function to calculate factorial",
        "Using recursion approach"
    )
    print(response)
Enter fullscreen mode Exit fullscreen mode

4. tmux와 연동

tmux를 사용하면 터미널 세션을 유지하면서 코드를 실행할 수 있습니다:

# tmux 세션 생성
tmux new-session -s aider_session -d

# 세션에 명령어 실행
tmux send-keys -t aider_session "python aider_agent.py" Enter

# 세션에 직접 입력 전달
tmux send-keys -t aider_session "print('Hello World')" Enter
Enter fullscreen mode Exit fullscreen mode

5. 사용자 정의 도구 개발

다음은 일반적인 도구들을 구현하는 예제입니다:

# tools.py
import os
import subprocess
import re

class CodeSearchTool:
    def __init__(self, project_root):
        self.project_root = project_root

    def search_in_files(self, pattern, file_extensions=None):
        """특정 패턴을 파일에서 검색"""
        if file_extensions is None:
            file_extensions = ['.py', '.js', '.ts', '.html', '.css']

        results = []
        for root, dirs, files in os.walk(self.project_root):
            for file in files:
                if any(file.endswith(ext) for ext in file_extensions):
                    filepath = os.path.join(root, file)
                    try:
                        with open(filepath, 'r', encoding='utf-8') as f:
                            content = f.read()
                            matches = re.finditer(pattern, content)
                            for match in matches:
                                results.append({
                                    'file': filepath,
                                    'line': content[:match.start()].count('\n') + 1,
                                    'context': match.group()
                                })
                    except Exception:
                        continue
        return results

class GitTool:
    def __init__(self):
        pass

    def git_status(self):
        return subprocess.run(['git', 'status'], 
                              capture_output=True, text=True).stdout

    def git_diff(self, file_path):
        return subprocess.run(['git', 'diff', file_path], 
                              capture_output=True, text=True).stdout

class FileOperationTool:
    def __init__(self):
        pass

    def read_file(self, filepath):
        try:
            with open(filepath, 'r') as f:
                return f.read()
        except Exception as e:
            return f"Error reading file: {str(e)}"

    def write_file(self, filepath, content):
        try:
            with open(filepath, 'w') as f:
                f.write(content)
            return "File written successfully"
        except Exception as e:
            return f"Error writing file: {str(e)}"
Enter fullscreen mode Exit fullscreen mode

6. 컨텍스트 윈도우 관리

대규모 코드베이스를 처리할 때 컨텍스트 윈도우를 관리하는 것이 중요합니다:

# context_manager.py
import tiktoken
from typing import List, Dict

class ContextManager:
    def __init__(self, max_tokens=2048):
        self.max_tokens = max_tokens
        self.encoding = tiktoken.get_encoding("cl100k_base")

    def truncate_context(self, context: str) -> str:
        """컨텍스트를 최대 토큰 수에 맞게 자르기"""
        tokens = self.encoding.encode(context)
        if len(tokens) <= self.max_tokens:
            return context

        # 토큰 수를 초과하는 경우, 마지막으로 자르기
        truncated_tokens = tokens[:self.max_tokens]
        return self.encoding.decode(truncated_tokens)

    def build_context(self, files: List[str], max_lines=1000) -> str:
        """다중 파일 컨텍스트 빌드"""
        context_parts = []
        total_tokens = 0

        for filepath in files[:10]:  # 최대 10개 파일만 처리
            try:
                with open(filepath, 'r') as f:
                    content = f.read()
                    # 긴 파일은 줄 수 제한
                    lines = content.split('\n')[:max_lines]
                    truncated_content = '\n'.join(lines)

                    # 토큰 수 계산
                    token_count = len(self.encoding.encode(truncated_content))
                    if total_tokens + token_count > self.max_tokens:
                        break

                    context_parts.append(f"\n# {filepath}\n{truncated_content}")
                    total_tokens += token_count
            except Exception:
                continue

        return '\n'.join(context_parts)
Enter fullscreen mode Exit fullscreen mode

7. 비용/속도 최적화

로컬 vs API 모델 사용 시 최적화 전략:

# 로컬 모델 최적화
# 1. 모델 가중치 압축
llama.cpp --model ./models/llama-2-7b-chat.Q4_K_M.gguf \
  --n-gpu-layers 100 \
  --ctx-size 2048

# 2. CPU 최적화
export OMP_NUM_THREADS=4
export MKL_NUM_THREADS=4

# 3. 메모리 사용량 줄이기
llama-server --model ./models/llama-2-7b-chat.Q4_K_M.gguf \
  --n-gpu-layers 0 \
  --n-predict 128
Enter fullscreen mode Exit fullscreen mode

8. 실제 워크플로우 예제

다음은 실제 개발 워크플로우 예제입니다:

# 1. 프로젝트 초기 설정
mkdir my_project && cd my_project
git init

# 2. AI 에이전트 실행
python aider_agent.py

# 3. 커맨드 사용 예시
# 코드 생성
echo "Create a Flask app with a single route" | python aider_agent.py

# 파일 검색
python tools.py search "def calculate" .py

# Git 상태 확인
python tools.py git_status

# 4. tmux 세션 관리
tmux new-session -s dev_session -d
tmux send-keys -t dev_session "python aider_agent.py" Enter
Enter fullscreen mode Exit fullscreen mode

최종 터미널 스크립트

다음은 실제 사용할 수 있는 터미널 스크립트입니다:


bash


---

📥 **Get the full guide on Gumroad**: https://gumroad.com/l/auto ($5)
Enter fullscreen mode Exit fullscreen mode

Top comments (0)