0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

X(旧twiiter)でプチ話題、生成AIで書かれたコードかどうか検知するサービス"AI Code Detector by Span"を触ってみた

Posted at

はじめに

こんにちは。突然ですが、先日Xを閲覧していると以下のポストが流れてきました。

生成AIで書かれたコードかどうかを95%の精度で検知するサービスが始まったらしいです。その名も、AI Code Detector by Span

対応する言語としては、TypeScriptとpythonに対応しているようです。

では実際に自分で書いたpythonのコードと生成AIに書かせたコードの2つを試してみたいと思います。

自分で書いたpythonコードを渡す

pythonで適当なコードを渡してみます。

渡すコード

python
def dollar_to_yen(dollar,rate):
    return dollar * rate

# 引数にリテラルを指定して呼び出す
yen = dollar_to_yen(100,105)
print("為替レート:105")
print(f"100ドルは{yen}")

rate = 100
dollar = 150

# 引数に変数を指定して呼び出す
yen = dollar_to_yen(dollar,rate)
print(f"為替レート:{rate}")
print(f"{dollar}ドルは{yen}")

では検知してもらいましょう。確認っと。

image.png

おっと、

チェックするためには最低1000文字を張り付ける必要があるそうです。

ということで、改めてコードを作成します。

python
class Customer:
  bmi = 22
  def __init__ (self, number, name, height=0):
    self.__number = number
    self.__name = name
    self.__height = height

  # nameのゲッターメソッド
  def get_name(self):
    return self.__name

  # numberのゲッターメソッド
  def get_number(self):
    return self.__number

  # numberのセッターメソッド
  def set_number(self, number):
    self.__number = number

  # heightのゲッターメソッド
  def get_height(self):
    return self.__height

  def std_weight(self):
    return Customer.bmi * (self.__height / 100) ** 2

# インスタンスを生成
taro = Customer(101, "ヤマダタロウ", 180)

name = taro.get_name()
taro.set_number(99)
number = taro.get_number()
height = taro.get_height()
print(f"{number}:{name} {height}cm")

# 以下、同じ処理を繰り返す

hanako = Customer(102, "ヤマダハナコ", 160)
print(f"{hanako.get_number()}:{hanako.get_name()} {hanako.get_height()}cm")

ichiro = Customer(103, "スズキイチロウ", 170)
print(f"{ichiro.get_number()}:{ichiro.get_name()} {ichiro.get_height()}cm")

jiro = Customer(104, "タナカジロウ", 165)
print(f"{jiro.get_number()}:{jiro.get_name()} {jiro.get_height()}cm")


for i in range(5, 300):
    c = Customer(100+i, f"カスタマー{i}", 150 + (i % 50))
    print(f"{c.get_number()}:{c.get_name()} {c.get_height()}cm 標準体重={c.std_weight():.1f}kg")

すると、

image.png

Your code is 0% written by AI.となりました。自分で書いたコードですからね。うれしい。
では次に、生成AIに書かせたコードで試してみたいと思います。

生成AIに書かせたpythonコードを渡す

今回はchatgptに書かせたコードを渡してみます。

生成AIに投げたプロンプト

以下の内容を生成AIに投げてみます。

プロンプト
コーディングをお願いします。 
使用する言語:python 
生成してほしいコード:お会計システム 
条件:1000文字以上になるまで

渡すコード

python
import sys

class Item:
    def __init__(self, code: int, name: str, price: float):
        self.code = code
        self.name = name
        self.price = price

    def __str__(self):
        return f"[{self.code}] {self.name} - {self.price:.2f}"


class Cart:
    def __init__(self):
        self.items = []

    def add_item(self, item: Item, quantity: int = 1):
        for _ in range(quantity):
            self.items.append(item)
        print(f"{item.name}{quantity} 個追加しました。")

    def remove_item(self, code: int, quantity: int = 1):
        removed_count = 0
        for i in range(quantity):
            for cart_item in self.items:
                if cart_item.code == code:
                    self.items.remove(cart_item)
                    removed_count += 1
                    break
        if removed_count > 0:
            print(f"商品コード {code}{removed_count} 個削除しました。")
        else:
            print("指定の商品はカートに存在しません。")

    def calculate_total(self):
        return sum(item.price for item in self.items)

    def show_cart(self):
        if not self.items:
            print("カートは空です。")
        else:
            print("=== カートの中身 ===")
            summary = {}
            for item in self.items:
                if item.code not in summary:
                    summary[item.code] = {"name": item.name, "price": item.price, "count": 0}
                summary[item.code]["count"] += 1

            for code, info in summary.items():
                print(f"{info['name']} x {info['count']} = {info['price']*info['count']}")

            print(f"合計金額: {self.calculate_total()}")


class Payment:
    def __init__(self, total_amount: float):
        self.total_amount = total_amount

    def pay_by_cash(self, cash_amount: float):
        if cash_amount < self.total_amount:
            print("支払い金額が不足しています。")
            return False
        change = cash_amount - self.total_amount
        print(f"現金 {cash_amount} 円を受け取りました。お釣りは {change} 円です。")
        return True

    def pay_by_card(self, card_number: str):
        if len(card_number) != 16 or not card_number.isdigit():
            print("カード番号が不正です。16桁の数字を入力してください。")
            return False
        print(f"カード番号 {card_number[-4:]}**** にて {self.total_amount} 円を支払いました。")
        return True


class BillingSystem:
    def __init__(self):
        self.catalog = []
        self.cart = Cart()

    def add_item_to_catalog(self, code: int, name: str, price: float):
        item = Item(code, name, price)
        self.catalog.append(item)

    def show_catalog(self):
        print("=== 商品一覧 ===")
        for item in self.catalog:
            print(item)

    def find_item_by_code(self, code: int):
        for item in self.catalog:
            if item.code == code:
                return item
        return None

    def run(self):
        while True:
            print("\n=== お会計システム ===")
            print("1. 商品一覧表示")
            print("2. カートに商品追加")
            print("3. カートから商品削除")
            print("4. カートの中身確認")
            print("5. 支払い")
            print("6. 終了")
            choice = input("番号を入力してください: ")

            if choice == "1":
                self.show_catalog()
            elif choice == "2":
                self.show_catalog()
                try:
                    code = int(input("商品コードを入力してください: "))
                    quantity = int(input("数量を入力してください: "))
                except ValueError:
                    print("入力が不正です。")
                    continue
                item = self.find_item_by_code(code)
                if item:
                    self.cart.add_item(item, quantity)
                else:
                    print("商品が見つかりません。")
            elif choice == "3":
                try:
                    code = int(input("削除する商品コードを入力してください: "))
                    quantity = int(input("削除する数量を入力してください: "))
                except ValueError:
                    print("入力が不正です。")
                    continue
                self.cart.remove_item(code, quantity)
            elif choice == "4":
                self.cart.show_cart()
            elif choice == "5":
                total = self.cart.calculate_total()
                if total == 0:
                    print("カートが空です。支払いできません。")
                    continue
                print(f"お支払い金額は {total} 円です。")
                pay_method = input("支払い方法を選んでください (cash/card): ")
                payment = Payment(total)
                if pay_method == "cash":
                    try:
                        cash_amount = float(input("現金の金額を入力してください: "))
                    except ValueError:
                        print("入力が不正です。")
                        continue
                    if payment.pay_by_cash(cash_amount):
                        self.cart = Cart()  # 支払い成功後、カートをリセット
                elif pay_method == "card":
                    card_number = input("カード番号を入力してください(16桁): ")
                    if payment.pay_by_card(card_number):
                        self.cart = Cart()
                else:
                    print("支払い方法が不正です。")
            elif choice == "6":
                print("システムを終了します。")
                sys.exit()
            else:
                print("無効な選択です。")


if __name__ == "__main__":
    system = BillingSystem()
    # 商品を登録
    system.add_item_to_catalog(101, "りんご", 120)
    system.add_item_to_catalog(102, "みかん", 80)
    system.add_item_to_catalog(103, "バナナ", 100)
    system.add_item_to_catalog(104, "牛乳", 150)
    system.add_item_to_catalog(105, "パン", 200)
    system.add_item_to_catalog(106, "", 300)
    system.add_item_to_catalog(107, "お米", 2500)
    system.add_item_to_catalog(108, "", 1200)
    system.add_item_to_catalog(109, "", 1000)
    system.add_item_to_catalog(110, "野菜", 500)

    # 実行
    system.run()

さあ、どうなるのか見ものですね。
"Your code in 100% written by AI" 生成AIが100%で書かれたコードと検知しました。
その通りです。お見事。
image.png

なぜ検知することが可能なの?

どうして検知することが可能なのか、公式サイトに使用している技術が掲載されているのでまとめておきます。

どのように機能しますか?
AIコード検出機能は、数百万ものAI生成および人間が記述したコードサンプルでトレーニングされた機械学習分類器span-detect-1を搭載しています。意味的に生成されたコードの「チャンク」を解析し、スタイル、構文、構造のパターンに基づいて、AI生成か人間が記述したものかを分類します。

要するに、検知に使用されている技術は以下の通り。

  • 機械学習分類器「span-detect-1」
  • コードのチャンク解析
  • 特徴分析
  • 分類機能

大量のコードサンプルを学習した機械学習モデルが、書き方の癖や構造的特徴を見抜くことで検知が可能になっています。

触ってみた感想

触ってみた感想として95%の精度があると公式情報に記述がありますが、実際のところどうなのでしょうか。こればかりは検証してみないことにはわかりません。

AI対AIチェッカーの戦いになるのかなー。今後も注目して見ていきたいと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?