logdetective 0.2.10__py3-none-any.whl → 0.2.11__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.
logdetective/server.py CHANGED
@@ -30,7 +30,7 @@ class Response(BaseModel):
30
30
  https://llama-cpp-python.readthedocs.io/en/latest/api-reference/#llama_cpp.llama_types.CreateCompletionResponse
31
31
  response_certainty: float
32
32
  """
33
- explanation: CreateCompletionResponse
33
+ explanation: Dict
34
34
  response_certainty: float
35
35
 
36
36
 
@@ -44,7 +44,8 @@ class StagedResponse(Response):
44
44
  snippets:
45
45
  list of dictionaries { 'snippet' : '<original_text>, 'comment': CreateCompletionResponse }
46
46
  """
47
- snippets: List[Dict[str, str | CreateCompletionResponse]]
47
+ snippets: List[Dict[str, str | Dict]]
48
+
48
49
 
49
50
  LOG = logging.getLogger("logdetective")
50
51
 
@@ -113,7 +114,7 @@ def process_url(url: str) -> str:
113
114
  def mine_logs(log: str) -> List[str]:
114
115
  """Extract snippets from log text
115
116
  """
116
- extractor = DrainExtractor(verbose=True, context=True, max_clusters=8)
117
+ extractor = DrainExtractor(verbose=True, context=True, max_clusters=16)
117
118
 
118
119
  LOG.info("Getting summary")
119
120
  log_summary = extractor(log)
@@ -125,7 +126,7 @@ def mine_logs(log: str) -> List[str]:
125
126
  return log_summary
126
127
 
127
128
 
128
- async def submit_text(text: str, max_tokens: int = 0, log_probs: int = 1, stream: bool = False,
129
+ async def submit_text(text: str, max_tokens: int = -1, log_probs: int = 1, stream: bool = False,
129
130
  model: str = "default-model"):
130
131
  """Submit prompt to LLM.
131
132
  max_tokens: number of tokens to be produces, 0 indicates run until encountering EOS
@@ -134,8 +135,8 @@ async def submit_text(text: str, max_tokens: int = 0, log_probs: int = 1, stream
134
135
  LOG.info("Analyzing the text")
135
136
  data = {
136
137
  "prompt": text,
137
- "max_tokens": str(max_tokens),
138
- "logprobs": str(log_probs),
138
+ "max_tokens": max_tokens,
139
+ "logprobs": log_probs,
139
140
  "stream": stream,
140
141
  "model": model}
141
142
 
@@ -186,13 +187,13 @@ async def analyze_log(build_log: BuildLog):
186
187
  if "logprobs" in response["choices"][0]:
187
188
  try:
188
189
  certainty = compute_certainty(
189
- response["choices"][0]["logprobs"]["top_logprobs"])
190
+ response["choices"][0]["logprobs"]["content"][0]["top_logprobs"])
190
191
  except ValueError as ex:
191
192
  LOG.error("Error encountered while computing certainty: %s", ex)
192
193
  raise HTTPException(
193
194
  status_code=400,
194
195
  detail=f"Couldn't compute certainty with data:\n"
195
- f"{response["choices"][0]["logprobs"]["top_logprobs"]}") from ex
196
+ f"{response["choices"][0]["logprobs"]["content"][0]["top_logprobs"]}") from ex
196
197
 
197
198
  return Response(explanation=response, response_certainty=certainty)
198
199
 
@@ -213,27 +214,27 @@ async def analyze_log_staged(build_log: BuildLog):
213
214
  *[submit_text(SNIPPET_PROMPT_TEMPLATE.format(s)) for s in log_summary])
214
215
 
215
216
  analyzed_snippets = [
216
- {"snippet":e[0], "comment":e[1]} for e in zip(log_summary, analyzed_snippets)]
217
+ {"snippet": e[0], "comment": e[1]} for e in zip(log_summary, analyzed_snippets)]
217
218
 
218
219
  final_prompt = PROMPT_TEMPLATE_STAGED.format(
219
220
  f"\n{SNIPPET_DELIMITER}\n".join([
220
221
  f"[{e["snippet"]}] : [{e["comment"]["choices"][0]["text"]}]"
221
- for e in analyzed_snippets]))
222
+ for e in analyzed_snippets]))
222
223
 
223
224
  final_analysis = await submit_text(final_prompt)
224
-
225
+ print(final_analysis)
225
226
  certainty = 0
226
227
 
227
228
  if "logprobs" in final_analysis["choices"][0]:
228
229
  try:
229
230
  certainty = compute_certainty(
230
- final_analysis["choices"][0]["logprobs"]["top_logprobs"])
231
+ final_analysis["choices"][0]["logprobs"]["content"][0]["top_logprobs"])
231
232
  except ValueError as ex:
232
233
  LOG.error("Error encountered while computing certainty: %s", ex)
233
234
  raise HTTPException(
234
235
  status_code=400,
235
236
  detail=f"Couldn't compute certainty with data:\n"
236
- f"{final_analysis["choices"][0]["logprobs"]["top_logprobs"]}") from ex
237
+ f"{final_analysis["choices"][0]["logprobs"]["content"][0]["top_logprobs"]}") from ex
237
238
 
238
239
  return StagedResponse(
239
240
  explanation=final_analysis, snippets=analyzed_snippets, response_certainty=certainty)
logdetective/utils.py CHANGED
@@ -15,10 +15,17 @@ LOG = logging.getLogger("logdetective")
15
15
  def chunk_continues(text: str, index: int) -> bool:
16
16
  """Set of heuristics for determining whether or not
17
17
  does the current chunk of log text continue on next line.
18
+
19
+ Following rules are checked, in order:
20
+ * is the next character is whitespace
21
+ * is the previous character backslash '\\'
22
+ * is the previous character colon ':'
23
+
18
24
  """
19
25
  conditionals = [
20
26
  lambda i, string: string[i + 1].isspace(),
21
- lambda i, string: string[i - 1] == "\\"
27
+ lambda i, string: string[i - 1] == "\\",
28
+ lambda i, string: string[i - 1] == ":"
22
29
  ]
23
30
 
24
31
  for c in conditionals:
@@ -74,7 +81,7 @@ def initialize_model(model_pth: str, filename_suffix: str = ".gguf", verbose: bo
74
81
  return model
75
82
 
76
83
 
77
- def compute_certainty(probs: List[Dict[str, float] | None]) -> float:
84
+ def compute_certainty(probs: List[Dict]) -> float:
78
85
  """Compute certainty of repsponse based on average logit probability.
79
86
  Log probability is log(p), isn't really readable for most people, especially in compound.
80
87
  In this case it's just a matter of applying inverse operation exp.
@@ -85,7 +92,8 @@ def compute_certainty(probs: List[Dict[str, float] | None]) -> float:
85
92
  """
86
93
 
87
94
  top_logprobs = [
88
- np.exp(x) * 100 for e in probs if isinstance(e, dict) for x in e.values()]
95
+ np.exp(e["logprob"]) * 100 for e in probs]
96
+
89
97
  certainty = np.median(top_logprobs, axis=0)
90
98
  if np.isnan(certainty):
91
99
  raise ValueError("NaN certainty of answer")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: logdetective
3
- Version: 0.2.10
3
+ Version: 0.2.11
4
4
  Summary: Log using LLM AI to search for build/test failures and provide ideas for fixing these.
5
5
  License: Apache-2.0
6
6
  Author: Jiri Podivin
@@ -0,0 +1,12 @@
1
+ logdetective/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ logdetective/constants.py,sha256=6XekuU7sbkY1Pmu4NJajgFbJ0no8PQ3DxQm8NeLKtjE,1383
3
+ logdetective/drain3.ini,sha256=ni91eCT1TwTznZwcqWoOVMQcGEnWhEDNCoTPF7cfGfY,1360
4
+ logdetective/extractors.py,sha256=xfan_dbGCrLH4cguJ2F6W6UkxXMz24Vob39r5-GsNV8,3102
5
+ logdetective/logdetective.py,sha256=j34E_udG7dDY5usWmsJ0q767-Fay3K5Aw_lBZUORPSI,4373
6
+ logdetective/server.py,sha256=lgWvsY41rGNixxg5OS7f339Nt2WHWTIOyBG28Jd-zVI,9636
7
+ logdetective/utils.py,sha256=j3u_JruoM57q_7dX3enV04t6WGEg3YNWbu5wmEGmP-I,5019
8
+ logdetective-0.2.11.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
9
+ logdetective-0.2.11.dist-info/METADATA,sha256=69f1Tcc7TDbnKjcgVs9GAWtwp3erF6bYQYGx0Q1uBV0,9791
10
+ logdetective-0.2.11.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
11
+ logdetective-0.2.11.dist-info/entry_points.txt,sha256=3K_vXja6PmcA8sNdUi63WdImeiNhVZcEGPTaoJmltfA,63
12
+ logdetective-0.2.11.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.0.1
2
+ Generator: poetry-core 2.1.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,12 +0,0 @@
1
- logdetective/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- logdetective/constants.py,sha256=6XekuU7sbkY1Pmu4NJajgFbJ0no8PQ3DxQm8NeLKtjE,1383
3
- logdetective/drain3.ini,sha256=ni91eCT1TwTznZwcqWoOVMQcGEnWhEDNCoTPF7cfGfY,1360
4
- logdetective/extractors.py,sha256=xfan_dbGCrLH4cguJ2F6W6UkxXMz24Vob39r5-GsNV8,3102
5
- logdetective/logdetective.py,sha256=j34E_udG7dDY5usWmsJ0q767-Fay3K5Aw_lBZUORPSI,4373
6
- logdetective/server.py,sha256=ryk6bQ4xV4CTlenxiI9SgOOc0bE_GD_z46Ooo7PjFCs,9596
7
- logdetective/utils.py,sha256=Q51mjbeevD6fIF84QYuc1kgC768a38zCJkJwn7TuJA0,4845
8
- logdetective-0.2.10.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
9
- logdetective-0.2.10.dist-info/METADATA,sha256=8qmL187ApXgT57eXP_r2-4F732EyH5YTFiGYbcmVIQw,9791
10
- logdetective-0.2.10.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
11
- logdetective-0.2.10.dist-info/entry_points.txt,sha256=3K_vXja6PmcA8sNdUi63WdImeiNhVZcEGPTaoJmltfA,63
12
- logdetective-0.2.10.dist-info/RECORD,,