diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 673458a..daa887c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,4 +13,4 @@ repos: args: [ --fix ] - id: ruff-format types_or: [ python, pyi ] -exclude: 'generated/.*|artifacts/.*' +exclude: 'generated/.*|artifacts/.*|.*\.json$' diff --git a/docs/index.md b/docs/index.md index 6104ee3..b1e86bf 100644 --- a/docs/index.md +++ b/docs/index.md @@ -43,6 +43,8 @@ uv run python -m template_langgraph.tasks.run_issue_formatter_agent - [Build a custom workflow](https://langchain-ai.github.io/langgraph/concepts/why-langgraph/) - [LangGraphの(LLMなし)Human-in-the-loopを試してみた](https://qiita.com/te_yama/items/db38201af60dec76384d) +- [🤖 LangGraph Multi-Agent Supervisor](https://github.com/langchain-ai/langgraph-supervisor-py) +- [Software Design誌「実践LLMアプリケーション開発」第24回サンプルコード](https://github.com/mahm/softwaredesign-llm-application/tree/main/24) ### Sample Codes diff --git a/langgraph.json b/langgraph.json index f1a5bad..1c7a599 100644 --- a/langgraph.json +++ b/langgraph.json @@ -3,10 +3,11 @@ "." ], "graphs": { + "supervisor_agent": "template_langgraph.agents.supervisor_agent:graph", "chat_with_tools_agent": "template_langgraph.agents.chat_with_tools_agent.agent:graph", "kabuto_helpdesk_agent": "template_langgraph.agents.kabuto_helpdesk_agent:graph", "issue_formatter_agent": "template_langgraph.agents.issue_formatter_agent.agent:graph", "task_decomposer_agent": "template_langgraph.agents.task_decomposer_agent.agent:graph" }, "env": ".env" -} +} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index f997f1c..0b2fd9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,7 @@ dependencies = [ "langchain-openai>=0.3.28", "langchain-text-splitters>=0.3.9", "langgraph>=0.6.2", + "langgraph-supervisor>=0.0.29", "openai>=1.98.0", "pydantic-settings>=2.9.1", "pypdf>=5.9.0", diff --git a/template_langgraph/agents/chat_with_tools_agent/agent.py b/template_langgraph/agents/chat_with_tools_agent/agent.py index c11fa0c..cc60123 100644 --- a/template_langgraph/agents/chat_with_tools_agent/agent.py +++ b/template_langgraph/agents/chat_with_tools_agent/agent.py @@ -76,7 +76,9 @@ def create_graph(self): workflow.add_edge("finalize", END) # Compile the graph - return workflow.compile() + return workflow.compile( + name=ChatWithToolsAgent.__name__, + ) def initialize(self, state: AgentState) -> AgentState: """Initialize the agent with the given state.""" diff --git a/template_langgraph/agents/issue_formatter_agent/agent.py b/template_langgraph/agents/issue_formatter_agent/agent.py index e5e5cdc..76d3758 100644 --- a/template_langgraph/agents/issue_formatter_agent/agent.py +++ b/template_langgraph/agents/issue_formatter_agent/agent.py @@ -24,7 +24,9 @@ def create_graph(self): workflow.add_edge("analyze", END) # Compile the graph - return workflow.compile() + return workflow.compile( + name=IssueFormatterAgent.__name__, + ) def analyze(self, state: AgentState) -> AgentState: """Analyze the issue and extract relevant information.""" diff --git a/template_langgraph/agents/supervisor_agent.py b/template_langgraph/agents/supervisor_agent.py new file mode 100644 index 0000000..b3e1292 --- /dev/null +++ b/template_langgraph/agents/supervisor_agent.py @@ -0,0 +1,36 @@ +from langgraph_supervisor import create_supervisor + +from template_langgraph.agents.chat_with_tools_agent.agent import graph as chat_with_tools_agent_graph +from template_langgraph.agents.issue_formatter_agent.agent import graph as issue_formatter_agent_graph +from template_langgraph.agents.task_decomposer_agent.agent import graph as task_decomposer_agent_graph +from template_langgraph.llms.azure_openais import AzureOpenAiWrapper +from template_langgraph.loggers import get_logger + +logger = get_logger(__name__) + +PROMPT = """ +KABUTO に関する質問に答えるために、必要な情報を収集し適切な回答を提供します。 +- 過去の FAQ やドキュメントを参照して、質問に対する答えを見つける必要がある場合は Chat with Tools Agent を使用します。 +- 質問の内容を整理し、適切な形式で回答するために Issue Formatter Agent を使用します。 +- 質問が複雑であったり追加の情報が必要な場合は、 Task Decomposer Agent を使用してタスクを分解し、順次処理します。 +- 質問が明確でない場合は、追加の情報を求めるための質問を行います。 +- 質問が単純な場合は、直接回答を提供します。 +""" + + +class SupervisorAgent: + def __init__(self): + self.agent = create_supervisor( + agents=[ + chat_with_tools_agent_graph, + issue_formatter_agent_graph, + task_decomposer_agent_graph, + ], + model=AzureOpenAiWrapper().chat_model, + prompt=PROMPT, + debug=True, + supervisor_name=SupervisorAgent.__name__, + ) + + +graph = SupervisorAgent().agent diff --git a/template_langgraph/agents/task_decomposer_agent/agent.py b/template_langgraph/agents/task_decomposer_agent/agent.py index 942d842..afcb960 100644 --- a/template_langgraph/agents/task_decomposer_agent/agent.py +++ b/template_langgraph/agents/task_decomposer_agent/agent.py @@ -32,7 +32,9 @@ def create_graph(self): "end": END, }, ) - return workflow.compile() + return workflow.compile( + name=TaskDecomposerAgent.__name__, + ) def chat(self, state: AgentState) -> AgentState: """Chat with tools using the state.""" diff --git a/uv.lock b/uv.lock index 655bc87..03ed925 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '3.14'", @@ -1797,6 +1797,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a5/03/a8ab0e8ea74be6058cb48bb1d85485b5c65d6ea183e3ee1aa8ca1ac73b3e/langgraph_sdk-0.2.0-py3-none-any.whl", hash = "sha256:150722264f225c4d47bbe7394676be102fdbf04c4400a0dd1bd41a70c6430cc7", size = 50569, upload-time = "2025-07-22T17:31:04.582Z" }, ] +[[package]] +name = "langgraph-supervisor" +version = "0.0.29" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "langchain-core" }, + { name = "langgraph" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/f0/fc8d5b5926caf3becfc75ff399c4b855daaff957f804973942457864ce94/langgraph_supervisor-0.0.29.tar.gz", hash = "sha256:0ab6e06e102096071d605268a4138084b87128f0c965e1544f77a7d4f65ca16b", size = 21095, upload-time = "2025-07-28T14:16:23.079Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/15/e3b4ad69b2a5fd6ba3d92bcca92b59ebd3a40f2a55751946728506ba618e/langgraph_supervisor-0.0.29-py3-none-any.whl", hash = "sha256:611dd4545f566f690d30004af3742887ec78134921118706ae7eeb12ce77763d", size = 16039, upload-time = "2025-07-28T14:16:22.259Z" }, +] + [[package]] name = "langsmith" version = "0.4.9" @@ -3655,6 +3668,7 @@ dependencies = [ { name = "langchain-openai" }, { name = "langchain-text-splitters" }, { name = "langgraph" }, + { name = "langgraph-supervisor" }, { name = "openai" }, { name = "pydantic-settings" }, { name = "pypdf" }, @@ -3685,6 +3699,7 @@ requires-dist = [ { name = "langchain-openai", specifier = ">=0.3.28" }, { name = "langchain-text-splitters", specifier = ">=0.3.9" }, { name = "langgraph", specifier = ">=0.6.2" }, + { name = "langgraph-supervisor", specifier = ">=0.0.29" }, { name = "openai", specifier = ">=1.98.0" }, { name = "pydantic-settings", specifier = ">=2.9.1" }, { name = "pypdf", specifier = ">=5.9.0" },