laminate-cli 0.1.2__tar.gz → 0.1.4__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.
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/PKG-INFO +21 -10
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/README.md +20 -10
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/laminate/cli.py +19 -0
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/laminate/llm.py +33 -25
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/laminate_cli.egg-info/PKG-INFO +21 -10
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/laminate_cli.egg-info/requires.txt +1 -0
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/pyproject.toml +3 -2
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/LICENSE +0 -0
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/laminate/__init__.py +0 -0
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/laminate/categorize.py +0 -0
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/laminate/gitlog.py +0 -0
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/laminate/render.py +0 -0
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/laminate_cli.egg-info/SOURCES.txt +0 -0
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/laminate_cli.egg-info/dependency_links.txt +0 -0
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/laminate_cli.egg-info/entry_points.txt +0 -0
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/laminate_cli.egg-info/top_level.txt +0 -0
- {laminate_cli-0.1.2 → laminate_cli-0.1.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: laminate-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Generate release-ready changelogs from git history using a local LLM
|
|
5
5
|
Author-email: Apleut <me@apleut.dev>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -20,6 +20,7 @@ Requires-Dist: llama-cpp-python
|
|
|
20
20
|
Requires-Dist: pydantic
|
|
21
21
|
Requires-Dist: typer
|
|
22
22
|
Requires-Dist: rich
|
|
23
|
+
Requires-Dist: platformdirs
|
|
23
24
|
Dynamic: license-file
|
|
24
25
|
|
|
25
26
|
<div style="text-align: center;">
|
|
@@ -97,25 +98,35 @@ pip install llama-cpp-python --extra-index-url https://abetlen.github.io/llama-c
|
|
|
97
98
|
Then install Laminate:
|
|
98
99
|
|
|
99
100
|
```bash
|
|
100
|
-
pip install
|
|
101
|
+
pip install laminate-cli
|
|
101
102
|
```
|
|
102
103
|
|
|
103
104
|
## Model
|
|
104
105
|
|
|
105
106
|
Laminate runs a **local GGUF model** using [`llama-cpp-python`](https://github.com/abetlen/llama-cpp-python).
|
|
106
107
|
|
|
107
|
-
|
|
108
|
+
[Phi-4-mini-instruct](https://huggingface.co/unsloth/Phi-4-mini-instruct-GGUF) is a good pick, and is the model used for Laminate's development.
|
|
108
109
|
|
|
109
|
-
|
|
110
|
-
models/
|
|
111
|
-
└── your-model.gguf
|
|
112
|
-
```
|
|
110
|
+
Laminate looks for exactly one `.gguf` file in two places, in this order:
|
|
113
111
|
|
|
114
|
-
|
|
112
|
+
1. **A `models/` folder in your current directory**, which the recommended location if you're running Laminate from a cloned repo:
|
|
113
|
+
|
|
114
|
+
```text
|
|
115
|
+
models/
|
|
116
|
+
└── your-model.gguf
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
2. **Your OS's standard application data folder**, under `Laminate/models/`, used automatically if no local `models/` folder is found. This is the normal location if you installed via `pip install laminate-cli`:
|
|
120
|
+
|
|
121
|
+
| OS | Location |
|
|
122
|
+
|---|---|
|
|
123
|
+
| Windows | `%LOCALAPPDATA%\Apleut\Laminate\models\` |
|
|
124
|
+
| macOS | `~/Library/Application Support/Laminate/models/` |
|
|
125
|
+
| Linux | `~/.local/share/Laminate/models/` |
|
|
115
126
|
|
|
116
|
-
|
|
127
|
+
Create the folder if it doesn't already exist, and place your `.gguf` file inside.
|
|
117
128
|
|
|
118
|
-
If
|
|
129
|
+
If Laminate can't find a model, or finds more than one `.gguf` file in whichever folder it checks, it will stop and tell you exactly which locations it looked in and what to fix.
|
|
119
130
|
|
|
120
131
|
The model is intentionally kept separate from the package because GGUF models can be large and have different licensing requirements.
|
|
121
132
|
|
|
@@ -73,25 +73,35 @@ pip install llama-cpp-python --extra-index-url https://abetlen.github.io/llama-c
|
|
|
73
73
|
Then install Laminate:
|
|
74
74
|
|
|
75
75
|
```bash
|
|
76
|
-
pip install
|
|
76
|
+
pip install laminate-cli
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
## Model
|
|
80
80
|
|
|
81
81
|
Laminate runs a **local GGUF model** using [`llama-cpp-python`](https://github.com/abetlen/llama-cpp-python).
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
[Phi-4-mini-instruct](https://huggingface.co/unsloth/Phi-4-mini-instruct-GGUF) is a good pick, and is the model used for Laminate's development.
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
models/
|
|
87
|
-
└── your-model.gguf
|
|
88
|
-
```
|
|
85
|
+
Laminate looks for exactly one `.gguf` file in two places, in this order:
|
|
89
86
|
|
|
90
|
-
|
|
87
|
+
1. **A `models/` folder in your current directory**, which the recommended location if you're running Laminate from a cloned repo:
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
models/
|
|
91
|
+
└── your-model.gguf
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
2. **Your OS's standard application data folder**, under `Laminate/models/`, used automatically if no local `models/` folder is found. This is the normal location if you installed via `pip install laminate-cli`:
|
|
95
|
+
|
|
96
|
+
| OS | Location |
|
|
97
|
+
|---|---|
|
|
98
|
+
| Windows | `%LOCALAPPDATA%\Apleut\Laminate\models\` |
|
|
99
|
+
| macOS | `~/Library/Application Support/Laminate/models/` |
|
|
100
|
+
| Linux | `~/.local/share/Laminate/models/` |
|
|
91
101
|
|
|
92
|
-
|
|
102
|
+
Create the folder if it doesn't already exist, and place your `.gguf` file inside.
|
|
93
103
|
|
|
94
|
-
If
|
|
104
|
+
If Laminate can't find a model, or finds more than one `.gguf` file in whichever folder it checks, it will stop and tell you exactly which locations it looked in and what to fix.
|
|
95
105
|
|
|
96
106
|
The model is intentionally kept separate from the package because GGUF models can be large and have different licensing requirements.
|
|
97
107
|
|
|
@@ -287,4 +297,4 @@ For changes to Laminate itself, pull requests are welcome.
|
|
|
287
297
|
|
|
288
298
|
## License
|
|
289
299
|
|
|
290
|
-
License information will be added before the first stable release.
|
|
300
|
+
License information will be added before the first stable release.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import typer
|
|
2
2
|
|
|
3
3
|
from concurrent.futures import ThreadPoolExecutor
|
|
4
|
+
from importlib.metadata import version as get_version, PackageNotFoundError
|
|
4
5
|
|
|
5
6
|
import sys
|
|
6
7
|
|
|
@@ -17,6 +18,17 @@ app = typer.Typer(add_completion=False)
|
|
|
17
18
|
console = Console()
|
|
18
19
|
|
|
19
20
|
|
|
21
|
+
def _version_callback(value: bool):
|
|
22
|
+
if not value:
|
|
23
|
+
return
|
|
24
|
+
try:
|
|
25
|
+
v = get_version("laminate-cli")
|
|
26
|
+
except PackageNotFoundError:
|
|
27
|
+
v = "unknown (not installed as a package)"
|
|
28
|
+
typer.echo(f"laminate {v}")
|
|
29
|
+
raise typer.Exit()
|
|
30
|
+
|
|
31
|
+
|
|
20
32
|
@app.command()
|
|
21
33
|
def generate(
|
|
22
34
|
repo: str = typer.Option(".", help="Path to the git repository."),
|
|
@@ -26,6 +38,13 @@ def generate(
|
|
|
26
38
|
output: str = typer.Option("CHANGELOG.md", help="Path to write the generated changelog to."),
|
|
27
39
|
batch_size: int = typer.Option(15, "--batch-size", help="Number of commits sent to the LLM per batch."),
|
|
28
40
|
release: str = typer.Option(None, "--release", help="Version number for this release, e.g. 1.1.0. If omitted, the changelog is headed [Unreleased]."),
|
|
41
|
+
version: bool = typer.Option(
|
|
42
|
+
False,
|
|
43
|
+
"--version",
|
|
44
|
+
callback=_version_callback,
|
|
45
|
+
is_eager=True,
|
|
46
|
+
help="Show Laminate's version and exit.",
|
|
47
|
+
),
|
|
29
48
|
):
|
|
30
49
|
if repo != ".":
|
|
31
50
|
typer.echo(f"Reading commits from '{repo}'...")
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
from llama_cpp import Llama
|
|
3
|
+
from platformdirs import user_data_dir
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
_CANDIDATE_DIRS = [
|
|
6
|
+
Path.cwd() / "models",
|
|
7
|
+
Path(user_data_dir("Laminate", "Apleut")) / "models",
|
|
8
|
+
]
|
|
5
9
|
|
|
6
|
-
DEFAULT_N_CTX = 4096
|
|
10
|
+
DEFAULT_N_CTX = 4096
|
|
7
11
|
_llm: Llama | None = None
|
|
8
12
|
|
|
9
13
|
|
|
@@ -12,29 +16,33 @@ class LLMError(Exception):
|
|
|
12
16
|
|
|
13
17
|
|
|
14
18
|
def _find_model_file() -> Path:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
19
|
+
checked = []
|
|
20
|
+
|
|
21
|
+
for candidate_dir in _CANDIDATE_DIRS:
|
|
22
|
+
checked.append(str(candidate_dir))
|
|
23
|
+
|
|
24
|
+
if not candidate_dir.exists():
|
|
25
|
+
continue
|
|
26
|
+
|
|
27
|
+
gguf_files = list(candidate_dir.glob("*.gguf"))
|
|
28
|
+
|
|
29
|
+
if len(gguf_files) == 1:
|
|
30
|
+
return gguf_files[0]
|
|
31
|
+
|
|
32
|
+
if len(gguf_files) > 1:
|
|
33
|
+
names = ", ".join(f.name for f in gguf_files)
|
|
34
|
+
raise LLMError(
|
|
35
|
+
f"Multiple .gguf files found in {candidate_dir} ({names}) - "
|
|
36
|
+
"keep only one so Laminate knows which to load."
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
checked_str = "\n - ".join(checked)
|
|
40
|
+
raise LLMError(
|
|
41
|
+
"No .gguf model file found. Laminate checked:\n - "
|
|
42
|
+
f"{checked_str}\n"
|
|
43
|
+
"Download a compatible model (see README) and place it in one "
|
|
44
|
+
"of those folders (create the folder if it doesn't exist)."
|
|
45
|
+
)
|
|
38
46
|
|
|
39
47
|
|
|
40
48
|
def get_llm(n_ctx: int = DEFAULT_N_CTX) -> Llama:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: laminate-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Generate release-ready changelogs from git history using a local LLM
|
|
5
5
|
Author-email: Apleut <me@apleut.dev>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -20,6 +20,7 @@ Requires-Dist: llama-cpp-python
|
|
|
20
20
|
Requires-Dist: pydantic
|
|
21
21
|
Requires-Dist: typer
|
|
22
22
|
Requires-Dist: rich
|
|
23
|
+
Requires-Dist: platformdirs
|
|
23
24
|
Dynamic: license-file
|
|
24
25
|
|
|
25
26
|
<div style="text-align: center;">
|
|
@@ -97,25 +98,35 @@ pip install llama-cpp-python --extra-index-url https://abetlen.github.io/llama-c
|
|
|
97
98
|
Then install Laminate:
|
|
98
99
|
|
|
99
100
|
```bash
|
|
100
|
-
pip install
|
|
101
|
+
pip install laminate-cli
|
|
101
102
|
```
|
|
102
103
|
|
|
103
104
|
## Model
|
|
104
105
|
|
|
105
106
|
Laminate runs a **local GGUF model** using [`llama-cpp-python`](https://github.com/abetlen/llama-cpp-python).
|
|
106
107
|
|
|
107
|
-
|
|
108
|
+
[Phi-4-mini-instruct](https://huggingface.co/unsloth/Phi-4-mini-instruct-GGUF) is a good pick, and is the model used for Laminate's development.
|
|
108
109
|
|
|
109
|
-
|
|
110
|
-
models/
|
|
111
|
-
└── your-model.gguf
|
|
112
|
-
```
|
|
110
|
+
Laminate looks for exactly one `.gguf` file in two places, in this order:
|
|
113
111
|
|
|
114
|
-
|
|
112
|
+
1. **A `models/` folder in your current directory**, which the recommended location if you're running Laminate from a cloned repo:
|
|
113
|
+
|
|
114
|
+
```text
|
|
115
|
+
models/
|
|
116
|
+
└── your-model.gguf
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
2. **Your OS's standard application data folder**, under `Laminate/models/`, used automatically if no local `models/` folder is found. This is the normal location if you installed via `pip install laminate-cli`:
|
|
120
|
+
|
|
121
|
+
| OS | Location |
|
|
122
|
+
|---|---|
|
|
123
|
+
| Windows | `%LOCALAPPDATA%\Apleut\Laminate\models\` |
|
|
124
|
+
| macOS | `~/Library/Application Support/Laminate/models/` |
|
|
125
|
+
| Linux | `~/.local/share/Laminate/models/` |
|
|
115
126
|
|
|
116
|
-
|
|
127
|
+
Create the folder if it doesn't already exist, and place your `.gguf` file inside.
|
|
117
128
|
|
|
118
|
-
If
|
|
129
|
+
If Laminate can't find a model, or finds more than one `.gguf` file in whichever folder it checks, it will stop and tell you exactly which locations it looked in and what to fix.
|
|
119
130
|
|
|
120
131
|
The model is intentionally kept separate from the package because GGUF models can be large and have different licensing requirements.
|
|
121
132
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "laminate-cli"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.4"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name="Apleut", email="me@apleut.dev" },
|
|
6
6
|
]
|
|
@@ -22,6 +22,7 @@ dependencies = [
|
|
|
22
22
|
"pydantic",
|
|
23
23
|
"typer",
|
|
24
24
|
"rich",
|
|
25
|
+
"platformdirs",
|
|
25
26
|
]
|
|
26
27
|
|
|
27
28
|
license = "MIT"
|
|
@@ -42,4 +43,4 @@ requires = ["setuptools>=68"]
|
|
|
42
43
|
build-backend = "setuptools.build_meta"
|
|
43
44
|
|
|
44
45
|
[tool.setuptools.packages.find]
|
|
45
|
-
include = ["laminate*"]
|
|
46
|
+
include = ["laminate*"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|