googleapis/google-cloud-php

There seems some problems setting values for the Part when call PredictionServiceClient->generateContent

hosanluo opened this issue · 1 comments

My code

$config = config('services.google');
$modelName = 'gemini-1.5-pro-001';
$locationId = 'us-central1';
$apiEndpoint = "$locationId-aiplatform.googleapis.com";
$model = \Google\Cloud\AIPlatform\V1\Client\PredictionServiceClient::projectLocationPublisherModelName($config['project_id'], $locationId, 'google', $modelName);
$clientOptions = ['credentials' => $config, 'apiEndpoint' => $apiEndpoint];

$predictionServiceClient = new \Google\Cloud\AIPlatform\V1\Client\PredictionServiceClient($clientOptions);
$inlineData = new \Google\Cloud\AIPlatform\V1\Blob($imageContentArray[0]);

// wrong.
$part = new \Google\Cloud\AIPlatform\V1\Part();
$part->setText($text);
$part->setInlineData($inlineData);
$contentsParts = [$part];

// correct
$contentsParts = [
    'text' => (new \Google\Cloud\AIPlatform\V1\Part())->setText($text),
    'inline_data' => (new \Google\Cloud\AIPlatform\V1\Part())->setInlineData($inlineData)
];

$content = (new \Google\Cloud\AIPlatform\V1\Content())->setParts($contentsParts)->setRole('user');
$contents = [$content];
$request = new \Google\Cloud\AIPlatform\V1\GenerateContentRequest();
$request->setModel($model)->setContents($contents);

When i try to chain call Part to set value. the next value will recover the prev value. The previous value will be missing. see the wrong part in my code. when i setInlineData, the text will be empty string. Here is the code used by Message in the package to set the value:

//File \Google\Protobuf\Internal\Message
protected function writeOneof($number, $value)
{
    $field = $this->desc->getFieldByNumber($number);
    $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()];
    $oneof_name = $oneof->getName();
    if ($value === null) {
        $this->$oneof_name = new OneofField($oneof);
    } else {
        $oneof_field = $this->$oneof_name;
        $oneof_field->setValue($value);
        $oneof_field->setFieldName($field->getName());
        $oneof_field->setNumber($number);
    }
}

I see in this funtiion "$field->getOneOfIndex()" always be 0. Is there a problem with that?

May I ask if my use is incorrect , or do I need to instantiate the Part multiple times to set the value?

hi @hosanluo !
This is Working as Intended, although I agree the OneOf behavior in Protobuf can be confusing.

The Part message only accepts OneOf for the data field, which includes the fields that you're setting. So when you call setInlineData after calling setText, it erases the value you provided in setText (as only one of those fields can be set at time):

$part = new \Google\Cloud\AIPlatform\V1\Part();
 // sets the "text" field
$part->setText($text);
// sets the "inline_data" field, but removes the "text" field, because the message only accepts one of those two fields
$part->setInlineData($inlineData); 

The bit you've provided as correct behaves in the same way, but in this instance you've successfully created TWO Part objects, and setting the data field differently for each of them. So to do this the other way would look something like this:

$part1 = new \Google\Cloud\AIPlatform\V1\Part();
 // sets the "text" field
$part1->setText($text);

$part2 = new \Google\Cloud\AIPlatform\V1\Part();
// sets the "inline_data" field
$part2->setInlineData($inlineData); 
$content = (new \Google\Cloud\AIPlatform\V1\Content())->setParts([$part1, $part2]);