06-langchain-agents

2024. 1. 14. 17:34langchain

05-langchain-retrieval-augmentation.ipynb는 에러가 뜨는 원인을 몰라 일단 제외하였습니다.

 

에이전트 🤖

에이전트는 "도구"와 같습니다. 이를 통해 LLM은 Google 검색에 액세스하고, Python으로 복잡한 계산을 수행하고, 심지어 SQL 쿼리도 수행할 수 있습니다.

이 노트에서는 에이전트와 LangChain에서 에이전트를 사용하는 방법을 살펴봅니다.

In [ ]:
!python3 -m venv langchain
!source langchain/bin/activate
In [ ]:
!pip install -qU langchain openai google-search-results wikipedia sqlalchemy

이 노트북을 실행하려면 OpenAI LLM을 사용해야 합니다. 여기에서는 전체 노트북에 사용할 LLM을 설정합니다. 메시지가 표시되면 openai api 키를 입력하기만 하면 됩니다.

In [ ]:
from getpass import getpass

OPENAI_API_KEY = getpass()
In [ ]:
from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI(
    openai_api_key=OPENAI_API_KEY,
    temperature=0
)

이전과 마찬가지로 각 호출에서 토큰을 계산합니다.

In [ ]:
from langchain.callbacks import get_openai_callback

def count_tokens(agent, query):
    with get_openai_callback() as cb:
        result = agent(query)
        print(f'Spent a total of {cb.total_tokens} tokens')

    return result

모든 설정을 마쳤으면 에이전트로 이동해 보겠습니다.

대리인이란 무엇입니까?

정의: 상담원의 핵심은 LLM이 작업 흐름에서 도구를 사용할 수 있는 가능성을 제공하는 것입니다. 이것은 langchain이 인기 있는 chatgpt 구현에서 출발하는 지점이며 우리는 이것이 빌더로서 우리에게 제공하는 것을 엿볼 수 있습니다. 지금까지 우리는 여러 구성 요소를 개별적으로 다루었습니다.

에이전트의 공식 정의는 다음과 같습니다.

상담원은 LLM을 사용하여 수행할 작업과 순서를 결정합니다. 작업은 도구를 사용하고 해당 출력을 관찰하거나 사용자에게 반환하는 것일 수 있습니다.

이번 내용에서는 '일반'이라고 부르는 내용을 다룰 것입니다. 실제로 많은 메타 작업을 수행할 수 있는 에이전트입니다. 다양한 작업에 맞게 조정된 더 구체적인 에이전트('에이전트 툴킷'이라고 함)가 있지만 이에 대해서는 향후 버전에서 다루겠습니다.

데이터베이스 생성

우리는 에이전트를 사용하여 소규모 주식 샘플 데이터베이스와 상호 작용할 것입니다. 이는 설명 목적으로 구축할 더미 도구일 뿐이므로 자세한 내용은 다루지 않겠습니다.

In [ ]:
from sqlalchemy import MetaData

metadata_obj = MetaData()
In [ ]:
from sqlalchemy import Column, Integer, String, Table, Date, Float

stocks = Table(
    "stocks",
    metadata_obj,
    Column("obs_id", Integer, primary_key=True),
    Column("stock_ticker", String(4), nullable=False),
    Column("price", Float, nullable=False),
    Column("date", Date, nullable=False),
)
In [ ]:
from sqlalchemy import create_engine

engine = create_engine("sqlite:///:memory:")
metadata_obj.create_all(engine)
In [ ]:
from datetime import datetime

observations = [
    [1, 'ABC', 200, datetime(2023, 1, 1)],
    [2, 'ABC', 208, datetime(2023, 1, 2)],
    [3, 'ABC', 232, datetime(2023, 1, 3)],
    [4, 'ABC', 225, datetime(2023, 1, 4)],
    [5, 'ABC', 226, datetime(2023, 1, 5)],
    [6, 'XYZ', 810, datetime(2023, 1, 1)],
    [7, 'XYZ', 803, datetime(2023, 1, 2)],
    [8, 'XYZ', 798, datetime(2023, 1, 3)],
    [9, 'XYZ', 795, datetime(2023, 1, 4)],
    [10, 'XYZ', 791, datetime(2023, 1, 5)],
]
In [ ]:
from sqlalchemy import insert

def insert_obs(obs):
    stmt = insert(stocks).values(
    obs_id=obs[0],
    stock_ticker=obs[1],
    price=obs[2],
    date=obs[3]
    )

    with engine.begin() as conn:
        conn.execute(stmt)
In [ ]:
for obs in observations:
    insert_obs(obs)

SQLDatabase가 여기에 있으므로 langchain_experimental 라이브러리를 여기에 설치합니다. 이는 향후 변경되어 공식 Chainlangchain 라이브러리로 옮겨질 수 있습니다.

In [ ]:
!pip install langchain_experimental -qU
In [ ]:
from langchain.utilities import SQLDatabase
from langchain_experimental.sql import SQLDatabaseChain

db = SQLDatabase(engine)
sql_chain = SQLDatabaseChain(llm=llm, database=db, verbose=True)

에이전트 유형

이 섹션에서는 여러 에이전트를 검토하고 그들이 어떻게 생각하는지 그리고 그들이 무엇을 할 수 있는지 살펴보겠습니다.

langchain의 사전 구축된 에이전트 중 하나를 사용하려면 세 가지 변수가 필요합니다.

  • 도구 또는 툴킷 정의
  • llm 정의
  • 에이전트 유형 정의

에이전트 유형 #1: Zero Shot React

이 첫 번째 예에서는 약간 다른 유형의 에이전트, 즉 자체 메소인 create_sql_agent로 인스턴스화할 수 있는 SQL 에이전트를 사용합니다. 다른 에이전트는 아래의 다른 예에서 볼 수 있듯이 보다 일반적인 방식으로 인스턴스화됩니다.

이 방법은 tools의 간단한 목록 대신 툴킷을 사용합니다. 이에 대한 자세한 내용은 문서에서 확인할 수 있습니다. 이 사용 사례에서는 SQLDatabaseToolkit를 사용합니다.

이름에서 알 수 있듯이 이 에이전트를 사용하여 '제로 샷'을 수행합니다. 입력에 대한 작업. 이는 우리가 여러 개의 상호의존적인 상호작용을 가지지 않고 오직 하나만 가지게 된다는 것을 의미합니다. 즉, 이 에이전트에는 메모리가 없습니다.

이제 에이전트를 초기화할 준비가 되었습니다! 에서 verbose를 사용하여 에이전트의 '생각'이 무엇인지 확인할 수 있습니다. 프로세스.True

중요 사항: 에이전트와 상호작용할 때 max_iterations 매개변수를 설정하는 것이 매우 중요합니다. 에이전트가 많은 리소스를 소비하는 무한 루프에 빠질 수 있기 때문입니다. 토큰. 많은 도구와 복잡한 추론을 허용하기 위해 기본값은 15이지만 대부분의 애플리케이션에서는 이 값을 훨씬 낮게 유지해야 합니다.

In [ ]:
from langchain.agents import create_sql_agent
from langchain.agents.agent_toolkits import SQLDatabaseToolkit
from langchain.agents.agent_types import AgentType

agent_executor = create_sql_agent(
    llm=llm,
    toolkit=SQLDatabaseToolkit(db=db, llm=llm),
    verbose=True,
    agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    max_iterations=3
)

새로 생성된 에이전트가 실제로 작동하는 모습을 살펴보겠습니다! 우리는 주가에 대한 수학 연산과 관련된 질문을 할 것입니다.

In [ ]:
result = count_tokens(
    agent_executor,
    "What is the multiplication of the ratio between stock " +
    "prices for 'ABC' and 'XYZ' in January 3rd and the ratio " +
    "between the same stock prices in January the 4th?"
)

여기에 프롬프트가 무엇인지 살펴보겠습니다.

In [ ]:
print(agent_executor.agent.llm_chain.prompt.template)

여기서 우리가 스스로에게 물어봐야 할 질문은 에이전트가 체인과 어떻게 다릅니까?

에이전트의 로직과 방금 인쇄한 프롬프트를 살펴보면 몇 가지 분명한 차이점을 볼 수 있습니다. 먼저 프롬프트에 포함된 도구가 있습니다. 두 번째로 우리는 이전에는 연쇄적으로 즉각적이었지만 지금은 '생각', ​​'행동', '행동 입력', '관찰'을 포함하는 사고 과정을 가지고 있습니다.

지금은 LLM이 이제 '추론'할 수 있는 능력을 갖고 있다고만 말하면 충분합니다. 도구를 가장 효과적으로 사용하는 방법에 대해 알아보고 각 도구에 대한 간략한 설명과 함께 지능적인 방법으로 도구를 결합할 수 있습니다.

마지막으로 'agent_scratchpad'에 주목해 봅시다. 에이전트가 이미 수행한 모든 생각이나 행동을 여기에 추가할 것입니다. 이런 방식으로 각 시점에서 에이전트는 자신이 발견한 내용을 알게 되고 사고 과정을 계속할 수 있습니다. 즉, 도구를 사용한 후 스크래치 패드에 자신의 생각과 관찰 내용을 추가하고 거기에서 픽업합니다.

에이전트 유형 #2: 대화형 React

제로 샷 에이전트는 정말 흥미롭지만 앞서 말했듯이 메모리가 없습니다. 우리가 이야기한 내용을 기억하고 그에 대해 추론하고 도구를 사용할 수 있는 비서를 원한다면 어떻게 될까요? 이를 위해 대화형 반응 에이전트가 있습니다.

이 예에서는 수학 도구를 사용하고 아래와 같이 로드합니다.

In [ ]:
from langchain.agents import load_tools

tools = load_tools(
    ["llm-math"],
    llm=llm
)

여기서 사용되는 메모리 유형은 추론 체인의 이전 단계를 기억할 수 있는 간단한 버퍼 메모리입니다.

In [ ]:
from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory(memory_key="chat_history")
In [ ]:
from langchain.agents import initialize_agent

conversational_agent = initialize_agent(
    agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION,
    tools=tools,
    llm=llm,
    verbose=True,
    max_iterations=3,
    memory=memory,
)
In [ ]:
result = count_tokens(
    conversational_agent,
    "What's the result of an investment of $10,000 growing at 8% annually for 5 years with compound interest?"
)

아래에서 볼 수 있듯이 프롬프트는 비슷하지만 효과적인 어시스턴트가 되는 지침과 메모리 구성 요소의 채팅 기록을 포함할 수 있는 지점이 포함되어 있습니다.

In [ ]:
print(conversational_agent.agent.llm_chain.prompt.template)

이전 질문과 관련된 질문에 답하려고 하면 어떤 일이 일어나는지 살펴보겠습니다.

In [ ]:
result = count_tokens(
    conversational_agent,
    "If we start with $15,000 instead and follow the same 8% annual growth for 5 years with compound interest, how much more would we have compared to the previous scenario?"
)

에이전트 유형 #3: React Docstore

이 유형의 에이전트는 지금까지 본 것과 유사하지만 문서 저장소와의 상호 작용을 포함합니다. 사용할 수 있는 도구는 '검색' 그리고 '조회' 두 개뿐입니다.

'검색'으로 그러면 관련 기사가 표시되고 '조회' 상담원은 기사에서 올바른 정보를 찾을 것입니다. 이는 아마도 예에서 확인하는 것이 가장 쉬울 것입니다.

In [ ]:
from langchain import Wikipedia
from langchain.agents.react.base import DocstoreExplorer, Tool

docstore=DocstoreExplorer(Wikipedia())
tools = [
    Tool(
        name="Search",
        func=docstore.search,
        description='search wikipedia'
    ),
    Tool(
        name="Lookup",
        func=docstore.lookup,
        description='lookup a term in wikipedia'
    )
]     
In [ ]:
docstore_agent = initialize_agent(
    tools,
    llm,
    agent="react-docstore",
    verbose=True,
    max_iterations=3
)
In [ ]:
count_tokens(docstore_agent, "What were Archimedes' last words?")

프롬프트가 너무 크기 때문에 여기서는 프롬프트를 인쇄하지 않겠습니다. 하지만 원하시면 직접 해 보실 수 있습니다.

간단히 말하면 여기에는 Question > Thought > Action > Observation 루프(Search 및 Lookup 도구 포함)

이 접근 방식에 대해 자세히 알아보려면 ReAct의 문서를 참조하세요.

상담원 유형 #4: 검색을 통해 스스로 질문하기

이는 LLM을 사용하여 검색 엔진으로 정보를 추출할 때 사용하는 첫 번째 선택 에이전트입니다. 상담원은 후속 질문을 하고 검색 기능을 사용하여 최종 답변을 얻는 데 도움이 되는 중간 답변을 얻습니다.

In [ ]:
from langchain import OpenAI, SerpAPIWrapper
from langchain.agents import initialize_agent, Tool

search = SerpAPIWrapper(serpapi_api_key='api_key')
tools = [
    Tool(
        name="Intermediate Answer",
        func=search.run,
        description='google search'
    )
]

self_ask_with_search = initialize_agent(tools, llm, agent="self-ask-with-search", verbose=True)

Serpapi 키가 필요하기 때문에 이 에이전트와 상호 작용하지 않습니다. 그러나 프롬프트를 확인하면 작동 방식에 대한 몇 가지 예를 볼 수 있습니다.

In [ ]:
print(self_ask_with_search.agent.llm_chain.prompt.template)

보시다시피 프롬프트는 기본적으로 LLM이 최종 답변을 얻을 때까지 검색 도구에 후속 질문을 하는 방법을 보여주는 일련의 많은 예입니다.

마무리

에이전트를 위한 모든 것! 그 외에도 상담원과 함께 할 수 있는 일이 많이 있습니다. 예를 들면 다음과 같습니다.

  • 나만의 맞춤 에이전트 만들기
  • 다른 많은 도구(맞춤형 도구도 포함)와 함께 사용하세요.
  • 편리한 UI 인터페이스를 통해 상담원의 모든 통화를 추적하세요.
In [ ]:
출처 : https://github.com/pinecone-io/examples/blob/master/learn/generation/langchain/handbook/06-langchain-agents.ipynb

'langchain' 카테고리의 다른 글

03-1-langchain-conversational-memory  (1) 2024.01.16
09-langchain-streaming  (0) 2024.01.15
04-langchain-chat  (0) 2024.01.13
03a-token-counter  (0) 2024.01.12
03-langchain-conversational-memory  (2) 2024.01.11