experimental boosting changes
Browse files- README.md +7 -5
- download_model.py +12 -10
- start.sh +2 -1
README.md
CHANGED
|
@@ -18,6 +18,7 @@ It automatically downloads the target Hugging Face model from `MODEL_NAME`, stor
|
|
| 18 |
Set these in the Space settings:
|
| 19 |
|
| 20 |
- `MODEL_NAME`: Hugging Face repo id that contains one or more GGUF files
|
|
|
|
| 21 |
- `HF_TOKEN`: Hugging Face token used for the download
|
| 22 |
- `API_PASSWORD`: bearer token required by the API
|
| 23 |
|
|
@@ -33,6 +34,7 @@ Optional tuning variables:
|
|
| 33 |
- `PERF_PROFILE`: `low_latency`, `balanced` (default), or `throughput`
|
| 34 |
- `REASONING`: reasoning mode, accepts `True`, `False`, or `auto` and maps to llama.cpp `--reasoning`
|
| 35 |
- `LANGSEARCH_API_KEY`: optional API key for LangSearch web search tool (free tier: 1 req/sec, 60/min, 1000/day)
|
|
|
|
| 36 |
- `NO_WARMUP`: set to `1` to skip model warmup and save startup time
|
| 37 |
- `PORT`: listen port, default `7860`
|
| 38 |
|
|
@@ -59,13 +61,13 @@ For small 2B models on CPU-only inference (~2-4 t/s baseline), optimize these se
|
|
| 59 |
**High Impact:**
|
| 60 |
- The server forces `--parallel 1`, so only one request runs at a time and all CPU is focused on the active query
|
| 61 |
- `BATCH_SIZE` & `UBATCH_SIZE`: Use **64-256** for faster prompt ingestion; tiny values like 8 cause many small prompt batches
|
| 62 |
-
- `CTX_SIZE`: Use **2048** unless you need long conversations; larger context increases KV/cache work
|
| 63 |
- `PERF_PROFILE`: Use **`balanced`** for normal personal use; `throughput` only changes prompt batch sizing now
|
| 64 |
|
| 65 |
**Medium Impact:**
|
| 66 |
- `NO_WARMUP=1`: Skip model warmup to reduce startup latency by ~0.2s
|
| 67 |
-
- `CACHE_TYPE_K`, `CACHE_TYPE_V`:
|
| 68 |
-
- `
|
|
|
|
| 69 |
|
| 70 |
**Example for 2B model (CPU-only):**
|
| 71 |
```
|
|
@@ -74,13 +76,14 @@ BATCH_SIZE=128
|
|
| 74 |
UBATCH_SIZE=128
|
| 75 |
PERF_PROFILE=balanced
|
| 76 |
REASONING=False
|
|
|
|
| 77 |
```
|
| 78 |
|
| 79 |
Expected: faster first-token latency from prompt ingestion. Generation speed is still CPU-bound on the free tier, so a 2B Q4 model will usually remain in the low single-digit tokens/sec range.
|
| 80 |
|
| 81 |
## Web Search Tool (Standalone)
|
| 82 |
|
| 83 |
-
When `LANGSEARCH_API_KEY` is set, `start.sh` enables llama.cpp's shell tool so the model can launch the local LangSearch wrapper.
|
| 84 |
|
| 85 |
llama.cpp does not expose arbitrary external HTTP APIs as first-class built-in tools, so LangSearch is still implemented as a local wrapper that runs through the shell tool.
|
| 86 |
|
|
@@ -159,7 +162,6 @@ curl http://localhost:7860/v1/completions \
|
|
| 159 |
-d '{
|
| 160 |
"model": "model",
|
| 161 |
"prompt": "Explain KV cache in one paragraph.",
|
| 162 |
-
"max_tokens": 128,
|
| 163 |
"stream": false
|
| 164 |
}'
|
| 165 |
```
|
|
|
|
| 18 |
Set these in the Space settings:
|
| 19 |
|
| 20 |
- `MODEL_NAME`: Hugging Face repo id that contains one or more GGUF files
|
| 21 |
+
- `MODEL_FILE`: optional exact GGUF filename inside `MODEL_NAME`; useful for testing faster/lower quality quants
|
| 22 |
- `HF_TOKEN`: Hugging Face token used for the download
|
| 23 |
- `API_PASSWORD`: bearer token required by the API
|
| 24 |
|
|
|
|
| 34 |
- `PERF_PROFILE`: `low_latency`, `balanced` (default), or `throughput`
|
| 35 |
- `REASONING`: reasoning mode, accepts `True`, `False`, or `auto` and maps to llama.cpp `--reasoning`
|
| 36 |
- `LANGSEARCH_API_KEY`: optional API key for LangSearch web search tool (free tier: 1 req/sec, 60/min, 1000/day)
|
| 37 |
+
- `ENABLE_TOOLS`: set to `1` to enable llama.cpp shell tool support when `LANGSEARCH_API_KEY` is present, default `0`
|
| 38 |
- `NO_WARMUP`: set to `1` to skip model warmup and save startup time
|
| 39 |
- `PORT`: listen port, default `7860`
|
| 40 |
|
|
|
|
| 61 |
**High Impact:**
|
| 62 |
- The server forces `--parallel 1`, so only one request runs at a time and all CPU is focused on the active query
|
| 63 |
- `BATCH_SIZE` & `UBATCH_SIZE`: Use **64-256** for faster prompt ingestion; tiny values like 8 cause many small prompt batches
|
|
|
|
| 64 |
- `PERF_PROFILE`: Use **`balanced`** for normal personal use; `throughput` only changes prompt batch sizing now
|
| 65 |
|
| 66 |
**Medium Impact:**
|
| 67 |
- `NO_WARMUP=1`: Skip model warmup to reduce startup latency by ~0.2s
|
| 68 |
+
- `CACHE_TYPE_K`, `CACHE_TYPE_V`: Try `q4_0` instead of `f16` to reduce KV cache bandwidth and memory use at longer contexts
|
| 69 |
+
- `ENABLE_TOOLS`: Leave as `0` unless you need tool calling. Built-in shell tools add prompt/tool overhead and should not be exposed publicly.
|
| 70 |
+
- `MODEL_FILE`: If the repo has multiple GGUFs, test a lighter quant such as `Q4_0`, `Q4_K_S`, or `Q3_K_M` for speed/quality tradeoffs.
|
| 71 |
|
| 72 |
**Example for 2B model (CPU-only):**
|
| 73 |
```
|
|
|
|
| 76 |
UBATCH_SIZE=128
|
| 77 |
PERF_PROFILE=balanced
|
| 78 |
REASONING=False
|
| 79 |
+
ENABLE_TOOLS=0
|
| 80 |
```
|
| 81 |
|
| 82 |
Expected: faster first-token latency from prompt ingestion. Generation speed is still CPU-bound on the free tier, so a 2B Q4 model will usually remain in the low single-digit tokens/sec range.
|
| 83 |
|
| 84 |
## Web Search Tool (Standalone)
|
| 85 |
|
| 86 |
+
When `ENABLE_TOOLS=1` and `LANGSEARCH_API_KEY` is set, `start.sh` enables llama.cpp's shell tool so the model can launch the local LangSearch wrapper.
|
| 87 |
|
| 88 |
llama.cpp does not expose arbitrary external HTTP APIs as first-class built-in tools, so LangSearch is still implemented as a local wrapper that runs through the shell tool.
|
| 89 |
|
|
|
|
| 162 |
-d '{
|
| 163 |
"model": "model",
|
| 164 |
"prompt": "Explain KV cache in one paragraph.",
|
|
|
|
| 165 |
"stream": false
|
| 166 |
}'
|
| 167 |
```
|
download_model.py
CHANGED
|
@@ -54,24 +54,26 @@ def main() -> None:
|
|
| 54 |
models_dir.mkdir(parents=True, exist_ok=True)
|
| 55 |
|
| 56 |
repo_marker = models_dir / "model.repo"
|
|
|
|
|
|
|
|
|
|
| 57 |
# If a repo marker exists, check whether the previously downloaded file exists
|
| 58 |
if repo_marker.exists():
|
| 59 |
marker = repo_marker.read_text(encoding="utf-8").strip()
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
else
|
| 63 |
-
|
| 64 |
-
if prev_repo == model_name and prev_file:
|
| 65 |
cached = models_dir / prev_file
|
| 66 |
if cached.exists():
|
| 67 |
print(f"using cached model: {cached}")
|
| 68 |
return
|
|
|
|
|
|
|
| 69 |
# Use a temporary directory (under /tmp) for downloads to avoid permission issues
|
| 70 |
download_dir = Path(tempfile.mkdtemp(prefix="hf-download-"))
|
| 71 |
|
| 72 |
-
# allow user to request a specific file in the repo (useful when repo has no .gguf)
|
| 73 |
-
model_file_override = os.environ.get("MODEL_FILE", "").strip()
|
| 74 |
-
|
| 75 |
# previous cache check moved above
|
| 76 |
|
| 77 |
# Ensure any stale temp dir is removed with a permissive onerror handler
|
|
@@ -161,7 +163,7 @@ def main() -> None:
|
|
| 161 |
|
| 162 |
if repo_marker.exists():
|
| 163 |
repo_marker.unlink()
|
| 164 |
-
repo_marker.write_text(f"{model_name}|{selected_basename}", encoding="utf-8")
|
| 165 |
|
| 166 |
try:
|
| 167 |
shutil.rmtree(download_dir, onerror=_rmtree_onerror)
|
|
@@ -171,4 +173,4 @@ def main() -> None:
|
|
| 171 |
|
| 172 |
|
| 173 |
if __name__ == "__main__":
|
| 174 |
-
main()
|
|
|
|
| 54 |
models_dir.mkdir(parents=True, exist_ok=True)
|
| 55 |
|
| 56 |
repo_marker = models_dir / "model.repo"
|
| 57 |
+
model_file_override = os.environ.get("MODEL_FILE", "").strip()
|
| 58 |
+
selection_key = f"file:{model_file_override}" if model_file_override else ""
|
| 59 |
+
|
| 60 |
# If a repo marker exists, check whether the previously downloaded file exists
|
| 61 |
if repo_marker.exists():
|
| 62 |
marker = repo_marker.read_text(encoding="utf-8").strip()
|
| 63 |
+
marker_parts = marker.split("|")
|
| 64 |
+
prev_repo = marker_parts[0] if len(marker_parts) > 0 else ""
|
| 65 |
+
prev_file = marker_parts[1] if len(marker_parts) > 1 else ""
|
| 66 |
+
prev_selection_key = marker_parts[2] if len(marker_parts) > 2 else ""
|
| 67 |
+
if prev_repo == model_name and prev_file and (not selection_key or prev_selection_key == selection_key):
|
| 68 |
cached = models_dir / prev_file
|
| 69 |
if cached.exists():
|
| 70 |
print(f"using cached model: {cached}")
|
| 71 |
return
|
| 72 |
+
elif prev_repo == model_name and prev_file and selection_key and prev_selection_key != selection_key:
|
| 73 |
+
print("cached model does not match MODEL_FILE override; selecting requested file", flush=True)
|
| 74 |
# Use a temporary directory (under /tmp) for downloads to avoid permission issues
|
| 75 |
download_dir = Path(tempfile.mkdtemp(prefix="hf-download-"))
|
| 76 |
|
|
|
|
|
|
|
|
|
|
| 77 |
# previous cache check moved above
|
| 78 |
|
| 79 |
# Ensure any stale temp dir is removed with a permissive onerror handler
|
|
|
|
| 163 |
|
| 164 |
if repo_marker.exists():
|
| 165 |
repo_marker.unlink()
|
| 166 |
+
repo_marker.write_text(f"{model_name}|{selected_basename}|{selection_key}", encoding="utf-8")
|
| 167 |
|
| 168 |
try:
|
| 169 |
shutil.rmtree(download_dir, onerror=_rmtree_onerror)
|
|
|
|
| 173 |
|
| 174 |
|
| 175 |
if __name__ == "__main__":
|
| 176 |
+
main()
|
start.sh
CHANGED
|
@@ -75,6 +75,7 @@ REQUESTED_CACHE_TYPE_K="${CACHE_TYPE_K:-}"
|
|
| 75 |
REQUESTED_CACHE_TYPE_V="${CACHE_TYPE_V:-}"
|
| 76 |
export REASONING="${REASONING:-auto}"
|
| 77 |
export TOOLS="${TOOLS:-}"
|
|
|
|
| 78 |
export NO_WARMUP="${NO_WARMUP:-0}"
|
| 79 |
export LANGSEARCH_API_KEY="${LANGSEARCH_API_KEY:-}"
|
| 80 |
|
|
@@ -192,7 +193,7 @@ case "${REASONING,,}" in
|
|
| 192 |
;;
|
| 193 |
esac
|
| 194 |
|
| 195 |
-
if [ -n "$LANGSEARCH_API_KEY" ] && [ -z "$TOOLS" ]; then
|
| 196 |
TOOLS="exec_shell_command"
|
| 197 |
fi
|
| 198 |
|
|
|
|
| 75 |
REQUESTED_CACHE_TYPE_V="${CACHE_TYPE_V:-}"
|
| 76 |
export REASONING="${REASONING:-auto}"
|
| 77 |
export TOOLS="${TOOLS:-}"
|
| 78 |
+
export ENABLE_TOOLS="${ENABLE_TOOLS:-0}"
|
| 79 |
export NO_WARMUP="${NO_WARMUP:-0}"
|
| 80 |
export LANGSEARCH_API_KEY="${LANGSEARCH_API_KEY:-}"
|
| 81 |
|
|
|
|
| 193 |
;;
|
| 194 |
esac
|
| 195 |
|
| 196 |
+
if [ "$ENABLE_TOOLS" = "1" ] && [ -n "$LANGSEARCH_API_KEY" ] && [ -z "$TOOLS" ]; then
|
| 197 |
TOOLS="exec_shell_command"
|
| 198 |
fi
|
| 199 |
|