Feature services
High-level AI services for TYPO3 with prompt engineering and response parsing.
Overview
The feature services layer provides domain-specific AI
capabilities for TYPO3 extensions. Each service wraps
the core Llm with specialized
prompts, response parsing, and configuration optimized
for specific use cases.
Architecture
┌─────────────────────────────────────────────────────────┐
│ Consuming Extensions │
│ (rte-ckeditor-image, textdb, contexts) │
└──────────────────────┬──────────────────────────────────┘
│ Dependency Injection
┌──────────────────────▼──────────────────────────────────┐
│ Feature Services │
│ - CompletionService │
│ - VisionService │
│ - EmbeddingService │
│ - TranslationService │
└──────────────────────┬──────────────────────────────────┘
│ LLM abstraction
┌──────────────────────▼──────────────────────────────────┐
│ LlmServiceManager │
│ (Provider routing, caching, rate limiting) │
└──────────────────────┬──────────────────────────────────┘
│ Provider calls
┌──────────────────────▼──────────────────────────────────┐
│ Provider Implementations │
│ (OpenAI, Anthropic, Gemini, etc.) │
└─────────────────────────────────────────────────────────┘
CompletionService
Purpose: Text generation and completion.
Use cases
- Content generation.
- Rule generation (contexts extension).
- Content summarization.
- SEO meta generation.
Key features
- JSON response formatting (native JSON mode on every provider, ADR-128).
- Schema-validated structured output — a strict JSON-schema subset, provider-enforced, with one repair round-trip (ADR-126).
- Markdown generation.
- Factual mode (low creativity).
- Creative mode (high creativity).
- System prompt support.
Example
use Netresearch\NrLlm\Service\Feature\CompletionService;
use Netresearch\NrLlm\Service\Option\ChatOptions;
$completion = $completionService->complete(
prompt: 'Explain TYPO3 in simple terms',
options: new ChatOptions(
temperature: 0.3,
maxTokens: 200,
responseFormat: 'markdown',
),
);
echo $completion->content;
Methods
// Standard completion
$response = $completionService->complete($prompt);
// JSON output
$data = $completionService->completeJson('List 5 colors as a JSON array');
// Markdown output
$markdown = $completionService->completeMarkdown('Write docs for this API');
// Factual (low creativity, high consistency)
$response = $completionService->completeFactual('What is the capital of France?');
// Creative (high creativity)
$response = $completionService->completeCreative('Write a haiku about coding');
// Structured: schema-validated JSON (strict subset, ADR-126); ->data is
// the payload, ->response the answering call, ->usage every attempt
$data = $completionService->completeStructured('Rate this text', [
'type' => 'object',
'required' => ['score', 'reason'],
'properties' => [
'score' => ['type' => 'number'],
'reason' => ['type' => 'string'],
],
])->data;
VisionService
Purpose: Image analysis and metadata generation.
Use cases
- Alt text generation (rte-ckeditor-image).
- SEO title generation.
- Detailed descriptions.
- Custom image analysis.
Key features
- Prompts for accessible alt text, which needs review in its page context.
- Prompts for concise image titles.
- Sequential processing of image arrays.
- Base64 and URL support.
Example
use Netresearch\NrLlm\Service\Feature\VisionService;
// Single image
$altText = $visionService->generateAltText(
'https://example.com/image.jpg'
);
// Batch processing
$altTexts = $visionService->generateAltText([
'https://example.com/img1.jpg',
'https://example.com/img2.jpg',
]);
Methods
// Generate an alt-text suggestion for review
$altText = $visionService->generateAltText('https://example.com/image.jpg');
// Request a concise title
$title = $visionService->generateTitle('https://example.com/image.png');
// Generate detailed description
$description = $visionService->generateDescription($imageUrl);
// Custom analysis
$analysis = $visionService->analyzeImage(
$imageUrl,
'What colors are prominent in this image?'
);
EmbeddingService
Purpose: Text-to-vector conversion and similarity search.
Use cases
- Semantic translation memory (textdb).
- Content similarity.
- Duplicate detection.
- Semantic search.
Key features
- Aggressive caching (deterministic).
- Batch processing.
- Cosine similarity calculations.
- Top-K similarity search.
Example
use Netresearch\NrLlm\Service\Feature\EmbeddingService;
// Generate embedding
$vector = $embeddingService->embed('Search query text');
// Find similar
$similar = $embeddingService->findMostSimilar(
queryVector: $vector,
candidateVectors: $allVectors,
topK: 5
);
Methods
// Generate embedding (cached automatically)
$vector = $embeddingService->embed('Some text');
// Full response with metadata
$response = $embeddingService->embedFull('Some text');
// Batch embedding
$vectors = $embeddingService->embedBatch(['Text 1', 'Text 2']);
// Calculate cosine similarity
$similarity = $embeddingService->cosineSimilarity($vectorA, $vectorB);
// Find most similar vectors
$results = $embeddingService->findMostSimilar(
$queryVector,
$candidateVectors,
topK: 5
);
// Normalize a vector
$normalized = $embeddingService->normalize($vector);
TranslationService
Purpose: Language translation with quality control.
Use cases
- Translation suggestions (textdb).
- Content localization.
- Glossary-aware translation.
Key features
- Language detection.
- Glossary support.
- Formality levels.
- Domain specialization.
- Quality scoring.
Example
use Netresearch\NrLlm\Service\Feature\TranslationService;
use Netresearch\NrLlm\Service\Option\TranslationOptions;
$result = $translationService->translate(
text: 'The TYPO3 extension is great',
targetLanguage: 'de',
options: new TranslationOptions(
glossary: ['TYPO3' => 'TYPO3'],
formality: 'formal',
domain: 'technical',
),
);
echo $result->translation;
echo $result->confidence;
Methods
use Netresearch\NrLlm\Service\Option\TranslationOptions;
// Basic translation
$result = $translationService->translate('Hello, world!', 'de');
// With options
$result = $translationService->translate(
$text,
targetLanguage: 'de',
sourceLanguage: 'en',
options: new TranslationOptions(
formality: 'formal',
domain: 'technical',
glossary: [
'TYPO3' => 'TYPO3',
'extension' => 'Erweiterung',
],
preserveFormatting: true,
),
);
// TranslationResult properties
$translation = $result->translation;
$sourceLanguage = $result->sourceLanguage;
$confidence = $result->confidence;
// Batch translation
$results = $translationService->translateBatch($texts, 'de');
// Language detection
$language = $translationService->detectLanguage($text);
// Quality scoring
$score = $translationService->scoreTranslationQuality($source, $translation, 'de');
Installation
Dependency injection
Add to your extension's Configuration/Services.yaml:
services:
Your\Extension\Service\YourService:
public: true
arguments:
$visionService: '@Netresearch\NrLlm\Service\Feature\VisionService'
$translationService: '@Netresearch\NrLlm\Service\Feature\TranslationService'
$completionService: '@Netresearch\NrLlm\Service\Feature\CompletionService'
$embeddingService: '@Netresearch\NrLlm\Service\Feature\EmbeddingService'
Usage in your extension
<?php
namespace Your\Extension\Service;
use Netresearch\NrLlm\Service\Feature\VisionServiceInterface;
class YourService
{
public function __construct(
private readonly VisionServiceInterface $visionService
) {}
public function enhanceImage(string $imageUrl): array
{
return [
'alt' => $this->visionService->generateAltText($imageUrl),
'title' => $this->visionService->generateTitle($imageUrl),
'description' => $this->visionService->generateDescription($imageUrl),
];
}
}
Default prompts
Resources/ contains a reference catalog
of ten prompt templates. The runtime does not load that catalog. Feature
services use their own built-in prompts; applications can use the catalog
as a starting point for their own prompt snippets or custom analysis.
Vision
vision.- Alt-text suggestions for accessibility review.alt_ text vision.- SEO-optimized titles.seo_ title vision.- Detailed descriptions.description
Translation
translation.- General purpose translation.general translation.- Technical documentation.technical translation.- Marketing copy.marketing
Completion
completion.- TYPO3 contexts rules.rule_ generation completion.- Content summarization.content_ summary completion.- SEO meta descriptions.seo_ meta
Embedding
embedding.- Semantic search configuration.semantic_ search
Testing
Unit tests
# Run all unit tests
Build/Scripts/runTests.sh -s unit
# Alternative: Via Composer script
composer ci:test:php:unit
Mocking services
use Netresearch\NrLlm\Service\Feature\VisionServiceInterface;
use PHPUnit\Framework\TestCase;
class YourServiceTest extends TestCase
{
public function testImageEnhancement(): void
{
$visionMock = $this->createMock(VisionServiceInterface::class);
$visionMock->method('generateAltText')
->willReturn('Test alt text');
$service = new YourService($visionMock);
$result = $service->enhanceImage('https://example.com/test.jpg');
$this->assertEquals('Test alt text', $result['alt']);
}
}
Performance
Caching
- Embeddings: 24h cache (deterministic).
- Vision and completion: No response cache is enabled by these services.
- Translation: Opt in with a positive
Translation; caching also requires a resolvable configuration and the cache service.Options:: cache Ttl
Batch processing
Image arrays provide a convenient batch interface. Each image makes its own provider request, in order; batching does not reduce the number of requests.
// One provider request per image, with results in the same order
$altTexts = $visionService->generateAltText($imageUrls);
Configuration
Custom prompts
Pass a custom analysis prompt to the vision service:
$analysis = $visionService->analyzeImage(
$imageUrl,
'Describe the visible objects for this product catalog.',
);
For configuration-owned prompts, use the backend's LLM configurations and prompt snippets. The API documentation describes those records and their composition; they do not replace the feature service's built-in prompt constants.
Service options
Services accept the options object for their operation:
use Netresearch\NrLlm\Service\Option\ChatOptions;
$result = $completionService->complete(
prompt: 'Generate text',
options: new ChatOptions(
temperature: 0.7,
maxTokens: 1000,
topP: 0.9,
frequencyPenalty: 0.0,
presencePenalty: 0.0,
responseFormat: 'json',
systemPrompt: 'Custom instructions',
stopSequences: ["\n\n", 'END'],
),
);
Extension integration examples
rte-ckeditor-image
use Netresearch\NrLlm\Service\Feature\VisionService;
class ImageAiService
{
public function __construct(
private readonly VisionService $visionService
) {}
public function enhanceImage(string $absoluteImageUrl): array
{
return [
'alt' => $this->visionService->generateAltText($absoluteImageUrl),
'title' => $this->visionService->generateTitle($absoluteImageUrl),
];
}
}
Resolve a FAL file's public URL to an absolute HTTPS URL before calling this service, or read the file and supply a base64 data URL.
textdb
use Netresearch\NrLlm\Service\Feature\TranslationService;
use Netresearch\NrLlm\Service\Feature\EmbeddingService;
class AiTranslationService
{
public function __construct(
private readonly TranslationService $translationService,
private readonly EmbeddingService $embeddingService
) {}
public function suggestTranslation(
string $text,
string $lang,
array $candidateVectors,
): array
{
$vector = $this->embeddingService->embed($text);
return [
'translation' => $this->translationService->translate($text, $lang),
'similar' => $this->embeddingService->findMostSimilar(
$vector,
$candidateVectors,
),
];
}
}
contexts
use Netresearch\NrLlm\Service\Feature\CompletionService;
use Netresearch\NrLlm\Service\Option\ChatOptions;
class RuleGeneratorService
{
public function __construct(
private readonly CompletionService $completionService
) {}
public function generateRule(string $description): ?array
{
return $this->completionService->completeJson(
"Generate TYPO3 context rule: $description",
new ChatOptions(temperature: 0.2),
);
}
}
File structure
nr-llm/
├── Classes/
│ ├── Domain/
│ │ └── Model/
│ │ ├── CompletionResponse.php
│ │ ├── VisionResponse.php
│ │ ├── TranslationResult.php
│ │ ├── EmbeddingResponse.php
│ │ ├── UsageStatistics.php
│ │ └── RenderedPrompt.php
│ ├── Service/
│ │ └── Feature/
│ │ ├── CompletionService.php
│ │ ├── VisionService.php
│ │ ├── EmbeddingService.php
│ │ └── TranslationService.php
│ └── Exception/
│ └── InvalidArgumentException.php
├── Configuration/
│ └── Services.yaml
├── Resources/
│ └── Private/
│ └── Data/
│ └── DefaultPrompts.php
└── Tests/
└── Unit/
└── Service/
└── Feature/
├── CompletionServiceTest.php
├── VisionServiceTest.php
└── EmbeddingServiceTest.php
Requirements
- TYPO3 v13.4+.
- PHP 8.2+.
- nr-llm core extension (
Llm).Service Manager