langgraph의 공식문서를 번역해 놓은 자료입니다. 필요한 경우 부연 설명을 추가하였습니다. 문제가 되면 삭제하겠습니다.
https://langchain-ai.github.io/langgraph/tutorials/multi_agent/hierarchical_agent_teams/
이전 예제(Agent Supervisor)에서는 단일 supervisor 노드(supervisor node)를 도입하여 서로 다른 작업자 노드(worker nodes) 간에 작업을 라우팅하는 개념을 소개했다.
그러나 단일 작업자(worker)에게 할당된 작업이 너무 복잡해지면 어떻게 될까? 혹은 작업자의 수가 지나치게 많아진다면 어떻게 될까?
일부 애플리케이션에서는 작업을 계층적으로 분산하는 것이 더 효과적일 수 있다.
이를 위해, 서로 다른 서브그래프(subgraph)를 구성하고 최상위 감독자(top-level supervisor)와 중간 감독자(mid-level supervisors)를 함께 생성할 수 있다.
이를 통해 간단한 연구 보조 도우미(research assistant)를 만들어 보자. 그래프의 구조는 다음과 비슷하게 보일 것이다.
이 노트북은 Wu 외 다수가 작성한 논문 "AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation"에서 영감을 받았다. 이 예제에서는 다음 작업을 수행하게 된다.
- 에이전트들이 웹에 접근하고 파일을 작성할 수 있는 도구를 정의한다.
- 그래프와 에이전트를 생성하는 데 도움을 줄 유틸리티 함수를 정의한다.
- 각 팀(웹 리서치 팀 + 문서 작성 팀)을 생성하고 정의한다.
- 모든 요소를 조합하여 전체 시스템을 구성한다.
준비
먼저, 필요한 패키지들을 설치하고 API 키를 설정해 보자.
$ pip install -U langgraph langchain_community langchain_openai langchain_experimental
from dotenv import load_dotenv
load_dotenv()
도구 생성
각 팀은 하나 이상의 에이전트로 구성되며, 각 에이전트는 하나 이상의 도구를 사용하게 된다. 아래에서는 서로 다른 팀에서 사용할 모든 도구를 정의하자.
ResearchTeam 도구 정의
연구팀(Research Team)은 웹에서 정보를 찾기 위해 검색 엔진과 URL 스크래퍼(URL Scraper)를 사용할 수 있다. 이 외에도 연구팀의 성능을 향상시키기 위해 추가 기능을 자유롭게 추가할 수 있다.
from typing import Annotated, List
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.tools import tool
tavily_tool = TavilySearchResults(max_results=5)
@tool
def scrape_webpages(urls: List[str]) -> str:
"""Use requests and bs4 to scrape the provided web pages for detailed information."""
loader = WebBaseLoader(urls)
docs = loader.load()
return "\n\n".join(
[
f'<Document name="{doc.metadata.get("title", "")}">\n{doc.page_content}\n</Document>'
for doc in docs
]
)
Document Writing Team 도구
다음으로, 문서 작성 팀(Document Writing Team)이 사용할 몇 가지 기본적인 파일 접근 도구를 정의한다.
이 도구는 에이전트에게 파일 시스템에 접근할 권한을 부여하므로, 보안상 위험할 수 있다. 또한, 도구 설명이 성능에 최적화되지 않았다.
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Dict, Optional
from langchain_experimental.utilities import PythonREPL
from typing_extensions import TypedDict
_TEMP_DIRECTORY = TemporaryDirectory()
WORKING_DIRECTORY = Path(_TEMP_DIRECTORY.name)
@tool
def create_outline(
points: Annotated[List[str], "List of main points or sections."],
file_name: Annotated[str, "File path to save the outline."],
) -> Annotated[str, "Path of the saved outline file."]:
"""Create and save an outline."""
with (WORKING_DIRECTORY / file_name).open("w") as file:
for i, point in enumerate(points):
file.write(f"{i + 1}. {point}\n")
return f"Outline saved to {file_name}"
@tool
def read_document(
file_name: Annotated[str, "File path to save the document."],
start: Annotated[Optional[int], "The start line. Default is 0"] = None,
end: Annotated[Optional[int], "The end line. Default is None"] = None,
) -> str:
"""Read the specified document."""
with (WORKING_DIRECTORY / file_name).open("r") as file:
lines = file.readlines()
if start is not None:
start = 0
return "\n".join(lines[start:end])
@tool
def write_document(
content: Annotated[str, "Text content to be written into the document."],
file_name: Annotated[str, "File path to save the document."],
) -> Annotated[str, "Path of the saved document file."]:
"""Create and save a text document."""
with (WORKING_DIRECTORY / file_name).open("w") as file:
file.write(content)
return f"Document saved to {file_name}"
@tool
def edit_document(
file_name: Annotated[str, "Path of the document to be edited."],
inserts: Annotated[
Dict[int, str],
"Dictionary where key is the line number (1-indexed) and value is the text to be inserted at that line.",
],
) -> Annotated[str, "Path of the edited document file."]:
"""Edit a document by inserting text at specific line numbers."""
with (WORKING_DIRECTORY / file_name).open("r") as file:
lines = file.readlines()
sorted_inserts = sorted(inserts.items())
for line_number, text in sorted_inserts:
if 1 <= line_number <= len(lines) + 1:
lines.insert(line_number - 1, text + "\n")
else:
return f"Error: Line number {line_number} is out of range."
with (WORKING_DIRECTORY / file_name).open("w") as file:
file.writelines(lines)
return f"Document edited and saved to {file_name}"
repl = PythonREPL()
@tool
def python_repl(
code: Annotated[str, "The python code to execute to generate your chart."],
):
"""Use this to execute python code. If you want to see the output of a value,
you should print it out with `print(...)`. This is visible to the user."""
try:
result = repl.run(code)
except BaseException as e:
return f"Failed to execute. Error: {repr(e)}"
return f"Successfully executed:\n\`\`\`python\n{code}\n\`\`\`\nStdout: {result}"
헬퍼 유틸리티
작업을 좀 더 간결하게 하기 위해 몇 가지 유틸리티 함수를 만든다.
- 작업자 에이전트 생성
- 서브 그래프에 대한 감독자 생성
이 함수들은 나중에 그래프 구성 코드를 단순화하여 진행 상황을 더 쉽게 파악할 수 있도록 도와줄 것이다.
from typing import List, Optional
from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI
from langgraph.graph import END, StateGraph, START
from langchain_core.messages import HumanMessage, trim_messages
llm = ChatOpenAI(model="gpt-4o")
# trim_messages는 특정 토큰 수 혹은 지정된 메시지 수로 채팅 이력의 크기를 줄이기 위해 사용된다.
trimmer = trim_messages(
max_tokens=100000,
strategy="last",
token_counter=llm,
include_system=True,
)
def agent_node(state, agent, name):
result = agent.invoke(state)
return {
"messages": [HumanMessage(content=result["messages"][-1].content, name=name)]
}
def create_team_supervisor(llm: ChatOpenAI, system_prompt, members) -> str:
"""An LLM-based router."""
options = ["FINISH"] + members
function_def = {
"name": "route",
"description": "Select the next role.",
"parameters": {
"title": "routeSchema",
"type": "object",
"properties": {
"next": {
"title": "Next",
"anyOf": [
{"enum": options},
],
},
},
"required": ["next"],
},
}
prompt = ChatPromptTemplate.from_messages(
[
("system", system_prompt),
MessagesPlaceholder(variable_name="messages"),
(
"system",
"Given the conversation above, who should act next?"
" Or should we FINISH? Select one of: {options}",
),
]
).partial(options=str(options), team_members=", ".join(members))
return (
prompt
| trimmer
| llm.bind_functions(functions=[function_def], function_call="route")
| JsonOutputFunctionsParser()
)
Agent Teams 정의
이제 계층적인 팀을 정의할 수 있다. "Player 선택"
Research Team
리서치 팀은 검색 에이전트와 웹 스크래핑 "research_agent"를 두 개의 작업자 노드로 가질 것이다. 이제 이를 생성하고, 팀 감독자도 정의해 보자.
import functools
import operator
from langchain_core.messages import BaseMessage, HumanMessage
from langchain_openai.chat_models import ChatOpenAI
from langgraph.prebuilt import create_react_agent
# ResearchTeam 그래프 상태
class ResearchTeamState(TypedDict):
# 각 팀 멤버가 작업을 완료하면 메시지가 추가된다.
messages: Annotated[List[BaseMessage], operator.add]
# 팀 멤버들이 서로의 기술 세트를 인식할 수 있도록 추적된다.
team_members: List[str]
# 작업을 라우팅하는데 사용된다. supervisor는 결정을 내릴 때마다 이것을 업데이트하는 함수를 호출한다.
next: str
llm = ChatOpenAI(model="gpt-4o-mini")
search_agent = create_react_agent(llm, tools=[tavily_tool])
search_node = functools.partial(agent_node, agent=search_agent, name="Search")
research_agent = create_react_agent(llm, tools=[scrape_webpages])
research_node = functools.partial(agent_node, agent=research_agent, name="WebScraper")
supervisor_agent = create_team_supervisor(
llm,
"You are a supervisor tasked with managing a conversation between the"
" following workers: Search, WebScraper. Given the following user request,"
" respond with the worker to act next. Each worker will perform a"
" task and respond with their results and status. When finished,"
" respond with FINISH.",
["Search", "WebScraper"],
)
필요한 구성 요소를 모두 만들었으므로, 이제 이들의 상호작용을 정의하는 것이 쉽다. 팀 그래프에 노드를 추가하고, 전환 기준을 결정하는 엣지를 정의하자.
research_graph = StateGraph(ResearchTeamState)
research_graph.add_node("Search", search_node)
research_graph.add_node("WebScraper", research_node)
research_graph.add_node("supervisor", supervisor_agent)
# 제어 플로우 정의
research_graph.add_edge("Search", "supervisor")
research_graph.add_edge("WebScraper", "supervisor")
research_graph.add_conditional_edges(
"supervisor",
lambda x: x["next"],
{"Search": "Search", "WebScraper": "WebScraper", "FINISH": END},
)
research_graph.add_edge(START, "supervisor")
chain = research_graph.compile()
# 이 함수는 상위 그래프 상태와 하위 그래프 상태를 교환한다.
# 이렇게 하면 각 그래프의 상태가 섞이지 않는다.
def enter_chain(message: str):
results = {
"messages": [HumanMessage(content=message)],
}
return results
research_chain = enter_chain | chain
from IPython.display import Image, display
display(
Image(
chain.get_graph(xray=True).draw_mermaid_png(
output_file_path="./hierarchical.png"
)
)
)
이제 이 팀에 직접 작업할 수 있다.
for s in research_chain.stream(
"2022년 한국시리즈는 언제야?", {"recursion_limit": 100}
):
if "__end__" not in s:
print(s)
print("---")
{'supervisor': {'next': 'Search'}}
---
{'Search': {'messages': [HumanMessage(content='2022년 한국시리즈는 10월 31일부터 시작되었습니다. 포스트시즌은 10월 13일부터 진행되었습니다. 더 자세한 내용은 [여기](https://m.blog.naver.com/opulent8/222893912980)에서 확인할 수 있습니다.', additional_kwargs={}, response_metadata={}, name='Search')]}}
---
{'supervisor': {'next': 'FINISH'}}
---
Document Writing Team
아래와 같은 방식으로 문서 작성 팀을 생성하자. 이번에는 각 에이전트에게 서로 다른 파일 쓰기 도구에 대한 접근 권한을 부여할 것이다.
여기서 에이전트에게 파일 시스템 접근을 허용하는데, 이는 모든 경우에서 안전하지 않을 수 있다.
import operator
from pathlib import Path
# 문서 작성 팀 그래프 상태
class DocWritingState(TypedDict):
# 내부적으로 팀의 대화를 추적한다.
messages: Annotated[List[BaseMessage], operator.add]
# This provides each worker with context on the others' skill sets
# 각 작업자가 다른 작업자의 기술 세트에 대해 인식할 수 있도록 추적된다.
team_members: str
# 이것은 감독이 langgraph에게 누가 다음에 일할지 알려준다.
next: str
# 이것은 공유 디렉토리 상태를 추적한다.
current_files: str
# 각 작업자 에이전트가 작업을 시작하기 전에 실행된다.
# 이렇게 하면 작업 디렉토리의 현재 상태를 더 잘 인식할 수 있다.
def prelude(state):
written_files = []
if not WORKING_DIRECTORY.exists():
WORKING_DIRECTORY.mkdir()
try:
written_files = [
f.relative_to(WORKING_DIRECTORY) for f in WORKING_DIRECTORY.rglob("*")
]
except Exception:
pass
if not written_files:
return {**state, "current_files": "No files written."}
return {
**state,
"current_files": "\nBelow are files your team has written to the directory:\n"
+ "\n".join([f" - {f}" for f in written_files]),
}
llm = ChatOpenAI(model="gpt-4o-mini")
doc_writer_agent = create_react_agent(
llm, tools=[write_document, edit_document, read_document]
)
# 각 호출 전에 현재 디렉토리 작업 상태를 주입한다.
context_aware_doc_writer_agent = prelude | doc_writer_agent
doc_writing_node = functools.partial(
agent_node, agent=context_aware_doc_writer_agent, name="DocWriter"
)
note_taking_agent = create_react_agent(llm, tools=[create_outline, read_document])
context_aware_note_taking_agent = prelude | note_taking_agent
note_taking_node = functools.partial(
agent_node, agent=context_aware_note_taking_agent, name="NoteTaker"
)
chart_generating_agent = create_react_agent(llm, tools=[read_document, python_repl])
context_aware_chart_generating_agent = prelude | chart_generating_agent
chart_generating_node = functools.partial(
agent_node, agent=context_aware_note_taking_agent, name="ChartGenerator"
)
doc_writing_supervisor = create_team_supervisor(
llm,
"You are a supervisor tasked with managing a conversation between the"
" following workers: {team_members}. Given the following user request,"
" respond with the worker to act next. Each worker will perform a"
" task and respond with their results and status. When finished,"
" respond with FINISH.",
["DocWriter", "NoteTaker", "ChartGenerator"],
)
objects를 직접 생성함으로서 그래프를 구성할 수 있다.
# 그래프 생성
# 이 문서를 위해 루프를 풀었음을 유의하라
authoring_graph = StateGraph(DocWritingState)
authoring_graph.add_node("DocWriter", doc_writing_node)
authoring_graph.add_node("NoteTaker", note_taking_node)
authoring_graph.add_node("ChartGenerator", chart_generating_node)
authoring_graph.add_node("supervisor", doc_writing_supervisor)
# 항상 발생하는 엣지 추가
authoring_graph.add_edge("DocWriter", "supervisor")
authoring_graph.add_edge("NoteTaker", "supervisor")
authoring_graph.add_edge("ChartGenerator", "supervisor")
# 라우팅이 적용되는 엣지 추가
authoring_graph.add_conditional_edges(
"supervisor",
lambda x: x["next"],
{
"DocWriter": "DocWriter",
"NoteTaker": "NoteTaker",
"ChartGenerator": "ChartGenerator",
"FINISH": END,
},
)
authoring_graph.add_edge(START, "supervisor")
chain = authoring_graph.compile()
# 이 함수는 상위 그래프 상태와 하위 그래프 상태를 교환한다.
# 이렇게 하면 각 그래프의 상태가 섞이지 않는다.
def enter_chain(message: str, members: List[str]):
results = {
"messages": [HumanMessage(content=message)],
"team_members": ", ".join(members),
}
return results
# 그래프를 래핑하기 위해 enter/exit 함수를 재사용한다.
authoring_chain = (
functools.partial(enter_chain, members=authoring_graph.nodes)
| authoring_graph.compile()
)
from IPython.display import Image, display
display(
Image(chain.get_graph().draw_mermaid_png(output_file_path="./hierarchical2.png"))
)
for s in authoring_chain.stream(
# "Write an outline for poem and then write the poem to disk.",
"시에 대한 개요를 작성하고 그리고 시를 디스크에 쓰세요.",
{"recursion_limit": 100},
):
if "__end__" not in s:
print(s)
print("---")
{'supervisor': {'next': 'DocWriter'}}
---
{'DocWriter': {'messages': [HumanMessage(content='시에 대한 개요를 작성하여 "poem_overview.txt"라는 파일에 저장하였습니다. 추가로 필요한 내용이나 요청이 있으시면 말씀해 주세요!', additional_kwargs={}, response_metadata={}, name='DocWriter')]}}
---
{'supervisor': {'next': 'NoteTaker'}}
---
{'NoteTaker': {'messages': [HumanMessage(content='시에 대한 개요를 "poem_overview.txt" 파일에 저장하였습니다. 추가로 필요한 내용이나 요청이 있으시면 말씀해 주세요!', additional_kwargs={}, response_metadata={}, name='NoteTaker')]}}
---
{'supervisor': {'next': 'ChartGenerator'}}
---
{'ChartGenerator': {'messages': [HumanMessage(content='시에 대한 개요가 "poem_overview.txt" 파일에 저장되었습니다. 추가로 필요한 내용이나 요청이 있으시면 말씀해 주세요!', additional_kwargs={}, response_metadata={}, name='ChartGenerator')]}}
---
{'supervisor': {'next': 'FINISH'}}
---
레이어 추가
이 설계에서는 상향식 계획 정책을 적용하고 있다. 이미 두 개의 그래프를 만들었지만, 두 그래프 간에 작업을 어떻게 라우팅할지 결정해야 한다.
세 번째 그래프를 만들어 이전 두 그래프를 조정하고, 이 상위 상태가 서로 다른 그래프 간에 어떻게 공유될지 정의하는 커넥터를 추가할 것이다.
from langchain_core.messages import BaseMessage
from langchain_openai.chat_models import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o")
supervisor_node = create_team_supervisor(
llm,
"You are a supervisor tasked with managing a conversation between the"
" following teams: {team_members}. Given the following user request,"
" respond with the worker to act next. Each worker will perform a"
" task and respond with their results and status. When finished,"
" respond with FINISH.",
["ResearchTeam", "PaperWritingTeam"],
)
# Top-level graph state
class State(TypedDict):
messages: Annotated[List[BaseMessage], operator.add]
next: str
def get_last_message(state: State) -> str:
return state["messages"][-1].content
def join_graph(response: dict):
return {"messages": [response["messages"][-1]]}
# Define the graph.
super_graph = StateGraph(State)
# First add the nodes, which will do the work
super_graph.add_node("ResearchTeam", get_last_message | research_chain | join_graph)
super_graph.add_node(
"PaperWritingTeam", get_last_message | authoring_chain | join_graph
)
super_graph.add_node("supervisor", supervisor_node)
# Define the graph connections, which controls how the logic
# propagates through the program
super_graph.add_edge("ResearchTeam", "supervisor")
super_graph.add_edge("PaperWritingTeam", "supervisor")
super_graph.add_conditional_edges(
"supervisor",
lambda x: x["next"],
{
"PaperWritingTeam": "PaperWritingTeam",
"ResearchTeam": "ResearchTeam",
"FINISH": END,
},
)
super_graph.add_edge(START, "supervisor")
super_graph = super_graph.compile()
display(
Image(
super_graph.get_graph().draw_mermaid_png(output_file_path="hierarchical3.png")
)
)
for s in super_graph.stream(
{
"messages": [
HumanMessage(content="AI agents를 조사해서 간단한 보고서를 작성해줘")
],
},
{"recursion_limit": 150},
):
if "__end__" not in s:
print(s)
print("---")
{'supervisor': {'next': 'ResearchTeam'}}
---
{'ResearchTeam': {'messages': [HumanMessage(content='### 보고서: AI 에이전트 (AI Agents)\n\n#### 1. 정의\nAI 에이전트는 자율적으로 결정을 내리고, 동적인 환경에서 데이터를 수집하여 미리 설정된 목표를 달성하기 위한 최적의 행동을 선택하는 AI 시스템입니다. 이는 인간이 설정한 목표를 바탕으로 독립적으로 작업을 수행할 수 있는 능력을 가지고 있습니다.\n\n#### 2. 주요 기능\n- **자율성**: AI 에이전트는 환경과 상호작용하며 새로운 지식을 습득하고 스스로 판단을 내릴 수 있습니다.\n- **자동화**: 반복적이고 시간 소모적인 작업을 자동으로 처리하여 자원을 절약합니다. 예를 들어, 고객 서비스 분야에서 챗봇과 가상 비서가 이를 수행합니다.\n- **적응성**: AI 에이전트는 환경 변화에 따라 행동을 조정할 수 있습니다.\n\n#### 3. 장점\n- **효율성 개선**: 다양한 고객 요구 사항을 처리할 수 있어, 인간의 개입 없이도 운영을 개선할 수 있습니다.\n- **시간 절약**: 반복적인 작업을 자동으로 수행하여 직원들이 더 중요한 업무에 집중할 수 있도록 도와줍니다.\n- **24/7 지원**: 고객 서비스 분야에서 지속적으로 서비스를 제공할 수 있습니다.\n\n#### 4. 도전 과제\n- **기술적 한계**: 복잡한 문제 해결에 있어 현재 AI 에이전트는 제한적이며, 예외 상황에 대한 대처 능력이 부족할 수 있습니다.\n- **안전성 문제**: AI 에이전트가 독립적으로 결정을 내리는 과정에서 발생할 수 있는 윤리적 및 안전성 문제도 존재합니다.\n\n#### 5. 응용 분야\nAI 에이전트는 고객 서비스, 데이터 분석, 개인화된 추천 시스템 등 다양한 분야에서 활용되고 있으며, 우리의 생활과 업무 방식을 혁신할 잠재력을 가지고 있습니다.\n\n#### 6. AI 에이전트의 종류\n- **간단 반사 에이전트**: 간단한 규칙에 따라 작동하며, 특정 입력에 대해 정해진 출력을 제공합니다.\n- **모델 기반 반사 에이전트**: 과거 경험을 바탕으로 현재의 상황을 분석하여 결정을 내립니다.\n- **목표 기반 에이전트**: 특정 목표를 달성하기 위해 다양한 접근 방식을 평가하여 최적의 결정을 내립니다.\n- **유틸리티 기반 에이전트**: 다양한 시나리오를 평가하여 최대의 결과를 추구합니다.\n- **학습 에이전트**: 자신이 수행한 작업에서 학습하여 성능을 지속적으로 개선합니다.\n\n#### 7. 결론\nAI 에이전트는 현대 기술의 중요한 발전 중 하나로, 다양한 분야에서 사용되고 있습니다. 하지만 그 사용에는 여전히 해결해야 할 여러 과제가 존재하며, 지속적인 연구와 개발이 필요합니다.\n\n#### 참고 자료\n1. [MIT Technology Review - What are AI agents?](https://www.technologyreview.com/2024/07/05/1094711/what-are-ai-agents/)\n2. [AWS - What is an AI agent?](https://aws.amazon.com/what-is/ai-agents/)\n3. [Vox - The move from AI chatbots to AI agents](https://www.vox.com/future-perfect/24114582/artificial-intelligence-agents-openai-chatgpt-microsoft-google-ai-safety-risk-anthropic-claude)\n4. [Otter.ai - A guide to AI agents](https://otter.ai/blog/what-are-ai-agents-a-guide-to-types-benefits-and-examples)\n5. [GitHub - What are AI agents and why do they matter?](https://github.blog/ai-and-ml/generative-ai/what-are-ai-agents-and-why-do-they-matter/) \n\n이 보고서는 AI 에이전트에 대한 기본적인 이해를 돕고, 그 기능과 응용 분야를 설명하는 데 중점을 두었습니다.', additional_kwargs={}, response_metadata={}, name='WebScraper')]}}
---
{'supervisor': {'next': 'PaperWritingTeam'}}
---
{'PaperWritingTeam': {'messages': [HumanMessage(content='보고서의 개요가 "AI_Agents_Report_Outline.txt" 파일로 저장되었습니다. 이 파일은 AI 에이전트에 대한 기본적인 이해를 돕고, 그 기능과 응용 분야를 설명하는 데 중점을 두고 있습니다. 추가적인 도움이 필요하시면 말씀해 주세요!', additional_kwargs={}, response_metadata={}, name='ChartGenerator')]}}
---
{'supervisor': {'next': 'PaperWritingTeam'}}
---
{'PaperWritingTeam': {'messages': [HumanMessage(content='AI 에이전트에 대한 기본적인 이해를 돕기 위한 개요가 "AI_Agents_Report_Outline.txt" 파일로 저장되었습니다. 파일은 다음과 같은 내용을 포함하고 있습니다:\n\n1. AI 에이전트의 정의 및 개념\n2. AI 에이전트의 기능\n3. AI 에이전트의 응용 분야\n4. AI 에이전트의 장점 및 단점\n5. 미래의 AI 에이전트\n6. 결론 및 요약\n\n추가적인 도움이 필요하시면 언제든지 말씀해 주세요!', additional_kwargs={}, response_metadata={}, name='ChartGenerator')]}}
---
{'supervisor': {'next': 'PaperWritingTeam'}}
---
{'PaperWritingTeam': {'messages': [HumanMessage(content='"AI_Agents_Report_Outline.txt" 파일이 성공적으로 저장되었습니다. 파일에는 AI 에이전트에 대한 기본적인 개요가 포함되어 있습니다. 추가적인 도움이 필요하시면 언제든지 말씀해 주세요!', additional_kwargs={}, response_metadata={}, name='ChartGenerator')]}}
---
{'supervisor': {'next': 'PaperWritingTeam'}}
---
{'PaperWritingTeam': {'messages': [HumanMessage(content='AI 에이전트에 대한 개요를 제공해 주셔서 감사합니다! 다음 단계로 어떤 내용을 더 다루고 싶으신가요? 각 항목에 대해 더 깊이 있는 정보가 필요하신가요, 아니면 특정 주제에 대해 자세히 알고 싶으신가요?', additional_kwargs={}, response_metadata={}, name='ChartGenerator')]}}
---
{'supervisor': {'next': 'PaperWritingTeam'}}
---
{'PaperWritingTeam': {'messages': [HumanMessage(content='각 항목에 대해 더 깊이 있는 정보를 제공해 드릴 수 있습니다. 다음 중 어떤 주제에 대해 자세히 알고 싶으신가요?\n\n1. **AI 에이전트의 종류**\n2. **AI 에이전트의 응용 분야**\n3. **AI 에이전트의 작동 원리**\n4. **윤리적 고려사항**\n5. **미래 전망**\n\n특정 항목을 선택해 주시면, 해당 주제에 대해 자세히 설명해 드리겠습니다!', additional_kwargs={}, response_metadata={}, name='DocWriter')]}}
---
{'supervisor': {'next': 'PaperWritingTeam'}}
---
{'PaperWritingTeam': {'messages': [HumanMessage(content='AI 에이전트의 응용 분야에 대한 자세한 설명을 드리겠습니다. AI 에이전트는 다양한 산업에서 광범위하게 활용되고 있으며, 각각의 분야에서 혁신과 효율성을 가져오고 있습니다. 아래는 주요 응용 분야에 대한 설명입니다.\n\n### 1. 고객 서비스\nAI 에이전트는 주로 고객 지원을 위해 사용되는 챗봇 형태로 존재합니다. 이들은 고객의 질문에 실시간으로 답변하고, 일반적인 문의사항(FAQ)을 처리하며, 문제 해결을 지원합니다. 이를 통해 고객의 요구를 신속하게 충족시킬 수 있습니다.\n\n### 2. 의료\n의료 분야에서 AI 에이전트는 환자의 증상을 분석하고, 진단 지원 및 치료 계획을 추천하는 데 사용됩니다. 또한, 원격 진료와 건강 관리 시스템에서도 중요한 역할을 하며, 환자의 데이터를 분석하여 맞춤형 치료를 제공합니다.\n\n### 3. 금융\nAI 에이전트는 금융 시장 분석, 거래 자동화, 고객 서비스 개선에 활용됩니다. 이들은 시장의 동향을 예측하고, 사기 감지 및 위험 평가를 통해 금융 거래의 안전성을 높입니다.\n\n### 4. 교육\nAI 튜터는 학생 개개인의 학습 스타일과 수준에 맞춘 개인화된 학습 경험을 제공합니다. 이들은 학습 진도를 추적하고, 맞춤형 과제를 추천하여 학습 효과를 극대화합니다.\n\n### 5. 자율주행차\nAI 에이전트는 자율주행차의 핵심 기술로, 차량의 주변 환경을 인식하고 주행 경로를 계획하며 안전한 운전을 보장합니다. 이는 교통사고를 줄이고, 교통 흐름을 개선하는 데 기여합니다.\n\n### 6. 마케팅\nAI는 고객 데이터를 분석하여 맞춤형 광고를 제공하고, 고객 행동을 예측하여 마케팅 전략을 최적화하는 데 사용됩니다. 이는 기업의 마케팅 효율성을 높여줍니다.\n\n### 7. 제조업\nAI 에이전트는 생산 공정의 자동화를 지원하고 품질 관리를 개선하며 유지보수를 예측하는 데 활용됩니다. 이는 제조업체의 생산성을 높이고 비용을 절감하는 데 도움을 줍니다.\n\n### 8. 게임\nAI는 게임 캐릭터의 행동을 제어하고 플레이어의 행동에 반응하여 보다 몰입감 있는 경험을 제공합니다. 이는 게임의 재미와 도전 요소를 증가시킵니다.\n\n### 9. 스마트 홈\nAI 에이전트는 가정의 스마트 기기를 제어하여 에너지 효율을 높이고 사용자 편의를 증대시킵니다. 예를 들어, 음성 인식 기술을 통해 기기를 제어할 수 있습니다.\n\n### 10. 소셜 미디어\nAI는 소셜 미디어 플랫폼에서 콘텐츠 추천, 사용자 행동 분석 및 커뮤니티 관리에 활용됩니다. 이는 사용자 경험을 향상시키고 플랫폼의 참여도를 높이는 데 기여합니다.\n\n이처럼 AI 에이전트는 다양한 분야에서 혁신을 주도하며, 효율성과 사용자 경험을 개선하는 데 기여하고 있습니다. 각 분야의 특성에 맞추어 AI 기술이 발전함에 따라 앞으로의 응용 가능성은 더욱 확대될 것입니다.', additional_kwargs={}, response_metadata={}, name='ChartGenerator')]}}
---
{'supervisor': {'next': 'PaperWritingTeam'}}
---
{'PaperWritingTeam': {'messages': [HumanMessage(content='문서 "ai_agents_applications.txt"와 개요 "ai_agents_applications_outline.txt"의 내용을 읽어보았습니다. 아래는 두 문서에서 얻은 주요 내용입니다.\n\n### AI 에이전트의 응용 분야 개요\n\n1. **고객 서비스**\n - AI 에이전트는 주로 고객 지원을 위한 챗봇 형태로 존재하며, 고객의 질문에 실시간으로 답변하고 FAQ를 처리합니다.\n\n2. **의료**\n - 환자의 증상 분석, 진단 지원 및 치료 계획 추천에 사용됩니다. 원격 진료와 건강 관리 시스템에서도 중요한 역할을 합니다.\n\n3. **금융**\n - 금융 시장 분석, 거래 자동화 및 고객 서비스 개선에 활용됩니다. 사기 감지 및 위험 평가를 통해 거래의 안전성을 높입니다.\n\n4. **교육**\n - AI 튜터는 개인화된 학습 경험을 제공하고, 학습 진도를 추적하여 맞춤형 과제를 추천합니다.\n\n5. **자율주행차**\n - 차량의 주변 환경을 인식하고 주행 경로를 계획하여 안전한 운전을 보장합니다.\n\n6. **마케팅**\n - 고객 데이터를 분석하여 맞춤형 광고를 제공하고, 고객 행동을 예측하여 마케팅 전략을 최적화합니다.\n\n7. **제조업**\n - 생산 공정 자동화, 품질 관리 개선 및 유지보수 예측에 활용되어 생산성과 비용 절감에 기여합니다.\n\n8. **게임**\n - 게임 캐릭터의 행동을 제어하고 플레이어의 행동에 반응하여 몰입감 있는 경험을 제공합니다.\n\n9. **스마트 홈**\n - 가정의 스마트 기기를 제어하여 에너지 효율을 높이고 사용자 편의를 증대시킵니다.\n\n10. **소셜 미디어**\n - 콘텐츠 추천, 사용자 행동 분석 및 커뮤니티 관리에 활용되어 사용자 경험을 향상시킵니다.\n\n이와 같은 다양한 분야에서 AI 에이전트는 혁신과 효율성을 가져오며, 각 분야의 특성에 맞춰 발전하고 있습니다. 필요할 경우 이 문서나 개요를 언제든지 읽거나 편집할 수 있습니다.', additional_kwargs={}, response_metadata={}, name='ChartGenerator')]}}
---
{'supervisor': {'next': 'FINISH'}}
---