PHPackages                             ndrstmr/steg - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. ndrstmr/steg

ActiveLibrary[API Development](/categories/api)

ndrstmr/steg
============

The local inference bridge for PHP — lightweight client for OpenAI-compatible inference servers (vLLM, Ollama, LiteLLM, LocalAI)

v1.0.1(1mo ago)211↓90%1EUPL-1.2PHPPHP &gt;=8.4CI passing

Since Mar 24Pushed 1mo agoCompare

[ Source](https://github.com/ndrstmr/steg)[ Packagist](https://packagist.org/packages/ndrstmr/steg)[ RSS](/packages/ndrstmr-steg/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (14)Versions (4)Used By (1)

🌊 Steg — The Local Inference Bridge for PHP
===========================================

[](#-steg--the-local-inference-bridge-for-php)

[![CI](https://github.com/ndrstmr/steg/actions/workflows/ci.yml/badge.svg)](https://github.com/ndrstmr/steg/actions)[![License: EUPL-1.2](https://camo.githubusercontent.com/3b7871a41ea959dc3dcb73b77db0dd13b838353d6ffc04e3b2ecd170f15e4212/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4555504c2d2d312e322d626c75652e737667)](LICENSE)[![PHP](https://camo.githubusercontent.com/648ed134b95002a2a446ace9fa4ba020ed5bf9900d5d489832d911833f6d5212/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d253345253344382e342d3838393242462e737667)](https://php.net)[![Packagist](https://camo.githubusercontent.com/81b4afb1e74510c89a219a3f95ba7d6d7044bc7659daf0d2a23ca5401dd6e515/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6e647273746d722f73746567)](https://packagist.org/packages/ndrstmr/steg)

> A lightweight, BC-stable PHP client for OpenAI-compatible inference servers. Built for local-first AI in production. Zero framework lock-in.

Quickstart
----------

[](#quickstart)

```
composer require ndrstmr/steg symfony/http-client
```

```
use Steg\Factory\StegClientFactory;

$steg = StegClientFactory::fromDsn('vllm://localhost:8000/v1?model=llama-3.3-70b-awq');
echo $steg->ask('Erkläre Photosynthese in Leichter Sprache.');
```

Why Steg?
---------

[](#why-steg)

StegSymfony AIopenai-php/clientFocusLocal inferenceMulti-provider ecosystemOpenAI CloudBC-Promise✅ from v1.0❌ experimental✅Core dependencies2 (`psr/log`, `http-contracts`)15+ packages5+ packagesvLLM / Ollama✅ first-class⚠️ via Generic Bridge❌ not officiallyStreaming✅✅✅Tool Callingnot in scope✅ (Agent framework)✅Symfony Bundleoptional (`steg-bundle`)integrated (`ai-bundle`)community bundleSteg is purpose-built for local inference deployments and provides a BC-promise that `symfony/ai-platform` does not (yet) offer. Ideal as a stable fallback layer in production systems.

Supported Backends
------------------

[](#supported-backends)

BackendDSN FormatStatusvLLM`vllm://host:port/v1?model=name`✅ Full supportOllama`ollama://host:port?model=name`✅ Full supportLiteLLM`litellm://host:port/v1?model=name`✅ Full supportLocalAI`localai://host:port/v1?model=name`✅ Full supportllama.cpp server`llama://host:port/v1?model=name`✅ Full supportOpenAI (Cloud)`openai://api.openai.com/v1?model=gpt-4o&api_key=sk-...`⚠️ Works, not core focusMock`mock://default`✅ Tests &amp; offline dev> All backends share the same `OpenAiCompatibleClient` — DSN prefixes are convenience aliases that resolve to the correct `base_url` and default port.

Usage
-----

[](#usage)

### Client creation

[](#client-creation)

```
use Steg\Factory\StegClientFactory;

// DSN (recommended)
$steg = StegClientFactory::fromDsn('vllm://localhost:8000/v1?model=llama-3.3-70b-awq');
$steg = StegClientFactory::fromDsn('ollama://localhost:11434?model=llama3.2');
$steg = StegClientFactory::fromDsn('mock://default?response=Hello+World');

// Array config (e.g. from Symfony parameters)
$steg = StegClientFactory::fromConfig([
    'base_url' => 'http://localhost:8000/v1',
    'model'    => 'llama-3.3-70b-awq',
    'api_key'  => 'EMPTY',
    'timeout'  => 120,
]);
```

### Completion methods

[](#completion-methods)

```
// One-shot: single user prompt
$answer = $steg->ask('What is Leichte Sprache?');

// System + user: most common chat pattern
$answer = $steg->chat(
    system: 'You translate German administrative texts into Leichte Sprache.',
    user: 'Die Bundesregierung hat neue Gesetze beschlossen.',
);

// Full message history
use Steg\Model\ChatMessage;

$answer = $steg->complete([
    ChatMessage::system('You are a helpful assistant.'),
    ChatMessage::user('What is the capital of France?'),
    ChatMessage::assistant('The capital of France is Paris.'),
    ChatMessage::user('And Germany?'),
])->content;

// Streaming
foreach ($steg->stream([ChatMessage::user('Write a poem.')]) as $chunk) {
    echo $chunk->delta;
}
```

### CompletionOptions presets

[](#completionoptions-presets)

```
use Steg\Model\CompletionOptions;

$steg->ask('Generate JSON.', CompletionOptions::precise());        // temperature 0.1
$steg->ask('Write a story.', CompletionOptions::creative());       // temperature 0.9
$steg->ask('Translate.', CompletionOptions::leichteSprache());     // temperature 0.3
$steg->ask('Anything.', CompletionOptions::default());             // temperature 0.7

// Custom (immutable — returns new instance)
$opts = CompletionOptions::default()->withTemperature(0.5)->withMaxTokens(2048);
```

### Server health and model list

[](#server-health-and-model-list)

```
if ($steg->isHealthy()) {
    foreach ($steg->listModels() as $model) {
        echo $model->id.PHP_EOL;
    }
}
```

Exception Handling
------------------

[](#exception-handling)

```
use Steg\Exception\ConnectionException;
use Steg\Exception\InferenceException;
use Steg\Exception\ModelNotFoundException;
use Steg\Exception\InvalidResponseException;

try {
    $response = $steg->ask('Hello');
} catch (ConnectionException $e) {
    // Server unreachable or timeout
} catch (ModelNotFoundException $e) {
    // Model not loaded on the server
    echo 'Missing model: '.$e->getModelId();
} catch (InferenceException $e) {
    // Server returned 4xx/5xx
    echo 'HTTP '.$e->getHttpStatusCode();
} catch (InvalidResponseException $e) {
    // Response parsing failed
}
```

Testing with MockClient
-----------------------

[](#testing-with-mockclient)

```
use Steg\Client\MockClient;
use Steg\StegClient;

// Fixed responses, cycling
$client = new StegClient(MockClient::withResponses([
    'First response',
    'Second response',
]));

$client->ask('anything'); // → 'First response'
$client->ask('anything'); // → 'Second response'
$client->ask('anything'); // → 'First response' (loops)

// Dynamic responses via callback
$client = new StegClient(MockClient::withCallback(
    static fn (array $messages) => 'Echo: '.$messages[0]->content,
));
```

Symfony Integration
-------------------

[](#symfony-integration)

Install the optional bundle for automatic DI configuration and a Symfony Profiler panel:

```
composer require ndrstmr/steg-bundle
```

```
# config/packages/steg.yaml
steg:
    connections:
        vllm_local:
            dsn: '%env(STEG_VLLM_DSN)%'
            timeout: 120
    default_connection: vllm_local
```

```
use Steg\Client\InferenceClientInterface;

final class MyService
{
    public function __construct(
        private readonly InferenceClientInterface $steg,
    ) {}
}
```

See [docs/symfony-integration.md](docs/symfony-integration.md) for full details.

Requirements
------------

[](#requirements)

- PHP 8.4+
- `psr/log: ^3.0`
- `symfony/http-client-contracts: ^3.0`
- `symfony/http-client: 7.4.*` *(runtime, recommended)*

Documentation
-------------

[](#documentation)

- [Getting Started](docs/getting-started.md)
- [Configuration Reference](docs/configuration.md)
- [Supported Backends](docs/supported-backends.md)
- [Symfony Integration](docs/symfony-integration.md)

License
-------

[](#license)

Licensed under the [European Union Public Licence v1.2 (EUPL-1.2)](LICENSE).

Origin
------

[](#origin)

Steg was built in a public sector context to solve a real problem: a stable, local LLM client for production use — without framework lock-in.

---

Built by 👾 public sector dev crew

Notice
------

[](#notice)

This repository was developed with the assistance of AI code agents (Claude Code, Anthropic). The code was created as part of a development sprint and is not cleared for production use without prior review. Use at your own risk.

**License:** European Union Public Licence v. 1.2 (EUPL-1.2) — Copyright © 2026 Andreas Teumer

###  Health Score

43

—

FairBetter than 90% of packages

Maintenance90

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~42 days

Total

2

Last Release

48d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ec966b63930eb41af981e8daf965073bc19f42bc18f489d80ff420050a7a624e?d=identicon)[ndrstmr](/maintainers/ndrstmr)

---

Top Contributors

[![ndrstmr](https://avatars.githubusercontent.com/u/153233004?v=4)](https://github.com/ndrstmr "ndrstmr (1 commits)")

---

Tags

phpinferenceaiopenaiBridgellmollamalocal-firstvllm

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/ndrstmr-steg/health.svg)

```
[![Health](https://phpackages.com/badges/ndrstmr-steg/health.svg)](https://phpackages.com/packages/ndrstmr-steg)
```

###  Alternatives

[theodo-group/llphant

LLPhant is a library to help you build Generative AI applications.

1.7k371.6k6](/packages/theodo-group-llphant)[cognesy/instructor-php

The complete AI toolkit for PHP: unified LLM API, structured outputs, agents, and coding agent control

318117.1k1](/packages/cognesy-instructor-php)[deepseek-php/deepseek-php-client

deepseek PHP client is a robust and community-driven PHP client library for seamless integration with the Deepseek API, offering efficient access to advanced AI and data processing capabilities.

46784.5k5](/packages/deepseek-php-deepseek-php-client)[symfony/ai-platform

PHP library for interacting with AI platform provider.

521.2M216](/packages/symfony-ai-platform)[bitrix24/b24phpsdk

An official PHP library for the Bitrix24 REST API

10139.4k5](/packages/bitrix24-b24phpsdk)[rubix/server

Deploy your Rubix ML models to production with scalable stand-alone inference servers.

632.3k](/packages/rubix-server)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
