박정기
박정기
🗡️ AI 레전드
🎖️ 마스터 파트너
🚀 SNS 챌린지 달성자

[1DAY 1랭그래프] chain 에 대하여 #2일차

배경 및 목적

이번 13기 AI 스터디에 앞서, 1DAY 1랭그래프, 즉 하루에 1개의 랭그래프 개념을 설명하는 부분을 기획하게 됐습니다.

-> 랭그래프 스터디에 관심이 있다면 신청해주세요!

주황색 배경의 한국 광고

스터디 신청링크

이 프로젝트의 목표는 랭그래프를 쉽게 입문하실 수 있게 상세한 개념부터 코드까지 함께 공부해보실 수 있게 정리해서 드릴 예정입니다.

저는 랭그래프를 처음들어봐요!, 1일차 글을 보고 싶다면!?

-> 링크로 접속하기!

참고 자료

코랩 실습 링크

공식 랭그래프 강의 링크

활용 툴

파이썬, 코랩, 랭그래프, 랭체인

핵심 요약: LangGraph를 활용한 체인 구축

0. 주요 개념

LLM은 (예를 들어 GPT4o) 수학적인 계산, 정량적인 질문에 대하여 정확하게 답변을 하지 못합니다.

하지만 도구 (Tool)을 바인딩하여 쓴다면, 정확한 답변을 얻을 수 있습니다.

밑에 실습을 따라가 보시면, 다음과 같은 Graph를 설계할 수 있습니다.

수학적인 계산이 필요 없는 경우 -> LLM의 평범한 답변이 나오도록 라우팅

수학적인 계산이 필요한 질문을 받은 경우 -> Tool을 호출하도록 라우팅 -> 수학적인 계산을 하여 답변 생성

신경망을 만드는 과정을 보여주는 다이어그램

따라서 정량적인 질문을 받았을 때 답변을 다음을 활용하여 만들면 더 정확한 나만의 AI 에이전트를 만들 수 있을 것입니다.

1. 소개 및 검토

- 목표: 이전에 만든 노드, 일반 에지, 조건부 에지를 포함하는 간단한 그래프를 기반으로, 4가지 주요 개념을 결합한 체인을 구축합니다.

- 개념:

1. 채팅 메시지(Messages) 사용: 그래프 상태로 채팅 메시지를 활용.

2. 채팅 모델(Chat Models) 사용: 그래프 노드 내에서 채팅 모델을 활용.

3. 도구 바인딩(Binding Tools): 채팅 모델에 외부 도구를 바인딩.

4. 도구 호출 실행(Executing Tool Calls): 그래프 노드에서 도구 호출을 실행.

2. 환경 설정

- 라이브러리 설치: langchain_openai, langchain_core, langgraph 라이브러리를 설치합니다.

  %%capture --no-stderr

  %pip install --quiet -U langchain_openai langchain_core langgraph

3. 메시지(Messages) 정의

- 메시지 유형: HumanMessage, AIMessage, SystemMessage, ToolMessage 등 다양한 메시지 유형을 정의하여 대화 내 역할을 구분합니다.

- 메시지 생성: 초기 메시지 리스트를 생성하고, 각 메시지를 순차적으로 추가합니다.

  from pprint import pprint

  from langchain_core.messages import AIMessage, HumanMessage

  

  messages = [AIMessage(content="So you said you were researching ocean mammals?", name="Model")]

  messages.append(HumanMessage(content="Yes, that's right.", name="Lance"))

  messages.append(AIMessage(content="Great, what would you like to learn about.", name="Model"))

  messages.append(HumanMessage(content="I want to learn about the best place to see Orcas in the US.", name="Lance"))

  

  for m in messages:

      m.pretty_print()

4. 채팅 모델(Chat Models) 설정

- API 키 설정: OpenAI API 키를 설정하여 채팅 모델을 사용할 수 있도록 합니다.

  import os, getpass

  

  def setenv(var: str):

      if not os.environ.get(var):

          os.environ[var] = getpass.getpass(f"{var}: ")

  

  setenv("OPENAI_API_KEY")

- 모델 로드 및 호출: ChatOpenAI 모델을 로드하고, 생성한 메시지 리스트를 사용하여 모델을 호출합니다.

  from langchain_openai import ChatOpenAI

  llm = ChatOpenAI(model="gpt-4o")

  result = llm.invoke(messages)

  type(result)

  

  result

  

  result.response_metadata

5. 도구(Tools) 정의 및 바인딩

- 도구의 역할: 외부 시스템과의 상호작용을 위해 도구를 정의하고, 모델에 바인딩합니다. 이를 통해 모델은 특정 입력 스키마를 인식하고 도구를 호출할 수 있습니다.

- 도구 예시: 간단한 multiply 함수를 도구로 정의하고, 모델에 바인딩합니다.

def multiply(a: int, b: int) -> int:

      """Multiply a and b.

  

      Args:

          a: first int

          b: second int

      """

      return a * b

  

  llm_with_tools = llm.bind_tools([multiply])

- 도구 호출 예시: 사용자 입력에 따라 도구가 호출되고, 그 결과가 반환됩니다.

  tool_call = llm_with_tools.invoke([HumanMessage(content="What is 2 multiplied by 3", name="Lance")])

  tool_call

  

  tool_call.additional_kwargs['tool_calls']

6. 메시지를 상태로 사용하기

- 상태 정의: MessagesState를 TypedDict로 정의하여 messages 키를 상태로 사용합니다.

  from typing_extensions import TypedDict

  from langchain_core.messages import AnyMessage

  

  class MessagesState(TypedDict):

      messages: list[AnyMessage]

7. 리듀서(Reducers) 설정

- 문제점: 각 노드가 messages 키의 새 값을 반환할 때 이전 메시지가 덮어써지는 문제 발생.

- 해결책: add_messages 리듀서를 사용하여 새로운 메시지를 기존 메시지 리스트에 추가.

 from typing import Annotated

  from langgraph.graph.message import add_messages

  

  class MessagesState(TypedDict):

      messages: Annotated[list[AnyMessage], add_messages]

- 기본 제공: LangGraph는 미리 빌드된 MessagesState를 제공하여 사용자 정의 TypedDict를 간소화합니다.

  from langgraph.graph import MessagesState

  

  class MessagesState(MessagesState):

      # Add any keys needed beyond messages, which is pre-built

      pass

8. 그래프(Graph) 구축 및 실행

- 그래프 노드 정의: tool_calling_llm 노드를 정의하여 도구와 함께 LLM을 호출하고, 그 결과를 상태에 추가.

  from IPython.display import Image, display

  from langgraph.graph import StateGraph, START, END

  

  # Node

  def tool_calling_llm(state: MessagesState):

      return {"messages": [llm_with_tools.invoke(state["messages"])]}

- 그래프 빌드 및 시각화: StateGraph를 초기화하고, 노드 및 에지를 추가한 후 그래프를 컴파일하고 시각화.

  # Build graph

  builder = StateGraph(MessagesState)

  builder.add_node("tool_calling_llm", tool_calling_llm)

  builder.add_edge(START, "tool_calling_llm")

  builder.add_edge("tool_calling_llm", END)

  graph = builder.compile()

  

  # View

  display(Image(graph.get_graph().draw_mermaid_png()))

- 그래프 호출 및 결과 확인:

- 도구 호출 없이 실행: "Hello!" 입력 시 LLM이 도구 호출 없이 응답.

도구를 호출하는 과정을 보여주는 다이어그램
    messages = graph.invoke({"messages": HumanMessage(content="Hello!")})

    for m in messages['messages']:

        m.pretty_print()

- 도구 호출 포함 실행: "Multiply 2 and 3" 입력 시 LLM이 multiply 도구를 호출하여 결과를 반환.

    messages = graph.invoke({"messages": HumanMessage(content="Multiply 2 and 3")})

    for m in messages['messages']:

        m.pretty_print()

랭그래프, AI 에이전트 구현에 관심이 생겼나요?

->지금바로 랭그래프 스터디에 관심이 있다면 신청해주세요!

주황색 배경의 한국 광고

지피터스 13기 스터디 신청링크

3
지피터스 뉴스레터

이번 주 AI, 딱 쓸 것만

매주 월요일 오후,
읽고 바로 써먹을 AI 소식만