💎

Google Cloud Vertex AIのClaude APIをRubyから叩く

2024/07/16に公開

Google Cloud Vertex AIのAnthropic Claude APIをRuby(on Rails)から使うメモ。

前提

  • Ruby 3.3.3
  • Google CloudプロジェクトマネコンよりVertex AI ClaudeのAPIを有効化していること

RubyからClaudeのAPIを叩く

SDKはない(たぶん)

https://console.cloud.google.com/vertex-ai/publishers/anthropic/model-garden/claude-3-haiku

There are Anthropic SDKs available for Python and TypeScript.

とのことなので、Rubyを使う場合はSDKは利用できないと思われる。

そのため、SDKを介さずにAPIリクエストを組み立てることにする(幸い上記に直接HTTPリクエストする場合の例が載っている)。

クレデンシャルの取得

今回はアクセストークンの取得にアプリケーションデフォルトクレデンシャル(ADC)を使用する。

ローカル環境なら、

gcloud auth application-default login

でADCをセットできる。

リージョン

https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-claude?hl=ja#anthropic_claude_region_availability

Anthropic Claude を利用できるリージョン

によると、東京リージョン( asia-northeast1 )ではまだ使えない。そのため us-central1 を使う。

コード

以上より、以下のRubyコードでClaude HaikuのAPIを叩くことができた。

PROJECT_ID = "your-project-id"
LOCATION = "us-central1".freeze
MODEL = "claude-3-haiku@20240307".freeze
API_URL = "https://#{LOCATION}-aiplatform.googleapis.com/v1/projects/#{PROJECT_ID}/locations/#{LOCATION}/publishers/anthropic/models/#{MODEL}:rawPredict"
TEMPERATURE = 0.0
MAX_TOKENS = 512

# アクセストークンの取得にADC(アプリケーションデフォルトクレデンシャル)を使用
credentials = Google::Auth.get_application_default
access_token = credentials.fetch_access_token!["access_token"]

uri = URI(API_URL)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri.request_uri)
request["Authorization"] = "Bearer #{access_token}"
request["Content-Type"] = "application/json; charset=utf-8"

request.body = {
  anthropic_version: "vertex-2023-10-16",
  messages: [
    {
      role: "user",
      content: [
        {
          type: "text",
          text: "こんにちは"
        }
      ],
    }
  ],
  temperature: TEMPERATURE,
  max_tokens: MAX_TOKENS,
  stream: false,
}.to_json
response = http.request(request)

if response.code.to_i >= 400
  raise "HTTP Request failed with status code: #{response.code} body: #{response.body}"
end

parsed_overall = JSON.parse(response.body)
result = "{#{parsed_overall['content'][0]['text']}"
puts result

Discussion