Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# README.md and docs/*.md with site/template.html and site/style.css. Pull requests only
# build it (a doc that breaks the site shows up in review); main deploys it to GitHub Pages.
# The repository variable GOATCOUNTER (a GoatCounter site code) turns on visitor counts.
# The repository variable CONTEXT7_LIBRARY (e.g. /1bit-monster/engine) turns on the docs chat widget.
name: pages

on:
Expand All @@ -42,6 +43,7 @@ jobs:
- name: Build the site
env:
GOATCOUNTER: ${{ vars.GOATCOUNTER }}
CONTEXT7_LIBRARY: ${{ vars.CONTEXT7_LIBRARY }}
run: |
python3 -m pip install --quiet markdown==3.10.3
python3 tools/site.py _site
Expand Down
28 changes: 28 additions & 0 deletions context7.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"$schema": "https://context7.com/schema/context7.json",
"projectTitle": "1bit engine",
"description": "A C++ inference engine behind an OpenAI-compatible API, running inside Lemonade on AMD Ryzen AI (Strix Halo): the XDNA 2 NPU, HRX and Vulkan on the Radeon iGPU, ZINC for NVIDIA and Apple GPUs, MLX on Apple Silicon.",
"folders": [
"docs",
"blog"
],
"excludeFolders": [
"third_party",
"site",
"tools",
"tests",
"patches"
],
"excludeFiles": [
"LICENSE",
"NOTICE",
"archive.tsv"
],
"rules": [
"Serve models with `1bit serve`; it exposes an OpenAI-compatible API and runs as Lemonade's `onebit` backend.",
"Pick the device with `--device` (auto, npu, vulkan, hrx, rocm, zinc, mlx); an NPU model directory runs on the NPU fast lane, and Vulkan is the usual choice for plain GGUF files.",
"Prefer Unsloth Dynamic GGUFs: UD-Q4_K_XL is the lean default, UD-Q5_K_XL the accurate choice.",
"For one user at a time use `--mtp` without `--adaptive`; for many simultaneous requests use `--parallel` or `--adaptive`.",
"Documentation lives at https://1bit.gg; measured results are on the GitHub wiki."
]
}
1 change: 1 addition & 0 deletions site/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,6 @@
if (side && window.matchMedia("(max-width: 860px)").matches) side.open = false;
</script>
{{analytics}}
{{chat}}
</body>
</html>
19 changes: 19 additions & 0 deletions tools/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
# repository variable of that name), every page loads GoatCounter's counter, which sets
# no cookies. Unset, as in a local preview, the pages carry no analytics at all.
#
# Docs chat: with CONTEXT7_LIBRARY set to the engine's Context7 library id (pages.yml passes
# the repository variable of that name), every page carries Context7's chat widget, which
# answers from the docs Context7 indexed (see context7.json). Context7 only serves it once the
# library is claimed and 1bit.gg is on the widget's allowed domains; unset, no widget.
#
# Needs python-markdown (pip install markdown).
import html
import os
Expand Down Expand Up @@ -156,6 +161,19 @@ def analytics():
return f'<script data-goatcounter="https://{code}.goatcounter.com/count" async src="https://gc.zgo.at/count.js"></script>'


def chat_widget():
library = os.environ.get("CONTEXT7_LIBRARY", "").strip()
if not library:
return ""
if not re.fullmatch(r"/[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+", library):
sys.exit(f"CONTEXT7_LIBRARY must be a Context7 library id like /owner/repo, not {library!r}")
return (f'<script src="https://context7.com/widget.js" data-library="{library}" '
'data-color="#1779e1" data-position="bottom-right" '
'data-placeholder="Ask about the 1bit engine docs..." '
'data-welcome-message="Ask anything about the 1bit engine: install, serving, NPU, HRX, Vulkan, quantization." '
'async></script>')


def plain(markdown_text):
"""One paragraph of markdown as plain text."""
text = re.sub(r"\s*\(\[[^\]]*\.md\]\([^)]*\)\)", "", markdown_text) # "(docs/x.md)" asides
Expand Down Expand Up @@ -230,6 +248,7 @@ def write(self, name, title, main, kind, section, description=TAGLINE, extra_hea
.replace("{{nav}}", self.top_nav(section))
.replace("{{main}}", main)
.replace("{{analytics}}", analytics())
.replace("{{chat}}", chat_widget())
.replace("{{repo}}", REPO))
if extra_head:
page = page.replace("<head>", "<head>\n" + extra_head, 1)
Expand Down
Loading