Google Cloudのプロンプト管理を試してみる

# はじめに
Google CloudのVertexAIには、プロンプトの管理を行う機能が用意されています。
プロンプトをバージョニングして、VertexAIの生成モデルと連携することができます。

https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/prompt-classes?hl=ja

Googleが提唱する「GenOps」でもプロンプト管理は重要と言われています。

https://cloud.google.com/blog/ja/products/devops-sre/genops-learnings-from-microservices-and-traditional-devops


# プロンプト管理
## プロンプトの保存
プロンプトの保存方法は2つあります。
1. コンソール上でプロンプトを保存する
2. Vertex AI SDK経由でプロンプトを保存する

### コンソール上でプロンプトを保存する
Vertex AI Studioの「プロンプト管理」から「プロンプトを作成」を押す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968617/e9e34a58-7d14-2c80-bbe8-6244118c0c9f.png)

システム指示、Prompt、モデル、パラメータを設定して、保存を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968617/de064f62-371b-4076-8283-dbc928ff53b0.png)

プロンプトの保存が終わった後、Vertex AI Studioの「プロンプト管理」に移動すると、保存したプロンプトが表示されている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968617/4d8623ee-c33c-c39c-7d9d-0a8dbef5444d.png)

### Vertex AI SDK経由でプロンプトを保存する
Promptクラスを使用して、プロンプトの情報をカプセル化する。
```python
import vertexai
from vertexai.preview.prompts import Prompt

# Initialize vertexai
vertexai.init(project=PROJECT, location="us-central1")

local_prompt = Prompt(
    prompt_name="Prompt Test SDK",
    prompt_data="日本一高い山は？",
    model_name="gemini-2.0-flash-exp",
    system_instruction="あなたはユーザーからの質問に対して簡潔に回答するAIです。",
    # generation_config=GenerationConfig, # Optional,
    # safety_settings=SafetySetting, # Optional,
)
```

`create_version()`を使用して、プロンプトの保存を行う。
```python
from vertexai.preview import prompts

prompt_sdk = prompts.create_version(prompt=local_prompt)
```

Vertex AI Studioの「プロンプト管理」を確認すると、SDK経由でプロンプトが保存されていることが確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968617/3ff64b2d-565b-4526-25c0-597b4500e228.png)


## プロンプトの一覧表示
保存されているプロンプト情報を`list()`で表示する。
表示名とプロンプトIDが含まれている。
```python
prompts_metadata = prompts.list()
# [PromptMetadata(display_name='Prompt Test', prompt_id={プロンプトID})]
```

## プロンプトの読み込み
保存されているプロンプトを読み込むには、プロンプトIDを使用して`get()`を使用する。
```python
prompt = prompts.get(prompt_id={プロンプトID})
```

`prompt`の中身は以下のようになっている。
```bash
Prompt(prompt_data='日本一高い山は？', 
system_instruction=あなたはユーザーからの質問に対して簡潔に回答するAIです。),
model_name=projects/PROJECT_ID/locations/us-central1/publishers/google/models/gemini-2.0-flash-exp), 
generation_config=temperature: 1
top_p: 0.95
max_output_tokens: 1024
), 
prompt_id={プロンプトID})
```

## プロンプトのバージョニング
### コンソールの場合
プロンプトやモデルの設定を変更して、[コンソール上でプロンプトを保存する](#コンソール上でプロンプトを保存する)同様に保存を押す。

プロンプトの履歴から右側にバージョンが増えていて、プロンプトの違いを確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968617/69456990-6621-15bd-e340-0f46a9bfe5b8.png)


### SDK経由の場合
更新したいプロンプトIDを指定して、`create_version()`を実行する。
```python
prompt_sdk = prompts.create_version(prompt=local_prompt, prompt_id={プロンプトID})
```

プロンプトのバージョニング一覧を`list_versions()`で表示する。
```python
prompt_versions_metadata = prompts.list_versions(prompt_id={プロンプトID})
```

prompt_versions_metadataの中身は以下のようになっている。
```bash
[PromptVersionMetadata(display_name='Prompt Test SDK', prompt_id={プロンプトID}, version_id='1'),
 PromptVersionMetadata(display_name='Prompt Test SDK', prompt_id={プロンプトID}, version_id='2')]
```

## バージョンを指定してプロンプトを取得する
[プロンプトの読み込み](#プロンプトの読み込み)での`get()`の引数に`version_id`を指定することで、特定のバージョンのプロンプトが取得できる。
`version_id`を指定しないと、最新のバージョンのプロンプトを取得することになる。
```python
prompt = prompts.get(prompt_id={プロンプトID}, version_id=1)
```

### version_id=1の場合
```bash
Prompt(prompt_data='日本一高い山は？',
```

### version_id=2の場合
```bash
Prompt(prompt_data='日本一高い山は？　その英語名は？',
```

## バージョンの復元
以前のバージョンにプロンプトを`restore_version()`で復元ができる。
バージョン1を復元する場合、バージョン3としてバージョン1のプロンプトが作成される。
```python
prompt_version_metadata = prompts.restore_version(prompt_id={プロンプトID}, version_id=1)
```

## プロンプトの削除
`delete()`でプロンプトを削除できる。
```python
prompts.delete(prompt_id={プロンプトID})
```

# まとめ
Google Cloudのプロンプト管理をコンソール上とSDK経由の両方で試してみました。
生成AIではプロンプトの違いによって、期待する出力が異なります。
プロンプトのバージョン管理ができるので、プロンプトの再利用やプロンプトの最適化や定期的な評価をすることができます。
生成AIアプリケーション運用における「GenOps」をGoogle Cloudのサービスを利用することで、導入を簡易化できる予感がしました。