Files
context-paging/src/LLMSummarizer.php
2026-03-28 09:01:07 +00:00

136 lines
3.6 KiB
PHP

<?php
declare(strict_types=1);
namespace ContextPaging;
use Psr\Http\Message\ResponseInterface;
/**
* LLM-backed summarizer using OpenAI-compatible API.
*/
class LLMSummarizer implements SummarizerInterface
{
private CompletionsClientInterface $client;
private string $model;
private string $systemPrompt;
private int $maxTokens;
private float $temperature;
/**
* @param CompletionsClientInterface $client The LLM client
* @param string $model Model to use for summarization
* @param string $systemPrompt System prompt for summarization
* @param int $maxTokens Max tokens for summary output
* @param float $temperature Temperature for generation
*/
public function __construct(
CompletionsClientInterface $client,
string $model = 'HuggingFaceTB/SmolLM3-3B',
string $systemPrompt = 'You are a summarization assistant. Summarize the given text concisely, preserving key information. Be brief but comprehensive.',
int $maxTokens = 200,
float $temperature = 0.3
) {
$this->client = $client;
$this->model = $model;
$this->systemPrompt = $systemPrompt;
$this->maxTokens = $maxTokens;
$this->temperature = $temperature;
}
/**
* Generate a summary of the content.
*
* @param string $content The content to summarize
* @param array $context Optional context (role, previous messages, etc.)
* @return string The summary
*/
public function summarize(string $content, array $context = []): string
{
// Build the prompt
$userPrompt = $this->buildUserPrompt($content, $context);
$messages = [
['role' => 'system', 'content' => $this->systemPrompt],
['role' => 'user', 'content' => $userPrompt],
];
$response = $this->client->chat($messages, [
'model' => $this->model,
'max_tokens' => $this->maxTokens,
'temperature' => $this->temperature,
]);
return $this->extractContent($response);
}
/**
* Build the user prompt for summarization.
*/
private function buildUserPrompt(string $content, array $context): string
{
$role = $context['role'] ?? 'unknown';
$instruction = $context['instruction'] ?? 'Summarize in 2-3 sentences:';
$prompt = "{$instruction}\n\n";
if ($role !== 'unknown') {
$prompt .= "[Role: {$role}]\n";
}
$prompt .= $content;
return $prompt;
}
/**
* Extract content from the response.
*/
private function extractContent(ResponseInterface $response): string
{
$body = json_decode($response->getBody()->getContents(), true);
if (!isset($body['choices'][0]['message']['content'])) {
throw new \RuntimeException('No content in summarizer response');
}
return trim($body['choices'][0]['message']['content']);
}
/**
* Set the model.
*/
public function setModel(string $model): self
{
$this->model = $model;
return $this;
}
/**
* Set the max tokens for output.
*/
public function setMaxTokens(int $maxTokens): self
{
$this->maxTokens = $maxTokens;
return $this;
}
/**
* Set the temperature.
*/
public function setTemperature(float $temperature): self
{
$this->temperature = $temperature;
return $this;
}
/**
* Set the system prompt.
*/
public function setSystemPrompt(string $prompt): self
{
$this->systemPrompt = $prompt;
return $this;
}
}