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 +123 -31
- llumo/client.py +213 -228
- llumo/google.py +16 -16
- llumo/helpingFuntions.py +2 -2
- llumo/llumoSessionContext.py +91 -29
- llumo/openai.py +148 -136
- {llumo-0.2.28.dist-info → llumo-0.2.30.dist-info}/METADATA +1 -1
- llumo-0.2.30.dist-info/RECORD +20 -0
- llumo-0.2.28.dist-info/RECORD +0 -20
- {llumo-0.2.28.dist-info → llumo-0.2.30.dist-info}/WHEEL +0 -0
- {llumo-0.2.28.dist-info → llumo-0.2.30.dist-info}/licenses/LICENSE +0 -0
- {llumo-0.2.28.dist-info → llumo-0.2.30.dist-info}/top_level.txt +0 -0
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=
|
|
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
|
-
|
|
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 = "
|
|
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=
|
|
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=
|
|
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="
|
|
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
|
-
|
|
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="
|
|
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=
|
|
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="
|
|
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
|
-
|
|
544
|
+
prompt=self.prompt,
|
|
453
545
|
output="",
|
|
454
|
-
status="
|
|
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}")
|