Spaces:
Runtime error
Runtime error
Update utils/langgraph_pipeline.py
Browse files- utils/langgraph_pipeline.py +34 -42
utils/langgraph_pipeline.py
CHANGED
@@ -9,11 +9,12 @@ from agents import (
|
|
9 |
)
|
10 |
from langchain_core.messages import HumanMessage, AIMessage
|
11 |
from langchain_core.messages.base import BaseMessage
|
12 |
-
from langchain_core.tools import StructuredTool
|
13 |
from typing import TypedDict, List
|
14 |
|
15 |
|
16 |
-
#
|
|
|
|
|
17 |
class InputState(TypedDict):
|
18 |
messages: List[BaseMessage]
|
19 |
chat_log: list
|
@@ -28,53 +29,43 @@ class OutputState(TypedDict):
|
|
28 |
chat_log: list
|
29 |
|
30 |
|
31 |
-
#
|
32 |
-
# Bridge Node
|
33 |
-
#
|
34 |
-
def
|
35 |
-
"""
|
36 |
-
|
37 |
-
""
|
38 |
-
if "messages" not in state or not isinstance(state["messages"], list):
|
39 |
-
raise ValueError("Input must contain a 'messages' list.")
|
40 |
|
41 |
-
|
42 |
-
|
43 |
-
raise ValueError("Last message must be a HumanMessage.")
|
44 |
|
45 |
-
|
46 |
-
|
|
|
47 |
|
48 |
A new product request has been submitted:
|
49 |
|
50 |
-
"{
|
51 |
|
52 |
-
Please
|
53 |
- Goals
|
54 |
- Features
|
55 |
-
- User
|
56 |
- KPIs
|
57 |
"""
|
58 |
|
|
|
|
|
59 |
return {
|
60 |
-
"messages":
|
61 |
-
"chat_log":
|
62 |
}
|
63 |
|
64 |
|
65 |
-
#
|
66 |
-
|
67 |
-
|
68 |
-
name="bridge_to_product_manager",
|
69 |
-
description="Converts HumanMessage into structured system prompt for Product Manager."
|
70 |
-
)
|
71 |
-
|
72 |
-
bridge_node = ToolNode([bridge_tool])
|
73 |
-
|
74 |
-
|
75 |
-
# -----------------------------
|
76 |
-
# Define Other Agent ToolNodes
|
77 |
-
# -----------------------------
|
78 |
pm_node = ToolNode([product_manager_agent.run])
|
79 |
proj_node = ToolNode([project_manager_agent.run])
|
80 |
arch_node = ToolNode([software_architect_agent.run])
|
@@ -82,12 +73,14 @@ dev_node = ToolNode([software_engineer_agent.run])
|
|
82 |
qa_node = ToolNode([quality_assurance_agent.run])
|
83 |
|
84 |
|
85 |
-
#
|
86 |
-
#
|
87 |
-
#
|
88 |
graph = StateGraph(input=InputState, output=OutputState)
|
89 |
|
90 |
-
|
|
|
|
|
91 |
graph.add_node("ProductManager", pm_node)
|
92 |
graph.add_node("ProjectManager", proj_node)
|
93 |
graph.add_node("SoftwareArchitect", arch_node)
|
@@ -105,9 +98,9 @@ graph.add_edge("QualityAssurance", END)
|
|
105 |
compiled_graph = graph.compile()
|
106 |
|
107 |
|
108 |
-
#
|
109 |
-
#
|
110 |
-
#
|
111 |
def run_pipeline_and_save(prompt: str):
|
112 |
initial_state = {
|
113 |
"messages": [HumanMessage(content=prompt)],
|
@@ -115,5 +108,4 @@ def run_pipeline_and_save(prompt: str):
|
|
115 |
}
|
116 |
|
117 |
final_state = compiled_graph.invoke(initial_state)
|
118 |
-
|
119 |
return final_state["chat_log"], final_state["qa_output"]
|
|
|
9 |
)
|
10 |
from langchain_core.messages import HumanMessage, AIMessage
|
11 |
from langchain_core.messages.base import BaseMessage
|
|
|
12 |
from typing import TypedDict, List
|
13 |
|
14 |
|
15 |
+
# --------------------------
|
16 |
+
# State Definitions
|
17 |
+
# --------------------------
|
18 |
class InputState(TypedDict):
|
19 |
messages: List[BaseMessage]
|
20 |
chat_log: list
|
|
|
29 |
chat_log: list
|
30 |
|
31 |
|
32 |
+
# --------------------------
|
33 |
+
# Correctly Implemented Bridge Node
|
34 |
+
# --------------------------
|
35 |
+
def bridge_to_product_manager(state: dict) -> dict:
|
36 |
+
"""Ensure AIMessage is added after HumanMessage."""
|
37 |
+
messages = state.get("messages", [])
|
38 |
+
chat_log = state.get("chat_log", [])
|
|
|
|
|
39 |
|
40 |
+
if not messages or not isinstance(messages[-1], HumanMessage):
|
41 |
+
raise ValueError("Expected last message to be a HumanMessage")
|
|
|
42 |
|
43 |
+
prompt = messages[-1].content
|
44 |
+
|
45 |
+
structured = f"""# Stakeholder Prompt
|
46 |
|
47 |
A new product request has been submitted:
|
48 |
|
49 |
+
"{prompt}"
|
50 |
|
51 |
+
Please convert it into a structured product specification including:
|
52 |
- Goals
|
53 |
- Features
|
54 |
+
- User Stories
|
55 |
- KPIs
|
56 |
"""
|
57 |
|
58 |
+
ai_msg = AIMessage(content=structured)
|
59 |
+
|
60 |
return {
|
61 |
+
"messages": messages + [ai_msg],
|
62 |
+
"chat_log": chat_log + [{"role": "System", "content": structured}],
|
63 |
}
|
64 |
|
65 |
|
66 |
+
# --------------------------
|
67 |
+
# ToolNodes for All Agents
|
68 |
+
# --------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
pm_node = ToolNode([product_manager_agent.run])
|
70 |
proj_node = ToolNode([project_manager_agent.run])
|
71 |
arch_node = ToolNode([software_architect_agent.run])
|
|
|
73 |
qa_node = ToolNode([quality_assurance_agent.run])
|
74 |
|
75 |
|
76 |
+
# --------------------------
|
77 |
+
# Graph Definition
|
78 |
+
# --------------------------
|
79 |
graph = StateGraph(input=InputState, output=OutputState)
|
80 |
|
81 |
+
# ✅ Native function for bridge node (no ToolNode needed)
|
82 |
+
graph.add_node("Bridge", bridge_to_product_manager)
|
83 |
+
|
84 |
graph.add_node("ProductManager", pm_node)
|
85 |
graph.add_node("ProjectManager", proj_node)
|
86 |
graph.add_node("SoftwareArchitect", arch_node)
|
|
|
98 |
compiled_graph = graph.compile()
|
99 |
|
100 |
|
101 |
+
# --------------------------
|
102 |
+
# Pipeline Entry Function
|
103 |
+
# --------------------------
|
104 |
def run_pipeline_and_save(prompt: str):
|
105 |
initial_state = {
|
106 |
"messages": [HumanMessage(content=prompt)],
|
|
|
108 |
}
|
109 |
|
110 |
final_state = compiled_graph.invoke(initial_state)
|
|
|
111 |
return final_state["chat_log"], final_state["qa_output"]
|