llumo 0.2.40__py3-none-any.whl → 0.2.42__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
@@ -43,9 +43,9 @@ createEvalUrl = "https://backend-api.llumo.ai/api/v1/create-debug-log-for-sdk"
43
43
 
44
44
  class LlumoClient:
45
45
 
46
- def __init__(self, api_key, playground_id=None):
46
+ def __init__(self, api_key, playgroundID=None):
47
47
  self.apiKey = api_key
48
- self.playgroundID = playground_id
48
+ self.playgroundID = playgroundID
49
49
  self.evalData = []
50
50
  self.evals = []
51
51
  self.processMapping = {}
@@ -820,6 +820,8 @@ class LlumoClient:
820
820
  allBatches = []
821
821
  for index, row in dataframe.iterrows():
822
822
  # Extract required fields
823
+ query = row.get("query", "")
824
+ context = row.get("context", "")
823
825
  tools = row.get("tools", "")
824
826
  groundTruth = row.get("groundTruth", "")
825
827
  messageHistory = row.get("messageHistory", "")
@@ -827,42 +829,43 @@ class LlumoClient:
827
829
  output = row.get("output", "")
828
830
 
829
831
  # Initialize query and context
830
- query = ""
831
- context = ""
832
-
833
- # Process prompt template if provided
834
- if promptTemplate:
835
- # Extract template variables
836
- keys = re.findall(r"{{(.*?)}}", promptTemplate)
837
-
838
- if not all([key in dataframe.columns for key in keys]):
839
- raise LlumoAIError.InvalidPromptTemplate()
840
-
841
- # Populate template and separate query/context
842
- populated_template = promptTemplate
843
- for key in keys:
844
- value = row.get(key, "")
845
- if isinstance(value, str):
846
- length = len(value.split()) * 1.5
847
- if length <= 50:
848
- # Short value - include in query via template
849
- temp_obj = {key: value}
850
- populated_template = getInputPopulatedPrompt(populated_template, temp_obj)
851
- else:
852
- # Long value - add to context
853
- context += f" {key}: {value}, "
854
-
855
- query = populated_template.strip()
856
-
857
- # Add any remaining context from other fields
858
- if not context.strip():
859
- for key, value in row.items():
860
- if key not in keys and isinstance(value, str) and value.strip():
861
- context += f" {key}: {value}, "
862
- else:
863
- # No prompt template - use direct query and context fields
864
- query = row.get("query", "")
865
- context = row.get("context", "")
832
+ # query = ""
833
+ # context = ""
834
+
835
+ # # Process prompt template if provided
836
+ # if promptTemplate:
837
+ # # Extract template variables
838
+ # keys = re.findall(r"{{(.*?)}}", promptTemplate)
839
+
840
+ # if not all([key in dataframe.columns for key in keys]):
841
+ # # raise LlumoAIError.InvalidPromptTemplate()
842
+ # break
843
+
844
+ # # Populate template and separate query/context
845
+ # populated_template = promptTemplate
846
+ # for key in keys:
847
+ # value = row.get(key, "")
848
+ # if isinstance(value, str):
849
+ # length = len(value.split()) * 1.5
850
+ # if length <= 50:
851
+ # # Short value - include in query via template
852
+ # temp_obj = {key: value}
853
+ # populated_template = getInputPopulatedPrompt(populated_template, temp_obj)
854
+ # else:
855
+ # # Long value - add to context
856
+ # context += f" {key}: {value}, "
857
+
858
+ # query = populated_template.strip()
859
+
860
+ # # Add any remaining context from other fields
861
+ # if not context.strip():
862
+ # for key, value in row.items():
863
+ # if key not in keys and isinstance(value, str) and value.strip():
864
+ # context += f" {key}: {value}, "
865
+ # else:
866
+ # # No prompt template - use direct query and context fields
867
+ # query = row.get("query", "")
868
+ # context = row.get("context", "")
866
869
 
867
870
  INPUT_TOKEN_PRICE = 0.0000025
868
871
  OUTPUT_TOKEN_PRICE = 0.00001
@@ -885,7 +888,10 @@ class LlumoClient:
885
888
  "totalTokens": totalTokens,
886
889
  "cost": round(cost, 8),
887
890
  "modelsUsed": "gpt-4o",
888
- "latency":round(random.uniform(1,1.6),2)
891
+ "latency":round(random.uniform(1,1.6),2),
892
+ "promptTemplate": promptTemplate,
893
+ "systemInstructions": systemInstructions
894
+
889
895
 
890
896
  }
891
897
  currentTime = datetime(2025, 8, 2, 10, 20, 15, tzinfo=timezone.utc)
@@ -910,8 +916,7 @@ class LlumoClient:
910
916
  "columnID":rowID,
911
917
  "rowID":columnID,
912
918
  "latency": random.randint(1000, 1500),
913
- "promptTemplate":promptTemplate,
914
- "systemInstructions":systemInstructions
919
+
915
920
 
916
921
  }
917
922
 
@@ -921,7 +926,7 @@ class LlumoClient:
921
926
  for i, batch in enumerate(allBatches, start=1):
922
927
 
923
928
  try:
924
- # print(batch)
929
+ # print(batch)
925
930
  response = postForDebugLogs(record=batch,workspaceID=workspaceID)
926
931
 
927
932
  # failure case inside response
@@ -938,9 +943,6 @@ class LlumoClient:
938
943
 
939
944
  print("Records Uploaded successfully. You may now review your logs at: https://app.llumo.ai/logs")
940
945
 
941
-
942
- # Wait for results
943
-
944
946
  # def evaluateMultiple(
945
947
  # self,
946
948
  # data,
@@ -2082,6 +2084,115 @@ class LlumoClient:
2082
2084
  definationMapping=self.definationMapping,
2083
2085
  )
2084
2086
 
2087
+ def getEvaluateMultiple(
2088
+ self,
2089
+ data,
2090
+ evals
2091
+ ) -> List:
2092
+
2093
+ # print("Evaluating multiple data with evals:", data, evals)
2094
+
2095
+ dataID = uuid.uuid4().hex[:36]
2096
+
2097
+ self.validateApiKey()
2098
+
2099
+ if not self.workspaceID:
2100
+ raise LlumoAIError("Workspace ID not found after validation.")
2101
+
2102
+ payload = {
2103
+ "dataID": dataID,
2104
+ "data": data,
2105
+ "evals": evals,
2106
+ "workspaceID": self.workspaceID,
2107
+ "playgroundID": self.playgroundID,
2108
+ }
2109
+
2110
+ # print("payload", payload)
2111
+
2112
+ # Create evaluation
2113
+ requests.post(
2114
+ "https://backend-api.llumo.ai/api/v1/sdk/create-evaluation-Multiple",
2115
+ json=payload,
2116
+ headers={
2117
+ "Content-Type": "application/json",
2118
+ "Authorization": f"Bearer {self.apiKey}",
2119
+ },
2120
+ )
2121
+
2122
+ final_result_data = []
2123
+
2124
+ cursor = "0-0"
2125
+ limit = 10
2126
+ all_data_fetched = False
2127
+
2128
+ while not all_data_fetched:
2129
+ try:
2130
+ response = requests.get(
2131
+ "https://backend-api.llumo.ai/api/v1/sdk/poll",
2132
+ params={
2133
+ "cursor": cursor,
2134
+ "dataID": dataID,
2135
+ "limit": limit,
2136
+ },
2137
+ )
2138
+
2139
+ response_data = response.json()
2140
+ result_data = response_data.get("debugLog", {})
2141
+ print("resultData", result_data)
2142
+
2143
+ results = result_data.get("results", [])
2144
+ final_result_data.extend(results)
2145
+
2146
+ cursor = result_data.get("nextCursor")
2147
+
2148
+ if len(final_result_data) == len(data):
2149
+ all_data_fetched = True
2150
+
2151
+ time.sleep(10)
2152
+
2153
+ except Exception as error:
2154
+ print("error", error)
2155
+ all_data_fetched = True
2156
+
2157
+ # Shape results
2158
+ formatted_results = []
2159
+
2160
+ for row in final_result_data:
2161
+ score: Dict[str, float | None] = {}
2162
+ reasoning: Dict[str, str] = {}
2163
+
2164
+ for eval_name in evals:
2165
+ details = row.get(eval_name)
2166
+
2167
+ if isinstance(details, dict):
2168
+ if isinstance(details.get("value"), (int, float)):
2169
+ score[eval_name] = details.get("value")
2170
+ else:
2171
+ score[eval_name] = details.get("score")
2172
+ reasoning[eval_name] = details.get("reasoning", "")
2173
+
2174
+ elif "score" in row:
2175
+ score[eval_name] = (
2176
+ row["score"] if isinstance(row["score"], (int, float)) else None
2177
+ )
2178
+ reasoning[eval_name] = row.get("reasoning", "")
2179
+ else:
2180
+ score[eval_name] = None
2181
+ reasoning[eval_name] = ""
2182
+
2183
+ formatted_row = {
2184
+ "context": row.get("context", ""),
2185
+ "query": row.get("query", ""),
2186
+ "output": row.get("output", ""),
2187
+ "score": score,
2188
+ "reasoning": reasoning,
2189
+ }
2190
+
2191
+ # print(formatted_row)
2192
+ formatted_results.append(formatted_row)
2193
+
2194
+ return formatted_results
2195
+
2085
2196
 
2086
2197
  class SafeDict(dict):
2087
2198
  def __missing__(self, key):
@@ -30,7 +30,7 @@ def getLlumoRun():
30
30
 
31
31
  class LlumoSessionContext(LlumoClient):
32
32
  def __init__(self, logger, sessionID: Optional[str] = None):
33
- super().__init__(api_key=logger.apiKey, playground_id=logger.getPlaygroundID())
33
+ super().__init__(api_key=logger.apiKey, playgroundID=logger.getPlaygroundID())
34
34
  self.sessionID = sessionID or str(uuid.uuid4().hex[:14])
35
35
  self.logger = logger
36
36
  self.apiKey = logger.apiKey
@@ -102,9 +102,10 @@ class LlumoSessionContext(LlumoClient):
102
102
  "totalTokens": "",
103
103
  "cost": "",
104
104
  "modelsUsed": "gpt-4o",
105
+ "promptTemplate": promptTemplate,
106
+ "systemInstructions": systemInstructions
105
107
  },
106
- "promptTemplate":promptTemplate,
107
- "systemInstructions":systemInstructions
108
+
108
109
  }
109
110
 
110
111
  self.threadLlumoRun = _ctxLlumoRun.set(llumoRun)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llumo
3
- Version: 0.2.40
3
+ Version: 0.2.42
4
4
  Summary: Python SDK for interacting with the Llumo ai API.
5
5
  Home-page: https://www.llumo.ai/
6
6
  Author: Llumo
@@ -2,19 +2,19 @@ llumo/__init__.py,sha256=kkuppu7ZPiVZFdnYzJ9BM3syMbYHOSZLpwKwAvGHsnY,311
2
2
  llumo/callback.py,sha256=XQbImLnd64_B2Iir-FCaJcL5Kmpm3RlXJH2zDRXk_yk,25135
3
3
  llumo/callbacks-0.py,sha256=TEIOCWRvk2UYsTmBMBsnlgpqWvr-2y3a6d0w_e96NRM,8958
4
4
  llumo/chains.py,sha256=6lCgLseh04RUgc6SahhmvQj82quay2Mi1j8gPUlx8Es,2923
5
- llumo/client.py,sha256=W0_i5M5mN0B_YfDWaT6qDUGY93PeqzcK6JxZdIFXibk,79903
5
+ llumo/client.py,sha256=Sf9QaKWIsAHYAX78YQT2U93A0LuwkluKQQvCMg2vRwM,83386
6
6
  llumo/exceptions.py,sha256=1OyhN9YL9LcyUPUsqYHq6Rret0udATZAwMVJaio2_Ec,2123
7
7
  llumo/execution.py,sha256=nWbJ7AvWuUPcOb6i-JzKRna_PvF-ewZTiK8skS-5n3w,1380
8
8
  llumo/functionCalling.py,sha256=D5jYapu1rIvdIJNUYPYMTyhQ1H-6nkwoOLMi6eekfUE,7241
9
9
  llumo/google.py,sha256=6y9YnDFDRHv6-sQNT5LIsV9p31BCN0B9eow5KTRBWfM,2185
10
10
  llumo/helpingFuntions.py,sha256=eMR2Rq8vw4X5sIESOvjOBrEvyYE00Eq7XlQjV66eVcg,29977
11
11
  llumo/llumoLogger.py,sha256=ALM4461jItWcvYL9HzTGmB-X-M77YF_9PTeTPxtmP_E,2223
12
- llumo/llumoSessionContext.py,sha256=f4C6w5H7Fym6lC6KK8wY8kW5VPb0hNrBEvh6zkCSkfk,14881
12
+ llumo/llumoSessionContext.py,sha256=QaiQtB13dITTVINpzEAEVlO-fpW362XkgMjM1W4EHoo,14891
13
13
  llumo/models.py,sha256=aVEZsOOoQx5LeNtwSyBxqvrINq0izH3QWu_YjsMPE6o,2910
14
14
  llumo/openai.py,sha256=VstBzaORe8Tq0feUIIEszzcN1oq6TJfkPviaCr5d3Bw,8950
15
15
  llumo/sockets.py,sha256=pfWz1zTEiwqJhdbSy3i3_Y4WlIdJ3cuac11wMePeBS0,6130
16
- llumo-0.2.40.dist-info/licenses/LICENSE,sha256=tF9yAcfPV9xGT3ViWmC8hPvOo8BEk4ZICbUfcEo8Dlk,182
17
- llumo-0.2.40.dist-info/METADATA,sha256=qzr5dj9AT4vbOpU_IgwHpFcqojjupUusLIoBqYR-qXo,1662
18
- llumo-0.2.40.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
- llumo-0.2.40.dist-info/top_level.txt,sha256=d5zUTMI99llPtLRB8rtSrqELm_bOqX-bNC5IcwlDk88,6
20
- llumo-0.2.40.dist-info/RECORD,,
16
+ llumo-0.2.42.dist-info/licenses/LICENSE,sha256=tF9yAcfPV9xGT3ViWmC8hPvOo8BEk4ZICbUfcEo8Dlk,182
17
+ llumo-0.2.42.dist-info/METADATA,sha256=v5zWRFLNSHoMFuXVY3kgdaAcsj3L16AWmTQH6sFEs_k,1662
18
+ llumo-0.2.42.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
+ llumo-0.2.42.dist-info/top_level.txt,sha256=d5zUTMI99llPtLRB8rtSrqELm_bOqX-bNC5IcwlDk88,6
20
+ llumo-0.2.42.dist-info/RECORD,,
File without changes