elevenlabs_field-1.0.0-beta7/modules/ai_interpolator_elevenlabs_field/src/Plugin/AiInterpolatorFieldRules/ElevenLabsDialogue.php
modules/ai_interpolator_elevenlabs_field/src/Plugin/AiInterpolatorFieldRules/ElevenLabsDialogue.php
<?php
namespace Drupal\ai_interpolator_elevenlabs_field\Plugin\AiInterPolatorFieldRules;
use Drupal\ai_interpolator\PluginInterfaces\AiInterpolatorFieldRuleInterface;
use Drupal\ai_interpolator_openai\OpenAiBase;
use Drupal\ai_interpolator_openai\OpenAiRequester;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\elevenlabs_field\ElevenLabsApiService;
use Drupal\elevenlabs_field\ElevenLabsGenerateService;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* The rules for a ElevenLabs Field.
*
* @AiInterpolatorFieldRule(
* id = "ai_interpolator_elevenlabs_dialogue",
* title = @Translation("ElevenLabs Dialogue Creator"),
* field_rule = "elevenlabs",
* target = "file",
* )
*/
class ElevenLabsDialogue extends OpenAiBase implements AiInterpolatorFieldRuleInterface, ContainerFactoryPluginInterface {
/**
* {@inheritDoc}
*/
public $title = 'ElevenLabs Dialogue Creator';
/**
* The elevenLabs requester.
*/
public ElevenLabsApiService $elevenLabs;
/**
* The Open AI requester.
*/
public OpenAiRequester $openAi;
/**
* The elevenlabs generator.
*/
public ElevenLabsGenerateService $generator;
/**
* Construct an image field.
*
* @param array $configuration
* Inherited configuration.
* @param string $plugin_id
* Inherited plugin id.
* @param mixed $plugin_definition
* Inherited plugin definition.
* @param \Drupal\elevenlabs_field\ElevenLabsApiService $elevenLabs
* The elevenlabs requester.
* @param \Drupal\ai_interpolator_openai\OpenAiRequester $openAi
* The OpenAI requester.
* @param \Drupal\elevenlabs_field\ElevenLabsGenerateService $generator
* The elevenlabs generator.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
ElevenLabsApiService $elevenLabs,
OpenAiRequester $openAi,
ElevenLabsGenerateService $generator
) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $openAi);
$this->elevenLabs = $elevenLabs;
$this->openAi = $openAi;
$this->generator = $generator;
}
/**
* {@inheritDoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('elevenlabs_field.api_service'),
$container->get('ai_interpolator_openai.request'),
$container->get('elevenlabs_field.generator_service')
);
}
/**
* {@inheritDoc}
*/
public function needsPrompt() {
return TRUE;
}
/**
* {@inheritDoc}
*/
public function advancedMode() {
return TRUE;
}
/**
* {@inheritDoc}
*/
public function placeholderText() {
return "Based on the context text create a dialogue between podcast interviewer Richard Ayoade who is a fun loving character and Julia Stipes who is a serious guest expert on the topic and answering the questions. Start with an introduction and created 10 dialogues back and forth and then end with a thank you to the guest.
The elevenlabs voices to use are:
Richard Ayoade = {{ clyde }}
Julia Stipes = {{ rachel }}
Context:
{{ context }}";
}
/**
* {@inheritDoc}
*/
public function tokens() {
$voices = $this->elevenLabs->getVoices();
$tokens = [
'context' => 'The cleaned text from the base field.',
'raw_context' => 'The raw text from the base field. Can include HTML',
'max_amount' => 'The max amount of entries to set. If unlimited this value will be empty.',
];
foreach ($voices['voices'] as $voices) {
$tokens[strtolower($voices['name'])] = $this->t('Voice of %name', ['%name' => $voices['name']]);
}
return $tokens;
}
/**
* {@inheritDoc}
*/
public function extraAdvancedFormFields(ContentEntityInterface $entity, FieldDefinitionInterface $fieldDefinition) {
$form['interpolator_openai_model'] = [
'#type' => 'select',
'#title' => 'OpenAI Model',
'#description' => $this->t('Choose the model you want to use here.'),
'#options' => $this->openAi->getModels(),
'#default_value' => $fieldDefinition->getConfig($entity->bundle())->getThirdPartySetting('ai_interpolator', 'interpolator_openai_model', 'gpt-3.5-turbo-0613'),
'#weight' => 24,
];
$form['interpolator_openai_role'] = [
'#type' => 'textarea',
'#title' => 'OpenAI Role',
'#description' => $this->t('If the AI should have some specific role, write it here.'),
'#attributes' => [
'placeholder' => $this->t('You are an OSK assistant helping with coming up with company party ideas.'),
],
'#default_value' => $fieldDefinition->getConfig($entity->bundle())->getThirdPartySetting('ai_interpolator', 'interpolator_openai_role', ''),
'#weight' => 25,
];
return $form;
}
/**
* {@inheritDoc}
*/
public function generateTokens(ContentEntityInterface $entity, FieldDefinitionInterface $fieldDefinition, array $interpolatorConfig, $delta = 0) {
$tokens = parent::generateTokens($entity, $fieldDefinition, $interpolatorConfig);
$voices = $this->elevenLabs->getVoices();
foreach ($voices['voices'] as $voices) {
$tokens[strtolower($voices['name'])] = $voices['voice_id'];
}
return $tokens;
}
/**
* {@inheritDoc}
*/
public function generate(ContentEntityInterface $entity, FieldDefinitionInterface $fieldDefinition, array $interpolatorConfig) {
$prompts = parent::generate($entity, $fieldDefinition, $interpolatorConfig);
// Add to get functional output.
$total = [];
// Add to get functional output.
foreach ($prompts as $prompt) {
$prompt .= "\n\nDo not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation.
[
{\"value\": {\"speaker\": \"The name of the speaker\",\"speaker_id\": \"The id of the speaker\",\"text\": \"The dialogue\"}},
{\"value\": {\"speaker\": \"The name of the speaker\",\"speaker_id\": \"The id of the speaker\",\"text\": \"The dialogue\"}}
]
An example of a 3 dialogue output would be:
[
{\"value\": {\"speaker\": \"Jonas Nilsson\",\"speaker_id\": \"ThT5KcBeYPX3keUQqHPh\",\"text\": \"Hello and welcome to the show Jenny!\"}},
{\"value\": {\"speaker\": \"Jenny Moore\",\"speaker_id\": \"flq6f7yk4E4fJM5XTYuZ\",\"text\": \"Thank you Jonas, it's nice to be here.\"}},
{\"value\": {\"speaker\": \"Jonas Nilsson\",\"speaker_id\": \"ThT5KcBeYPX3keUQqHPh\",\"text\": \"I would like to start with asking you about tomorrows weather?\"}}
]";
try {
$values = $this->openAi->generateResponse($prompt, $fieldDefinition, $interpolatorConfig);
$total = array_merge_recursive($total, $values);
}
catch (\Exception $e) {
}
}
return $total;
}
/**
* {@inheritDoc}
*/
public function verifyValue(ContentEntityInterface $entity, $value, FieldDefinitionInterface $fieldDefinition) {
// Validate.
if (empty($value['speaker']) && empty($value['speaker_id']) && empty($value['text'])) {
return FALSE;
}
// Otherwise it is ok.
return TRUE;
}
/**
* {@inheritDoc}
*/
public function storeValues(ContentEntityInterface $entity, array $values, FieldDefinitionInterface $fieldDefinition) {
// Transform string to stripped.
foreach ($values as $key => $value) {
// We need to generate right away, since presave does not always invoke.
$data = $this->generator->generateFile($value['text'], $value['speaker_id'], $fieldDefinition, 'eleven_multilingual_v2', [
'stability' => 1,
'similarity_boost' => 0.75,
'style_exaggeration' => 0,
]);
if (!empty($data['file'])) {
$values[$key] = [
'target_id' => $data['file']->id(),
'history_item_id' => $data['history_item_id'],
'text' => $value['text'],
'speaker' => $value['speaker_id'],
'start_time' => 0,
'similarity_boost' => 0.75,
'style_exaggeration' => 0,
'stability' => 1,
];
}
}
// Then set the value.
$entity->set($fieldDefinition->getName(), $values);
}
}
