Google Gemini: API

Odborník na umělou inteligenci, vynikající PHP programátor a úžadný člověk David Grudl před časem zveřejnil sneak peek pluginu do Admineru, který dovoluje sestavovat SQL dotazy pomocí AI. Navázal tak na svůj SQL Wizard. Plugin ale nikdy nepublikoval, tak si možná část lidí myslela, že to je fake. Řekl jsem si, jak by asi bylo složité to doopravdy udělat, a ukázalo se, že úplně triviální! Použil jsem Google Gemini a z jednoduchosti jeho nasazení jsem byl velmi mile překvapen. Nemusíte chodit do žádné Google Cloud Console (která je neuvěřitelně nepřehledná), ale prostě přímo v AI Studiu vygenerujete klíč a hned vidíte URL, na kterém ho můžete použít. Implementace v PHP je pak už jednoduchá:

<?php
/** Položení dotazu Google Gemini
* @param string Dotaz v přirozeném jazyce
* @param string Klíč získáte na https://aistudio.google.com/apikey
* @param string Dostupné modely: https://ai.google.dev/gemini-api/docs/models#available-models
* @return string Odpověď umělé inteligence
* @copyright Jakub Vrána, https://php.vrana.cz/
*/
function gemini($prompt, $apiKey, $model = "gemini-2.0-flash") {
    $context = stream_context_create(array("http" => array(
        "method" => "POST",
        "header" => array("User-Agent: PHP", "Content-Type: application/json"),
        "content" => '{"contents": [{"parts":[{"text": ' . json_encode($prompt) . '}]}]}',
    )));
    $response = json_decode(file_get_contents("https://generativelanguage.googleapis.com/v1beta/models/$model:generateContent?key=$apiKey", false, $context));
    return $response->candidates[0]->content->parts[0]->text;
}
?>

V pluginu pak dotazu od uživatele předřadím schéma databáze a přidám nějakou omáčku, aby to vracelo skutečně jen SQL dotaz, který pak prostě zobrazím. Funguje to naprosto neskutečně:

Poradí si to dokonce i s češtinou, umí to vytvářet i INSERT, přidávat indexy a já nevím, co ještě:

Plugin vyžaduje Adminer 5.1.0, kam jsem přidal hook pro zobrazení promptu na tom správném místě, jinak si to žádnou změnu nevyžádalo.

Jakub Vrána, Seznámení s oblastí, 23.3.2025, diskuse: 7 (nové: 0)

Diskuse

Tomáš:

Pěkné, díky moc za updaty. Zjistil jsem, že při zapnutém pluginu CodeMirror se nevrací text do editoru SQL dotazu. Upravil jsem si takto.

codemirror.php:
var cmt = cm;

sql-gemini.php:
cmt.setValue(req.responseText);
cmt.refresh();

Jenda:

Co potřebuji upravit, abych tuhle featuru přidal do Editoru v read only režimu?

Jenda:

Do homepage() jsem pridal form, v headers() zpracovam gemini dotaz s tim ze ma delat jen selecty a ukladam sql do tridni promenne, a v homepage pred formularem zase vypisuju data z get_rows(). Skoncim pokud v odpovedi prijde delete/truncate/alter/insert...

ikona Jakub Vrána OpenID:

Super! Zveřejníš to? Já původně zvažoval dát tam tlačítko I'm feeling lucky, který by dotazy rovnou prováděl.

Jenda:

zatim to mam nějak takto:
<?php
 
function homepage() {
    if (
$this->gem) {
        if (
$this->containsForbiddenWords($this->gem)) {
          echo
"Chyba dotazu";
        } else {
          echo
$this->renderTable(Adminer\get_rows($this->gem));
        }
    }
    echo
"<form  action='' method='post' enctype='multipart/form-data' id='form'><p><textarea name='gemini' rows='5' cols='50' title='AI prompt'>" . Adminer\h($_POST["gemini"]) . "</textarea>
    <p><input type='submit' value='Hledej s AI'></p></form>\n"
;
    return
true;
  }

function
headers() {
    if (
$_POST["gemini"] && !isset($_POST["query"])) {
     
$prompt = "You are a data analyst. I have a " . Adminer\get_driver(Adminer\DRIVER) . " database with this structure:\n\n";
      foreach (
Adminer\tables_list() as $table => $type) {
       
$prompt .= Adminer\create_sql($table, false, "CREATE") . ";\n\n";
      }
     
$prompt .= "Only use SELECT statements. Do not use any commands that modify the database structure or data, such as INSERT, UPDATE, DELETE, TRUNCATE, or ALTER. Prefer returning more columns. Dont return any comments. Your task is to generate SQL query to retrieve data from the database for reporting purposes. Add column names into first row, if doing aggregation better use union all to display column names in first row. \n\n";
     
$prompt .= "Give me one SQL SELECT query and nothing else for following question:\n\n$_POST[gemini]\n\n";
     
//~ echo $prompt; exit;
     
$context = stream_context_create(array("http" => array(
       
"method" => "POST",
       
"header" => array("User-Agent: AdminerSqlGemini", "Content-Type: application/json"),
       
"content" => '{"contents": [{"parts":[{"text": ' . json_encode($prompt) . '}]}]}',
      )));
     
$response = json_decode(file_get_contents("https://generativelanguage.googleapis.com/v1beta/models/".$this->model.":generateContent?key=".$this->apiKey, false, $context));
     
$text = $response->candidates[0]->content->parts[0]->text;
     
$in_code = false;
     
$this->gem = "";
      foreach (
preg_split('~(^|\n)```(sql)?(\n|$)~', $text) as $part) {
       
$part = trim($part);
        if (
$part) {
         
$this->gem.= ($in_code ? $part : "/*\n$part\n*/") . "\n\n";
        }
       
$in_code = !$in_code;
      }
    }
  }
?>
Někdy poplete sql a do prvního řádku v selectu vloží konstanty názvů sloupcu místo hodnot.. je to mírně experimentální. Ani netuším, jestli to je správně použití homepage() a header()... zhodnotte

ikona Jakub Vrána OpenID:

Asi by to mohlo být v homepage() celé. Žádné hlavičky to zdá se neposílá, tak to být v headers() nemusí.

Jinak super!

Vložit komentář

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2025 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.