Home Ollama LLM 연결하기 — Hexagonal Architecture로 LLM Adapter 구현
Post
Cancel

Ollama LLM 연결하기 — Hexagonal Architecture로 LLM Adapter 구현

1. LLM 연결하기

진행하는 프로젝트에서는 AI Agent를 확장 가능한 구조로 만들고 싶었기에 Hexagonal Architecture를 기반으로 구현하려고 한다.

그런 관점에서 볼때 LLM은 외부 시스템에 해당하기 때문에 도메인 로직에서 직접 호출하지 않고 Port / Adapter 구조로 분리하여 구현되어야 한다.

이렇게 구조를 나누는 이유는

  • OpenLLM -> ClosedLLM 추가 및 변경 가능
  • 모델 추가 및 변경 가능
  • API방식 변경 가능
  • 테스트 가능
  • 의존성 분리

즉,

1
Domain -> Port -> Adapter -> LLM

구조로 연결하도록 하기 위함이다.

이번 글에서는 그 첫번째로 Ollama를 통해서 Qwen2.5:7b 모델을 Adapter로 연결해 본다.


2. LLM Port 정의

LLM은 외부 시스템이므로 Port를 먼저 정의한다.

경로 domain/port/llm_port.py

1
2
3
4
5
6
7
8
9
from abc import ABC, abstractmethod


class LLMPort(ABC):

    @abstractmethod
    def generate(self, prompt: str) -> str:
        pass

LLM을 사용하는 쪽에서는 이 인터페이스만 알고 있으면 된다. 이렇게 되면 Adapter를 변경해도 도메인 코드에 추가적은 추정은 필요 없어진다.

3. Ollama Adapter 구현

Adapter는 외부 시스템과 연결되는 구현체이므로 adapter레이어에 작성한다. 경로 adapter/llm/ollama_adapter.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import requests

from domain.port.llm_port import LLMPort


class OllamaLLMAdapter(LLMPort):

    def __init__(self, model: str):
        self.model = model
        self.url = "http://localhost:11434/api/generate"

    def generate(self, prompt: str) -> str:
        response = requests.post(
            self.url,
            json={
                "model": self.model,
                "prompt": prompt,
                "stream": False
            },
        )
        response.raise_for_status()
        data = response.json()
        return data["response"]

해당 Adapter

  • Ollama API 호출
  • 모델 실행
  • 결과반환

의 역할만 수행한다. 도메인 로직은 Ollama에 대해 알 필요가 없다.

4. Application Service에서 사용

Agent 실행 로직은 application 레ㅇ이어에 위치 시킨다. 경로 application/service/agent_service.py

1
2
3
4
5
6
7
8
9
10
from domain.port.llm_port import LLMPort


class AgentService:
    def __init__(self, llm: LLMPort):
        self.llm = llm

    def ask(self, text: str) -> str:
        return self.llm.generate(text)

Application

  • Port만 의존
  • Adapter 모름

이게 Hexagonal Architecture의 핵심이다.

5. 실행 코드 작성

main에서 Adapter를 생성하고 Service에 주입한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from adapter.llm.ollama_adapter import OllamaLLMAdapter
from application.service.agent_service import AgentService


def main():
    llm = OllamaLLMAdapter(
        model="qwen2.5:7b"
    )

    service = AgentService(llm)

    result = service.ask(
        "DDD가 무엇인지 설명해줘"
    )

    print(result)


if __name__ == "__main__":
    main()

위 코드를 실행하면 Ollama를 통해 qwen2.5:7b LLM 모델이 호출되어 응답을 받을 수 있게 된다.

호출 이미지

6. 현재 구조

현재 구조와 의존성 방향으로 봤을떄 의도한대로 Domain은 외부 의존성을 아무것도 모르게 된다.

이런 구조를 유지하면서 기능을 계속 추가할 예정이다.

7. 다음 단계

지금은 LLM만 연결한 상태이기 때문에 Agent라고 하기에는 부족한점이 많다.

AI Agent가 되려면 외부 기능을 사용할 수 있어야 한다. 다음 글에서는 Tool에 대해 알아보고 추가하여 외부 기능을 호출할 수 있도록 기능을 확장해 본다.

This post is licensed under CC BY 4.0 by the author.

AI Agent를 직접 만들어보려고 한 이유와 프로젝트 설정

Tool 구조 만들기 — AI Agent에서 외부 기능을 사용하는 방법