Search by

survos / llama-cpp

tacman1123

llama.cpp models inside the PHP process through FFI, and OCRonos-Vintage OCR correction on top of it. No HTTP, no Python.

Package info

github.com/survos/llama-cpp

pkg:composer/survos/llama-cpp

Fund package maintenance!

kbond

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

2.45.45 2026-11-12 22:39 UTC

This package is auto-updated.

Last update: 2026-11-13 19:22:58 UTC


README

llama.cpp models inside the PHP process, through FFI, and OCR post-correction with OCRonos-Vintage built on it. No HTTP service, no Python.

use Survos\LlamaCpp\LlamaModel;
use Survos\LlamaCpp\Ocronos\Corrector;

$model = new LlamaModel('/usr/local/lib/libllama_bridge.so', '/var/lib/models/ocronos-vintage-q8_0.gguf');
$corrector = new Corrector($model);

$done = $corrector->correct('Tne bride was dre.ssed in her mo.3t gallant attire.');
$done->text;                 // The bride was dressed in her most gallant attire.
$done->truncated;            // false: the model finished
$done->lengthIsSuspect();    // false: about as long as the source

$corrector->correct($page, segment: true);   // longer text, corrected a segment at a time
bin/ocronos "Tne Board of Superv1sors met at tbe Court Houfe on Monday laft."
bin/ocronos --segment < page.txt

What is in it

Class Does
LlamaModel One GGUF model: countTokens(), generate() (greedy: the same prompt always gives the same text), loads(). Loads on first use and stays loaded.
Ocronos\Corrector The correction prompt, the 480-token input limit, segmenting of longer passages (paragraph, line, sentence, word), joining with the source's own separators. A port of ai-tools' cv/text_correction.py.
Ocronos\Correction The text, token counts, truncated, and lengthIsSuspect().
TextModelInterface What the corrector needs from a model, so it can be tested without one.

Fidelity

Checked against ai-tools' PyTorch implementation (the reference, at the same pinned model revision) on nine passages, one of them long enough to be segmented: the corrected text, the token counts and the segment boundaries are identical. That held for all four files tried:

File Size Eight passages
f32 (lossless) 500 MB 2.0 s
f16 252 MB 1.5 s
q8_0 136 MB 0.7 s
q4_k_m 91 MB 0.9 s

PyTorch took 3.9 s for the same eight on the same machine (Apple M4, CPU). Nine passages is a small sample: quantised files can differ on other text, so compare on your own before relying on one. q8_0 is the suggested one.

What to know about the model

  • It rewrites. It modernises spelling ("to-day" becomes "today") and can change a name it does not know. Keep the source OCR and store the correction beside it, never over it.
  • It continues patterns. Given the same paragraph twelve times it wrote it sixteen times. lengthIsSuspect() flags a correction whose length is more than a quarter away from its source's.
  • It is small: a prompt of at most 480 tokens and a 1,024-token context. Without segment: true a longer passage is refused, never cut short.
  • truncated means the model ran out of room before finishing: treat that text as incomplete.

Setting up

  1. llama.cpp as a shared library with its header: brew install llama.cpp on macOS; on Linux build it with -DBUILD_SHARED_LIBS=ON.
  2. The bridge: bin/build-bridge.sh [output-directory] compiles bridge/llama_bridge.cpp against it. PHP calls this small C library rather than llama.h directly, because llama.h passes large structs by value and changes them between releases.
  3. The model: bin/convert-ocronos.sh <llama.cpp source checkout> [output-directory] downloads the pinned OCRonos-Vintage weights (Apache-2.0) and writes the f32 and q8_0 GGUF files. It needs Python with torch and transformers once, for the conversion only.

PHP needs the FFI extension, and ffi.enable=1 under a web server (the command line always has FFI). Keep the LlamaModel for the life of the process (a FrankenPHP worker, a queue consumer): one load, about 0.2 s, serves everything after it. Verified on macOS arm64 with llama.cpp 0.9.0; Linux has not been tried.