136 lines
3.6 KiB
PHP
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;
|
|
}
|
|
}
|