LLM 시대, LangChain(랭체인)으로 배우는 AI 소프트웨어 개발
LangChain(랭체인)은 LLM을 사용하여 애플리케이션을 개발하기 위한 프레임워크입니다. 개발자는 LangChain을 사용하여 LLM을 사용하는 응용프로그램을 쉽게 개발할 수 있습니다. LangChain은 LLM을 활용하는 편리한 기능을 다양한 컴포넌트로 제공합니다. 또한 컴포넌트간의 연계를 실현하는 전용언어 LCEL(LangChain Expression Language)도 제공하고 있습니다. 아래 그림은 LangChain(랭체인)의 구성을 보여줍니다.
LangChain(랭체인)의 구성요소는 주로 다음 3가지 범주로 분류됩니다.
모델 입출력
RAG지원
에이전트 지원
모델 I/O 컴포넌트는 LLM을 사용하는데 필수적인 구성요소입니다. LLM을 사용하는 최소 애플리케이션은 이러한 컴포넌트를 사용하여 구축할 수 있습니다. 한편으로 RAG지원의 컴포넌트는 RAG를 실현하는데 필요한 기능세트를 제공합니다. 마찬가지로 에이전트지원의 컴포넌트는 AI에이전트를 구현하는데 필요한 기능을 제공합니다.
LCEL은 Python에서 이러한 컴포넌트를 쉽게 사용할 수 있도록 지원하는 전용 언어입니다. LCEL을 사용함으로써, 컴포넌트끼리의 조합을 깔끔하게 기술할 수 있습니다. LCEL로 작성된 프로그램은 일반적인 Python프로그램입니다. 이 대문에 전용언어라고 했ㅆ지만 Python과 다른 처리 시스템이 필요하지 않습니다.
이번에는 아래와 같은 순서로 설명합니다.
대화모델
프롬프트 템플릿
출력파서
LCEL
RAG 지원
에이전트 지원
1번부터 3번까지의 내용을 익혀서 LLM을 사용하는 최소한 애플리케이션을 개발할 수 있습니다. 또한 4번 LCEL을 익히면 LangChain(랭체인)답게 컴포넌트를 사용할 수 있게 됩니다. LCEL에서 제공하는 구문을 사용하지 않아도 LangChain을 사용할 수 있습니다. 그러나 나중에 설명하는 RAG나 에이전트 프로그램을 간결하게 설명하기 위해서는 LCEL을 알아야 합니다. LCEL에 대해 설명한 다음 5번과 6번에 대해 설명합니다. 참고로 5번과 6번은 관심있는 순번대로 읽어도 되며 보다 발전적인 에이전트를 구축하기 위한 방법은 나중에 따로 설명합니다.
LangChain(랭체인)의 대화모델은 API공급자가 제공하는 API를 추상화한 통합 인터페이스를 제공합니다. 각 API 공급자가 제공하는 API에는 조금씩 차이가 있습니다. 예를 들어, 같은 방식으로 '다음 메시지를 생성한다'라는 목적을 가지는 것도 API공급자마다 조금씩 입출력 형식이 다릅니다. LangChain의 대화모델은 이 차이를 채우는 역할을 합니다.
LangChain의 대화모델은 주로 다음기능을 제공합니다.
대화모델 만들기
대화모델 호출(텍스트 전용, 멀티모달)
스트림 호출
배치호출
출력포멧 지정(구조화 출력)
도구 지정
이 중 API공급자간에 차이가 있는 것은 주로 대화모델을 만드는 것입니다. 대화모델은 클래스로 제공되지만 API공급자마다 다른 클래스가 제공됩니다. 일단 클래스를 인스턴스화하면 대부부닁 기능은 API공급자에 의존하지 않습니다. API공급자에 의존하는 기능으로서는 멀티모달로 대화모델 호출을 들 수 있습니다.
이런 기능에 대해 순서대로 설명합니다.
대화 모델을 사용하려면 대화모델의 인스턴스를 생성해야 합니다. 대화모델은 LangChain에서 사용하는 API공급자별 클래스로 제공됩니다.
아래 표는 API 공급자별 클래스목록을 보여줍니다. 대화모델 클래스에는 API공급자별 전용 패키지가 있습니다. 따라서 해당 패키지에서 대화모델 클래스를 가져와야 합니다. 또한 생성자 인수는 API공급자마다 다릅니다.
예를 들어, OpenAI 대화모델 클래스를 가져오고 인스턴스를 생성하는 코드는 다음과 같습니다.
여기서는 langchain_openai에서 ChatOpenAI를 가져오고 ChatOpenAI의 생성자를 호출하여 대화모델을 만듭니다. 여기서 작성하는 모델은 'gpt-4o'입니다. 또한 temperature 파라미터에 0을 지정합니다. 마찬가지로 Google의 대화모델을 만들려면 다음을 수행합니다.
여기에서는 모델에 "gemini-pro", temperature 파라미터에 0을 지정합니다. ChatGoogleGenerativeAI를 포함한 langchain_google_gemini패키지는 LangChain본문과는 별도의 패키지입니다. 이 패키지를 사용하려면 먼저 다음 명령으로 설치해야 합니다.
다른 API공급자의 대화모델을 사용하는 경우에도 비슷한 절차가 필요합니다.
대화모델의 가장 기본적인 사용법은 invoke메소드를 사용한 호출입니다. 대화모델은 하나 이상의 메시지를 입력으로 다음 메시지를 생성할 수 있습니다. 메시지를 전달하는 방법에는 2가지가 있습니다.
단일 문자열로 호출
메시지 목록에서 호출
메시지목록에서 호출하는 경우 대화 모델이 멀티모달이 가능하면 메시지에 텍스트뿐만 아니라, 이미지등을 지정할 수도 있습니다. 다음은 이런 방법을 순서대로 설명합니다.
▣ 단일 문자열로 호출
단일문자열을 인수로 invoke메소드를 호출하면 해당 문자열에 대한 응답을 대화모델에 생성할 수 있습니다. 이제 LangChain(랭체인)을 사용하여 모델에 액세스해 봅시다. 아래 코드는 랭체인(LangChain)을 사용하여 모델에 접근하는 예시를 봅시다.
단일문자열로 대화 모델 호출 (src/langchain/model_access.py)
먼저 대화모델을 사용하는 클래스를 가져옵니다.
여기에서는 OpenAI대화모델을 가져옵니다. 사용하는 API공급자에 따라 적절한 클래스를 가져옵니다. API키가 환경변수로 설정되어 있다고 가정합니다. 예를 들어, OpenAI모델을 사용하는 경우 OPENAI_API_KEY에 API키를 설정합니다. 그런 다음 ChatOpenAI클래스를 사용하여 ChatOpenAI객체를 만듭니다.
여기서는 생성자 인수를 생략하고 기본값을 사용합니다. ChatOpenAI클래스는 OpenAI의 대화모델에 해당합니다. 다른 모델을 사용하는 경우 다른 클래스를 사용해야 합니다. 마지막으로 대화모델의 invoke메소드를 사용하여 모델에 입력을 제공하여 출력을 가져옵니다.
invoke메소드는 모델에 입력하는 메시지를 문자열로 전달합니다. 그런 다음 출력을 확인합니다. 출력은 AIMessage객체로 리턴됩니다. 결과적으로 OpenAI API를 사용하는 경우 다음과 같은 출력을 얻을 수 있습니다. Anthropic, Google 대화모델을 사용하는 경우에도 비슷한 결과를 얻을 수 있습니다.
▣ 메시지 목록을 통한 호출 (텍스트 전용)
대화모델은 채팅기록을 포함한 메시지 목록을 전달할 수 있습니다. 이 메시지 목록은 이전 메시지에서 새 메시지로 순서대로 저장됩니다. 대화모델은 이 채팅기록에 이어 다음과 같은 자연스러운 메시지를 출력합니다.
목록에 저장된 각 마세지는 누구의 발언으로 인한 것인지를 구별해야 합니다. 이것을 나타나는 것이 메시지의 종류입니다. 아래 표는 메시지 유형을 나열합니다.
메시지 유형 목록
HumanMessage는 사용자의 메시지를 나타냅니다. 또한 AIMessage는 모델의 메시지를 나타냅니다. 그러나 실제로는 모델의 메시지도 자유롭게 설정할 수 있습니다.
SystemMessage는 모델의 동작을 지시하는 시스템 메시지입니다.
ToolMessage는 도구 호출의 결과를 모델에 주기 위한 특수 메시지입니다. 도구 호출에 대해서는 나중에 따로 설명하지만 모델에 의한 함수호출이라고 생각해 문제가 없습니다.
우선 HumanMessage, AIMessage, SystemMemssage를 이용한 메시지 리스트에서 대화 모델을 호출한 예를 보여줍니다.
메시지 목록으로 대화모델 호출 (src/langchain/model_access2.py)
HumanMessage, AIMessage 및 SystemMessage는 클래스로 제공되므로 우선 이를 가져옵니다.
이런 클래스는 langchain_core.messages에 존재합니다.그런 다음 유사한 메시지 목록을 만듭니다.
우선 시스템메시지, 이후 사용자로부터의 메시지와 모델로부터의 메시지를 번갈아 늘어놓아 채팅 히스토리를 작성합니다. 마지막이 사용자로부터의 메시지가 되도록 합니다. 각 메시지는 SystemMessage, HumanMessage, AIMessage클래스중 하나의 인스턴스로 작성됩니다.
이런 메시지는 LangChain에서 내부적으로 API공급자별 메시지로 변환됩니다. 예를 들어, OpenAI API를 사용하는 경우 위 채팅기록은 다음과 같은 형식으로 변환됩니다.
이 형식은 다른 API공급자의 메시지와 직접 호환되지 않습니다. 예를 들어, OpenAI API가 아닌 Gemini API를 직접 사용하는 경우 'assistant'라는 역할 대신 'model'이라는 역할을 사용해야 합니다. 또한, 'content' 대신 'parts'를 지정해야 합니다. LangChain(랭체인)이 제공하는 클래스는 API공급자마다의 차이를 잘 흡수해줍니다.
마지막으로 작성한 메시지 목록을 invoke메소드에 전달하여 대화모델을 호출할 수 있습니다.
이 코드를 실행하면 다음과 같은 출력을 얻을 수 있습니다.
여기서 '데이브'란, 채팅 이력 중에서 사용자가 지칭한 이름입니다. 마지막 메시지에는 사용자가 지칭하는 이름이 포함되어 있지 않습니다. 그러나 LLM은 주어진 채팅기록을 바탕으로 사용자가 지칭하는 이름을 반환합니다. 이것은 주어진 전체 메시지 목록이 LLM추론에 사용됨을 나타냅니다.
▣ 메시지 목록을 통한 호출 (멀티모달)
사용하는 대화모델이 멀티모달을 지원하는 경우 메시지에 텍스트가 아닌 데이터를 포함할 수 있습니다. 예를 들어, ChatOpenAI를 사용하여 메시지에 JPEG이미지를 포함시킬 수 있습니다. 멀티모달 메시지는 API공급자별로 형식이 결정됩니다. 이 글을 쓰는 시점 기준으로 멀티모달 메시지는 API공급자간 호환되지 않습니다. 이 강좌에서는 OpenAI를 기준으로 LangChain에서 멀티모달을 사용하는 방법을 소개합니다.
메시지 목록을 통한 대화모델 호출 : 멀티모달(src/langchain/model_access3.py)
이 프로그램에서는 explain_image라는 함수로 LLM에 이미지설명을 요구하는 처리를 구현하고 있습니다. 메시지 목록에 이미지를 포함하는 부분은 다음과 같은 코드로 수행합니다.
여기서 content에 지정하는 목록은 OpenAI 특정형식입니다. 이 목록의 멤버는 type을 키로 가진 사전입니다. type값은 이 사전이 무엇을 보유하는지를 나타냅니다. 이미지가 포함된 사전의 경우 type으로 image_url을 지정합니다. 그리고 image_url 키값에 URL을 지정합니다. 이 URL은 데이터를 Base64인코딩 형식으로 포함하여 이미지 데이터 전체를 직접 URL일부로 취급할 수 있습니다. 이미지를 Base64인코딩형식으러 얻는 것은 아래와 같습니다.
여기서는 파일에서 JPEG이미지를 읽고 image_data에 저장합니다. 대화모델의 invoke메소드에 의한 호출방법은 메시지가 텍스트 전용인 경우와 동일합니다.
여기에서는 message를 [ ~ ]로 둘러싸는 것으로 리스트로 하고 있습니다.
예를 들어, 여러 책위에 사과가 놓인 사진 JPEG파일을 지정하면 아래와 같은 출력을 얻을 수 있습니다.
스트림 호출에서는 모델의 응답을 순차적으로 취득할 수 있습니다. 스트림 호출이 아닌 대화모델의 invoke메소드를 사용했을 경우, 모델의 응답은 한번에 얻어집니다. 따라서 애플리케이션은 모델의 모든 출력을 얻을 때까지 기다려야 합니다. 이는 챗봇과 같은 응답성이 요구되는 애플리케이션에는 적합하지 않기에 스트림 호출이 도움이 됩니다.
스트림 호출에서는 stream메소드를 사용해 모델의 응답을 순차적으로 얻을 수 있습니다. 모델에 대한 입력은 invoke메소드와 마찬가지로 단일문자열 또는 메시지 목록을 사용합니다. 출력은 반복자로 반환됩니다.
LangChain(랭체인)의 장점중 하나는 API공급자별 구현의 차이를 흡수하고 통합 인터페이스를 제공한다는 것입니다. 스트림 호출에 대해서도 LangChain(랭체인)의 stream메소드를 사용하면 내부적인 구현이 토큰단위인지 정리해서 처리되고 있는지 관계없이 똑같이 취급할 수 있습니다. 이렇게하면 API공급자를 전환해도 코드를 변경할 필요가 없ㅅ습니다.
예를 들어, 아래 코드는 스트림 호출을 사용하여 대화모델을 호출하는 프로그램을 보여줍니다. 여기서는 ChatOpenAI클래스를 사용하여 대화모델의 인스턴스를 만들고 stream메소드를 사용하여 모델에 메시지를 전달합니다. stream메소드는 모델의 응답을 반복자로 리턴합니다. 얻은 iterator에 for문을 사용하여 응답을 순차적으로 얻고 print함수로 출력합니다. end=""를 지정하는 것으로 개행을 억제하고 flush=True를 지정하는 것으로 출력을 버퍼링하지 않고 바로 표시하도록 합니다.
대화모델의 응답이 순차적으로 표시됩니다. 이런 방식으로 스트림 호출을 사용하여 실시간으로 모델응답을 검색하고 표시할 수 있습니다. 스트림호출은 챗봇이나 실시간응답이 필요한 애플리케이션에서 유용합니다. 사용자가 모델이 생각하는 도중 경과를 표시하면 보다 대화형 상호작용이 가능합니다.
스트림 호출을 통한 대화모델 호출(src/langchain/model_stream.py)
일괄호출은 한번에 여러 대화를 처리합니다. 대화모델의 invoke메소드는 하나의 대화만 처리했습니다. 그러나 한번에 여러 대화를 처리할 수 있으면 편리합니다. 예를 들어, 많은 양의 데이터를 함께 LLM으로 처리하고 싶거나 여ㅑ러 요청을 동시에 처리해야 하는 경우입니다. LangChain(랭체인)의 일괄호출 기능을 사용하면 이러한 요구사항을 효율적으로 충족할 수 있습니다.
일괄호출에서는 batch메소드를 사용하여 여러 대화를 한번에 처리합니다. 모델에 의한 입력은 invoke메소드 입력을 리스트로 한 것을 사용할 수 있습니다. 출력도 마찬가지로 메시지 목록으로 반환됩니다.
스트림 호출과 같이 LangChain(랭체인)의 batch메소드를 사용하면 API제공자 마다 구현의 차이를 인식할 필요는 없습니다. 내부적으로 일괄처리되지 않더라도 LangChain(랭체인)은 일괄처리와 동일한 기능을 제공합니다. 이를 통해 개발자는 API 공급자의 선택에 얽매이지 않고 일관된 방식으로 일괄처리를 할 수 있습니다. 아래 코드에서는 일괄호출을 사용하여 대화모델을 호출하는 예를 살펴봅시다. 이 프로그램에서는 ChatOpenAI 클래스를 사용하여 대화모델을 호출해 봅시다.이 프로그램에서는 ChatOpenAI클래스를 사용하여 대화 모델의 인스턴스를 만들고 batch메소드를 사용하여 여러 메시지를 한번에 전달합니다. batch메소는 메시지 목록을 수신하고 응답 목록을 리턴합니다. 여기서는 for문을 사용하여 응답목록에서 각 메시지를 검색하고 print함수로 출력합니다.
일괄 호출로 대화모델 호출(src/langchain/model_batch2.py)
LangChain(랭체인)은 출력을 구조화하기 위한 기능(Structured Output)을 제공합니다. LLM의 출력은 달리 지정하지 않으면 특세트 형식으로 반환됩니다. 그러나, 프로그램 일부로 LLM을 사용하는 경우 텍스트 형식이 아닌 구조화된 형식으로 출력을 받아보는 것이 바람작합니다. 이경우 with_structured_output메소드를 사용하여 모델에 대한 출력형식을 지정할 수 있습니다.
출력형식은 Pydantic모델을 사용합니다. Pydantic은 데이터 구조를 검증하는 라이브러리입니다. 출력형식으로 사용할 데이터 구조를 Pydantic의 데이터 모델로 정의하고 이를 통해 출력 형식을 지정할 수 있습니다. 또한 with_structured_outpuit 메소드는 Pydantic의 데이터 모델을 인수로 사용합니다.
▣ 간단한 데이터 모델
첫번쨰 예제는 천체정보를 LLM에 문의하고 그 결과를 데이모델형식으로 받는 프로그램을 아래에서 보여줍니다.
간단한 데이터 모델을 이용한 출력구조화(src/langchain/output1.py)
우선 다음 가져오기 문에서 Pydantic을 사용하는 클래스를 가져옵니다.
여기서 BaseModel과 Field는 Pydantic에서 데이터 모델을 정의하는 클래스입니다.
그런 다음 BaseModel과 FIeld를 사용하여 데이터모델을 다음과 같이 정의합니다.
CelestialBody클래스는 천제정보를 나타내는 데이터 모델입니다. name, radius, mass type은 각각의 천체명, 반지름, 질량 및 유형을 나타내는 필드입니다. 또한 각 유형에서 str, float, Literal["항성", "행성", "위성"]을 지정합니다.
Literal은 지정된 문자열 리터럴 중 하나를 취하신 형식을 나타냅니다. 그리고 Field클래스를 사용하여 각 필드에 대한 정보를 작성합니다.
여기서는 대화모델에 대해 with_structured_output메소드를 호출하고 출력형식을 지정합니다. llm_with_structued_output은 출력형식이 지정된 LLM 객체입니다.
마지막으로 LLM에 문의하여 지정된 출력형식을 결과를 받습니다.
llm_with_structured_output객체에 대해 invoke메소드를 호출하여 LLM에 쿼리합니다. invoke메소드를 호출하는 방법은 출력형식을 지정하지 않은 경우가 동일합니다. 그러나 대화모델의 출력은 CelestialBody클래스이 인터스턴스로 반환합니다.
jupiter.radius, jupiter.mass, jupiter.type값이 각각 표시되는지 확인할 수 있습니다.
▣ 중첩된 데이터 모델
데이터 모델은 중첩할 수 있습니다. 그리고 중첩된 데이터 모델을사용하여 출력방식을 지정할수도 있습니다. 여기에서는 방금 만든 천체를 나타내는 데이터 모델을 사용하여 태양계 정보를 얻는 예를 보여줍니다. 우선 행선계의 데이터 모델을 새롭게 정의하고 이 데이터모델의 정의에 천체의 데이터모델을 사용합니다.
행성 시스템에는 여러 천체가 포함되어 있으므로 천체의 데이터모델을 목록으로 사용합니다. 이 프로그램은 아래 코드에 나와 있습니다.
중첩데이터 모델를 이용한 출력구조(src/langchain/output2.py)
행성계의 데이터모델은 다음과 같습니다.
PlanetarySystem 클래스는 행성계를 나태고 있는 데이터 모델이 있습니다.여기서는 방금 정의한 CelestialBody의 기본 제공 유형 힌트이며 목록을 나타내는 유형입니다.
List[CelestiaBody)]는 CelestialBody기본 제공 유형 힌트이며 목록을 나타냅니다. 또한 center_body필드는 중심이 되는 항성을 나타냅니다. CelestialBody클래스를 사용해 중심이 되는 항성을 나타내는 필드로 정의하고 있습니다. 그런 다음 age필드는 행성계 나이를 나타냅니다. 마지막으로 name 필드는 행성시스템의 이름을 나타냅니다. 다음은 출력형식을 지정합니다.
앞에서 말했던 with_structured_output 메소드 인수는 Pydantic에서 정의한 데이터모델을 지정합니다. 여기에서는 PlanetarySystem 클래스를 사용하여 출력형식을 지정합니다. 그런 다음 출력형식이 지정된 LLM객체를 사용하여 LLM에 쿼리하고 결과를 받습니다.
LangChain(랭체인)은 LLM이 도구를 사용할 수 있도록 하는 기능을 제공합니다. 대화모델에 대해 bind_tool 메소드를 사용하여 도구를 대화모델에 등록할 수 있습니다. 또한 @tool 데코레이터를 사용하여 도구를 쉽게 정의할 수 있습니다. LLM은 기본적으로 프롬프트를 입력으로 받고 텍스트만 출력할 수 있습니다. 그러나, LLM이 도구를 사용할 수 있게 함으로써 더 복잡한 작업을 수행할 수 있습니다.
여기서 도구는 LLM에서 호출할 수 있는 Python 함수입니다. @tool 데코레이터를 사용하여 함수를 정의하여 LLM이 호출할 수 있는 함수를 만들 수 있습니다. 작성한 도구는 bind_tool 메소드를 사용하여 대화모델에 등록할 수 있습니다. 또한, 일반적으로 자주 사용되는 도구를 LangChain(랭체인)에서 미리 제공됩니다.
아래 표는 LangChain(랭체인)에서 제공하는 도구 목록입니다. LLM이 필요에 따라 이러한 도구를 호출할 수 있도록 함으로써 LLM능력을 확장할 수 있습니다. 예를 들어, PythonREPL 도구를 사용하면 LLM이 Python코드를 실행하고 결과를 반환할 수 있습니다. 또한 SQL 데이터베이스 도구를 사용하여 LLM이 데이터베이스에 액세스하고 데이터를 검색하거나 업데이트할 수 있습니다.
사실, LLM이 직접 도구를 호출하는 것은 아닙니다. LLM은 도구 호출이 필요한 경우 응답에서 도구 호출을 지시합니다. LLM 호출자는 지시를 받고 대신 도구를 호출하고 결과를 LLM에 리턴합니다. 그러면 LLM은 결과를 바탕으로 응답을 생성합니다.
LangChain(랭체인)에서 제공하는 도구목록
▣ 도구 정의 및 사용
여기서는 도구를 호출하여 LLM이 외부 세계와 상호작용하는 예를 시뮬레이션해보겠습니다. 예를 들어, "2001년 우주여행"(Clarke 1968)의 대사를 참고로 인공지능 HAL9000과 보먼선장의 대화를 시뮬레이션해 보겠습니다. HAL9000은 선박의 모든 시스템을 관리하는 고급 인공지능입니다. 소설에서는 보먼선장의 다음 대사가 있습니다.
HAL9000은 이에 따라 포드 라이트를 왼쪽으로 회전시킵니다. LLM도 도구를 사용하여 유사한 작업을 수행할 수 있습니다. 아래 코드는 소설을 참고로 한 HAL9000과 보먼선장의 대화를 시뮬레이션하는 프로그램을 보여줍니다.
도구를 이용한 대화모델과의 상호작용(src/langchain/model_tool.py)
먼저 도구를 정의하는데 필요한 데코레이터를 가져옵니다.
tool은 도구를 정의하는 데코레이터입니다. @tool 데코레이터를 사용하면 일반함수를 정의하는 방법으로 LLM에 전달하는 도구를 정의할 수 있습니다. @tool 데코레이터는 다음과 같이 사용합니다.
light_control은 빛을 오른쪽으로 degrees도 회전하는 함수입니다. 일반 함수정의와 다른 점은 @tool 데코레이터가 있다는 것입니다. 본래 이 함수는 라이트를 오른쪽으로 degrees도 돌리는 코드를 구현할 필요가 있지만, 단순히 로그를 출력하도록 하고 있습니다. 여기서 light_control함수는 각도를 입력으로 하고 그 각도만큼 라이트를 오른쪽으로 회전시키는 처리를 상정하고 있습니다. 또한, 왼쪽으로 회전시킬 경우 degrees의 부호를 반전시키는 것을 상정합니다. 또한 회전의 성부를 돌려주기 위해서 bool형 값을 돌려주도록 하고 있습니다. 그런 다음 light_control을 LLM에 도구로 등록합니다.
이 문장에서는 light_control함수를 도구로 LLM에 등록합니다. bind_tools메소드는 도구로 등록할 함수목록을 전달합니다. 이 경우 light_control함수를 목록에 넣고 전달합니다. 여기에서는 등록하고 있는 도구가 하나뿐이지만, 복수의 도굴를 등록할 수도 있습니다.
LLM의 경우, HAL9000과 보먼선장의 대화를 시뮬레이션하는 메시지는 다음과 같습니다.
여기서 SystemMessage는 시스템 메시지를 나타내는 클래스입니다. HumanMessage는 사용자 메시지를 나타내는 클래스입니다. 사용자는 보먼선장으로 가정합니다. 이것을 다음 코드로 LLM에 전달하여 HAL9000과 보먼선장의 대화를 시뮬레이션합니다.
이 코드에서는 llm_with_tool 객체의 invoke메소드를 사용하여 LLM에 메시지를 전달합니다. 메시지에서 포드 라이트를 20도 왼쪽으로 돌리라는 지시를 제공하므로 light_control함수 호출이 예상됩니다.
LLM이 도구 호출을 지시하는지 여부는 response.tool_calls의 내용에서 확인할 수 있습니다. tool_calls는 도구 호출을 지시하는 정보가 있는 목록입니다. LLM이 여러 도구 호출을 지시하면 tool_calls에 여러 요소가 포함됩니다. 여기서는 response.tool_calls에 값이 있으면 도구를 호출하는 프로세스를 수행합니다. tool_calls가 None이 아닌 경우 도구를 호출하는 작업을 수행합니다. 구체적으로는 tool_calls내용을 스캔하고 light_control함수를 호출합니다. 각 call의 내용은 도구 호출에 대한 정보가 있는 사전입니다.
call의 사전은 도구의 이름, 인수, 도구 호출의 ID등을 키로서 가집니다. 여기서는 light_control 함수호출을 기대하므로 light_control함수를 호출하여 결과를 메시지에 추가합니다. 일반 함수와 달리 lighjt_control함수는 light_control.invoke()형식으로 호출합니다. invoke메소드는 @tool데코레이터에 의해 추가된 메소드입니다. 이 메소드를 사용하면 call["args"]에 포함된 인수를 사용하여 light_control함수를 호출할 수 있습니다. value는 light_control함수의 반환값을 저장합니다. 이 값을 사용하여 도구호출 결과를 테이블 ToolMessage 객체를 만듭니다. ToolMessage는 도구 호출의 결과를 나타내는 클래스입니다.
ToolMessage는 HumanMessage 및 AIMessage와 마찬가지로 메시지목록에 저장됩니다. 마지막으로 도구 실행결과가 포함된 챗팅기록을 LLM에 전달하여 상호작용을 계속합니다.
이 코드는 도구 실행결과를 포함하는 챗팅 기록을 LLM에 전달합니다.
첫번쨰 행은 light_control함수가 호출되었을 대의 로그를 나타냅니다. 로그에는 light_control함수가 수신한 인수가 표시됩니다. 다음 줄은 HAL9000이 포드의 빛을 왼쪽으로 20도 회전시켰음을 나타냅니다. 메시지는 LLM의 메시지를 나타냅니다.
실제 소설에서 HAL9000은 명령을 실행하지만 응답하지는 않습니다. 이를 계기로 보만선장은 HAL9000의 이변을 깨닫지만, 이번 시뮬레이션에서는 HAL9000이 응답하고 있습니다. 참고로 이 예시에서는 light_control함수가 단순한 로그를 출력하는 것만으로 라이트의 회전은 실시하고 있지 않습니다.
light_control함수가 false를 반환하도록 구현하면 라이트 회전이 실패했음을 나타낼 수도 있습니다. 이 경우 HAL9000은 라이트 회전에 실패했음을 알리는 메시지를 반환합니다.
©2024-2025 GAEBAL AI, Hand-crafted & made with Damon Jaewoo Kim.
GAEBAL AI 개발사: https://gaebalai.com
AI 강의 및 개발, 컨설팅 문의: https://talk.naver.com/ct/w5umt5