반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

https://python.langchain.com/docs/expression_language/how_to/fallbacks

 

Add fallbacks | 🦜️🔗 Langchain

There are many possible points of failure in an LLM application, whether that be issues with LLM API's, poor model outputs, issues with other integrations, etc. Fallbacks help you gracefully handle and isolate these issues.

python.langchain.com

 

Add fallbacks

 

There are many possible points of failure in an LLM application, whether that be issues with LLM API's, poor model outputs, issues with other integrations, etc. Fallbacks help you gracefully handle and isolate these issues.

 

LLM API 문제, 잘못된 모델 출력, 기타 통합 문제 등 LLM 애플리케이션에는 실패할 수 있는 지점이 많이 있습니다. 폴백은 이러한 문제를 적절하게 처리하고 격리하는 데 도움이 됩니다.

 

Crucially, fallbacks can be applied not only on the LLM level but on the whole runnable level.

 

결정적으로 폴백은 LLM 수준뿐만 아니라 전체 실행 가능 수준에 적용될 수 있습니다.

 

Handling LLM API Errors

 

This is maybe the most common use case for fallbacks. A request to an LLM API can fail for a variety of reasons - the API could be down, you could have hit rate limits, any number of things. Therefore, using fallbacks can help protect against these types of things.

 

이는 아마도 폴백의 가장 일반적인 사용 사례일 것입니다. LLM API에 대한 요청은 다양한 이유로 실패할 수 있습니다. API가 다운되거나 속도 제한에 도달하는 등 여러 가지 이유로 실패할 수 있습니다. 따라서 fallbacks를 사용하면 이러한 유형의 문제로부터 보호하는 데 도움이 될 수 있습니다.

 

IMPORTANT: By default, a lot of the LLM wrappers catch errors and retry. You will most likely want to turn those off when working with fallbacks. Otherwise the first wrapper will keep on retrying and not failing.

 

중요: 기본적으로 많은 LLM wrappers 가 오류를 포착하고 다시 시도합니다. 폴백 작업을 할 때는 이 기능을 끄고 싶을 가능성이 높습니다. 그렇지 않으면 첫 번째 래퍼가 계속 재시도하고 실패하지 않습니다.

 

from langchain.chat_models import ChatOpenAI, ChatAnthropic

First, let's mock out what happens if we hit a RateLimitError from OpenAI

 

먼저 OpenAI에서 RateLimitError가 발생하면 어떤 일이 발생하는지 모의해 보겠습니다.

 

from unittest.mock import patch
from openai.error import RateLimitError
# Note that we set max_retries = 0 to avoid retrying on RateLimits, etc
openai_llm = ChatOpenAI(max_retries=0)
anthropic_llm = ChatAnthropic()
llm = openai_llm.with_fallbacks([anthropic_llm])
# Let's use just the OpenAI LLm first, to show that we run into an error
with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):
    try:
         print(openai_llm.invoke("Why did the chicken cross the road?"))
    except:
        print("Hit error")

이 코드는 ChatOpenAI와 ChatAnthropic 대화 모델을 설정하고, RateLimitError가 발생하도록 모의 실험을 수행하는 예시를 제공합니다. 

  1. 필수 모듈 및 클래스 가져오기:
    • langchain.chat_models 모듈에서 ChatOpenAI 및 ChatAnthropic 클래스를 가져옵니다. 이 클래스들은 대화 모델을 설정하고 사용하는 데 도움을 줍니다.
    • unittest.mock 모듈에서 patch 클래스를 가져옵니다. 이 클래스를 사용하여 함수 호출을 모의로 변경합니다.
    • openai.error 모듈에서 RateLimitError 클래스를 가져옵니다. 이 클래스는 OpenAI API 요청 제한(Rate Limit) 오류를 나타냅니다.
  2. 대화 모델 설정:
    • ChatOpenAI(max_retries=0)는 "ChatOpenAI" 대화 모델을 설정하며, max_retries를 0으로 설정하여 요청 제한(Rate Limit) 오류 시 재시도(retry)를 피합니다.
    • ChatAnthropic()는 "ChatAnthropic" 대화 모델을 설정합니다.
    • openai_llm.with_fallbacks([anthropic_llm])는 "openai_llm" 대화 모델을 설정하며, "ChatAnthropic" 대화 모델을 대체 옵션으로 사용합니다.
  3. RateLimitError 모의 실험:
    • with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):는 openai.ChatCompletion.create 함수 호출을 모의로 변경하여 RateLimitError를 발생하도록 설정합니다.
    • try: 블록은 RateLimitError가 발생할 가능성이 있는 코드를 포함합니다.
    • openai_llm.invoke("Why did the chicken cross the road?")는 "openai_llm" 대화 모델을 사용하여 질문을 호출합니다.
    • except: 블록은 RateLimitError가 발생한 경우 실행되며, "Hit error"를 출력합니다.

이 코드는 RateLimitError를 처리하는 방법을 모의 실험을 통해 보여줍니다. RateLimitError는 OpenAI API의 요청 제한을 초과한 경우 발생하는 오류입니다.

 

    Hit error

 

# Now let's try with fallbacks to Anthropic
with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):
    try:
         print(llm.invoke("Why did the chicken cross the road?"))
    except:
        print("Hit error")

이 코드는 ChatOpenAI와 ChatAnthropic 대화 모델을 설정하고, RateLimitError가 발생하도록 모의 실험을 수행합니다. 이번에는 "llm" 대화 모델이 대체 옵션으로 "ChatAnthropic" 대화 모델을 사용하여 실험합니다. 

  1. RateLimitError 모의 실험:
    • with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):는 openai.ChatCompletion.create 함수 호출을 모의로 변경하여 RateLimitError를 발생하도록 설정합니다.
    • try: 블록은 RateLimitError가 발생할 가능성이 있는 코드를 포함합니다.
    • llm.invoke("Why did the chicken cross the road?")는 "llm" 대화 모델을 사용하여 질문을 호출합니다.
    • except: 블록은 RateLimitError가 발생한 경우 실행되며, "Hit error"를 출력합니다.

이 코드는 "llm" 대화 모델이 RateLimitError가 발생하는 상황에서 "ChatAnthropic" 대화 모델로 대체되어 정상적으로 처리하는 방법을 모의 실험을 통해 보여줍니다. RateLimitError가 발생하면 "ChatAnthropic" 대화 모델이 대신 사용되어 오류를 처리합니다.

 

    content=' I don\'t actually know why the chicken crossed the road, but here are some possible humorous answers:\n\n- To get to the other side!\n\n- It was too chicken to just stand there. \n\n- It wanted a change of scenery.\n\n- It wanted to show the possum it could be done.\n\n- It was on its way to a poultry farmers\' convention.\n\nThe joke plays on the double meaning of "the other side" - literally crossing the road to the other side, or the "other side" meaning the afterlife. So it\'s an anti-joke, with a silly or unexpected pun as the answer.' additional_kwargs={} example=False

 

We can use our "LLM with Fallbacks" as we would a normal LLM.

 

일반 LLM처럼 "폴백이 포함된 LLM"을 사용할 수 있습니다.

 

from langchain.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "You're a nice assistant who always includes a compliment in your response"),
        ("human", "Why did the {animal} cross the road"),
    ]
)
chain = prompt | llm
with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):
    try:
         print(chain.invoke({"animal": "kangaroo"}))
    except:
        print("Hit error")

이 코드는 ChatPromptTemplate을 사용하여 대화 템플릿을 설정하고, RateLimitError가 발생하도록 모의 실험을 수행합니다. 이 템플릿은 사용자와 시스템 간의 대화에서 "compliment"를 항상 포함하는 섬사적인(Assistant) 응답을 생성하는 목적으로 설계되었습니다. 

  1. ChatPromptTemplate 설정:
    • ChatPromptTemplate.from_messages()를 사용하여 대화 템플릿을 생성합니다.
    • 템플릿에는 시스템과 사용자 간의 대화 메시지가 정의되어 있습니다.
    • 시스템 메시지는 "You're a nice assistant who always includes a compliment in your response"로 설정되어 있으며, Assistant가 항상 칭찬을 포함하는 좋은 Assistant임을 나타냅니다.
    • 사용자 메시지는 "Why did the {animal} cross the road"로 설정되어 있으며, "{animal}" 부분은 나중에 사용자가 지정할 수 있는 변수로 사용됩니다.
  2. 대화 체인 설정:
    • chain = prompt | llm는 설정한 대화 템플릿과 "llm" 대화 모델을 연결하여 실행 체인을 설정합니다.
  3. RateLimitError 모의 실험:
    • with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):는 openai.ChatCompletion.create 함수 호출을 모의로 변경하여 RateLimitError를 발생하도록 설정합니다.
    • try: 블록은 RateLimitError가 발생할 가능성이 있는 코드를 포함합니다.
    • chain.invoke({"animal": "kangaroo"})는 "chain" 대화 체인을 사용하여 "{animal}" 변수를 "kangaroo"로 설정하여 질문을 호출합니다.
    • except: 블록은 RateLimitError가 발생한 경우 실행되며, "Hit error"를 출력합니다.

이 코드는 섬사적인(Assistant) 대화 템플릿과 "llm" 대화 모델을 사용하여 RateLimitError가 발생하는 상황에서 어떻게 오류를 처리하는지를 모의 실험을 통해 보여줍니다. RateLimitError가 발생하면 오류를 처리하는 방법을 확인할 수 있습니다.

    content=" I don't actually know why the kangaroo crossed the road, but I'm happy to take a guess! Maybe the kangaroo was trying to get to the other side to find some tasty grass to eat. Or maybe it was trying to get away from a predator or other danger. Kangaroos do need to cross roads and other open areas sometimes as part of their normal activities. Whatever the reason, I'm sure the kangaroo looked both ways before hopping across!" additional_kwargs={} example=False

 

Specifying errors to handle

We can also specify the errors to handle if we want to be more specific about when the fallback is invoked:

 

fallback이 호출되는 시기에 대해 더 구체적으로 알고 싶다면 처리할 오류를 지정할 수도 있습니다.

 

llm = openai_llm.with_fallbacks([anthropic_llm], exceptions_to_handle=(KeyboardInterrupt,))

chain = prompt | llm
with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):
    try:
         print(chain.invoke({"animal": "kangaroo"}))
    except:
        print("Hit error")

이 코드는 설정한 ChatOpenAI 및 ChatAnthropic 대화 모델을 사용하여 RateLimitError가 발생하도록 모의 실험을 수행하고, 이 때 특정 예외(KeyboardInterrupt)를 처리하는 방법을 보여줍니다. 

  1. RateLimitError 모의 실험:
    • with patch('openai.ChatCompletion.create', side_effect=RateLimitError()):는 openai.ChatCompletion.create 함수 호출을 모의로 변경하여 RateLimitError를 발생하도록 설정합니다.
    • try: 블록은 RateLimitError가 발생할 가능성이 있는 코드를 포함합니다.
    • chain.invoke({"animal": "kangaroo"})는 "chain" 대화 체인을 사용하여 "{animal}" 변수를 "kangaroo"로 설정하여 질문을 호출합니다.
    • except: 블록은 RateLimitError가 발생한 경우 실행되며, "Hit error"를 출력합니다.
  2. 대화 모델 및 RateLimitError 처리:
    • openai_llm.with_fallbacks([anthropic_llm], exceptions_to_handle=(KeyboardInterrupt,))는 "openai_llm" 대화 모델에 대체 옵션으로 "anthropic_llm" 대화 모델을 추가하며, RateLimitError 외에도 KeyboardInterrupt 예외를 처리하기 위해 exceptions_to_handle를 설정합니다.
    • 이렇게 설정한 "llm" 대화 모델을 사용하여 대화 체인을 생성합니다.

이 코드는 RateLimitError가 발생하거나 KeyboardInterrupt 예외가 발생하는 경우, 대체 옵션으로 "anthropic_llm" 대화 모델로 전환하여 오류를 처리하는 방법을 보여줍니다. KeyboardInterrupt 예외는 사용자가 프로그램을 중지할 때 발생하는 예외이며, 이러한 예외가 발생하는 경우 대체 모델로 전환하여 안전하게 처리할 수 있습니다.

    Hit error

 

Fallbacks for Sequences

We can also create fallbacks for sequences, that are sequences themselves. Here we do that with two different models: ChatOpenAI and then normal OpenAI (which does not use a chat model). Because OpenAI is NOT a chat model, you likely want a different prompt.

 

시퀀스 자체인 시퀀스에 대한 대체를 만들 수도 있습니다. 여기서는 ChatOpenAI와 일반 OpenAI(채팅 모델을 사용하지 않음)라는 두 가지 모델을 사용하여 이를 수행합니다. OpenAI는 채팅 모델이 아니기 때문에 다른 프롬프트를 원할 가능성이 높습니다.

 

# First let's create a chain with a ChatModel
# We add in a string output parser here so the outputs between the two are the same type
from langchain.schema.output_parser import StrOutputParser

chat_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "You're a nice assistant who always includes a compliment in your response"),
        ("human", "Why did the {animal} cross the road"),
    ]
)
# Here we're going to use a bad model name to easily create a chain that will error
chat_model = ChatOpenAI(model_name="gpt-fake")
bad_chain = chat_prompt | chat_model | StrOutputParser()
# Now lets create a chain with the normal OpenAI model
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate

prompt_template = """Instructions: You should always include a compliment in your response.

Question: Why did the {animal} cross the road?"""
prompt = PromptTemplate.from_template(prompt_template)
llm = OpenAI()
good_chain = prompt | llm
# We can now create a final chain which combines the two
chain = bad_chain.with_fallbacks([good_chain])
chain.invoke({"animal": "turtle"})

 

이 코드는 먼저 ChatModel과 String Output Parser를 사용하여 대화 체인을 생성하고, 그런 다음 정상적인 OpenAI 모델과 연결하여 오류 처리를 수행하는 방법을 보여줍니다.

 

첫 번째 대화 체인 생성:

    • ChatPromptTemplate.from_messages()를 사용하여 대화 템플릿을 생성합니다. 이 템플릿은 시스템이 항상 칭찬을 포함하도록 지시하고 사용자로부터 "{animal}" 변수를 받는 대화를 설정합니다.
    • ChatOpenAI(model_name="gpt-fake")는 "gpt-fake"와 같은 잘못된 모델 이름을 사용하여 오류가 발생하는 "bad_chain" 대화 모델을 설정합니다.
    • chat_prompt | chat_model | StrOutputParser()는 "chat_prompt" 템플릿과 "chat_model" 대화 모델을 연결하고, 출력 형식을 일치시키기 위해 String Output Parser를 추가합니다.
  1. 정상적인 대화 체인 생성:
    • PromptTemplate.from_template(prompt_template)를 사용하여 대화 템플릿을 생성합니다. 이 템플릿은 Assistant가 항상 칭찬을 포함해야 함을 지시하고 "{animal}" 변수를 받는 대화를 설정합니다.
    • OpenAI()를 사용하여 정상적인 "llm" 대화 모델을 설정합니다.
    • prompt | llm는 "prompt" 템플릿과 "llm" 대화 모델을 연결하여 정상적인 대화 체인인 "good_chain"을 설정합니다.
  2. 대체 옵션을 포함하는 최종 대화 체인 생성:
    • bad_chain.with_fallbacks([good_chain])는 "bad_chain" 대화 체인을 "good_chain" 대화 체인으로 대체 옵션을 추가하여 최종 대화 체인 "chain"을 생성합니다.
  3. 대화 체인 호출:
    • chain.invoke({"animal": "turtle"})는 "chain" 대화 체인을 사용하여 "{animal}" 변수를 "turtle"로 설정하여 질문을 호출합니다.

이 코드는 대화 체인에서 모델 오류 처리 및 대체 모델 사용의 예시를 제공합니다. "bad_chain"에서 오류가 발생하면 "good_chain"으로 대체하여 정상적으로 처리됩니다.

 

반응형