Skip to content

Commit

Permalink
1452: Moved into symfony commands
Browse files Browse the repository at this point in the history
  • Loading branch information
cableman committed May 28, 2024
1 parent ebcd13d commit 0f929f6
Show file tree
Hide file tree
Showing 8 changed files with 287 additions and 113 deletions.
21 changes: 21 additions & 0 deletions drush.services.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
services:
llm.service.completion.command:
class: Drupal\llm_services\Commands\ModelCompletionCommand
arguments:
- '@plugin.manager.llm_services'
tags:
- { name: console.command }

llm.service.install.command:
class: Drupal\llm_services\Commands\ProviderInstallCommand
arguments:
- '@plugin.manager.llm_services'
tags:
- { name: console.command }

llm.service.list.command:
class: Drupal\llm_services\Commands\ProviderListCommand
arguments:
- '@plugin.manager.llm_services'
tags:
- { name: console.command }
6 changes: 3 additions & 3 deletions src/Client/OllamaCompletionResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
* The response from the model.
* @param bool $done
* The module completion state.
* @param string $context
* @param array<int> $context
* The generated context when completed.
*/
public function __construct(
private string $model,
private string $response,
private bool $done,
private string $context,
private array $context,
) {
}

Expand Down Expand Up @@ -53,7 +53,7 @@ public function getStatus(): bool {
/**
* {@inheritdoc}
*/
public function getContext(): string {
public function getContext(): array {
return $this->context;
}

Expand Down
113 changes: 113 additions & 0 deletions src/Commands/ModelCompletionCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

declare(strict_types=1);

namespace Drupal\llm_services\Commands;

use Drupal\llm_services\Model\Message;
use Drupal\llm_services\Model\Payload;
use Drupal\llm_services\Plugin\LLModelProviderManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
* This is a literal copy of the example Symfony Console command
* from the documentation.
*
* See:
* http://symfony.com/doc/2.7/components/console/introduction.html#creating-a-basic-command
*/
class ModelCompletionCommand extends Command {

/**
* Default constructor.
*
* @param \Drupal\llm_services\Plugin\LLModelProviderManager $providerManager
* The provider manager.
*/
public function __construct(
private readonly LLModelProviderManager $providerManager,
) {
parent::__construct();
}

/**
* {@inheritDoc}
*/
protected function configure(): void {
$this
->setName('llm:model:completion')
->setDescription('Make a completion request to a model')
->addUsage('llm:model:completion ollama llama2 "Why is the sky blue?')
->addArgument(
name: 'provider',
mode: InputArgument::REQUIRED,
description: 'Name of the provider (plugin).'
)
->addArgument(
name: 'name',
mode: InputArgument::REQUIRED,
description: 'Name of the model to use.'
)
->addArgument(
name: 'prompt',
mode: InputArgument::REQUIRED,
description: 'The prompt to generate a response for.'
)
->addOption(
name: 'temperature',
mode: InputOption::VALUE_REQUIRED,
description: 'The temperature of the model. Increasing the temperature will make the model answer more creatively.',
default: '0.8'
)
->addOption(
name: 'top-k',
mode: InputOption::VALUE_REQUIRED,
description: 'Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers.',
default: '40'
)
->addOption(
name: 'top-p',
mode: InputOption::VALUE_REQUIRED,
description: 'A higher value (e.g., 0.95) will lead to more diverse text, while a lower value (e.g., 0.5) will generate more focused and conservative text.',
default: '0.9'
);
}

/**
* {@inheritDoc}
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
$providerName = $input->getArgument('provider');
$name = $input->getArgument('name');
$prompt = $input->getArgument('prompt');

$temperature = $input->getOption('temperature');
$topK = $input->getOption('top-k');
$topP = $input->getOption('top-p');

$provider = $this->providerManager->createInstance($providerName);

$payLoad = new Payload();
$payLoad->model = $name;
$payLoad->options = [
'temperature' => $temperature,
'top_k' => $topK,
'top_p' => $topP,
];
$msg = new Message();
$msg->content = $prompt;
$payLoad->messages[] = $msg;

foreach ($provider->completion($payLoad) as $res) {
$output->write($res->getResponse());
}
$output->write("\n");

return Command::SUCCESS;
}

}
79 changes: 79 additions & 0 deletions src/Commands/ProviderInstallCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

declare(strict_types=1);

namespace Drupal\llm_services\Commands;

use Drupal\llm_services\Model\Message;
use Drupal\llm_services\Model\Payload;
use Drupal\llm_services\Plugin\LLModelProviderManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
* Install model in provider (if supported).
*/
class ProviderInstallCommand extends Command {

/**
* Default constructor.
*
* @param \Drupal\llm_services\Plugin\LLModelProviderManager $providerManager
* The provider manager.
*/
public function __construct(
private readonly LLModelProviderManager $providerManager,
) {
parent::__construct();
}

/**
* {@inheritDoc}
*/
protected function configure(): void {
$this
->setName('llm:provider:install')
->setDescription('Install model in provider')
->addUsage('llm:install:model ollama llama2')
->addArgument(
name: 'provider',
mode: InputArgument::REQUIRED,
description: 'Name of the provider (plugin).'
)
->addArgument(
name: 'name',
mode: InputArgument::REQUIRED,
description: 'Name of the model to use.'
);
}

/**
* {@inheritDoc}
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
* @throws \Drupal\llm_services\Exceptions\CommunicationException
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
$providerName = $input->getArgument('provider');
$name = $input->getArgument('name');

$provider = $this->providerManager->createInstance($providerName);

foreach ($provider->installModel($name) as $progress) {
if (isset($progress['total']) && isset($progress['completed'])) {
$percent = ($progress['completed'] / $progress['total']) * 100;
$output->writeln(sprintf('%s (%0.2f%% downloaded)', $progress['status'], $percent));
}
else {
$output->writeln($progress['status']);
}
}
$output->write("\n");

return Command::SUCCESS;
}

}
67 changes: 67 additions & 0 deletions src/Commands/ProviderListCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace Drupal\llm_services\Commands;

use Drupal\llm_services\Model\Message;
use Drupal\llm_services\Model\Payload;
use Drupal\llm_services\Plugin\LLModelProviderManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
* Install models from a given provider.
*/
class ProviderListCommand extends Command {

/**
* Default constructor.
*
* @param \Drupal\llm_services\Plugin\LLModelProviderManager $providerManager
* The provider manager.
*/
public function __construct(
private readonly LLModelProviderManager $providerManager,
) {
parent::__construct();
}

/**
* {@inheritDoc}
*/
protected function configure(): void {
$this
->setName('llm:provider:list')
->setDescription('Install model in provider')
->addUsage('llm:install:model ollama llama2')
->addArgument(
name: 'provider',
mode: InputArgument::REQUIRED,
description: 'Name of the provider (plugin).'
);
}

/**
* {@inheritDoc}
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
* @throws \Drupal\llm_services\Exceptions\CommunicationException
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
$providerName = $input->getArgument('provider');

$provider = $this->providerManager->createInstance($providerName);
$models = $provider->listModels();

foreach ($models as $model) {
$output->writeln($model['name'] . ' (' . $model['modified'] . ')');
}

return Command::SUCCESS;
}

}
Loading

0 comments on commit 0f929f6

Please sign in to comment.