🤖

Geminiで真偽判定する機能を作ってみた(Ruby on Rails)

2024/10/01に公開

最近流行りのAI。
今まではWEB版のChatGPTで満足していたのですが、個人開発(自社開発)してる Asked Q&A というサービスにAIを導入してみたい欲が高まり、唐突にAPIでAIを使ってみることにしました。
https://asked.page

なぜGeminiを選んだのか?

Titleにも書いている通り、今回はGoogleのGeminiを採用しました。
https://gemini.google.com

Geminiを採用した理由は

です。

単純作業を自動化するくらいならどれを選んでも変わらないと思うので、とりあえず気軽に使えるものを選んだ感じですね。

問題点

GeminiはRails向けのgemを提供しておらず、Get codeの選択肢に Rubyがないのです。。。

弊社では、フロントエンドにNext.js、バックエンドにRailsを採用しています。
そのため、バックエンドで使いたい場合はGeminiにリクエストする機能を自作する必要があります。

作ってみた

ないのであれば作ればよいだけなので、サクッと実装してみました。
今回自動化したい内容は、

  • センシティブ判定
    • 投稿されたコンテンツにセンシティブな内容が含まれているか?
    • ※この結果次第でページに表示する広告を切り替えたいため
  • ハラスメント判定
    • 投稿されたメッセージに悪意が含まれているか?
    • ※悪意が含まれたメッセージをユーザーに見せたくないため

の確認なので、「渡された値をAIで真偽判定するClass」という設計にしてます。

実装したClass

# frozen_string_literal: true

class Gemini::Flash::GenerateContent::Boolean
  def initialize(system_instruction:, text:)
    @system_instruction = system_instruction
    @text = text
  end

  def run
    http_request = prepare_http_request
    http_request[:request].body = request_body
    response = http_request[:http].request(http_request[:request])

    raise "Gemini: response is not success" unless response.is_a?(Net::HTTPSuccess)

    parsed_response = JSON.parse(response.body)
    text_content = parsed_response.dig("candidates", 0, "content", "parts", 0, "text")
    json = JSON.parse(text_content).symbolize_keys

    ActiveRecord::Type::Boolean.new.cast(json[:response])
  end

  private

  def prepare_http_request
    endpoint = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent"
    url = URI.parse("#{endpoint}?key=#{Rails.application.credentials.gemini[:api_key]}")
    http = Net::HTTP.new(url.host, url.port)
    http.use_ssl = true
    request = Net::HTTP::Post.new(url, { "Content-Type" => "application/json" })
    { http:, request: }
  end

  def request_body
    {
      systemInstruction: {
        parts: [{
          text: @system_instruction
        }],
        role: "model"
      },
      contents: [{
        parts: [{
          text: @text
        }],
        role: "user"
      }],
      generationConfig: {
        responseMimeType: "application/json",
        responseSchema: {
          type: "object",
          properties: {
            response: {
              type: "boolean"
            }
          }
        }
      }
    }.to_json
  end
end

面倒なので細かい実装の説明は省きます。
書いてある通りに動きます。

使い方

命令文( system_instruction )と検証対象( text )を渡すだけです。
試しに、簡単な真偽判定を実行してみるとこんな感じの結果が返ります。

workspace(dev)> Gemini::Flash::GenerateContent::Boolean.new(system_instruction: "計算結果が正しことを確認してください", text: "1+1は2ですか?").run
=> true
workspace(dev)> Gemini::Flash::GenerateContent::Boolean.new(system_instruction: "計算結果が正しことを確認してください", text: "1+1は999ですか?").run
=> false

有効活用できそうな人へ

汎用的に作ったこともあって、他の使い道も多いと思います。
使いたい人がいたらほとんどそのまま使えるので、もしよければコピペしてどうぞ。

Discussion