llumo 0.2.28__py3-none-any.whl → 0.2.30__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
llumo/callback.py CHANGED
@@ -11,11 +11,12 @@ import re
11
11
 
12
12
 
13
13
  class LlumoCallbackHandler(BaseCallbackHandler):
14
- def __init__(self, session: LlumoSessionContext = None):
14
+ def __init__(self, session: LlumoSessionContext = None,agentType = "react_agent"):
15
15
  if session is None:
16
16
  raise ValueError("LlumoSessionContext is required")
17
17
 
18
18
  self.sessionLogger = session
19
+ self.agentType = agentType
19
20
 
20
21
  # Initialize timing and state variables
21
22
  self.llmStartTime = None
@@ -26,6 +27,7 @@ class LlumoCallbackHandler(BaseCallbackHandler):
26
27
 
27
28
  # Initialize tracking variables
28
29
  self.prompt = ""
30
+ self.searchQuery = ""
29
31
  self.currentToolName = None
30
32
  self.currentToolInput = None
31
33
  self.currentAgentName = None
@@ -45,8 +47,14 @@ class LlumoCallbackHandler(BaseCallbackHandler):
45
47
  self.currentObservation = ""
46
48
  self.isAgentExecution = False
47
49
 
50
+
51
+
48
52
  def on_chain_start(self, serialized: Dict[str, Any], inputs: Dict[str, Any], **kwargs: Any) -> None:
49
53
  """Called when a chain starts - this includes agent execution"""
54
+ # print("ON CHAIN START: ",inputs)
55
+ # print("ON CHAIN START: serialized",serialized)
56
+ # print("ON CHAIN START: kwargs",kwargs)
57
+
50
58
  try:
51
59
  self.prompt = inputs.get("input", "")
52
60
  self.chainStartTime = time.time()
@@ -62,6 +70,7 @@ class LlumoCallbackHandler(BaseCallbackHandler):
62
70
  self.currentToolInput = None
63
71
  self.hasErrors = False
64
72
  self.lastError = None
73
+ self.toolDescription = {}
65
74
 
66
75
  # Dynamically detect agent name from serialized data
67
76
  if serialized is not None:
@@ -91,6 +100,26 @@ class LlumoCallbackHandler(BaseCallbackHandler):
91
100
  except Exception as e:
92
101
  print(f"[ERROR] in on_chain_start: {e}")
93
102
 
103
+ try:
104
+ self.sessionLogger.logQueryStep(
105
+ stepName = "Query Invocation",
106
+ model = "unknown",
107
+ provider = "unknown",
108
+ inputTokens = round(len(self.prompt.split()) * 1.5),
109
+ query = self.prompt,
110
+ status = "SUCCESS"
111
+ )
112
+ except Exception as e:
113
+ self.sessionLogger.logQueryStep(
114
+ stepName="Query Invocation",
115
+ model="unknown",
116
+ provider="unknown",
117
+ inputTokens=0,
118
+ query="",
119
+ status="FAILURE"
120
+ )
121
+ print(f"[ERROR] Failed to log user input: {e}")
122
+
94
123
  def on_chain_end(self, outputs: Dict[str, Any], **kwargs: Any) -> None:
95
124
  """Called when a chain ends"""
96
125
  try:
@@ -98,15 +127,16 @@ class LlumoCallbackHandler(BaseCallbackHandler):
98
127
  # Use logAgentStep for final completion
99
128
  self.sessionLogger.logAgentStep(
100
129
  stepName="Agent Execution Completed",
101
- agentType="react_agent",
130
+ agentType=self.agentType,
102
131
  agentName=self.currentAgentName or "unknown",
103
132
  numStepsTaken=self.agentsSteps,
104
133
  tools=self.toolsUsed,
105
134
  query=self.prompt,
106
135
  status="SUCCESS",
107
- message=f"Final output: {outputs['output']}. ReAct steps: {json.dumps(self.reactSteps)}",
136
+ # message=f"Final output: {outputs['output']}. ReAct steps: {json.dumps(self.reactSteps)}",
108
137
  )
109
138
 
139
+
110
140
  # Reset execution state after chain ends
111
141
  self.isAgentExecution = False
112
142
 
@@ -118,6 +148,14 @@ class LlumoCallbackHandler(BaseCallbackHandler):
118
148
  self.llmStartTime = time.time()
119
149
  self.stepTime = time.time()
120
150
 
151
+ if self.prompt == "":
152
+ match = re.search(r"Human:\s*(.*)",prompts[0], re.DOTALL)
153
+ if match:
154
+ user_question = match.group(1).strip()
155
+ self.prompt = user_question # 👉 What is LangChain?
156
+ else:
157
+ self.prompt = ""
158
+
121
159
  # Dynamically get model info
122
160
  model = "unknown"
123
161
  if serialized and "kwargs" in serialized:
@@ -204,7 +242,6 @@ class LlumoCallbackHandler(BaseCallbackHandler):
204
242
  # Parse ReAct reasoning from LLM output if we're in agent execution
205
243
  if self.isAgentExecution and output:
206
244
  self._parse_react_reasoning(output)
207
-
208
245
  try:
209
246
  self.sessionLogger.logLlmStep(
210
247
  stepName="LLM Call Completed",
@@ -212,17 +249,62 @@ class LlumoCallbackHandler(BaseCallbackHandler):
212
249
  provider=self.llmProvider,
213
250
  inputTokens=int(input_tokens),
214
251
  outputTokens=int(output_tokens),
215
- temperature=float(kwargs.get("temperature", 0.7)),
216
- promptTruncated=False,
252
+ # temperature=float(kwargs.get("temperature", 0.7)),
253
+ # promptTruncated=False,
217
254
  latencyMs=duration_ms,
218
- query=str(self.prompt),
255
+ prompt=str(self.prompt),
219
256
  output=output,
220
257
  status=status,
221
- message=error_message if status == "ERROR" else "",
258
+ # message=error_message if status == "ERROR" else "",
222
259
  )
260
+
223
261
  except Exception as e:
224
262
  print(f"[ERROR] Failed to log LLM end: {e}")
225
263
 
264
+ def on_retriever_start(self, serialized, query, run_id, parent_run_id=None, **kwargs):
265
+ self.prompt = query
266
+ self.searchQuery = query
267
+
268
+ def on_retriever_end(self, documents, run_id, parent_run_id=None, **kwargs):
269
+
270
+ try:
271
+ chunkSize = len(documents[0].page_content) if documents and documents[0].page_content else 0
272
+ except Exception:
273
+ chunkSize = 0
274
+
275
+ source = ( kwargs.get("metadata", {}).get("source") or kwargs.get("tags") or "unknown")
276
+
277
+ try:
278
+ self.sessionLogger.logRetrieverStep(
279
+ stepName="Context Retrieval Complete",
280
+ retrieverSource = str(source),
281
+ topK = len(documents),
282
+ chunkSize = chunkSize,
283
+ context = [doc.page_content for doc in documents],
284
+ searchQuery = self.prompt if self.prompt != "" else self.searchQuery,
285
+ latencyMs = 120, # mock latency, replace with real timing if needed
286
+ status = "SUCCESS"
287
+ )
288
+ except Exception as e:
289
+ print(f"[ERROR] Failed to log chain output: {e}")
290
+
291
+ def on_retriever_error(self, error, run_id, parent_run_id=None, **kwargs):
292
+
293
+ try:
294
+ self.sessionLogger.logRetrieverStep(
295
+ stepName="Context Retrieval Error",
296
+ retrieverSource = kwargs.get("metadata", {}).get("source", "unknown"),
297
+ topK = 0,
298
+ chunkSize = 0,
299
+ context = [],
300
+ searchQuery = self.prompt if self.prompt != "" else self.searchQuery,
301
+ latencyMs = 0, # mock latency, replace with real timing if needed
302
+ status = "FAILURE"
303
+ )
304
+ except Exception as e:
305
+ print(f"[ERROR] Failed to log chain output: {e}")
306
+
307
+
226
308
  def _parse_react_reasoning(self, llm_output: str):
227
309
  """Parse ReAct reasoning pattern from LLM output"""
228
310
  try:
@@ -265,6 +347,9 @@ class LlumoCallbackHandler(BaseCallbackHandler):
265
347
 
266
348
  def on_tool_start(self, serialized: Dict[str, Any], input_str: str, **kwargs: Any) -> None:
267
349
  """Called when a tool starts executing"""
350
+ # print("ON TOOL START: ",serialized)
351
+ # print("ON TOOL START: ",kwargs)
352
+
268
353
  self.toolStartTime = time.time()
269
354
  self.stepTime = time.time()
270
355
 
@@ -272,6 +357,7 @@ class LlumoCallbackHandler(BaseCallbackHandler):
272
357
  self.currentToolName = (serialized.get("name") or
273
358
  serialized.get("_type") or
274
359
  "unknown")
360
+ self.currentToolDescription = serialized.get("description","No description found")
275
361
 
276
362
  # Handle the case where input_str is "None" or None
277
363
  if input_str == "None" or input_str is None:
@@ -316,13 +402,13 @@ class LlumoCallbackHandler(BaseCallbackHandler):
316
402
  self.sessionLogger.logToolStep(
317
403
  stepName="Tool Execution Completed",
318
404
  toolName=self.currentToolName or "unknown",
405
+ description = self.currentToolDescription,
319
406
  input=self.currentToolInput or {"input": ""},
320
407
  output=output_str,
321
408
  latencyMs=duration_ms,
322
409
  status="SUCCESS",
323
- message="",
410
+ # message="",
324
411
  )
325
-
326
412
  print(f"[DEBUG] Tool completed: {self.currentToolName} -> {output_str}")
327
413
 
328
414
  except Exception as e:
@@ -331,7 +417,7 @@ class LlumoCallbackHandler(BaseCallbackHandler):
331
417
  def on_agent_action(self, action: AgentAction, **kwargs: Any) -> None:
332
418
  """Called when an agent takes an action"""
333
419
  self.agentsSteps += 1
334
- print("ON AGENT ACTION: ", action)
420
+ # print("ON AGENT ACTION: ", action)
335
421
 
336
422
  try:
337
423
  # Dynamically extract information from action
@@ -352,52 +438,54 @@ class LlumoCallbackHandler(BaseCallbackHandler):
352
438
  })
353
439
 
354
440
  # Log the agent action step using logAgentStep
355
- current_status = "ERROR" if self.hasErrors else "SUCCESS"
441
+ current_status = "FAILURE" if self.hasErrors else "SUCCESS"
356
442
  reasoning_text = self.currentThought if self.currentThought else "No reasoning captured"
357
443
 
358
444
  self.sessionLogger.logAgentStep(
359
445
  stepName=f"Agent Action Step {self.agentsSteps}",
360
- agentType="react_agent",
446
+ agentType=self.agentType,
361
447
  agentName=self.currentAgentName or "unknown",
362
448
  numStepsTaken=self.agentsSteps,
363
449
  tools=[tool_name],
364
450
  query=self.prompt,
365
451
  status=current_status,
366
- message=f"Executing {tool_name} with input: {tool_input}. Reasoning: {reasoning_text}",
452
+ # message=f"Executing {tool_name} with input: {tool_input}. Reasoning: {reasoning_text}",
367
453
  )
368
454
 
455
+
456
+
369
457
  except Exception as e:
370
458
  print(f"[ERROR] Failed to log agent action: {e}")
371
459
 
372
460
  def on_agent_finish(self, finish: AgentFinish, **kwargs: Any) -> None:
373
461
  """Called when an agent completes execution"""
374
- print("ON AGENT FINISH:", finish)
462
+ # print("ON AGENT FINISH:", finish)
375
463
  # We don't need to log anything here since the final result is already logged in on_chain_end
376
464
  pass
377
465
 
378
466
  def on_agent_error(self, error: Exception, **kwargs: Any) -> None:
379
467
  """Called when an agent encounters an error"""
380
- print("ITS A AGENT ERROR:", error)
468
+ # print("ITS A AGENT ERROR:", error)
381
469
  self.hasErrors = True
382
470
  self.lastError = str(error)
383
471
 
384
472
  try:
385
473
  self.sessionLogger.logAgentStep(
386
474
  stepName="Agent Execution Error",
387
- agentType="react_agent",
475
+ agentType=self.agentType,
388
476
  agentName=self.currentAgentName or "unknown",
389
477
  numStepsTaken=self.agentsSteps,
390
478
  tools=self.toolsUsed,
391
479
  query=self.prompt,
392
- status="ERROR",
393
- message=str(error),
480
+ status="FAILURE",
481
+ # message=str(error),
394
482
  )
395
483
  except Exception as e:
396
484
  print(f"[ERROR] Failed to log agent error: {e}")
397
485
 
398
486
  def on_tool_error(self, error: Exception, **kwargs: Any) -> None:
399
487
  """Called when a tool encounters an error"""
400
- print("ITS A TOOL ERROR:", error)
488
+
401
489
  self.hasErrors = True
402
490
  self.lastError = str(error)
403
491
 
@@ -410,18 +498,19 @@ class LlumoCallbackHandler(BaseCallbackHandler):
410
498
  self.sessionLogger.logToolStep(
411
499
  stepName="Tool Execution Failed",
412
500
  toolName=self.currentToolName or "unknown",
501
+ description=self.currentToolDescription,
413
502
  input=self.currentToolInput or {"input": ""},
414
503
  output="",
415
504
  latencyMs=0,
416
- status="ERROR",
417
- message=str(error),
505
+ status="FAILURE",
506
+ # message=str(error),
418
507
  )
419
508
  except Exception as e:
420
509
  print(f"[ERROR] Failed to log tool error: {e}")
421
510
 
422
511
  def on_chain_error(self, error: Exception, **kwargs: Any) -> None:
423
512
  """Called when a chain encounters an error"""
424
- print("ITS A CHAIN ERROR:", error)
513
+ # print("ITS A CHAIN ERROR:", error)
425
514
  self.hasErrors = True
426
515
  self.lastError = str(error)
427
516
 
@@ -430,14 +519,17 @@ class LlumoCallbackHandler(BaseCallbackHandler):
430
519
  # Use logAgentStep for agent-related chain errors
431
520
  self.sessionLogger.logAgentStep(
432
521
  stepName="Agent Chain Error",
433
- agentType="react_agent",
522
+ agentType=self.agentType,
434
523
  agentName=self.currentAgentName or "unknown",
435
524
  numStepsTaken=self.agentsSteps,
436
525
  tools=self.toolsUsed,
437
526
  query=self.prompt,
438
- status="ERROR",
439
- message=str(error),
527
+ status="FAILURE",
528
+ # message=str(error),
440
529
  )
530
+
531
+
532
+
441
533
  else:
442
534
  # Use logLlmStep for general chain errors
443
535
  self.sessionLogger.logLlmStep(
@@ -446,13 +538,13 @@ class LlumoCallbackHandler(BaseCallbackHandler):
446
538
  provider=self.llmProvider,
447
539
  inputTokens=0,
448
540
  outputTokens=0,
449
- temperature=0.0,
450
- promptTruncated=False,
541
+ # temperature=0.0,
542
+ # promptTruncated=False,
451
543
  latencyMs=0,
452
- query=self.prompt,
544
+ prompt=self.prompt,
453
545
  output="",
454
- status="ERROR",
455
- message=str(error),
546
+ status="FAILURE",
547
+ # message=str(error),
456
548
  )
457
549
  except Exception as e:
458
550
  print(f"[ERROR] Failed to log chain error: {e}")