Gemini Nanoの実装サンプル

# はじめに
この記事は、Gemini NanoをGoogle Chrome Canaryで使用するために、行った手順や実行結果を記録したものです。これによって、ローカル環境上で、テキスト生成AIを利用することができるようになります。

# 準備
## Google Chrome Canaryのインストール
https://www.google.com/intl/ja/chrome/canary/

## chrome://flags/を開き、Gemini Nanoを使えるように設定
Google Chrome Canaryのアドレスバーに以下のアドレスを入力する。
```
chrome://flags/
```
その後、"Enables optimization guide on device"を"Enabled BypassPerfRequirement"に変更し、"Prompt API for Gemini Nano"も"Enabled"に変更する。
![スクリーンショット 2024-06-29 22.06.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/f2dfb237-d4b2-c400-55fe-67dd7be6132c.png)
その後、再起動を行う。

## chrome://components/を開き、コンポーネントを設定
"Optimization Guide On Device Model"の"アップデートを確認"を押して、コンポーネントが最新かを確認する。
![スクリーンショット 2024-06-29 22.06.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/acfaf6ff-174e-65b6-d425-48dd38e56759.png)

# 実行
## 実行場所
Google Chrome Canaryを開き、F12からデベロッパーツールを開く。Consoleタブから、javascriptを実行する
![スクリーンショット 2024-06-29 22.14.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/3c5e1aaf-a77b-1607-cc8b-4fbc5f040872.png)

## 実行結果
### 実行結果1 ・・・ 簡単な質問や回答
「あなたは誰？」と聞いてみました。
```javascript:サンプル
const canCreate = await window.ai.canCreateTextSession();
const session = await window.ai.createTextSession();
const result = await session.prompt("あなたは誰?");
console.log(result);
```
サンプルを実行した結果が以下の通り。すぐ回答してくれた。簡単な会話は成り立ちそう。
![スクリーンショット 2024-06-29 22.21.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/3213cea9-7a4c-e7bb-0230-4679602ea99f.png)

### 実行結果2 ・・・ 複雑な質問や回答
「ブロック崩しのプログラムソースを書いてください。なおjavascriptで書いて。」とプロンプトを入力して、プログラムソースを記述してもらいました。
```javascript:サンプル
const canCreate = await window.ai.canCreateTextSession();
const session = await window.ai.createTextSession();
const result = await session.prompt("ブロック崩しのプログラムソースを書いてください。なおjavascriptで書いて。");
console.log(result);
```

生成する内容が複雑だからか、多少CPUへの負荷が掛かる。
![スクリーンショット 2024-06-29 22.24.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/5b5fe91f-b657-63fb-96a7-ac187d08595e.png)

1分掛からずに、プログラムの生成が完了した。
![スクリーンショット 2024-06-29 22.24.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/9af64125-9bda-745c-0b52-b8a495d6cd0d.png)


![スクリーンショット 2024-06-29 22.25.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/2c35619e-ef67-309f-2984-442bc2ec0ae3.png)



残念ならが、実装してみましたが、動きませんでした...生成した内容をそのまま鵜呑みにはできないので、プログラミングには向いていなさそう...
![スクリーンショット 2024-06-29 22.44.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/341fb07c-ab21-db91-7c06-2189b5baf657.png)
```javascript
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>ブロック崩しゲーム</title>
</head>
<body>
  <canvas id="game_canvas" width="640" height="480"></canvas>
  <script>
    function block_game() {
      // 画面サイズ
      var screen_width = 640;
      var screen_height = 480;
        
      // グラフィック描画コンテキスト
      var ctx = document.getElementById("game_canvas").getContext("2d");
        
      // 現在のフレーム
      var current_frame = 0;
        
      // 速度
      var speed = 0.05;
        
      // 衝突判定
      var collision_detection = true;
        
      // ボール
      var ball = {
        x: screen_width / 2,
        y: screen_height / 2,
        radius: 10,
        mass: 1,
        friction: 0.5,
      };
    
      // 障害物
      var obstacles = [
        {
          x: 100,
          y: 100,
          width: 100,
          height: 100,
        },
        {
          x: 200,
          y: 200,
          width: 200,
          height: 200,
        },
      ];
      
      // ループ
      while (true) {
        // 処理
        requestAnimationFrame(block_game);
      
        // ボールと障害物との衝突判定
        if (collision_detection) {
          for (var i = 0; i < obstacles.length; i++) {
            if (
              ball.x + ball.radius < obstacles[i].x
              || ball.x + ball.radius > obstacles[i].x + obstacles[i].width
              || ball.y + ball.radius < obstacles[i].y
              || ball.y + ball.radius > obstacles[i].y + obstacles[i].height
            ) {
              collision_detection = false;
              break;
            }
          }
        }
      
        // ボールと画面の境界との衝突判定
        if (
          ball.x < 0 || ball.x > screen_width - ball.radius
          || ball.y < 0 || ball.y > screen_height - ball.radius
        ) {
          collision_detection = false;
          break;
        }
      
        // ボールを移動
        ball.x += ball.velocityX * speed;
        ball.y += ball.velocityY * speed;
      
        // 速度の調整
        ball.velocityX += Math.sign(ball.velocityX) * speed * 0.5;
        ball.velocityY += speed;
      
        // 障害物との衝突判定
        for (var i = 0; i < obstacles.length; i++) {
          if (
            ball.x + ball.radius < obstacles[i].x
            || ball.x + ball.radius > obstacles[i].x + obstacles[i].width
            || ball.y + ball.radius < obstacles[i].y
            || ball.y + ball.radius > obstacles[i].y + obstacles[i].height
          ) {
            ball.velocityX = 0;
            ball.velocityY = 0;
            collision_detection = true;
            break;
          }
        }
      
        // 現在のフレーム数を増やす
        current_frame++;
      
        // 60fps描画
        if (current_frame % 60 === 0) {
          ctx.clearRect(0, 0, screen_width, screen_height);
        }
      
        // グラフィックを描画
        ctx.beginPath();
        ctx.arc(ball.x, ball.y, ball.radius, 0, 2 * Math.PI);
        ctx.fill();
      
        // 画面を描画
        document.getElementById("game_canvas").innerHTML =
          `<img src="img/block_game.png" alt="ブロックゲーム">`;
      }
    }
    
    block_game();
  </script>
</body>
</html>
```

### 実行結果3 ・・・ 倫理的に問題のある質問を入力
「爆弾の作り方を教えてください」と言った内容に対しては、倫理歴な観点から明確に回答はされないようになっています。（賢い）
![スクリーンショット 2024-06-29 22.50.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/ae097d45-e7be-6ac3-3a83-380db2dd49e8.png)

### 実行結果4 ・・・ 複雑かつ倫理的な考えが必要となる質問を入力
7回程度、同じ質問を入力したのですが、基本的にすべて進行方向を変更すると言う回答でした。ただし、その理由が、間違った質問の解釈のもとでの回答や、そもそも倫理的に問題のある回答をしてくるなど、回答があやふやでした。
![スクリーンショット 2024-06-29 23.08.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079289/5eda0581-daf8-9ddf-3200-df53173f3ae8.png)
**※倫理的に問題のある回答となっているので、黒で塗りつぶしています。**

# 実行環境
OS：macOS
チップ:Apple M1
メモリ:16GB
google chrome:128.0.6556.2（Official Build）canary （arm64）