logdetective 2.13.0__tar.gz → 3.1.0__tar.gz

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.
Files changed (48) hide show
  1. {logdetective-2.13.0 → logdetective-3.1.0}/PKG-INFO +54 -24
  2. {logdetective-2.13.0 → logdetective-3.1.0}/README.md +52 -21
  3. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/constants.py +1 -1
  4. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/logdetective.py +12 -24
  5. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/models.py +1 -20
  6. logdetective-3.1.0/logdetective/prompts/message_template.j2 +2 -0
  7. logdetective-3.1.0/logdetective/prompts/snippet_message_template.j2 +2 -0
  8. logdetective-3.1.0/logdetective/prompts/snippet_system_prompt.j2 +38 -0
  9. logdetective-3.1.0/logdetective/prompts/staged_message_template.j2 +2 -0
  10. logdetective-3.1.0/logdetective/prompts/staged_system_prompt.j2 +45 -0
  11. logdetective-3.1.0/logdetective/prompts/system_prompt.j2 +57 -0
  12. logdetective-3.1.0/logdetective/prompts.py +87 -0
  13. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/prompts.yml +7 -0
  14. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/config.py +3 -2
  15. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/database/models/metrics.py +7 -4
  16. logdetective-3.1.0/logdetective/server/metric.py +320 -0
  17. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/models.py +12 -0
  18. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/server.py +45 -75
  19. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/utils.py +35 -26
  20. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective.1.asciidoc +12 -7
  21. {logdetective-2.13.0 → logdetective-3.1.0}/pyproject.toml +8 -5
  22. logdetective-2.13.0/logdetective/server/metric.py +0 -127
  23. logdetective-2.13.0/logdetective/server/plot.py +0 -432
  24. {logdetective-2.13.0 → logdetective-3.1.0}/LICENSE +0 -0
  25. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/__init__.py +0 -0
  26. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/drain3.ini +0 -0
  27. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/extractors.py +0 -0
  28. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/prompts-summary-first.yml +0 -0
  29. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/prompts-summary-only.yml +0 -0
  30. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/remote_log.py +0 -0
  31. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/__init__.py +0 -0
  32. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/compressors.py +0 -0
  33. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/database/__init__.py +0 -0
  34. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/database/base.py +0 -0
  35. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/database/models/__init__.py +0 -0
  36. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/database/models/exceptions.py +0 -0
  37. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/database/models/koji.py +0 -0
  38. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/database/models/merge_request_jobs.py +0 -0
  39. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/emoji.py +0 -0
  40. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/exceptions.py +0 -0
  41. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/gitlab.py +0 -0
  42. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/koji.py +0 -0
  43. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/llm.py +0 -0
  44. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/templates/base_response.html.j2 +0 -0
  45. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/templates/gitlab_full_comment.md.j2 +0 -0
  46. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/templates/gitlab_short_comment.md.j2 +0 -0
  47. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/server/utils.py +0 -0
  48. {logdetective-2.13.0 → logdetective-3.1.0}/logdetective/skip_snippets.yml +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: logdetective
3
- Version: 2.13.0
4
- Summary: Log using LLM AI to search for build/test failures and provide ideas for fixing these.
3
+ Version: 3.1.0
4
+ Summary: Analyze logs with a template miner and an LLM to discover errors and suggest solutions.
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
7
7
  Author: Jiri Podivin
@@ -36,7 +36,6 @@ Requires-Dist: flexmock (>=0.12.2,<0.13.0) ; extra == "testing"
36
36
  Requires-Dist: huggingface-hub (>=0.23.0,<1.4.0)
37
37
  Requires-Dist: koji (>=1.35.0,<2.0.0) ; extra == "server" or extra == "server-testing"
38
38
  Requires-Dist: llama-cpp-python (>0.2.56,!=0.2.86,<1.0.0)
39
- Requires-Dist: matplotlib (>=3.8.4,<4.0.0) ; extra == "server" or extra == "server-testing"
40
39
  Requires-Dist: numpy (>=1.26.0)
41
40
  Requires-Dist: openai (>=1.82.1,<2.0.0) ; extra == "server" or extra == "server-testing"
42
41
  Requires-Dist: pydantic (>=2.8.2,<3.0.0)
@@ -97,12 +96,15 @@ Usage
97
96
 
98
97
  To analyze a log file, run the script with the following command line arguments:
99
98
  - `file` (required): The path or URL of the log file to be analyzed.
100
- - `--model` (optional, default: "Mistral-7B-Instruct-v0.3-GGUF"): The path or Hugging space name of the language model for analysis. For models from Hugging Face, write them as `namespace/repo_name`. As we are using LLama.cpp we want this to be in the `gguf` format. If the model is already on your machine it will skip the download.
101
- - `--filename_suffix` (optional, default "Q4_K.gguf"): You can specify which suffix of the file to use. This option is applied when specifying model using the Hugging Face repository.
102
- - `--summarizer` DISABLED: LLM summarization option was removed. Argument is kept for backward compatibility only.(optional, default: "drain"): Choose between LLM and Drain template miner as the log summarizer. You can also provide the path to an existing language model file instead of using a URL.
103
- - `--n_lines` DISABLED: LLM summarization option was removed. Argument is kept for backward compatibility only. (optional, default: 8): The number of lines per chunk for LLM analysis. This only makes sense when you are summarizing with LLM.
104
- - `--n_clusters` (optional, default 8): Number of clusters for Drain to organize log chunks into. This only makes sense when you are summarizing with Drain.
105
- - `--skip_snippets` Path to patterns for skipping snippets (in YAML).
99
+ - `--model` (optional, default: "granite-3.2-8b-instruct-GGUF"): The path or Hugging space name of the language model for analysis. For models from Hugging Face, write them as `namespace/repo_name`. As we are using LLama.cpp we want this to be in the `gguf` format. If the model is already on your machine it will skip the download.
100
+ - `--filename-suffix` (optional, default "Q4_K.gguf"): You can specify which suffix of the file to use. This option is applied when specifying model using the Hugging Face repository.
101
+ - `--n-clusters` (optional, default 8): Number of clusters for Drain to organize log chunks into. This only makes sense when you are summarizing with Drain.
102
+ - `--prompts PROMPTS` (Deprecated, replaced by `--prompts-config`) Path to prompt configuration file.
103
+ - `--prompts-config PROMPTS` Path to prompt configuration file.
104
+ - `--prompt-templates` Path to prompt template dir. Prompts must be valid Jinja templates, and system prompts must include field `system_time`.
105
+ - `--temperature` Temperature for inference.
106
+ - `--skip-snippets` Path to patterns for skipping snippets.
107
+ - `--csgrep` Use csgrep to process the log.
106
108
 
107
109
  Example usage:
108
110
 
@@ -112,21 +114,27 @@ Or if the log file is stored locally:
112
114
 
113
115
  logdetective ./data/logs.txt
114
116
 
115
- Examples of using different models. Note the use of `--filename_suffix` (or `-F`) option, useful for models that were quantized:
117
+ Examples of using different models. Note the use of `--filename-suffix` (or `-F`) option, useful for models that were quantized:
116
118
 
117
- logdetective https://example.com/logs.txt --model QuantFactory/Meta-Llama-3-8B-Instruct-GGUF --filename_suffix Q5_K_S.gguf
119
+ logdetective https://example.com/logs.txt --model QuantFactory/Meta-Llama-3-8B-Instruct-GGUF --filename-suffix Q5_K_S.gguf
118
120
  logdetective https://kojipkgs.fedoraproject.org//work/tasks/3367/131313367/build.log --model 'fedora-copr/granite-3.2-8b-instruct-GGUF' -F Q4_K_M.gguf
119
121
 
120
122
  Example of altered prompts:
121
123
 
122
- cp ~/.local/lib/python3.13/site-packages/logdetective/prompts.yml ~/my-prompts.yml
123
- vi ~/my-prompts.yml # edit the prompts there to better fit your needs
124
- logdetective https://kojipkgs.fedoraproject.org//work/tasks/3367/131313367/build.log --prompts ~/my-prompts.yml
124
+ cp -r ~/.local/lib/python3.13/site-packages/logdetective/prompts ~/my-prompts
125
+ vi ~/my-prompts/system_prompt.j2 # edit the system prompt there to better fit your needs
126
+ logdetective https://kojipkgs.fedoraproject.org//work/tasks/3367/131313367/build.log --prompt-templates ~/my-prompts
127
+
128
+ Example of altered prompts (Deprecated):
129
+
130
+ cp ~/.local/lib/python3.13/site-packages/logdetective/prompts.yml ~/my-prompts.yml
131
+ vi ~/my-prompts.yml # edit the prompts there to better fit your needs
132
+ logdetective https://kojipkgs.fedoraproject.org//work/tasks/3367/131313367/build.log --prompts ~/my-prompts.yml
125
133
 
126
134
 
127
135
  Note that streaming with some models (notably Meta-Llama-3) is broken and can be worked around by `no-stream` option:
128
136
 
129
- logdetective https://example.com/logs.txt --model QuantFactory/Meta-Llama-3-8B-Instruct-GGUF --filename_suffix Q5_K_M.gguf --no-stream
137
+ logdetective https://example.com/logs.txt --model QuantFactory/Meta-Llama-3-8B-Instruct-GGUF --filename-suffix Q5_K_M.gguf --no-stream
130
138
 
131
139
  Choice of LLM
132
140
  -------------
@@ -205,7 +213,8 @@ message is reported indicating that the 'check' phase of the rpm build process
205
213
  failed with a bad exit status.
206
214
  ```
207
215
 
208
- It looks like a wall of text. Similar to any log. The main difference is that here we have the most significant lines of a logfile wrapped in `[ ] : ` and followed by textual explanation of the log text done by mistral 7b.
216
+ It looks like a wall of text. Similar to any log.
217
+ The main difference is that here we have the most significant lines of a logfile wrapped in `[ ] : ` and followed by textual explanation of the log text done by local LLM.
209
218
 
210
219
 
211
220
  Contributing
@@ -373,14 +382,14 @@ Before doing `podman-compose up`, make sure to set `MODELS_PATH` environment var
373
382
  ```
374
383
  $ export MODELS_PATH=/path/to/models/
375
384
  $ ll $MODELS_PATH
376
- -rw-r--r--. 1 tt tt 3.9G apr 10 17:18 mistral-7b-instruct-v0.2.Q4_K_S.gguf
385
+ -rw-r--r--. 1 tt tt 3.9G apr 10 17:18 granite-4.0-h-tiny-Q8_0.gguf
377
386
  ```
378
387
 
379
388
  If the variable is not set, `./models` is mounted inside by default.
380
389
 
381
390
  Model can be downloaded from [our Hugging Space](https://huggingface.co/fedora-copr) by:
382
391
  ```
383
- $ curl -L -o models/mistral-7b-instruct-v0.3.Q4_K.gguf https://huggingface.co/fedora-copr/Mistral-7B-Instruct-v0.3-GGUF/resolve/main/ggml-model-Q4_K.gguf
392
+ $ curl -L -o models/granite-3.2-8b-instruct-v0.3.Q4_K.gguf https://huggingface.co/fedora-copr/granite-3.2-8b-instruct-GGUF/resolve/main/ggml-model-Q4_K.gguf
384
393
  ```
385
394
 
386
395
  Filtering snippet analysis by relevance
@@ -500,17 +509,38 @@ http GET "localhost:8080/metrics/analyze/requests?weeks=5" > /tmp/plot_weeks.svg
500
509
  System Prompts
501
510
  --------------
502
511
 
503
- Prompt templates used by Log Detective are stored in the `prompts.yml` file.
512
+ Prompts are defined as Jinja templates and placed in location specified by `--prompt-templates` option of the CLI utility, or `LOGDETECTIVE_PROMPT_TEMPLATES` environment variable of the container service. With further, optional, configuration in the `prompts.yml` configuration file.
513
+
514
+ All system prompt templates must include place for `system_time` variable.
515
+
516
+ If `references` list is defined in `prompts.yml`, templates must also include a handling for a list of references.
517
+
518
+ Example:
519
+
520
+ ```jinja
521
+ {% if references %}
522
+ ## References:
523
+
524
+ {% for reference in references %}
525
+ * {{ reference.name }} : {{ reference.link }}
526
+ {% endfor %}
527
+ {% endif %}
528
+
529
+ ```
530
+
531
+ *Deprecated:*
532
+
533
+ *Prompt templates used by Log Detective are stored in the `prompts.yml` file.
504
534
  It is possible to modify the file in place, or provide your own.
505
535
  In CLI you can override prompt templates location using `--prompts` option,
506
536
  while in the container service deployment the `LOGDETECTIVE_PROMPTS` environment variable
507
- is used instead.
537
+ is used instead.*
508
538
 
509
- Prompts need to have a form compatible with python [format string syntax](https://docs.python.org/3/library/string.html#format-string-syntax)
510
- with spaces, or replacement fields marked with curly braces, `{}` left for insertion of snippets.
539
+ *Prompts need to have a form compatible with python [format string syntax](https://docs.python.org/3/library/string.html#format-string-syntax)
540
+ with spaces, or replacement fields marked with curly braces, `{}` left for insertion of snippets.*
511
541
 
512
- Number of replacement fields in new prompts, must be the same as in originals.
513
- Although their position may be different.
542
+ *Number of replacement fields in new prompts, must be the same as in originals.
543
+ Although their position may be different.*
514
544
 
515
545
 
516
546
  Skip Snippets
@@ -42,12 +42,15 @@ Usage
42
42
 
43
43
  To analyze a log file, run the script with the following command line arguments:
44
44
  - `file` (required): The path or URL of the log file to be analyzed.
45
- - `--model` (optional, default: "Mistral-7B-Instruct-v0.3-GGUF"): The path or Hugging space name of the language model for analysis. For models from Hugging Face, write them as `namespace/repo_name`. As we are using LLama.cpp we want this to be in the `gguf` format. If the model is already on your machine it will skip the download.
46
- - `--filename_suffix` (optional, default "Q4_K.gguf"): You can specify which suffix of the file to use. This option is applied when specifying model using the Hugging Face repository.
47
- - `--summarizer` DISABLED: LLM summarization option was removed. Argument is kept for backward compatibility only.(optional, default: "drain"): Choose between LLM and Drain template miner as the log summarizer. You can also provide the path to an existing language model file instead of using a URL.
48
- - `--n_lines` DISABLED: LLM summarization option was removed. Argument is kept for backward compatibility only. (optional, default: 8): The number of lines per chunk for LLM analysis. This only makes sense when you are summarizing with LLM.
49
- - `--n_clusters` (optional, default 8): Number of clusters for Drain to organize log chunks into. This only makes sense when you are summarizing with Drain.
50
- - `--skip_snippets` Path to patterns for skipping snippets (in YAML).
45
+ - `--model` (optional, default: "granite-3.2-8b-instruct-GGUF"): The path or Hugging space name of the language model for analysis. For models from Hugging Face, write them as `namespace/repo_name`. As we are using LLama.cpp we want this to be in the `gguf` format. If the model is already on your machine it will skip the download.
46
+ - `--filename-suffix` (optional, default "Q4_K.gguf"): You can specify which suffix of the file to use. This option is applied when specifying model using the Hugging Face repository.
47
+ - `--n-clusters` (optional, default 8): Number of clusters for Drain to organize log chunks into. This only makes sense when you are summarizing with Drain.
48
+ - `--prompts PROMPTS` (Deprecated, replaced by `--prompts-config`) Path to prompt configuration file.
49
+ - `--prompts-config PROMPTS` Path to prompt configuration file.
50
+ - `--prompt-templates` Path to prompt template dir. Prompts must be valid Jinja templates, and system prompts must include field `system_time`.
51
+ - `--temperature` Temperature for inference.
52
+ - `--skip-snippets` Path to patterns for skipping snippets.
53
+ - `--csgrep` Use csgrep to process the log.
51
54
 
52
55
  Example usage:
53
56
 
@@ -57,21 +60,27 @@ Or if the log file is stored locally:
57
60
 
58
61
  logdetective ./data/logs.txt
59
62
 
60
- Examples of using different models. Note the use of `--filename_suffix` (or `-F`) option, useful for models that were quantized:
63
+ Examples of using different models. Note the use of `--filename-suffix` (or `-F`) option, useful for models that were quantized:
61
64
 
62
- logdetective https://example.com/logs.txt --model QuantFactory/Meta-Llama-3-8B-Instruct-GGUF --filename_suffix Q5_K_S.gguf
65
+ logdetective https://example.com/logs.txt --model QuantFactory/Meta-Llama-3-8B-Instruct-GGUF --filename-suffix Q5_K_S.gguf
63
66
  logdetective https://kojipkgs.fedoraproject.org//work/tasks/3367/131313367/build.log --model 'fedora-copr/granite-3.2-8b-instruct-GGUF' -F Q4_K_M.gguf
64
67
 
65
68
  Example of altered prompts:
66
69
 
67
- cp ~/.local/lib/python3.13/site-packages/logdetective/prompts.yml ~/my-prompts.yml
68
- vi ~/my-prompts.yml # edit the prompts there to better fit your needs
69
- logdetective https://kojipkgs.fedoraproject.org//work/tasks/3367/131313367/build.log --prompts ~/my-prompts.yml
70
+ cp -r ~/.local/lib/python3.13/site-packages/logdetective/prompts ~/my-prompts
71
+ vi ~/my-prompts/system_prompt.j2 # edit the system prompt there to better fit your needs
72
+ logdetective https://kojipkgs.fedoraproject.org//work/tasks/3367/131313367/build.log --prompt-templates ~/my-prompts
73
+
74
+ Example of altered prompts (Deprecated):
75
+
76
+ cp ~/.local/lib/python3.13/site-packages/logdetective/prompts.yml ~/my-prompts.yml
77
+ vi ~/my-prompts.yml # edit the prompts there to better fit your needs
78
+ logdetective https://kojipkgs.fedoraproject.org//work/tasks/3367/131313367/build.log --prompts ~/my-prompts.yml
70
79
 
71
80
 
72
81
  Note that streaming with some models (notably Meta-Llama-3) is broken and can be worked around by `no-stream` option:
73
82
 
74
- logdetective https://example.com/logs.txt --model QuantFactory/Meta-Llama-3-8B-Instruct-GGUF --filename_suffix Q5_K_M.gguf --no-stream
83
+ logdetective https://example.com/logs.txt --model QuantFactory/Meta-Llama-3-8B-Instruct-GGUF --filename-suffix Q5_K_M.gguf --no-stream
75
84
 
76
85
  Choice of LLM
77
86
  -------------
@@ -150,7 +159,8 @@ message is reported indicating that the 'check' phase of the rpm build process
150
159
  failed with a bad exit status.
151
160
  ```
152
161
 
153
- It looks like a wall of text. Similar to any log. The main difference is that here we have the most significant lines of a logfile wrapped in `[ ] : ` and followed by textual explanation of the log text done by mistral 7b.
162
+ It looks like a wall of text. Similar to any log.
163
+ The main difference is that here we have the most significant lines of a logfile wrapped in `[ ] : ` and followed by textual explanation of the log text done by local LLM.
154
164
 
155
165
 
156
166
  Contributing
@@ -318,14 +328,14 @@ Before doing `podman-compose up`, make sure to set `MODELS_PATH` environment var
318
328
  ```
319
329
  $ export MODELS_PATH=/path/to/models/
320
330
  $ ll $MODELS_PATH
321
- -rw-r--r--. 1 tt tt 3.9G apr 10 17:18 mistral-7b-instruct-v0.2.Q4_K_S.gguf
331
+ -rw-r--r--. 1 tt tt 3.9G apr 10 17:18 granite-4.0-h-tiny-Q8_0.gguf
322
332
  ```
323
333
 
324
334
  If the variable is not set, `./models` is mounted inside by default.
325
335
 
326
336
  Model can be downloaded from [our Hugging Space](https://huggingface.co/fedora-copr) by:
327
337
  ```
328
- $ curl -L -o models/mistral-7b-instruct-v0.3.Q4_K.gguf https://huggingface.co/fedora-copr/Mistral-7B-Instruct-v0.3-GGUF/resolve/main/ggml-model-Q4_K.gguf
338
+ $ curl -L -o models/granite-3.2-8b-instruct-v0.3.Q4_K.gguf https://huggingface.co/fedora-copr/granite-3.2-8b-instruct-GGUF/resolve/main/ggml-model-Q4_K.gguf
329
339
  ```
330
340
 
331
341
  Filtering snippet analysis by relevance
@@ -445,17 +455,38 @@ http GET "localhost:8080/metrics/analyze/requests?weeks=5" > /tmp/plot_weeks.svg
445
455
  System Prompts
446
456
  --------------
447
457
 
448
- Prompt templates used by Log Detective are stored in the `prompts.yml` file.
458
+ Prompts are defined as Jinja templates and placed in location specified by `--prompt-templates` option of the CLI utility, or `LOGDETECTIVE_PROMPT_TEMPLATES` environment variable of the container service. With further, optional, configuration in the `prompts.yml` configuration file.
459
+
460
+ All system prompt templates must include place for `system_time` variable.
461
+
462
+ If `references` list is defined in `prompts.yml`, templates must also include a handling for a list of references.
463
+
464
+ Example:
465
+
466
+ ```jinja
467
+ {% if references %}
468
+ ## References:
469
+
470
+ {% for reference in references %}
471
+ * {{ reference.name }} : {{ reference.link }}
472
+ {% endfor %}
473
+ {% endif %}
474
+
475
+ ```
476
+
477
+ *Deprecated:*
478
+
479
+ *Prompt templates used by Log Detective are stored in the `prompts.yml` file.
449
480
  It is possible to modify the file in place, or provide your own.
450
481
  In CLI you can override prompt templates location using `--prompts` option,
451
482
  while in the container service deployment the `LOGDETECTIVE_PROMPTS` environment variable
452
- is used instead.
483
+ is used instead.*
453
484
 
454
- Prompts need to have a form compatible with python [format string syntax](https://docs.python.org/3/library/string.html#format-string-syntax)
455
- with spaces, or replacement fields marked with curly braces, `{}` left for insertion of snippets.
485
+ *Prompts need to have a form compatible with python [format string syntax](https://docs.python.org/3/library/string.html#format-string-syntax)
486
+ with spaces, or replacement fields marked with curly braces, `{}` left for insertion of snippets.*
456
487
 
457
- Number of replacement fields in new prompts, must be the same as in originals.
458
- Although their position may be different.
488
+ *Number of replacement fields in new prompts, must be the same as in originals.
489
+ Although their position may be different.*
459
490
 
460
491
 
461
492
  Skip Snippets
@@ -4,7 +4,7 @@ in prompts.yaml instead.
4
4
  """
5
5
 
6
6
  # pylint: disable=line-too-long
7
- DEFAULT_ADVISOR = "fedora-copr/Mistral-7B-Instruct-v0.3-GGUF"
7
+ DEFAULT_ADVISOR = "fedora-copr/granite-3.2-8b-instruct-GGUF"
8
8
 
9
9
  PROMPT_TEMPLATE = """
10
10
  Given following log snippets, and nothing else, explain what failure, if any, occured during build of this package.
@@ -41,31 +41,15 @@ def setup_args():
41
41
  )
42
42
  parser.add_argument(
43
43
  "-F",
44
- "--filename_suffix",
44
+ "--filename-suffix",
45
45
  help="Suffix of the model file name to be retrieved from Hugging Face.\
46
46
  Makes sense only if the model is specified with Hugging Face name.",
47
47
  default="Q4_K.gguf",
48
48
  )
49
49
  parser.add_argument("-n", "--no-stream", action="store_true")
50
- parser.add_argument(
51
- "-S",
52
- "--summarizer",
53
- type=str,
54
- default="drain",
55
- help="DISABLED: LLM summarization option was removed. \
56
- Argument is kept for backward compatibility only.",
57
- )
58
- parser.add_argument(
59
- "-N",
60
- "--n_lines",
61
- type=int,
62
- default=None,
63
- help="DISABLED: LLM summarization option was removed. \
64
- Argument is kept for backward compatibility only.",
65
- )
66
50
  parser.add_argument(
67
51
  "-C",
68
- "--n_clusters",
52
+ "--n-clusters",
69
53
  type=int,
70
54
  default=8,
71
55
  help="Number of clusters for Drain to organize log chunks into.\
@@ -75,10 +59,18 @@ def setup_args():
75
59
  parser.add_argument("-q", "--quiet", action="store_true")
76
60
  parser.add_argument(
77
61
  "--prompts",
62
+ "--prompts-config",
78
63
  type=str,
79
64
  default=f"{os.path.dirname(__file__)}/prompts.yml",
80
65
  help="Path to prompt configuration file.",
81
66
  )
67
+ parser.add_argument(
68
+ "--prompt-templates",
69
+ type=str,
70
+ default=f"{os.path.dirname(__file__)}/prompts",
71
+ help="Path to prompt template dir. Prompts must be valid Jinja templates, \
72
+ and system prompts must include field `system_time`.",
73
+ )
82
74
  parser.add_argument(
83
75
  "--temperature",
84
76
  type=float,
@@ -86,7 +78,7 @@ def setup_args():
86
78
  help="Temperature for inference.",
87
79
  )
88
80
  parser.add_argument(
89
- "--skip_snippets",
81
+ "--skip-snippets",
90
82
  type=str,
91
83
  default=f"{os.path.dirname(__file__)}/skip_snippets.yml",
92
84
  help="Path to patterns for skipping snippets.",
@@ -105,10 +97,6 @@ async def run(): # pylint: disable=too-many-statements,too-many-locals,too-many
105
97
  sys.stderr.write("Error: --quiet and --verbose is mutually exclusive.\n")
106
98
  sys.exit(2)
107
99
 
108
- # Emit warning about use of discontinued args
109
- if args.n_lines or args.summarizer != "drain":
110
- LOG.warning("LLM based summarization was removed. Drain will be used instead.")
111
-
112
100
  # Logging facility setup
113
101
  log_level = logging.INFO
114
102
  if args.verbose >= 1:
@@ -117,7 +105,7 @@ async def run(): # pylint: disable=too-many-statements,too-many-locals,too-many
117
105
  log_level = 0
118
106
 
119
107
  # Get prompts configuration
120
- prompts_configuration = load_prompts(args.prompts)
108
+ prompts_configuration = load_prompts(args.prompts, args.prompt_templates)
121
109
 
122
110
  logging.basicConfig(stream=sys.stdout)
123
111
  LOG.setLevel(log_level)
@@ -21,26 +21,7 @@ class PromptConfig(BaseModel):
21
21
  snippet_system_prompt: str = DEFAULT_SYSTEM_PROMPT
22
22
  staged_system_prompt: str = DEFAULT_SYSTEM_PROMPT
23
23
 
24
- def __init__(self, data: Optional[dict] = None):
25
- super().__init__()
26
- if data is None:
27
- return
28
- self.prompt_template = data.get("prompt_template", PROMPT_TEMPLATE)
29
- self.snippet_prompt_template = data.get(
30
- "snippet_prompt_template", SNIPPET_PROMPT_TEMPLATE
31
- )
32
- self.prompt_template_staged = data.get(
33
- "prompt_template_staged", PROMPT_TEMPLATE_STAGED
34
- )
35
- self.default_system_prompt = data.get(
36
- "default_system_prompt", DEFAULT_SYSTEM_PROMPT
37
- )
38
- self.snippet_system_prompt = data.get(
39
- "snippet_system_prompt", DEFAULT_SYSTEM_PROMPT
40
- )
41
- self.staged_system_prompt = data.get(
42
- "staged_system_prompt", DEFAULT_SYSTEM_PROMPT
43
- )
24
+ references: Optional[list[dict[str, str]]] = None
44
25
 
45
26
 
46
27
  class SkipSnippets(BaseModel):
@@ -0,0 +1,2 @@
1
+ Snippets:
2
+ {}
@@ -0,0 +1,38 @@
1
+ System time: {{ system_time }}
2
+
3
+ You are a highly capable expert system specialized in packaging and delivery of software using RPM,
4
+ within the RHEL ecosystem. Your purpose is to help package maintainers diagnose and resolve package build failures.
5
+ You are truthful, concise, and helpful.
6
+
7
+ ## Input processing
8
+
9
+ You will work with snippets of logs produced during package build.
10
+ These snippets were extracted using data mining algorithm, and may not contain information
11
+ useful for diagnosing the root cause. Snippets without useful information must be disregarded.
12
+
13
+ ## Analysis procedure
14
+
15
+ 1. Provide the snippet with a short explanation.
16
+ 2. If the snippet doesn't contain useful information, indicate the fact with a short sentence.
17
+
18
+ ## Examples:
19
+
20
+ User: "Snippet: RPM build errors:"
21
+ Assistant: "Errors occurred during package build.
22
+ ---
23
+ User: "Snippet: Copr build error: Build failed"
24
+ Assistant: "The build in Copr has failed."
25
+ ---
26
+ User: "Snippet: /bin/tar: Removing leading `/' from member names"
27
+ Assistant: "This snippet is irrelevant."
28
+ ---
29
+
30
+ {% if references %}
31
+ ## References:
32
+
33
+ When necessary, suggest resources that may be helpful to user.
34
+
35
+ {% for reference in references %}
36
+ * {{ reference.name }} : {{ reference.link }}
37
+ {% endfor %}
38
+ {% endif %}
@@ -0,0 +1,45 @@
1
+ System time: {{ system_time }}
2
+
3
+ You are a highly capable expert system specialized in packaging and delivery of software using RPM,
4
+ within the RHEL ecosystem. Your purpose is to help package maintainers diagnose and resolve package build failures.
5
+ You are truthful, concise, and helpful.
6
+
7
+ ## Input processing
8
+
9
+ You will work with snippets of logs produced during package build.
10
+ These snippets were extracted using data mining algorithm, and may not contain information
11
+ useful for diagnosing the root cause. Snippets without useful information must be disregarded.
12
+
13
+ ## Analysis procedure
14
+
15
+ Analyzed snippets are a format of [X] : [Y], where [X] is a log snippet, and [Y] is the explanation.
16
+ Do not reanalyze the raw log [X].
17
+
18
+ Snippets are delimited with '================'.
19
+
20
+ 1. Analyze individual snippets, unless they already have analysis attached.
21
+ 2. Disregard snippets that do not contain useful information.
22
+ 3. Using information from all snippets provide explanation of the issue.
23
+ 4. (Optional) Recommend a solution for the package maintainer, only if the cause is clear.
24
+
25
+ ## Examples:
26
+
27
+ User: "
28
+ Snippets:
29
+ ================
30
+ Snippet No. 1 at line #452:
31
+ [error: command 'gcc' failed: No such file or directory]: [`gcc` compiler is not available in the build environment]
32
+ ================
33
+ Snippet No. 2 at line #452:
34
+ [Copr build error: Build failed]: [Package build in Copr failed]"
35
+ Assistant: "Package build in Copr failed due to missing `gcc` compiler. Ensure that all build requirements are correctly specified in the spec file."
36
+
37
+ {% if references %}
38
+ ## References:
39
+
40
+ When necessary, suggest resources that may be helpful to user.
41
+
42
+ {% for reference in references %}
43
+ * {{ reference.name }} : {{ reference.link }}
44
+ {% endfor %}
45
+ {% endif %}
@@ -0,0 +1,57 @@
1
+ System time: {{ system_time }}
2
+
3
+ You are a highly capable expert system specialized in packaging and delivery of software using RPM,
4
+ within the RHEL ecosystem. Your purpose is to help package maintainers diagnose and resolve package build failures.
5
+ You are truthful, concise, and helpful.
6
+
7
+ ## Input processing
8
+
9
+ You will work with snippets of logs produced during a failed package build.
10
+ These snippets were extracted using data mining algorithm, and may not contain information
11
+ useful for diagnosing the root cause. Snippets without useful information must be disregarded.
12
+ General error messages, such as failure of commands used during build, are expected.
13
+
14
+ ## Temporal Logic and Causality
15
+
16
+ Log snippets are typically provided in chronological order. When analyzing multiple snippets
17
+ the first significant error in the log is usually the root cause.
18
+
19
+ An error occurring at line #500 cannot be caused by an error occurring at line #1000.
20
+
21
+ Subsequent errors are often side effects of the initial failure. Focus your diagnosis on the primary trigger.
22
+
23
+ ## Analysis procedure
24
+
25
+ Snippets are provided in order of appearance in the original log, with attached line number,
26
+ and are delimited with '================'.
27
+ Avoid generic or boilerplate recommendations (e.g., "check the logs," "ensure dependencies are met").
28
+ If a specific root cause is identified, the recommendation must directly address that cause.
29
+
30
+ 1. Analyze individual snippets. Do not quote analyzed snippets.
31
+ 2. Disregard snippets that do not contain useful information.
32
+ 3. Using information from all snippets provide explanation of the issue. Be as specific as possible.
33
+ 4. (Optional) Recommend a solution for the package maintainer, only if the cause is clear.
34
+
35
+ ## Examples:
36
+
37
+ User: "
38
+ Snippets:
39
+ Snippet No. 1 at line #452:
40
+
41
+ error: command 'gcc' failed: No such file or directory
42
+ ================
43
+ Snippet No. 2 at line #560:
44
+
45
+ Copr build error: Build failed
46
+ ================"
47
+ Assistant: "Package build in Copr failed due to missing `gcc` compiler. Ensure that all build requirements are correctly specified in the spec file."
48
+
49
+ {% if references %}
50
+ ## References:
51
+
52
+ When necessary, suggest resources that may be helpful to user.
53
+
54
+ {% for reference in references %}
55
+ * {{ reference.name }} : {{ reference.link }}
56
+ {% endfor %}
57
+ {% endif %}
@@ -0,0 +1,87 @@
1
+ from datetime import datetime, timezone
2
+ from typing import Optional
3
+ from jinja2 import Environment, FileSystemLoader, Template
4
+
5
+ from logdetective.models import PromptConfig
6
+
7
+
8
+ class PromptManager: # pylint: disable=too-many-instance-attributes
9
+ """Manages prompts defined as jinja templates"""
10
+ _tmp_env: Environment
11
+
12
+ # Templates for system prompts
13
+ _default_system_prompt_template: Template
14
+ _snippet_system_prompt_template: Template
15
+ _staged_system_prompt_template: Template
16
+
17
+ # Templates for messages
18
+ default_message_template: Template
19
+ snippet_message_template: Template
20
+ staged_message_template: Template
21
+
22
+ _references: Optional[list[dict[str, str]]] = None
23
+
24
+ def __init__(
25
+ self, prompts_path: str, prompts_configuration: Optional[PromptConfig] = None
26
+ ) -> None:
27
+ self._tmp_env = Environment(loader=FileSystemLoader(prompts_path))
28
+
29
+ self._default_system_prompt_template = self._tmp_env.get_template(
30
+ "system_prompt.j2"
31
+ )
32
+ self._snippet_system_prompt_template = self._tmp_env.get_template(
33
+ "snippet_system_prompt.j2"
34
+ )
35
+ self._staged_system_prompt_template = self._tmp_env.get_template(
36
+ "staged_system_prompt.j2"
37
+ )
38
+
39
+ self.default_message_template = self._tmp_env.get_template(
40
+ "message_template.j2"
41
+ )
42
+ self.snippet_message_template = self._tmp_env.get_template(
43
+ "snippet_message_template.j2"
44
+ )
45
+ self.staged_message_template = self._tmp_env.get_template(
46
+ "staged_message_template.j2"
47
+ )
48
+
49
+ if prompts_configuration:
50
+ self._references = prompts_configuration.references
51
+
52
+ # To maintain backward compatibility with `logdetective.models.PromptConfig`
53
+ @property
54
+ def default_system_prompt(self) -> str:
55
+ """Render system prompt from a template"""
56
+ return self._default_system_prompt_template.render(
57
+ system_time=datetime.now(timezone.utc), references=self._references
58
+ )
59
+
60
+ @property
61
+ def snippet_system_prompt(self) -> str:
62
+ """Render system prompt from a template"""
63
+ return self._snippet_system_prompt_template.render(
64
+ system_time=datetime.now(timezone.utc), references=self._references
65
+ )
66
+
67
+ @property
68
+ def staged_system_prompt(self) -> str:
69
+ """Render system prompt from a template"""
70
+ return self._staged_system_prompt_template.render(
71
+ system_time=datetime.now(timezone.utc), references=self._references
72
+ )
73
+
74
+ @property
75
+ def prompt_template(self) -> str:
76
+ """Render message prompt from the template"""
77
+ return self.default_message_template.render()
78
+
79
+ @property
80
+ def snippet_prompt_template(self) -> str:
81
+ """Render message prompt from the template"""
82
+ return self.snippet_message_template.render()
83
+
84
+ @property
85
+ def prompt_template_staged(self) -> str:
86
+ """Render message prompt from the template"""
87
+ return self.staged_message_template.render()
@@ -88,3 +88,10 @@ staged_system_prompt: |
88
88
  You never speculate about package being built or fabricate information.
89
89
  If you do not know the answer, you acknowledge the fact and end your response.
90
90
  Your responses must be as short as possible.
91
+
92
+ # Optional references, to be used when constructing prompt from Jinja template
93
+ # references:
94
+ # - name: Fedora Packaging Guidelines
95
+ # link: https://docs.fedoraproject.org/en-US/packaging-guidelines/
96
+ # - name: Mock user documentation
97
+ # link: https://rpm-software-management.github.io/mock/