llumo 0.2.12__py3-none-any.whl → 0.2.13__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/client.py CHANGED
@@ -30,6 +30,7 @@ class LlumoClient:
30
30
  self.apiKey = api_key
31
31
  self.socket = LlumoSocketClient(socketUrl)
32
32
  self.processMapping = {}
33
+ self.definationMapping = {}
33
34
 
34
35
  def validateApiKey(self, evalName=" "):
35
36
  headers = {
@@ -87,6 +88,8 @@ class LlumoClient:
87
88
  self.trialEndDate = data["data"]["data"].get("trialEndDate", None)
88
89
  self.subscriptionEndDate = data["data"]["data"].get("subscriptionEndDate", None)
89
90
  self.email = data["data"]["data"].get("email", None)
91
+
92
+ self.definationMapping[evalName] = self.evalDefinition
90
93
 
91
94
  except Exception as e:
92
95
  # print(f"Error extracting data from response: {str(e)}")
@@ -315,6 +318,7 @@ class LlumoClient:
315
318
 
316
319
  for cnt, batch in enumerate(self.allBatches):
317
320
  try:
321
+
318
322
  self.postBatch(batch=batch, workspaceID=workspaceID)
319
323
  # print("Betch Posted with item len: ", len(batch))
320
324
  except Exception as e:
@@ -363,9 +367,9 @@ class LlumoClient:
363
367
  pd.set_option("future.no_silent_downcasting", True)
364
368
  df = dataframe.fillna("Some error occured").astype(object)
365
369
 
366
- if createPlayground(email, workspaceID, df):
370
+ if createPlayground(email, workspaceID, df,promptText=prompt_template,definationMapping=self.definationMapping,outputColName=outputColName):
367
371
  print(
368
- "Your data has been saved in the Llumo Experiment. Visit https://app.llumo.ai/evallm to see the results."
372
+ "Your data has been saved in the Llumo Experiment. Visit https://app.llumo.ai/evallm to see the results.Please rerun the experiment to see the results on playground."
369
373
  )
370
374
  else:
371
375
  return dataframe
@@ -387,9 +391,9 @@ class LlumoClient:
387
391
  pd.set_option("future.no_silent_downcasting", True)
388
392
  df = resultdf.fillna("Some error occured").astype(object)
389
393
 
390
- if createPlayground(self.email, self.workspaceID, df):
394
+ if createPlayground(self.email, self.workspaceID, df,definationMapping=self.definationMapping,outputColName=outputColName,promptText=prompt_template):
391
395
  print(
392
- "Your data has been saved in the Llumo Experiment. Visit https://app.llumo.ai/evallm to see the results."
396
+ "Your data has been saved in the Llumo Experiment. Visit https://app.llumo.ai/evallm to see the results.Please rerun the experiment to see the results on playground."
393
397
  )
394
398
  else:
395
399
  return resultdf
@@ -546,21 +550,22 @@ class LlumoClient:
546
550
  # dataframe["cost_saving"] = cost_saving
547
551
 
548
552
  return dataframe
549
-
550
553
  def run_sweep(
551
- self,
552
- templates: List[str],
553
- dataset: Dict[str, List[str]],
554
- model_aliases: List[AVAILABLEMODELS],
555
- apiKey: str,
556
- eval=["Response Correctness"],
557
- toEvaluate: bool = False,
558
- createExperiment: bool = False,
559
- ) -> pd.DataFrame:
554
+ self,
555
+ templates: List[str],
556
+ dataset: Dict[str, List[str]],
557
+ model_aliases: List[AVAILABLEMODELS],
558
+ apiKey: str,
559
+ eval=["Response Correctness"],
560
+ toEvaluate: bool = False,
561
+ createExperiment: bool = False,
562
+ ) -> pd.DataFrame:
563
+
560
564
  try:
561
565
  self.validateApiKey()
562
566
  except Exception as e:
563
- raise "Some error ocuured please check your API key"
567
+ raise Exception("Some error occurred, please check your API key")
568
+
564
569
  workspaceID = self.workspaceID
565
570
  email = self.email
566
571
  executor = ModelExecutor(apiKey)
@@ -570,57 +575,80 @@ class LlumoClient:
570
575
 
571
576
  results = []
572
577
 
573
- # Iterate through combinations
574
578
  for combo in combinations:
575
579
  for template in templates:
576
580
  prompt = template
577
581
  for k, v in combo.items():
578
582
  prompt = prompt.replace(f"{{{{{k}}}}}", v)
579
- # Add a row for each model
580
- for model in model_aliases:
581
- row = {
582
- "template": template,
583
- "prompt": prompt,
584
- **combo,
585
- "model": model.value,
586
- }
587
583
 
584
+ row = {
585
+ "prompt": prompt,
586
+ **combo,
587
+ }
588
+
589
+ for i, model in enumerate(model_aliases, 1):
588
590
  try:
589
591
  provider = getProviderFromModel(model)
590
- response = executor.execute(
591
- provider, model.value, prompt, apiKey
592
- )
593
- row["output"] = response
592
+ response = executor.execute(provider, model.value, prompt, apiKey)
593
+ outputKey = f"output_{i}"
594
+ row[outputKey] = response
594
595
  except Exception as e:
595
- row["output"] = f"Error: {str(e)}"
596
+ row[f"output_{i}"] = str(e)
596
597
 
597
- results.append(row)
598
+ results.append(row)
599
+
600
+
601
+
598
602
  df = pd.DataFrame(results)
599
- if toEvaluate:
600
603
 
601
- res = self.evaluateMultiple(df, eval=eval, prompt_template=str(templates[0]))
604
+
605
+ if toEvaluate==True:
606
+ dfWithEvals = df.copy()
607
+ for i, model in enumerate(model_aliases,1):
608
+ outputColName = f"output_{i}"
609
+ try:
610
+ res = self.evaluateMultiple(
611
+ df,
612
+ eval=eval,
613
+ prompt_template=str(templates[0]),
614
+ outputColName=outputColName,
615
+ )
616
+
617
+ # Rename all new columns with _i+1 (e.g., _1, _2)
618
+ for evalMetric in eval:
619
+ scoreCol = f"{evalMetric}"
620
+ reasonCol = f"{evalMetric} Reason"
621
+ if scoreCol in res.columns:
622
+ res = res.rename(columns={scoreCol: f"{scoreCol}_{i}"})
623
+ if reasonCol in res.columns:
624
+ res = res.rename(columns={reasonCol: f"{reasonCol}_{i}"})
625
+
626
+ # Drop duplicated columns from df (like prompt, variables, etc.)
627
+ newCols = [col for col in res.columns if col not in dfWithEvals.columns]
628
+ dfWithEvals = pd.concat([dfWithEvals, res[newCols]], axis=1)
629
+
630
+ except Exception as e:
631
+ print(f"Evaluation failed for model {model.value}: {str(e)}")
602
632
 
603
633
  if createExperiment:
604
634
  pd.set_option("future.no_silent_downcasting", True)
605
- res = res.fillna("Some error occured")
606
- if createPlayground(email, workspaceID, res):
607
- print(
608
- "Your data has been saved in the Llumo Experiment. Visit https://app.llumo.ai/evallm to see the results."
609
- )
635
+ dfWithEvals = dfWithEvals.fillna("Some error occurred")
636
+ if createPlayground(email, workspaceID, dfWithEvals, promptText=templates[0]):
637
+
638
+ print("Your data has been saved in the Llumo Experiment. Visit https://app.llumo.ai/evallm to see the results.")
610
639
  else:
611
- return res
612
-
640
+ return dfWithEvals
613
641
  else:
614
- if createExperiment:
642
+ if createExperiment==True:
615
643
  pd.set_option("future.no_silent_downcasting", True)
616
- df = df.fillna("Some error occured")
617
- if createPlayground(email, workspaceID, df):
618
- print(
619
- "Your data has been saved in the Llumo Experiment. Visit https://app.llumo.ai/evallm to see the results."
620
- )
621
- else:
644
+ df = df.fillna("Some error occurred")
645
+
646
+ if createPlayground(email, workspaceID, df, promptText=templates[0]):
647
+ print("Your data has been saved in the Llumo Experiment. Visit https://app.llumo.ai/evallm to see the results.")
648
+ else :
622
649
  return df
623
650
 
651
+
624
652
  # this function generates an output using llm and tools and evaluate that output
625
653
  def evaluateAgents(
626
654
  self,
@@ -638,6 +666,8 @@ class LlumoClient:
638
666
  toolResponseDf = LlumoAgentExecutor.run(
639
667
  dataframe, agents, model=model, model_api_key=model_api_key
640
668
  )
669
+
670
+
641
671
  evals = [
642
672
  "Tool Reliability",
643
673
  "Stepwise Progression",
@@ -667,31 +697,37 @@ class LlumoClient:
667
697
  def evaluateAgentResponses(
668
698
  self,
669
699
  dataframe,
670
- prompt_template="Give answer for the given query: {{query}}",
700
+ evals=["Final Task Alignment"],
701
+ outputColName="output",
671
702
  createExperiment: bool = False,
672
703
  ):
673
704
  try:
674
705
  if "query" and "messageHistory" and "tools" not in dataframe.columns:
675
706
  raise ValueError(
676
- "DataFrame must contain 'query', 'messageHistory', and 'tools' columns"
707
+ "DataFrame must contain 'query', 'messageHistory','output' ,and 'tools' columns. Make sure the columns names are same as mentioned here."
677
708
  )
678
- evals = [
679
- "Tool Reliability",
680
- "Stepwise Progression",
681
- "Tool Selection Accuracy",
682
- "Final Task Alignment",
683
- ]
709
+ prompt_template="Give answer for the given query: {{query}}"
710
+
711
+ # evals = [
712
+ # "Tool Reliability",
713
+ # "Stepwise Progression",
714
+ # "Tool Selection Accuracy",
715
+ # "Final Task Alignment",
716
+ # ]
684
717
  toolResponseDf = dataframe.copy()
685
718
  for eval in evals:
686
719
  # Perform evaluation
687
720
  toolResponseDf = self.evaluate(
688
- toolResponseDf, eval=eval, prompt_template=prompt_template
721
+ toolResponseDf, eval=eval, prompt_template=prompt_template,outputColName=outputColName
689
722
  )
723
+
724
+
690
725
  return toolResponseDf
691
726
 
692
727
  except Exception as e:
693
728
  raise e
694
729
 
730
+
695
731
  def runDataStream(
696
732
  self,
697
733
  dataframe,
@@ -852,7 +888,7 @@ class LlumoClient:
852
888
  pd.set_option("future.no_silent_downcasting", True)
853
889
  df = dataframe.fillna("Some error occured").astype(object)
854
890
 
855
- if createPlayground(email, workspaceID, df):
891
+ if createPlayground(email, workspaceID, df,queryColName=queryColName, dataStreamName=streamId):
856
892
  print(
857
893
  "Your data has been saved in the Llumo Experiment. Visit https://app.llumo.ai/evallm to see the results."
858
894
  )
llumo/helpingFuntions.py CHANGED
@@ -7,6 +7,7 @@ import requests
7
7
  import json
8
8
  import base64
9
9
  import os
10
+ import re
10
11
 
11
12
  subscriptionUrl = "https://app.llumo.ai/api/workspace/record-extra-usage"
12
13
  getStreamdataUrl = "https://app.llumo.ai/api/data-stream/all"
@@ -18,6 +19,8 @@ uploadColList = (
18
19
  uploadRowList = (
19
20
  "https://app.llumo.ai/api/New-Eval-API/new-upload-flow/uploadRowsInDBPlayground"
20
21
  )
22
+ createInsightUrl = "https://app.llumo.ai/api/New-Eval-API/insights-api/generate-playground-insights"
23
+ getPlaygroundInsightsUrl="https://app.llumo.ai/api/New-Eval-API/insights-api/get-all-playground-insights"
21
24
 
22
25
 
23
26
  def getProcessID():
@@ -210,30 +213,151 @@ def deleteColumnListInPlayground(workspaceID: str, playgroundID: str):
210
213
  return None
211
214
 
212
215
 
213
- def createColumn(workspaceID, dataframe, playgroundID):
214
-
216
+ def createColumn(workspaceID, dataframe, playgroundID, promptText=None,queryColName=None,outputColName= "output",dataStreamName=None,definationMapping=None):
215
217
  if len(dataframe) > 100:
216
218
  dataframe = dataframe.head(100)
217
219
  print("⚠️ Dataframe truncated to 100 rows for upload.")
218
220
 
219
- playgroundID = playgroundID
220
-
221
221
  coltemplate = {
222
222
  "workspaceID": workspaceID,
223
223
  "playgroundID": playgroundID,
224
224
  "columnListToUpload": [],
225
225
  }
226
+ allEvals = ['Response Completeness', 'Response Bias', 'Response Harmfulness', 'Input Toxicity', 'Input Harmfulness', 'Context Utilization', 'Relevance Retention', 'Semantic Cohesion', 'Final Task Alignment', 'Tool Reliability', 'Response Correctness', 'Response Toxicity', 'Input Bias', 'Input Relevancy', 'Redundancy Reduction', 'Response Sentiment', 'Tool Selection Accuracy', 'Stepwise Progression', 'Hallucination', 'Faithfulness', 'Answer Relevancy', 'Context Precision', 'Answer Similarity', 'Harmfulness', 'Maliciousness', 'Coherence', 'Answer Correctness', 'Context Recall', 'Context Entity Recall', 'Conciseness', 'customEvalColumn', 'Groundedness', 'Memory Utilization', 'Input Relevancy (Multi-turn)']
227
+
228
+
229
+
230
+ # Create a mapping of column names to unique column IDs
231
+ columnIDMapping = {}
226
232
 
233
+ # Iterate over each column in the dataframe
227
234
  for indx, col in enumerate(dataframe.columns):
228
- template = {
229
- "label": col,
230
- "type": "VARIABLE",
231
- "variableType": "STRING",
232
- "order": indx,
233
- "columnID": col,
234
- }
235
+ # Generate a unique column ID using uuid
236
+ columnID = str(uuid.uuid4().hex[:8])
237
+
238
+ columnIDMapping[col] = columnID
239
+
240
+
241
+ if col.startswith('output'):
242
+ # For output columns, create the prompt template with promptText
243
+ if promptText:
244
+ # Extract variables from promptText and set them as dependencies
245
+ dependencies = []
246
+
247
+ # Find variables inside {{variable}}
248
+ variables = re.findall(r'{{(.*?)}}', promptText)
249
+
250
+ # Loop through each variable and check if it exists as a column name
251
+ for var in variables:
252
+ varName = var.strip()
253
+ if varName in columnIDMapping: # Check if the variable is a column name
254
+ dependencies.append(columnIDMapping[varName]) # Add its columnID
255
+
256
+ # Now update the template for the output column
257
+
258
+ template={
259
+ "provider": "OPENAI",
260
+ "model": "GPT_4o",
261
+ "promptText": promptText,
262
+ "modelOptions": {
263
+ "temperature": 0,
264
+ "frequencyPenalty": 0,
265
+ "presencePenalty": 0,
266
+ "maxToken": 8192
267
+ },
268
+ "toolConfig": "none",
269
+ "concurrency": "",
270
+ "outputType": "STRING",
271
+ "isPromptSelected": True,
272
+ "isSmartPromptSelected": False,
273
+ "dependency": dependencies, # Use the dependencies extracted from promptText
274
+ "columnID": columnID, # Use the generated column ID
275
+ "label": col,
276
+ "type": "PROMPT",
277
+ "order": indx,
278
+ }
279
+
280
+ elif col.startswith('Data '):
281
+ if queryColName and dataStreamName:
282
+ dependencies = []
283
+ dependencies.append(columnIDMapping[queryColName])
284
+ template = {
285
+ "variableType": "STRING",
286
+ "dependency": dependencies,
287
+ "dataStreamName": dataStreamName,
288
+ "query": columnIDMapping[queryColName],
289
+ "columnID": columnID, # Use the generated column ID
290
+ "label": "Data stream",
291
+ "type": "DATA_STREAM",
292
+ "order": indx}
293
+
294
+ elif col in allEvals:
295
+
296
+ dependencies = []
297
+ variables = re.findall(r'{{(.*?)}}', promptText)
298
+
299
+ # Loop through each variable and check if it exists as a column name
300
+ for var in variables:
301
+ varName = var.strip()
302
+ if varName in columnIDMapping: # Check if the variable is a column name
303
+ dependencies.append(columnIDMapping[varName])
304
+
305
+ dependencies.append(columnIDMapping[outputColName]) # Add the output column ID
306
+ longDef = definationMapping.get(col, {}).get(col, "")
307
+ shortDef ="You have run this from SDK"
308
+ enum = col.upper().replace(" ","_")
309
+
310
+ template = {
311
+ "analytics": [
312
+ col.lower().replace(" ","_")
313
+ ],
314
+ "evaluationMetric": "ALL",
315
+ "evaluationModel": "GEMINI_PRO",
316
+ "selectPrompt": columnIDMapping[outputColName],
317
+ "scoreCondition": "GREATER_THAN",
318
+ "scoreValue": "50",
319
+ "scoreResult": "PASS",
320
+ "llmKpi": col,
321
+ "setRules": True,
322
+ "type": "EVAL",
323
+ "evalType": "LLM",
324
+ "similarityMetric": None,
325
+ "embeddingModel": None,
326
+ "groundTruth": None,
327
+ "dataStream": None,
328
+ "context": None,
329
+ "dependency": [columnIDMapping[outputColName]],
330
+ "hallucinationFields": {
331
+ "query": None,
332
+ "context": None,
333
+ "output": None
334
+ },
335
+ "definition": longDef,
336
+ "analyticsENUM": enum,
337
+ "prompt": shortDef,
338
+ "analyticsName": col,
339
+ "columnID": str(uuid.uuid4().hex[:8]),
340
+ "label": col,
341
+ "order": indx
342
+ }
343
+
344
+
345
+
346
+
347
+ else:
348
+
349
+ template = {
350
+ "label": col, # Label is the column name
351
+ "type": "VARIABLE", # Default type for non-output columns
352
+ "variableType": "STRING",
353
+ "order": indx,
354
+ "columnID": columnID, # Use the generated column ID
355
+ }
356
+
357
+ # Append the template to the column list
235
358
  coltemplate["columnListToUpload"].append(template)
236
359
 
360
+ # Prepare the row template structure
237
361
  rowTemplate = {
238
362
  "workspaceID": workspaceID,
239
363
  "playgroundID": playgroundID,
@@ -241,14 +365,22 @@ def createColumn(workspaceID, dataframe, playgroundID):
241
365
  "columnList": coltemplate["columnListToUpload"],
242
366
  }
243
367
 
368
+ # Populate dataToUploadList with rows from the dataframe
244
369
  for indx, row in dataframe.iterrows():
245
- row_dict = row.to_dict()
370
+ row_dict = {}
371
+
372
+ # For each column, we need to map the column ID to the corresponding value in the row
373
+ for col in dataframe.columns:
374
+ columnID = columnIDMapping[col] # Get the columnID from the mapping
375
+ row_dict[columnID] = row[col] # Map the columnID to the value in the row
376
+
377
+ # Add the row index (if necessary)
246
378
  row_dict["pIndex"] = indx
247
379
  rowTemplate["dataToUploadList"].append(row_dict)
248
380
 
381
+ # Return the column template, row template, and the column ID mapping
249
382
  return coltemplate, rowTemplate
250
383
 
251
-
252
384
  def uploadColumnListInPlayground(payload):
253
385
  url = uploadColList
254
386
  headers = {
@@ -292,10 +424,11 @@ def uploadRowsInDBPlayground(payload):
292
424
  return None
293
425
 
294
426
 
295
- def createPlayground(email, workspaceID, df):
427
+ def createPlayground(email, workspaceID, df, promptText=None,queryColName=None,dataStreamName=None,definationMapping=None,outputColName="output"):
428
+
296
429
  playgroundId = str(createEvalPlayground(email=email, workspaceID=workspaceID))
297
430
  payload1, payload2 = createColumn(
298
- workspaceID=workspaceID, dataframe=df, playgroundID=playgroundId
431
+ workspaceID=workspaceID, dataframe=df, playgroundID=playgroundId, promptText=promptText,queryColName=queryColName,dataStreamName=dataStreamName,definationMapping=definationMapping,outputColName=outputColName
299
432
  )
300
433
  deleteExistingRows = deleteColumnListInPlayground(
301
434
  workspaceID=workspaceID, playgroundID=playgroundId
@@ -305,3 +438,56 @@ def createPlayground(email, workspaceID, df):
305
438
 
306
439
  if rowListUpload:
307
440
  return True
441
+
442
+
443
+
444
+ def getPlaygroundInsights(workspaceID: str, activePlayground: str):
445
+ headers = {
446
+
447
+ "Content-Type": "application/json",
448
+ }
449
+
450
+ # Initial request to generate playground insights
451
+ payload = {
452
+ "activePlayground": activePlayground,
453
+ "workspaceID": workspaceID,
454
+ }
455
+
456
+ urlGenerate = createInsightUrl
457
+
458
+ responseGenerate = requests.post(urlGenerate, json=payload, headers=headers)
459
+
460
+ if responseGenerate.status_code == 200:
461
+ responseJson = responseGenerate.json()
462
+
463
+ insightStatus = responseJson.get("data", {}).get("insight", False)
464
+
465
+ if insightStatus:
466
+ # If insight is true, request to get all playground insights
467
+ urlGetAll = getPlaygroundInsightsUrl
468
+
469
+ responseGetAll = requests.post(urlGetAll, json=payload, headers=headers)
470
+
471
+ if responseGetAll.status_code == 200:
472
+ responseAllJson = responseGetAll.json()
473
+
474
+ data = responseAllJson.get("data", {}).get("data", [])
475
+
476
+ # Extract insight and solution
477
+ insights = []
478
+ for item in data:
479
+ insight = item.get("insight", "")
480
+ solution = item.get("solution", "")
481
+ insights.append({"insight": insight, "solution": solution})
482
+
483
+ return insights
484
+ else:
485
+ print(f"Error fetching all insights: {responseGetAll.status_code} - {responseGetAll.text}")
486
+ return None
487
+ else:
488
+ print("No insight generated.")
489
+ return None
490
+ else:
491
+ print(f"Error generating insight: {responseGenerate.status_code} - {responseGenerate.text}")
492
+ return None
493
+
llumo/sockets.py CHANGED
@@ -128,7 +128,7 @@ class LlumoSocketClient:
128
128
  self._listening_done.set()
129
129
  break
130
130
 
131
- time.sleep(1)
131
+ time.sleep(3)
132
132
 
133
133
  timeout_thread = threading.Thread(target=timeout_watcher, daemon=True)
134
134
  timeout_thread.start()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llumo
3
- Version: 0.2.12
3
+ Version: 0.2.13
4
4
  Summary: Python SDK for interacting with the Llumo ai API.
5
5
  Home-page: https://www.llumo.ai/
6
6
  Author: Llumo
@@ -0,0 +1,13 @@
1
+ llumo/__init__.py,sha256=O04b4yW1BnOvcHzxWFddAKhtdBEhBNhLdb6xgnpHH_Q,205
2
+ llumo/client.py,sha256=mVqxNyYMbHlL9lnkpw_H6_n98WYO38ZcLZNnQX1TjUE,35948
3
+ llumo/exceptions.py,sha256=iCj7HhtO_ckC2EaVBdXbAudNpuMDsYmmMEV5lwynZ-E,1854
4
+ llumo/execution.py,sha256=x88wQV8eL99wNN5YtjFaAMCIfN1PdfQVlAZQb4vzgQ0,1413
5
+ llumo/functionCalling.py,sha256=D5jYapu1rIvdIJNUYPYMTyhQ1H-6nkwoOLMi6eekfUE,7241
6
+ llumo/helpingFuntions.py,sha256=ah0FUQcRV3gfguvjQQ_aZzq59hpJttqAPJdjJVNYdFc,17110
7
+ llumo/models.py,sha256=YH-qAMnShmUpmKE2LQAzQdpRsaXkFSlOqMxHwU4zBUI,1560
8
+ llumo/sockets.py,sha256=i90l2rr08paa-ifKy2E5YMIS8r3yRBmu2CUOjhFKork,5579
9
+ llumo-0.2.13.dist-info/licenses/LICENSE,sha256=tF9yAcfPV9xGT3ViWmC8hPvOo8BEk4ZICbUfcEo8Dlk,182
10
+ llumo-0.2.13.dist-info/METADATA,sha256=W-ZVsTKhiPw6strlNQEqyufgOLfV9ZCjCpY6Dj3Qc94,1491
11
+ llumo-0.2.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
12
+ llumo-0.2.13.dist-info/top_level.txt,sha256=d5zUTMI99llPtLRB8rtSrqELm_bOqX-bNC5IcwlDk88,6
13
+ llumo-0.2.13.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- llumo/__init__.py,sha256=O04b4yW1BnOvcHzxWFddAKhtdBEhBNhLdb6xgnpHH_Q,205
2
- llumo/client.py,sha256=QMasCjzRmL38RuMUHoY39_ge2nIRdSOECjj1daicd-k,34144
3
- llumo/exceptions.py,sha256=iCj7HhtO_ckC2EaVBdXbAudNpuMDsYmmMEV5lwynZ-E,1854
4
- llumo/execution.py,sha256=x88wQV8eL99wNN5YtjFaAMCIfN1PdfQVlAZQb4vzgQ0,1413
5
- llumo/functionCalling.py,sha256=D5jYapu1rIvdIJNUYPYMTyhQ1H-6nkwoOLMi6eekfUE,7241
6
- llumo/helpingFuntions.py,sha256=lG_d3lQgJj6pI7v1YdLqdPojrLCNwybKz29zXrGaL5k,9090
7
- llumo/models.py,sha256=YH-qAMnShmUpmKE2LQAzQdpRsaXkFSlOqMxHwU4zBUI,1560
8
- llumo/sockets.py,sha256=Qxxqtx3Hg07HLhA4QfcipK1ChiOYhHZBu02iA6MfYlQ,5579
9
- llumo-0.2.12.dist-info/licenses/LICENSE,sha256=tF9yAcfPV9xGT3ViWmC8hPvOo8BEk4ZICbUfcEo8Dlk,182
10
- llumo-0.2.12.dist-info/METADATA,sha256=CYu8qMtD-XZuoQzC7YPZRlNgetEQPjMT1RiMGnHdZJs,1491
11
- llumo-0.2.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
12
- llumo-0.2.12.dist-info/top_level.txt,sha256=d5zUTMI99llPtLRB8rtSrqELm_bOqX-bNC5IcwlDk88,6
13
- llumo-0.2.12.dist-info/RECORD,,
File without changes