LLM Function Calling에서 안정적인 예외 처리와 재시도 구현

LLM (Large Language Model)의 Function Calling 또는 Tool Calling을 사용할 때, 함수에서 예외가 발생하면 Python 프로세스가 중단되는 경우가 있습니다. 이를 방지하고, 프로세스를 안전하게 유지하며 예외를 LLM에게 전달하기 위해 재시도(retry) 정책을 설정하는 방법을 알아보겠습니다. 특히 LangChain 프레임워크에서는 Tenacity 라이브러리를 활용하여 재시도 메커니즘을 내장하고 있습니다. 이번 포스팅에서는 tenacity.retry 장식자(Decorator)를 사용해 함수 재시도를 구현하고, 실패 시 커스터마이징된 응답을 반환하는 방법을 설명합니다.

LangChain에서 Function/Tool Calling의 문제

LLM/랭체인을 통한 Function/Tool Calling에서 호출된 함수에서 예외가 발생하면 다음과 같은 문제가 발생합니다:

  • 함수 실패 시 파이썬 프로세스가 중단될 수 있습니다.
  • 호출한 LLM은 함수 호출 결과를 받아오지 못하게 됩니다.

이를 해결하기 위해 함수 레벨에서 재시도 정책을 설정하고, 마지막 실패 시에도 안정적인 응답을 반환할 수 있어야 합니다.

Tenacity 라이브러리 소개

Tenacity는 Python의 강력한 재시도(retry) 라이브러리입니다. tenacity.retry 장식자를 사용하면 다양한 재시도 조건과 정책을 설정할 수 있습니다. 주요 기능은 다음과 같습니다:

  • 재시도 조건 설정: 특정 예외 발생 시 재시도
  • 재시도 횟수 및 간격 설정: 최대 재시도 횟수 및 대기 시간 지정
  • 마지막 실패 처리: 재시도 실패 후 별도의 콜백 실행

LangChain 내부에서도 Tenacity를 활용하여, 다양한 재시도 기능을 제공하고 있습니다.

Function Calling에 재시도 정책 적용하기

다음은 LangChain의 Tool에 사용할 함수를 tenacity.retry로 래핑하는 예제입니다.

from tenacity import retry, stop_after_attempt, wait_fixed, RetryCallState

def retry_error_callback(retry_state: RetryCallState) -> str:
    exc = retry_state.outcome.exception()
    return f"Exception: {exc.__class__.__name__}: {exc}"

# 재시도 정책 설정: 최대 3번 재시도, 2초 간격
@retry(
    stop=stop_after_attempt(3),
    wait=wait_fixed(2),
    retry_error_callback=retry_error_callback,
)
def get_yes24_book_detail(url: str) -> str:
    # 크롤링 코드이기에 네트워크 오류나 HTML 파싱 에러가 발생할 수 있습니다.
    return ...

# 함수를 호출했을 때, 예외가 발생하더라도 프로세스 중단없이 안정적으로 값을 반환하게 됩니다.
book_detail = get_yes24_book_detail("https://www.yes24.com/Product/Goods/139709711")

# Function Calling에서 이렇게 활용합니다.
tools = [
    get_yes24_book_detail,
]
  • 재시도 정책 설정
    • stop_after_attempt(3) : 최대 3번 재시도
    • wait_fixed(2) : 재시도 사이에 2초 대기
    • retry_error_callback : 마지막 재시도 후 실패 시 반환할 값을 설정
  • 예외 처리
    • RetryError 예외를 발생시키지 않고, retry_error_callback을 통해 문자열 형태의 실패 결과를 반환합니다.
  • 결과 반환
    • 함수가 성공하면 정상적으로 결과를 반환합니다.
    • 실패 시에도 프로세스가 중단되지 않고, 실패 내역을 문자열로 반환합니다.

LangChain에서 Tool로 활용하기

랭체인의 langchain.tools.Tool을 사용할 때에도 retry 장식자로 래핑한 함수를 적용하시면, 예외가 발생하더라도 안정적으로 함수 호출을 하실 수 있습니다.

여러 함수에 동일한 재시도 전략 지정하기

파이썬 장식자도 하나의 함수이므로, 이렇게 먼저 재시도 정책을 생성하신 후에

from tenacity import retry, stop_after_attempt, RetryCallState, wait_random

def retry_error_callback(retry_state: RetryCallState) -> str:
    exc = retry_state.outcome.exception()
    return f"Exception: {exc.__class__.__name__}: {exc}"

# 장식자가 아니라, 이렇게 함수처럼 활용 가능
retry_strategy = retry(
    # 모든 예외에 대해서 재시도. 특정 예외 클래스만 지정하고 싶다면?
    # retry=retry_if_exception_type(Value),
    stop=stop_after_attempt(3),  # 재시도 횟수
    wait=wait_random(1, 3),  # 재시도 대기 시간
    retry_error_callback=retry_error_callback,
)

아래와 같이 일관되게 재시도 전략을 지정하실 수 있습니다.

tools = [
    retry_strategy(get_yes24_book_detail),
    retry_strategy(other_function1),
    retry_strategy(other_function2),
]

마무리

LangChain을 사용해 LLM과 Function/Tool Calling을 구현할 때는 재시도 정책을 설정하여 안정성을 높이는 것이 중요합니다. Tenacity를 통해 쉽고 유연하게 재시도 로직을 구현해보세요! 🚀

  • 마지막 편집일시 : 2024년 12월 17일 3:53 오후
  • 최초 생성일시 : 2024년 12월 17일 3:53 오후
🌟 본 포스팅이 도움이 되셨다면 댓글 하나 남겨주시고, 널리 공유도 부탁드립니다. 🌟

댓글