배경 및 목적
이번 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 langgraph3. 메시지(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_metadata5. 도구(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
pass8. 그래프(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기 스터디 신청링크