에이전트는 언어 모델과 도구를 결합하여 작업에 대해 추론하고, 사용할 도구를 결정하며, 반복적으로 솔루션을 향해 작업하는 시스템을 만듭니다.create_agent는 프로덕션에 바로 사용할 수 있는 에이전트 구현을 제공합니다.LLM 에이전트는 목표를 달성하기 위해 루프 내에서 도구를 실행합니다.
에이전트는 중지 조건이 충족될 때까지 실행됩니다. 즉, 모델이 최종 출력을 내보내거나 반복 제한에 도달할 때까지 실행됩니다.
create_agent는 LangGraph를 사용하여 그래프 기반 에이전트 런타임을 구축합니다. 그래프는 에이전트가 정보를 처리하는 방법을 정의하는 노드(단계)와 엣지(연결)로 구성됩니다. 에이전트는 이 그래프를 통해 이동하며, 모델 노드(모델을 호출), 도구 노드(도구를 실행) 또는 미들웨어와 같은 노드를 실행합니다.Graph API에 대해 자세히 알아보세요.
모델 인스턴스를 사용하면 구성을 완전히 제어할 수 있습니다. temperature, max_tokens, timeouts, base_url과 같은 특정 매개변수 및 기타 공급자별 설정을 지정해야 할 때 사용하세요. 모델에서 사용 가능한 매개변수와 메서드를 보려면 참조를 참조하세요.
동적 모델은 현재 와 컨텍스트를 기반으로 에 선택됩니다. 이를 통해 정교한 라우팅 로직과 비용 최적화가 가능합니다.동적 모델을 사용하려면 요청에서 모델을 수정하는 @wrap_model_call 데코레이터를 사용하여 미들웨어를 생성하세요:
Copy
from langchain_openai import ChatOpenAIfrom langchain.agents import create_agentfrom langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponsebasic_model = ChatOpenAI(model="gpt-4o-mini")advanced_model = ChatOpenAI(model="gpt-4o")@wrap_model_calldef dynamic_model_selection(request: ModelRequest, handler) -> ModelResponse: """대화 복잡도에 따라 모델을 선택합니다.""" message_count = len(request.state["messages"]) if message_count > 10: # 긴 대화에는 고급 모델을 사용 model = advanced_model else: model = basic_model request.model = model return handler(request)agent = create_agent( model=basic_model, # 기본 모델 tools=tools, middleware=[dynamic_model_selection])
사전 바인딩된 모델(이미 bind_tools가 호출된 모델)은 구조화된 출력을 사용할 때 지원되지 않습니다. 구조화된 출력과 함께 동적 모델 선택이 필요한 경우 미들웨어에 전달되는 모델이 사전 바인딩되지 않았는지 확인하세요.
모델 구성 세부 정보는 모델을 참조하세요. 동적 모델 선택 패턴은 미들웨어의 동적 모델을 참조하세요.
도구 오류 처리 방식을 사용자 정의하려면 @wrap_tool_call 데코레이터를 사용하여 미들웨어를 생성하세요:
Copy
from langchain.agents import create_agentfrom langchain.agents.middleware import wrap_tool_callfrom langchain_core.messages import ToolMessage@wrap_tool_calldef handle_tool_errors(request, handler): """사용자 정의 메시지로 도구 실행 오류를 처리합니다.""" try: return handler(request) except Exception as e: # 모델에 사용자 정의 오류 메시지를 반환합니다 return ToolMessage( content=f"Tool error: Please check your input and try again. ({str(e)})", tool_call_id=request.tool_call["id"] )agent = create_agent( model="openai:gpt-4o", tools=[search, get_weather], middleware=[handle_tool_errors])
도구가 실패하면 에이전트는 사용자 정의 오류 메시지와 함께 ToolMessage를 반환합니다:
Copy
[ ... ToolMessage( content="Tool error: Please check your input and try again. (division by zero)", tool_call_id="..." ), ...]
에이전트는 ReAct(“추론 + 행동”) 패턴을 따르며, 간단한 추론 단계와 목표 지향적인 도구 호출을 번갈아 수행하고, 결과 관찰을 후속 결정에 반영하여 최종 답변을 제공할 수 있을 때까지 반복합니다.
ReAct 루프 예제
프롬프트: 현재 가장 인기 있는 무선 헤드폰을 식별하고 재고를 확인하세요.
Copy
================================ Human Message =================================Find the most popular wireless headphones right now and check if they're in stock
================================= Tool Message =================================Product WH-1000XM5: 10 units in stock
추론: “가장 인기 있는 모델과 재고 상태를 확인했습니다. 이제 사용자의 질문에 답변할 수 있습니다.”
행동: 최종 답변 생성
Copy
================================== Ai Message ==================================I found wireless headphones (model WH-1000XM5) with 10 units in stock...
에이전트는 메시지 상태를 통해 대화 기록을 자동으로 유지합니다. 대화 중에 추가 정보를 기억하도록 사용자 정의 상태 스키마를 사용하도록 에이전트를 구성할 수도 있습니다.상태에 저장된 정보는 에이전트의 단기 메모리로 생각할 수 있습니다:사용자 정의 상태 스키마는 TypedDict로 AgentState를 확장해야 합니다.사용자 정의 상태를 정의하는 두 가지 방법이 있습니다:
도구에서만 사용되는 사용자 정의 상태를 정의하는 바로 가기로 state_schema 매개변수를 사용하세요.
Copy
from langchain.agents import AgentStateclass CustomState(AgentState): user_preferences: dictagent = create_agent( model, tools=[tool1, tool2], state_schema=CustomState)# 에이전트는 이제 메시지 외에 추가 상태를 추적할 수 있습니다result = agent.invoke({ "messages": [{"role": "user", "content": "I prefer technical explanations"}], "user_preferences": {"style": "technical", "verbosity": "detailed"},})
langchain 1.0부터 사용자 정의 상태 스키마는 반드시TypedDict 타입이어야 합니다. Pydantic 모델과 데이터 클래스는 더 이상 지원되지 않습니다. 자세한 내용은 v1 마이그레이션 가이드를 참조하세요.
메모리에 대해 자세히 알아보려면 메모리를 참조하세요. 세션 간에 지속되는 장기 메모리 구현에 대한 정보는 장기 메모리를 참조하세요.
invoke로 에이전트를 호출하여 최종 응답을 받는 방법을 살펴보았습니다. 에이전트가 여러 단계를 실행하는 경우 시간이 걸릴 수 있습니다. 중간 진행 상황을 표시하려면 메시지가 발생할 때 스트리밍할 수 있습니다.
Copy
for chunk in agent.stream({ "messages": [{"role": "user", "content": "Search for AI news and summarize the findings"}]}, stream_mode="values"): # 각 청크는 해당 시점의 전체 상태를 포함합니다 latest_message = chunk["messages"][-1] if latest_message.content: print(f"Agent: {latest_message.content}") elif latest_message.tool_calls: print(f"Calling tools: {[tc['name'] for tc in latest_message.tool_calls]}")