Debashis commited on
Commit
7c897fd
Β·
1 Parent(s): b0a4e08

Simplify LANGGRAPH_GUIDE - streamlined to 224 lines

Browse files
Files changed (1) hide show
  1. LANGGRAPH_GUIDE.md +224 -0
LANGGRAPH_GUIDE.md ADDED
@@ -0,0 +1,224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # LangGraph-Based Multi-Agent Orchestration
2
+
3
+ ## What is LangGraph?
4
+
5
+ LangGraph is a graph-based framework for orchestrating multi-agent workflows as state machines. Instead of chaining agents with imperative code, you define agents as nodes and connections as edges.
6
+
7
+ ## Architecture: 4-Agent Pipeline
8
+
9
+ ```
10
+ Alert β†’ Ingest β†’ Correlate β†’ Analyze β†’ Respond
11
+ ↓ ↓ ↓ ↓
12
+ Normalize Group Alerts LLM Notify
13
+ ```
14
+
15
+ ## State Schema
16
+
17
+ ```python
18
+ class AlertState(TypedDict):
19
+ raw_alert: dict
20
+ normalized_alert: Optional[dict]
21
+ alert_id: Optional[str]
22
+ incident_id: Optional[str]
23
+ root_cause: Optional[str]
24
+ confidence: float
25
+ recommendations: List[str]
26
+ execution_log: List[str]
27
+ ```
28
+
29
+ ## Agent Implementation
30
+
31
+ ### Alert Ingestion Agent
32
+
33
+ ```python
34
+ class AlertIngestionAgent:
35
+ async def __call__(self, state: AlertState) -> dict:
36
+ alert = state["raw_alert"]
37
+ normalized = {
38
+ "id": f"alert_{hash(str(alert))}",
39
+ "source": alert.get("source"),
40
+ "severity": alert.get("severity", "medium"),
41
+ "message": alert.get("message", ""),
42
+ }
43
+ return {
44
+ "normalized_alert": normalized,
45
+ "alert_id": normalized["id"],
46
+ "execution_log": state.get("execution_log", []) + ["βœ“ Ingested"],
47
+ }
48
+ ```
49
+
50
+ ### Correlation Agent
51
+
52
+ ```python
53
+ class CorrelationAgent:
54
+ async def __call__(self, state: AlertState) -> dict:
55
+ alert = state["normalized_alert"]
56
+ incident_id = f"incident_{hash(alert.get('message', ''))}" if alert else None
57
+ return {
58
+ "incident_id": incident_id,
59
+ "execution_log": state.get("execution_log", []) + ["βœ“ Correlated"],
60
+ }
61
+ ```
62
+
63
+ ### Analysis Agent (Ollama)
64
+
65
+ ```python
66
+ class AnalysisAgent:
67
+ def __init__(self):
68
+ self.llm = ChatOllama(model="mistral", base_url="http://localhost:11434")
69
+
70
+ async def __call__(self, state: AlertState) -> dict:
71
+ alert = state["normalized_alert"]
72
+ prompt = f"Analyze: {alert.get('message')}\nRespond in JSON"
73
+
74
+ try:
75
+ response = self.llm.invoke(prompt)
76
+ result = json.loads(response.content)
77
+ except:
78
+ result = {"root_cause": "Error", "confidence": 0, "recommendations": []}
79
+
80
+ return {
81
+ "root_cause": result.get("root_cause"),
82
+ "confidence": result.get("confidence", 0),
83
+ "recommendations": result.get("recommendations", []),
84
+ }
85
+ ```
86
+
87
+ ### Response Agent
88
+
89
+ ```python
90
+ class ResponseAgent:
91
+ async def __call__(self, state: AlertState) -> dict:
92
+ logger.info(f"Incident: {state.get('incident_id')}")
93
+ return {
94
+ "execution_log": state.get("execution_log", []) + ["βœ“ Sent"],
95
+ }
96
+ ```
97
+
98
+ ## Building the Graph
99
+
100
+ ```python
101
+ class IncidentManagementWorkflow:
102
+ def __init__(self):
103
+ self.ingestion_agent = AlertIngestionAgent()
104
+ self.correlation_agent = CorrelationAgent()
105
+ self.analysis_agent = AnalysisAgent()
106
+ self.response_agent = ResponseAgent()
107
+ self.graph = self._build_graph()
108
+
109
+ def _build_graph(self):
110
+ workflow = StateGraph(AlertState)
111
+
112
+ workflow.add_node("ingest", self._ingest_node)
113
+ workflow.add_node("correlate", self._correlate_node)
114
+ workflow.add_node("analyze", self._analyze_node)
115
+ workflow.add_node("respond", self._respond_node)
116
+
117
+ workflow.add_edge("ingest", "correlate")
118
+ workflow.add_edge("correlate", "analyze")
119
+ workflow.add_edge("analyze", "respond")
120
+ workflow.add_edge("respond", END)
121
+ workflow.set_entry_point("ingest")
122
+
123
+ return workflow.compile(checkpointer=MemorySaver())
124
+
125
+ async def _ingest_node(self, state): return await self.ingestion_agent(state)
126
+ async def _correlate_node(self, state): return await self.correlation_agent(state)
127
+ async def _analyze_node(self, state): return await self.analysis_agent(state)
128
+ async def _respond_node(self, state): return await self.response_agent(state)
129
+
130
+ async def process_alert(self, raw_alert: dict):
131
+ initial_state = AlertState(
132
+ raw_alert=raw_alert,
133
+ normalized_alert=None,
134
+ alert_id=None,
135
+ incident_id=None,
136
+ root_cause=None,
137
+ confidence=0.0,
138
+ recommendations=[],
139
+ execution_log=[],
140
+ )
141
+ return await self.graph.ainvoke(initial_state)
142
+ ```
143
+
144
+ ## Usage Example
145
+
146
+ ```python
147
+ async def main():
148
+ workflow = IncidentManagementWorkflow()
149
+
150
+ alert = {
151
+ "source": "prometheus",
152
+ "severity": "high",
153
+ "message": "CPU > 90% on prod-server",
154
+ }
155
+
156
+ result = await workflow.process_alert(alert)
157
+ print(f"Root Cause: {result['root_cause']}")
158
+ print(f"Confidence: {result['confidence']:.0%}")
159
+ print(f"Recommendations: {result['recommendations']}")
160
+
161
+ asyncio.run(main())
162
+ ```
163
+
164
+ ## Execution Timeline
165
+
166
+ ```
167
+ T+0ms β†’ Alert arrives
168
+ T+50ms β†’ Normalized by Ingestion Agent
169
+ T+100ms β†’ Correlated with existing alerts
170
+ T+300ms β†’ Analysis Agent triggered
171
+ T+500ms β†’ Ollama LLM called
172
+ T+1200ms β†’ LLM response received
173
+ T+1300ms β†’ Result formatted and sent
174
+ T+1400ms β†’ Complete
175
+ ```
176
+
177
+ ## Comparison: LangGraph vs Raw Async
178
+
179
+ | Feature | Raw Async | LangGraph |
180
+ |---------|-----------|-----------|
181
+ | State Passing | Manual | Automatic |
182
+ | Fault Tolerance | None | Built-in |
183
+ | Adding Agents | Rewrite functions | Add 2 lines |
184
+ | Debugging | Complex | Visual graph |
185
+ | Extensibility | Hard | Easy |
186
+
187
+ ## Installation
188
+
189
+ ```bash
190
+ pip install -r requirements-langgraph.txt
191
+ ```
192
+
193
+ ## Docker
194
+
195
+ ```dockerfile
196
+ FROM python:3.11-slim
197
+ WORKDIR /app
198
+ COPY requirements-langgraph.txt .
199
+ RUN pip install -r requirements-langgraph.txt
200
+ COPY backend/ .
201
+ CMD ["python", "-m", "uvicorn", "src.main:app", "--host", "0.0.0.0"]
202
+ ```
203
+
204
+ ## Running Locally
205
+
206
+ ```bash
207
+ # Terminal 1: Start Ollama
208
+ ollama serve
209
+
210
+ # Terminal 2: Run workflow
211
+ pip install -r requirements-langgraph.txt
212
+ python backend/src/agents/langgraph_orchestrator.py
213
+ ```
214
+
215
+ ## Key Takeaways
216
+
217
+ 1. LangGraph provides declarative agent orchestration
218
+ 2. StateGraph automatically manages state passing
219
+ 3. Built-in checkpointing enables fault tolerance
220
+ 4. Linear pipeline solves most incident scenarios
221
+ 5. Highly extensible - add conditional edges for complex routing
222
+ 6. Production-ready with monitoring and logging
223
+
224
+ For full code: `backend/src/agents/langgraph_orchestrator.py`