Spaces:
Sleeping
Sleeping
| from typing import TypedDict | |
| from src.config.llm import model | |
| from langgraph.prebuilt import create_react_agent | |
| from langgraph_swarm import create_handoff_tool | |
| from langchain_core.messages import RemoveMessage | |
| from .prompt import roleplay_prompt, guiding_prompt | |
| from .tools import create_end_conversation_tool | |
| from typing_extensions import TypedDict, Annotated | |
| from langchain_core.messages import AnyMessage | |
| from langgraph.graph import add_messages | |
| from loguru import logger | |
| class State(TypedDict): | |
| active_agent: str | None | |
| messages: Annotated[list[AnyMessage], add_messages] | |
| scenario_title: str | |
| scenario_description: str | |
| scenario_context: str | |
| your_role: str | |
| key_vocabulary: str | |
| def trim_history(state: State): | |
| if not state.get("active_agent"): | |
| state["active_agent"] = "Roleplay Agent" | |
| history = state.get("messages", []) | |
| if len(history) > 25: | |
| num_to_remove = len(history) - 5 | |
| remove_messages = [ | |
| RemoveMessage(id=history[i].id) for i in range(num_to_remove) | |
| ] | |
| state["messages"] = remove_messages | |
| return state | |
| async def call_roleplay(state: State): | |
| logger.info("Calling roleplay agent...") | |
| roleplay_agent = create_react_agent( | |
| model, | |
| [ | |
| create_handoff_tool( | |
| agent_name="Guiding Agent", | |
| description="Hand off to Guiding Agent when user shows signs of needing help, guidance, or struggles with communication", | |
| ), | |
| create_end_conversation_tool(), | |
| ], | |
| prompt=roleplay_prompt.format( | |
| scenario_title=state["scenario_title"], | |
| scenario_description=state["scenario_description"], | |
| scenario_context=state["scenario_context"], | |
| your_role=state["your_role"], | |
| key_vocabulary=state["key_vocabulary"], | |
| ), | |
| name="Roleplay Agent", | |
| ) | |
| response = await roleplay_agent.ainvoke({"messages": state["messages"]}) | |
| return {"messages": response["messages"]} | |
| async def call_guiding_agent(state: State): | |
| logger.info("Calling guiding agent...") | |
| guiding_agent = create_react_agent( | |
| model, | |
| [ | |
| create_handoff_tool( | |
| agent_name="Roleplay Agent", | |
| description="Hand off back to Roleplay Agent when user is ready for scenario practice and shows improved confidence", | |
| ), | |
| create_end_conversation_tool(), | |
| ], | |
| prompt=guiding_prompt.format( | |
| scenario_title=state["scenario_title"], | |
| scenario_description=state["scenario_description"], | |
| scenario_context=state["scenario_context"], | |
| your_role=state["your_role"], | |
| key_vocabulary=state["key_vocabulary"], | |
| ), | |
| name="Guiding Agent", | |
| ) | |
| response = await guiding_agent.ainvoke({"messages": state["messages"]}) | |
| return {"messages": response["messages"]} | |
| def route_to_active_agent(state: State) -> str: | |
| if state["active_agent"] == "Roleplay Agent": | |
| return "Roleplay Agent" | |
| elif state["active_agent"] == "Guiding Agent": | |
| return "Guiding Agent" | |