adilpanwar's picture
Upload 16 files
927c050 verified
Raw
History Blame Contribute Delete
4.32 kB
"""Graph builder module. Assembles the complete multi-agent LangGraph workflow."""
import logging
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode, create_react_agent
from langgraph.checkpoint.memory import MemorySaver
from langgraph.store.memory import InMemoryStore
from src.state import State
from src.tools import music_tools, invoice_tools
from src.agents.prompts import INVOICE_SUBAGENT_PROMPT, SUPERVISOR_PROMPT
from src.agents.nodes import (
create_music_assistant_node,
should_continue,
should_interrupt,
create_verify_info_node,
human_input,
load_memory,
create_memory_node,
)
logger = logging.getLogger(__name__)
def build_graph(
model_name: str = "gpt-4o-mini",
temperature: float = 0,
openai_api_key: str = None,
openai_api_base: str = None,
):
llm_kwargs = {
"model": model_name,
"temperature": temperature,
}
if openai_api_key:
llm_kwargs["api_key"] = openai_api_key
if openai_api_base:
llm_kwargs["base_url"] = openai_api_base
llm = ChatOpenAI(**llm_kwargs)
logger.info(f"LLM initialized: {model_name}, temperature={temperature}")
# NOTE: Both stores are in-memory only — all data is lost on restart.
# For production, replace with SqliteSaver / persistent store.
in_memory_store = InMemoryStore()
checkpointer = MemorySaver()
# Music Catalog Sub-Agent (hand-built ReAct)
music_assistant_fn = create_music_assistant_node(llm, music_tools)
music_tool_node = ToolNode(music_tools)
music_workflow = StateGraph(State)
music_workflow.add_node("music_assistant", music_assistant_fn)
music_workflow.add_node("music_tool_node", music_tool_node)
music_workflow.add_edge(START, "music_assistant")
music_workflow.add_conditional_edges(
"music_assistant",
should_continue,
{"continue": "music_tool_node", "end": END},
)
music_workflow.add_edge("music_tool_node", "music_assistant")
music_catalog_subagent = music_workflow.compile(
name="music_catalog_subagent",
checkpointer=checkpointer,
store=in_memory_store,
)
logger.info("Music catalog sub-agent compiled.")
# Invoice Information Sub-Agent (pre-built ReAct)
invoice_information_subagent = create_react_agent(
llm,
tools=invoice_tools,
name="invoice_information_subagent",
prompt=INVOICE_SUBAGENT_PROMPT,
state_schema=State,
checkpointer=checkpointer,
store=in_memory_store,
)
logger.info("Invoice information sub-agent compiled.")
# Supervisor
from langgraph_supervisor import create_supervisor
supervisor_workflow = create_supervisor(
agents=[invoice_information_subagent, music_catalog_subagent],
output_mode="last_message",
model=llm,
prompt=SUPERVISOR_PROMPT,
state_schema=State,
)
supervisor_prebuilt = supervisor_workflow.compile(
name="supervisor",
checkpointer=checkpointer,
store=in_memory_store,
)
logger.info("Supervisor compiled.")
# Final Multi-Agent Graph
verify_info_fn = create_verify_info_node(llm)
create_memory_fn = create_memory_node(llm)
multi_agent = StateGraph(State)
multi_agent.add_node("verify_info", verify_info_fn)
multi_agent.add_node("human_input", human_input)
multi_agent.add_node("load_memory", load_memory)
multi_agent.add_node("supervisor", supervisor_prebuilt)
multi_agent.add_node("create_memory", create_memory_fn)
multi_agent.add_edge(START, "verify_info")
multi_agent.add_conditional_edges(
"verify_info",
should_interrupt,
{"continue": "load_memory", "interrupt": "human_input"},
)
multi_agent.add_edge("human_input", "verify_info")
multi_agent.add_edge("load_memory", "supervisor")
multi_agent.add_edge("supervisor", "create_memory")
multi_agent.add_edge("create_memory", END)
compiled_graph = multi_agent.compile(
name="multi_agent_final",
checkpointer=checkpointer,
store=in_memory_store,
)
logger.info("Final multi-agent graph compiled successfully.")
return compiled_graph, checkpointer, in_memory_store