DEV Community

matias yoon
matias yoon

Posted on

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

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

터미널에서 작동하는 AI 에이전트는 현대 개발 워크플로우의 핵심 요소입니다. 이 가이드에서는 개발자가 실제로 사용할 수 있는 터미널 AI 에이전트를 구축하는 방법을 자세히 설명합니다.

1. CLI AI 에이전트 생태계

현재 터미널 AI 에이전트는 다양한 도구로 구성되어 있습니다:

Aider: GitHub Copilot과 유사한 기능을 제공하는 에이전트
Continue.dev: VS Code 확장 프로그램을 기반으로 한 터미널 지원 도구
OpenCode: 오픈소스 기반의 코드 생성 도구

# Aider 설치
pip install aider
# 사용 예시
aider --help
Enter fullscreen mode Exit fullscreen mode

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

로컬 LLM을 터미널에서 사용하려면 API 서버를 설정해야 합니다. 아래는 llama.cpp를 기반으로 한 예시입니다:

# llama.cpp 설치
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
make

# 모델 다운로드 및 변환
wget https://huggingface.co/TheBloke/Mistral-7B-v0.1-GGUF/resolve/main/mistral-7b-v0.1.Q4_K_M.gguf
python convert.py mistral-7b-v0.1.Q4_K_M.gguf

# 로컬 API 서버 실행
./server -m mistral-7b-v0.1.Q4_K_M.gguf -c 2048 --host 127.0.0.1 --port 8080
Enter fullscreen mode Exit fullscreen mode

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

다음은 함수 호출 기능을 포함한 기본 CLI 에이전트입니다:

# terminal_agent.py
import openai
import json
import subprocess
import os
from typing import Dict, Any

class TerminalAgent:
    def __init__(self):
        self.client = openai.OpenAI(
            base_url="http://localhost:8080/v1",
            api_key="sk-no-key-required"
        )

    def call_function(self, function_name: str, arguments: Dict[str, Any]) -> str:
        """함수 호출"""
        if function_name == "run_command":
            return self.run_shell_command(arguments["command"])
        elif function_name == "read_file":
            return self.read_file(arguments["path"])
        elif function_name == "write_file":
            return self.write_file(arguments["path"], arguments["content"])
        else:
            return f"Unknown function: {function_name}"

    def run_shell_command(self, command: str) -> str:
        """쉘 명령어 실행"""
        try:
            result = subprocess.run(
                command, 
                shell=True, 
                capture_output=True, 
                text=True,
                timeout=30
            )
            return result.stdout + result.stderr
        except subprocess.TimeoutExpired:
            return "Command timed out"

    def read_file(self, path: str) -> str:
        """파일 읽기"""
        try:
            with open(path, 'r') as f:
                return f.read()
        except Exception as e:
            return f"Error reading file: {str(e)}"

    def write_file(self, path: str, content: str) -> str:
        """파일 쓰기"""
        try:
            os.makedirs(os.path.dirname(path), exist_ok=True)
            with open(path, 'w') as f:
                f.write(content)
            return f"File written successfully to {path}"
        except Exception as e:
            return f"Error writing file: {str(e)}"

    def chat(self, prompt: str) -> str:
        """AI와 대화"""
        response = self.client.chat.completions.create(
            model="local",
            messages=[
                {"role": "system", "content": """
                You are a helpful terminal assistant. You can execute commands, 
                read/write files, and provide programming assistance.
                Available functions:
                - run_command(command): Execute shell commands
                - read_file(path): Read file content
                - write_file(path, content): Write content to file
                Always respond in JSON format with 'function' and 'arguments' fields.
                """},
                {"role": "user", "content": prompt}
            ],
            temperature=0.7,
            max_tokens=1024
        )

        return response.choices[0].message.content

# 실행 예시
if __name__ == "__main__":
    agent = TerminalAgent()
    while True:
        user_input = input("Terminal Agent> ")
        if user_input.lower() in ['exit', 'quit']:
            break
        response = agent.chat(user_input)
        print(response)
Enter fullscreen mode Exit fullscreen mode

4. tmux와의 통합

tmux를 활용해 에이전트를 터미널 세션과 통합합니다:

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

# 세션에 명령어 전송
tmux send-keys -t ai_agent "python terminal_agent.py" Enter

# 세션에 명령어 전송 함수
function send_to_agent() {
    tmux send-keys -t ai_agent "$1" Enter
}

# 사용 예시
send_to_agent "list files"
Enter fullscreen mode Exit fullscreen mode

5. 사용자 정의 도구 개발

다음은 코드 검색 및 파일 작업 도구입니다:

# custom_tools.py
import os
import glob
import re
from typing import List

class CodeSearchTool:
    def __init__(self, root_path: str = "."):
        self.root_path = root_path

    def search_code(self, pattern: str, file_extensions: List[str] = None) -> List[str]:
        """코드 검색"""
        if file_extensions is None:
            file_extensions = ['*.py', '*.js', '*.ts', '*.java', '*.cpp']

        results = []
        for ext in file_extensions:
            search_path = os.path.join(self.root_path, '**', ext)
            for file_path in glob.glob(search_path, recursive=True):
                try:
                    with open(file_path, 'r') as f:
                        content = f.read()
                        if re.search(pattern, content, re.IGNORECASE):
                            results.append({
                                'path': file_path,
                                'matches': re.findall(pattern, content, re.IGNORECASE)
                            })
                except Exception:
                    continue
        return results

    def get_git_status(self) -> str:
        """Git 상태 확인"""
        try:
            result = subprocess.run(
                ['git', 'status', '--porcelain'],
                capture_output=True,
                text=True,
                cwd=self.root_path
            )
            return result.stdout
        except Exception as e:
            return f"Git error: {str(e)}"

# 파일 작업 도구
class FileOperationTool:
    def __init__(self):
        pass

    def find_files_by_pattern(self, pattern: str, directory: str = ".") -> List[str]:
        """패턴 기반 파일 찾기"""
        return glob.glob(os.path.join(directory, pattern), recursive=True)

    def count_lines_in_file(self, file_path: str) -> int:
        """파일 줄 수 계산"""
        try:
            with open(file_path, 'r') as f:
                return sum(1 for line in f)
        except Exception:
            return 0
Enter fullscreen mode Exit fullscreen mode

6. 컨텍스트 윈도우 관리

대규모 코드베이스의 경우 컨텍스트 윈도우를 관리해야 합니다:

# context_manager.py
class ContextManager:
    def __init__(self, max_tokens: int = 4096):
        self.max_tokens = max_tokens
        self.context = []

    def add_to_context(self, content: str, role: str = "user"):
        """컨텍스트에 추가"""
        self.context.append({
            "role": role,
            "content": content
        })

    def trim_context(self) -> str:
        """컨텍스트 자르기"""
        current_tokens = 0
        trimmed = []

        # 최근 항목부터 검사
        for item in reversed(self.context):
            content_length = len(item["content"])
            if current_tokens + content_length > self.max_tokens:
                break
            trimmed.append(item)
            current_tokens += content_length

        return list(reversed(trimmed))

    def get_context_prompt(self) -> str:
        """현재 컨텍스트를 프롬프트로 반환"""
        trimmed = self.trim_context()
        return "\n".join([item["content"] for item in trimmed])

# 사용 예시
context = ContextManager(max_tokens=2048)
context.add_to_context("import os", "system")
context.add_to_context("def hello():\n    print('hello')", "user")
prompt = context.get_context_prompt()
Enter fullscreen mode Exit fullscreen mode

7. 비용/속도 최적화

로컬 vs API 모델의 최적화 전략:


python
# optimization.py
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

class ModelOptimizer:
    def __init__(self

---

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

Top comments (0)