lepika 0.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.
- lepika-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +64 -0
- lepika-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- lepika-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +23 -0
- lepika-0.1.0/.github/ISSUE_TEMPLATE/question.yml +11 -0
- lepika-0.1.0/.github/dependabot.yml +7 -0
- lepika-0.1.0/.github/pull_request_template.md +13 -0
- lepika-0.1.0/.github/workflows/ci.yml +52 -0
- lepika-0.1.0/.github/workflows/release.yml +49 -0
- lepika-0.1.0/.gitignore +27 -0
- lepika-0.1.0/.pre-commit-config.yaml +7 -0
- lepika-0.1.0/CONTRIBUTING.md +57 -0
- lepika-0.1.0/LICENSE +21 -0
- lepika-0.1.0/PKG-INFO +183 -0
- lepika-0.1.0/README.md +151 -0
- lepika-0.1.0/SECURITY.md +30 -0
- lepika-0.1.0/docs/architecture.md +62 -0
- lepika-0.1.0/docs/assets/demo.gif +0 -0
- lepika-0.1.0/docs/assets/demo.tape +35 -0
- lepika-0.1.0/docs/assets/logo.png +0 -0
- lepika-0.1.0/docs/models.md +49 -0
- lepika-0.1.0/docs/server-mode.md +68 -0
- lepika-0.1.0/install.ps1 +34 -0
- lepika-0.1.0/install.sh +35 -0
- lepika-0.1.0/models.toml +54 -0
- lepika-0.1.0/pyproject.toml +82 -0
- lepika-0.1.0/src/lepika/__init__.py +1 -0
- lepika-0.1.0/src/lepika/acquire.py +221 -0
- lepika-0.1.0/src/lepika/cli.py +544 -0
- lepika-0.1.0/src/lepika/config.py +87 -0
- lepika-0.1.0/src/lepika/detect.py +163 -0
- lepika-0.1.0/src/lepika/doctor.py +124 -0
- lepika-0.1.0/src/lepika/engine.py +421 -0
- lepika-0.1.0/src/lepika/errors.py +10 -0
- lepika-0.1.0/src/lepika/express.py +784 -0
- lepika-0.1.0/src/lepika/hf.py +274 -0
- lepika-0.1.0/src/lepika/log.py +57 -0
- lepika-0.1.0/src/lepika/models.py +133 -0
- lepika-0.1.0/src/lepika/paths.py +40 -0
- lepika-0.1.0/src/lepika/proc.py +145 -0
- lepika-0.1.0/src/lepika/py.typed +0 -0
- lepika-0.1.0/src/lepika/server.py +521 -0
- lepika-0.1.0/src/lepika/stack/Caddyfile +14 -0
- lepika-0.1.0/src/lepika/stack/compose.nvidia.yml +10 -0
- lepika-0.1.0/src/lepika/stack/compose.yml +71 -0
- lepika-0.1.0/src/lepika/wizard.py +238 -0
- lepika-0.1.0/tests/conftest.py +41 -0
- lepika-0.1.0/tests/fakes.py +45 -0
- lepika-0.1.0/tests/test_cli.py +85 -0
- lepika-0.1.0/tests/test_cli_connect.py +229 -0
- lepika-0.1.0/tests/test_cli_expose.py +211 -0
- lepika-0.1.0/tests/test_cli_lifecycle.py +199 -0
- lepika-0.1.0/tests/test_cli_models.py +733 -0
- lepika-0.1.0/tests/test_cli_server.py +82 -0
- lepika-0.1.0/tests/test_cli_update.py +101 -0
- lepika-0.1.0/tests/test_config.py +128 -0
- lepika-0.1.0/tests/test_conftest_guards.py +27 -0
- lepika-0.1.0/tests/test_detect.py +136 -0
- lepika-0.1.0/tests/test_doctor.py +312 -0
- lepika-0.1.0/tests/test_engine.py +538 -0
- lepika-0.1.0/tests/test_express_ollama.py +712 -0
- lepika-0.1.0/tests/test_express_webui.py +610 -0
- lepika-0.1.0/tests/test_hf.py +310 -0
- lepika-0.1.0/tests/test_log.py +50 -0
- lepika-0.1.0/tests/test_models.py +150 -0
- lepika-0.1.0/tests/test_paths.py +32 -0
- lepika-0.1.0/tests/test_proc.py +155 -0
- lepika-0.1.0/tests/test_server_env.py +269 -0
- lepika-0.1.0/tests/test_server_stack.py +256 -0
- lepika-0.1.0/tests/test_vllm.py +364 -0
- lepika-0.1.0/tests/test_wizard.py +242 -0
- lepika-0.1.0/tests/test_wizard_mode.py +348 -0
- lepika-0.1.0/uv.lock +1144 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something LePika did, or failed to do, on your machine.
|
|
3
|
+
labels: ["bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for the report. The two command outputs below are what make a bug fixable in one round, so please paste them in full. LePika masks keys and tokens in its logs; still, skim before you paste.
|
|
9
|
+
- type: textarea
|
|
10
|
+
id: what-happened
|
|
11
|
+
attributes:
|
|
12
|
+
label: What happened
|
|
13
|
+
description: What you ran, what you saw, and what you expected instead.
|
|
14
|
+
placeholder: |
|
|
15
|
+
I ran `lepika` and picked Express mode. After pulling the model it printed
|
|
16
|
+
"✗ OpenWebUI did not become ready within 180s". I expected the browser to open.
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: doctor
|
|
21
|
+
attributes:
|
|
22
|
+
label: Output of `lepika doctor`
|
|
23
|
+
render: text
|
|
24
|
+
validations:
|
|
25
|
+
required: true
|
|
26
|
+
- type: textarea
|
|
27
|
+
id: logs
|
|
28
|
+
attributes:
|
|
29
|
+
label: Output of `lepika logs`
|
|
30
|
+
description: Paste the whole thing; the last lines are usually the useful ones.
|
|
31
|
+
render: text
|
|
32
|
+
validations:
|
|
33
|
+
required: true
|
|
34
|
+
- type: input
|
|
35
|
+
id: version
|
|
36
|
+
attributes:
|
|
37
|
+
label: LePika version
|
|
38
|
+
description: Output of `lepika --version`.
|
|
39
|
+
placeholder: lepika 0.1.0
|
|
40
|
+
validations:
|
|
41
|
+
required: true
|
|
42
|
+
- type: dropdown
|
|
43
|
+
id: mode
|
|
44
|
+
attributes:
|
|
45
|
+
label: Mode
|
|
46
|
+
options:
|
|
47
|
+
- Express (default, no Docker)
|
|
48
|
+
- Server (docker compose)
|
|
49
|
+
- Not sure
|
|
50
|
+
validations:
|
|
51
|
+
required: true
|
|
52
|
+
- type: input
|
|
53
|
+
id: machine
|
|
54
|
+
attributes:
|
|
55
|
+
label: Machine
|
|
56
|
+
description: OS and version, and the GPU if you have one.
|
|
57
|
+
placeholder: Windows 11, RTX 4070 · macOS 15, M2 · Ubuntu 24.04, no GPU
|
|
58
|
+
validations:
|
|
59
|
+
required: true
|
|
60
|
+
- type: textarea
|
|
61
|
+
id: extra
|
|
62
|
+
attributes:
|
|
63
|
+
label: Anything else
|
|
64
|
+
description: Model you picked, whether Ollama was already installed, anything unusual about the setup.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Ollama or OpenWebUI itself
|
|
4
|
+
url: https://github.com/ollama/ollama/issues
|
|
5
|
+
about: LePika drives these tools, it doesn't replace them. If the problem is inside the model or the chat UI, their trackers are the right place.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Something you want LePika to do.
|
|
3
|
+
labels: ["enhancement"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: The problem
|
|
9
|
+
description: What are you trying to do, and what gets in the way today?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: What you'd like
|
|
16
|
+
description: The command or behaviour you have in mind. A rough sketch is fine.
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: alternatives
|
|
21
|
+
attributes:
|
|
22
|
+
label: Alternatives you considered
|
|
23
|
+
description: Including doing it by hand with Ollama or OpenWebUI directly.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
name: Question
|
|
2
|
+
description: Something unclear about how LePika works.
|
|
3
|
+
labels: ["question"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: question
|
|
7
|
+
attributes:
|
|
8
|
+
label: Your question
|
|
9
|
+
description: If it's about your own setup, the output of `lepika status` and `lepika doctor` helps.
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
## What
|
|
2
|
+
|
|
3
|
+
<!-- One or two sentences: what changes, and why. Link the issue if there is one. -->
|
|
4
|
+
|
|
5
|
+
Closes #
|
|
6
|
+
|
|
7
|
+
## Checklist
|
|
8
|
+
|
|
9
|
+
- [ ] Title is a conventional commit (`feat:`, `fix:`, `docs:`, `test:`, `ci:`, `chore:`)
|
|
10
|
+
- [ ] Tests cover the change (the failing test came first)
|
|
11
|
+
- [ ] The gate passes locally: `uv run ruff check . && uv run ruff format --check . && uv run mypy src && uv run pytest -q && uv run bandit -c pyproject.toml -r src -q`
|
|
12
|
+
- [ ] README updated if a command, install line, or the platform table changed
|
|
13
|
+
- [ ] No new runtime dependency (LePika has three: typer, rich, structlog)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
# Least privilege: these jobs only ever read the checked-out repository.
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
checks:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
17
|
+
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
18
|
+
with:
|
|
19
|
+
enable-cache: true
|
|
20
|
+
- name: Sync dependencies
|
|
21
|
+
run: uv sync --dev
|
|
22
|
+
- name: Lint
|
|
23
|
+
run: uv run ruff check .
|
|
24
|
+
- name: Format check
|
|
25
|
+
run: uv run ruff format --check .
|
|
26
|
+
- name: Type check
|
|
27
|
+
run: uv run mypy src
|
|
28
|
+
- name: Tests
|
|
29
|
+
run: uv run pytest -q
|
|
30
|
+
- name: Security audit (code)
|
|
31
|
+
run: uv run bandit -c pyproject.toml -r src -q
|
|
32
|
+
- name: Security audit (dependencies)
|
|
33
|
+
run: uv run pip-audit
|
|
34
|
+
|
|
35
|
+
# The suite fakes every external effect, so this is about the platform itself:
|
|
36
|
+
# paths, signals, file modes, `ps` vs `tasklist`. Lint and types are the same
|
|
37
|
+
# everywhere and run once, above.
|
|
38
|
+
tests:
|
|
39
|
+
strategy:
|
|
40
|
+
fail-fast: false
|
|
41
|
+
matrix:
|
|
42
|
+
os: [macos-latest, windows-latest]
|
|
43
|
+
runs-on: ${{ matrix.os }}
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
46
|
+
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
47
|
+
with:
|
|
48
|
+
enable-cache: true
|
|
49
|
+
- name: Sync dependencies
|
|
50
|
+
run: uv sync --dev
|
|
51
|
+
- name: Tests
|
|
52
|
+
run: uv run pytest -q
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
# Publishes whatever main holds — for a version whose tag predates this
|
|
7
|
+
# workflow, or a re-run after a transient PyPI failure.
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
build:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
18
|
+
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
19
|
+
- name: Tag matches pyproject version
|
|
20
|
+
if: github.ref_type == 'tag'
|
|
21
|
+
run: |
|
|
22
|
+
version="$(python3 -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')"
|
|
23
|
+
test "v${version}" = "${GITHUB_REF_NAME}" || {
|
|
24
|
+
echo "pyproject.toml says ${version} but the tag says ${GITHUB_REF_NAME}"
|
|
25
|
+
exit 1
|
|
26
|
+
}
|
|
27
|
+
- name: Build sdist and wheel
|
|
28
|
+
run: uv build
|
|
29
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
30
|
+
with:
|
|
31
|
+
name: dist
|
|
32
|
+
path: dist/
|
|
33
|
+
|
|
34
|
+
publish:
|
|
35
|
+
needs: build
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
# OIDC trusted publishing against the PyPI publisher pinned to this workflow
|
|
38
|
+
# and the `pypi` environment — no API token exists anywhere.
|
|
39
|
+
environment:
|
|
40
|
+
name: pypi
|
|
41
|
+
url: https://pypi.org/project/lepika/
|
|
42
|
+
permissions:
|
|
43
|
+
id-token: write
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
46
|
+
with:
|
|
47
|
+
name: dist
|
|
48
|
+
path: dist/
|
|
49
|
+
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
lepika-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.venv/
|
|
8
|
+
.python-version
|
|
9
|
+
|
|
10
|
+
# Tooling caches
|
|
11
|
+
.pytest_cache/
|
|
12
|
+
.mypy_cache/
|
|
13
|
+
.ruff_cache/
|
|
14
|
+
.coverage
|
|
15
|
+
htmlcov/
|
|
16
|
+
|
|
17
|
+
# uv — note: uv.lock IS tracked; do not add it here
|
|
18
|
+
|
|
19
|
+
# Editors / OS
|
|
20
|
+
.DS_Store
|
|
21
|
+
.idea/
|
|
22
|
+
.vscode/
|
|
23
|
+
*.swp
|
|
24
|
+
|
|
25
|
+
# Local env / secrets
|
|
26
|
+
.env
|
|
27
|
+
*.local
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Contributing to LePika
|
|
2
|
+
|
|
3
|
+
Thanks for helping. LePika is small on purpose: a thin layer of Python that drives
|
|
4
|
+
Ollama, OpenWebUI, and `docker compose`. Read [`docs/architecture.md`](docs/architecture.md)
|
|
5
|
+
first; it lists the design rules a change has to keep.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
Only git and [uv](https://docs.astral.sh/uv/getting-started/installation/) are needed.
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
git clone https://github.com/MikaelSabuhi/lepika
|
|
13
|
+
cd lepika
|
|
14
|
+
uv sync --dev
|
|
15
|
+
uv run pre-commit install
|
|
16
|
+
uv run pytest -q
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The test suite runs in about a second with no network, no Docker, and no real
|
|
20
|
+
processes, because every external effect is an injected callable. New code follows
|
|
21
|
+
the same pattern.
|
|
22
|
+
|
|
23
|
+
## Making a change
|
|
24
|
+
|
|
25
|
+
1. Open an issue first for anything bigger than a small fix, so we agree on the shape
|
|
26
|
+
before you write it.
|
|
27
|
+
2. Work on a branch; `main` only changes through pull requests.
|
|
28
|
+
3. Write the failing test, then the code.
|
|
29
|
+
4. Run the gate before you push. It is the same one CI runs:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
uv run ruff check . && uv run ruff format --check . && uv run mypy src && uv run pytest -q && uv run bandit -c pyproject.toml -r src -q && uv run pip-audit
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
5. Open the PR. The title is a conventional commit (`feat:`, `fix:`, `docs:`, `test:`,
|
|
36
|
+
`ci:`, `chore:`); PRs are squash-merged, so that title becomes the commit on `main`.
|
|
37
|
+
Keep each PR to one change.
|
|
38
|
+
|
|
39
|
+
## Rules worth knowing before you start
|
|
40
|
+
|
|
41
|
+
- **Three runtime dependencies** (typer, rich, structlog). Use the standard library for
|
|
42
|
+
everything else; adding a dependency needs a discussion first.
|
|
43
|
+
- **Every user-facing failure is a `FriendlyError`**: one line saying what went wrong,
|
|
44
|
+
one line saying what to do. No tracebacks reach the user.
|
|
45
|
+
- **Shell out, don't reimplement.** If Ollama, OpenWebUI, uv, or Docker already do it,
|
|
46
|
+
LePika calls them.
|
|
47
|
+
- **Secrets never touch argv or logs.** Generated keys go in `0600` files.
|
|
48
|
+
- **The README is part of the product.** A change to a command, an install line, or the
|
|
49
|
+
platform table updates it in the same PR.
|
|
50
|
+
|
|
51
|
+
## Reporting a bug
|
|
52
|
+
|
|
53
|
+
Use the bug report template. `lepika doctor` and `lepika logs` output is what makes a
|
|
54
|
+
report actionable, so please include both.
|
|
55
|
+
|
|
56
|
+
Security problems go through private reporting instead of an issue — see
|
|
57
|
+
[SECURITY.md](SECURITY.md).
|
lepika-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mikael Sabuhi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
lepika-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: lepika
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: LePika — your own AI, at home, in one command
|
|
5
|
+
Project-URL: Homepage, https://github.com/MikaelSabuhi/lepika
|
|
6
|
+
Project-URL: Repository, https://github.com/MikaelSabuhi/lepika
|
|
7
|
+
Project-URL: Issues, https://github.com/MikaelSabuhi/lepika/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/MikaelSabuhi/lepika/releases
|
|
9
|
+
Author: Mikael Sabuhi
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: llm,local-ai,ollama,openwebui,self-host
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
17
|
+
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
19
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
25
|
+
Classifier: Topic :: Utilities
|
|
26
|
+
Classifier: Typing :: Typed
|
|
27
|
+
Requires-Python: >=3.11
|
|
28
|
+
Requires-Dist: rich>=13.7
|
|
29
|
+
Requires-Dist: structlog>=24.1
|
|
30
|
+
Requires-Dist: typer>=0.12
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
<p align="center">
|
|
34
|
+
<img src="https://raw.githubusercontent.com/MikaelSabuhi/lepika/main/docs/assets/logo.png" alt="LePika — a cat in a speech bubble with a terminal prompt" width="220">
|
|
35
|
+
</p>
|
|
36
|
+
|
|
37
|
+
<h1 align="center">LePika</h1>
|
|
38
|
+
|
|
39
|
+
<p align="center"><b>One command → local AI chat in your browser.</b><br><i>(luh-PEE-ka)</i></p>
|
|
40
|
+
|
|
41
|
+
<p align="center">
|
|
42
|
+
<a href="https://github.com/MikaelSabuhi/lepika/actions/workflows/ci.yml"><img src="https://github.com/MikaelSabuhi/lepika/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
43
|
+
<a href="https://pypi.org/project/lepika/"><img src="https://img.shields.io/pypi/v/lepika" alt="PyPI"></a>
|
|
44
|
+
<a href="https://github.com/MikaelSabuhi/lepika/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
|
|
45
|
+
</p>
|
|
46
|
+
|
|
47
|
+
<p align="center">
|
|
48
|
+
<img src="https://raw.githubusercontent.com/MikaelSabuhi/lepika/main/docs/assets/demo.gif" alt="lepika: detect the machine, pick a model, chat UI ready" width="720">
|
|
49
|
+
</p>
|
|
50
|
+
|
|
51
|
+
Your gaming GPU is already an AI machine. LePika self-hosts LLMs on the hardware you
|
|
52
|
+
already own — Mac (Metal), Linux and Windows (NVIDIA) — with zero configuration. No
|
|
53
|
+
Docker, no API keys, no monthly bill, and nothing you type ever leaves the box.
|
|
54
|
+
|
|
55
|
+
> Named after Pika, the cat who supervises this project. Like any cat, Pika has
|
|
56
|
+
> everything worth having at home and no use for the cloud. Same idea, for your AI.
|
|
57
|
+
|
|
58
|
+
## Install
|
|
59
|
+
|
|
60
|
+
**Mac / Linux**
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
curl -fsSL https://raw.githubusercontent.com/MikaelSabuhi/lepika/main/install.sh | sh
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Windows (PowerShell)**
|
|
67
|
+
|
|
68
|
+
```powershell
|
|
69
|
+
irm https://raw.githubusercontent.com/MikaelSabuhi/lepika/main/install.ps1 | iex
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Already have [uv](https://docs.astral.sh/uv/)?**
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
uv tool install lepika
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Then run `lepika`. It detects your OS, GPU, and RAM, offers the models that actually
|
|
79
|
+
fit your machine, installs [Ollama](https://ollama.com) +
|
|
80
|
+
[OpenWebUI](https://openwebui.com), pulls your pick, and opens the chat UI at
|
|
81
|
+
`http://localhost:3000`.
|
|
82
|
+
|
|
83
|
+
> LePika installs into `~/.local/bin` — if a new terminal can't find the
|
|
84
|
+
> `lepika` command, add that directory to your `PATH` or restart your shell.
|
|
85
|
+
|
|
86
|
+
Prefer to read the source first, or hack on it?
|
|
87
|
+
`git clone https://github.com/MikaelSabuhi/lepika && cd lepika && uv run lepika` —
|
|
88
|
+
git and [uv](https://docs.astral.sh/uv/getting-started/installation/) are the only
|
|
89
|
+
prerequisites; uv fetches its own Python.
|
|
90
|
+
|
|
91
|
+
## What it does
|
|
92
|
+
|
|
93
|
+
- **Native GPU, no containers** — Apple Metal on macOS, CUDA on Linux/Windows.
|
|
94
|
+
Ollama arrives via Homebrew, the official install script, or winget; OpenWebUI via
|
|
95
|
+
`uv tool`. CPU-only machines work too (LePika warns you they'll be slow).
|
|
96
|
+
- **Models that fit** — a curated list filtered to your RAM, so there's no guessing
|
|
97
|
+
whether a 27B fits in 16 GB.
|
|
98
|
+
- **Any model, one field** — Ollama tags, Hugging Face GGUF builds, or full-weight
|
|
99
|
+
safetensors repos. [Model guide →](https://github.com/MikaelSabuhi/lepika/blob/main/docs/models.md)
|
|
100
|
+
- **Private by default** — everything listens on `127.0.0.1` until you explicitly run
|
|
101
|
+
`lepika expose`.
|
|
102
|
+
- **Two modes** — ⚡ **Express** (default): everything native, no Docker.
|
|
103
|
+
🐳 **Server**: the same thing as one readable `docker compose` stack, for the box
|
|
104
|
+
under the desk. [Server guide →](https://github.com/MikaelSabuhi/lepika/blob/main/docs/server-mode.md)
|
|
105
|
+
|
|
106
|
+
LePika reuses an Ollama you already have instead of installing a second copy.
|
|
107
|
+
|
|
108
|
+
## Everyday commands
|
|
109
|
+
|
|
110
|
+
| Command | What it does |
|
|
111
|
+
| --- | --- |
|
|
112
|
+
| `lepika` | The setup wizard: detect → pick a model → install → chat |
|
|
113
|
+
| `lepika up` / `lepika down` | Start / stop the local AI stack |
|
|
114
|
+
| `lepika status` | Mode, engine, UI, and default model at a glance |
|
|
115
|
+
| `lepika doctor` | Diagnose the setup; every ✗ has a one-line fix |
|
|
116
|
+
| `lepika logs` | Tail LePika's logs (`--lines`, default 50) |
|
|
117
|
+
| `lepika update` | Upgrade the engine and OpenWebUI — chats kept |
|
|
118
|
+
| `lepika model add [ref]` | Download a model and make it the default (no ref → browse) |
|
|
119
|
+
| `lepika model import <dir>` | Import safetensors weights already on disk |
|
|
120
|
+
| `lepika model list` / `lepika model rm` | List / remove downloaded models |
|
|
121
|
+
| `lepika expose` | Share engine + UI on your network behind a generated key |
|
|
122
|
+
| `lepika connect <url>` | Use an engine on another machine (`--local` to go back) |
|
|
123
|
+
|
|
124
|
+
Global flags: `--version`, `--mode express|server` (the wizard's, not a per-command
|
|
125
|
+
switch), `--dry-run`, and `--help` on every command.
|
|
126
|
+
|
|
127
|
+
All state lives in one place: `~/.lepika` — config, logs, and (in Express mode)
|
|
128
|
+
OpenWebUI's own chats and uploads. That is what makes `lepika update` keep your chats.
|
|
129
|
+
Point `LEPIKA_HOME` somewhere else if you prefer.
|
|
130
|
+
|
|
131
|
+
## Why not just use Ollama directly?
|
|
132
|
+
|
|
133
|
+
You absolutely can. LePika drives [Ollama](https://ollama.com) and
|
|
134
|
+
[OpenWebUI](https://openwebui.com); it doesn't replace them. What it saves you:
|
|
135
|
+
|
|
136
|
+
| | By hand | With LePika |
|
|
137
|
+
| --- | --- | --- |
|
|
138
|
+
| First run | Install Ollama, install Python, install open-webui, set `OLLAMA_BASE_URL`, start both, find the port | One command |
|
|
139
|
+
| Choosing a model | Guess, download 20 GB, find out it swaps | A list filtered to the RAM you actually have |
|
|
140
|
+
| Wiring UI ↔ engine | Environment variables, by hand, per shell | Done for you |
|
|
141
|
+
| Something's broken | Two sets of logs, two projects' issue trackers | `lepika doctor`, one fix hint per failure |
|
|
142
|
+
| Staying current | Update each piece separately, per platform | `lepika update` |
|
|
143
|
+
|
|
144
|
+
If you'd rather run the raw tools, their docs are excellent and LePika gets out of your
|
|
145
|
+
way. Curious what it's doing on your behalf? It's a few files of plain Python in
|
|
146
|
+
[`src/lepika/`](https://github.com/MikaelSabuhi/lepika/tree/main/src/lepika): three dependencies, no magic.
|
|
147
|
+
|
|
148
|
+
## Requirements
|
|
149
|
+
|
|
150
|
+
- **Disk** for the models: ~0.5 GB for a tiny one, ~5 GB for a good all-rounder,
|
|
151
|
+
40 GB+ for the flagships.
|
|
152
|
+
- **8 GB RAM** recommended. Less works: LePika steers you to smaller models.
|
|
153
|
+
- **A GPU is optional.** CPU-only machines run everything, slowly, and LePika says so
|
|
154
|
+
up front.
|
|
155
|
+
- **macOS:** [Homebrew](https://brew.sh) (without it, LePika points you at the
|
|
156
|
+
Ollama.app download). **Windows:** winget, which ships with Windows 10/11.
|
|
157
|
+
Full-weight imports have their own fine print — see the [model guide](https://github.com/MikaelSabuhi/lepika/blob/main/docs/models.md).
|
|
158
|
+
|
|
159
|
+
## Documentation
|
|
160
|
+
|
|
161
|
+
- [Model guide](https://github.com/MikaelSabuhi/lepika/blob/main/docs/models.md) — every model-ref shape, full-weight imports, gated repos
|
|
162
|
+
- [Server mode](https://github.com/MikaelSabuhi/lepika/blob/main/docs/server-mode.md) — the compose stack, using a GPU box remotely, security
|
|
163
|
+
- [Architecture](https://github.com/MikaelSabuhi/lepika/blob/main/docs/architecture.md) — design rules and how it's built
|
|
164
|
+
|
|
165
|
+
## Roadmap
|
|
166
|
+
|
|
167
|
+
Both modes are v0.1 and work today. Next up: **a published package**, so installing is
|
|
168
|
+
a plain name instead of a repo URL. Star the repo to follow along, or open an issue
|
|
169
|
+
with what you'd want next.
|
|
170
|
+
|
|
171
|
+
## Contributing
|
|
172
|
+
|
|
173
|
+
Issues and pull requests are welcome; [CONTRIBUTING.md](https://github.com/MikaelSabuhi/lepika/blob/main/CONTRIBUTING.md) has the short
|
|
174
|
+
version of how a change gets in. Found a security problem?
|
|
175
|
+
[SECURITY.md](https://github.com/MikaelSabuhi/lepika/blob/main/SECURITY.md) says how to report it privately.
|
|
176
|
+
|
|
177
|
+
```sh
|
|
178
|
+
uv sync --dev && uv run pre-commit install && uv run pytest -q
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## License
|
|
182
|
+
|
|
183
|
+
[MIT](https://github.com/MikaelSabuhi/lepika/blob/main/LICENSE) © Mikael Sabuhi
|