Laya is an open-source, non-autoregressive decision model built for quick categorical choices and risk checks. Given text, it can choose a label, assign a score on a scale you define, or return a yes/no probability without generating a conversational answer. TypeSafe's Jev is built for the same kind of decisions and supports those three question types.
While Jev runs on TypeSafe's servers and is available through Laravel's AI SDK classification API, Laya runs on your infrastructure, where you pay for compute without a per-call API charge. Its laya-serve process accepts Jev-style requests at /v1/systemone.
LayaPHP, by Marc Reichel, is a PHP client for Laya. It sends text to laya-serve and returns typed PHP answers with confidence scores. Reichel says he has not yet tested the client with hosted Jev, despite the shared endpoint.
Classifying a product review
For a store that accepts product reviews, LayaPHP could be used to flag spam and abuse for moderation while recording each review's sentiment. predict() asks all three questions in one request:
use MarcReichel\Laya\Laya;use MarcReichel\Laya\Question; function classifyReview(Laya $laya, string $body): array{ $result = $laya->predict($body, [ 'spam' => Question::yesNo('Is this review spam or an advertisement?'), 'abuse' => Question::yesNo('Does this review contain insults, hate speech, or threats?'), 'sentiment' => Question::choice('What is the overall sentiment of this review?', [ 'positive' => 'praises the product', 'neutral' => 'describes the product without clear praise or criticism', 'negative' => 'criticises the product', ]), ]); $spam = $result->yesNo('spam'); $abuse = $result->yesNo('abuse'); $sentiment = $result->choice('sentiment'); $needsReview = $spam->yes() || $abuse->yes() || min($spam->answerConfidence, $abuse->answerConfidence, $sentiment->answerConfidence) < 0.7; return [ 'queue' => $needsReview ? 'manual-review' : 'publish', 'sentiment' => $sentiment->choice, ];}
yes() uses a 0.5 probability threshold by default. The separate answerConfidence value measures confidence in each answer. The code sends flagged reviews and answers below 0.7 to a person. I picked that number for this example; however, before letting Laya approve reviews, it is a good idea to compare its decisions with reviews your moderators have already handled.
Consider the review "The product works, but delivery took too long." In a local test with Laya 0.3.23, the code sent it to manual review: Laya chose a negative sentiment with confidence below 0.7. An advertisement and a review that insulted the staff also went to manual review. A newer Laya model could classify these examples differently.
Question::score() handles scales such as "not urgent," "soon," and "blocking," with the levels listed from lowest to highest. The answer includes the most likely level and a numeric score. The package's decide() method maps questions defined with PHP attributes onto enum, integer, and boolean constructor properties.
Running Laya and testing the integration
LayaPHP requires PHP 8.4 or newer and a PSR-18 HTTP client like Guzzle:
composer require marcreichel/laya-php guzzlehttp/guzzle
The package repository includes a Docker Compose file for laya-serve. From that repository, run docker compose up -d --wait to start the server at http://localhost:8000. The first classification request downloads about 1 GB of model weights into a Docker volume.
With the server running, Laravel 13 or newer automatically discovers the package's service provider. Add LAYA_URL=http://localhost:8000 to .env, and you can inject Laya into a job or service. The package's php artisan laya:health command checks that the server is reachable. The same client works outside Laravel: new Laya('http://localhost:8000') connects to that server directly.
The built-in Laya::fake() lets tests check the review-routing code without starting the model. Testing whether Laya classifies the reviews correctly still requires a running server.
The LayaPHP repository has the full setup instructions and runnable examples.