✏️

生成AIを使って爆速でコーディングできた話

2024/09/14に公開

はじめに

ある日友人からこんな相談を受けました。
「○○病院からもらったエクセルの表をデータベースのエクセルファイルを見ながら埋めていく仕事が面倒くさくて...」
タスクの内容 (後述) を聞くと、Pythonでプログラム書いて処理すれば楽になりそうだなって思ったので、Pythonのプログラムを提供することにしました。ただし、私の本業とは大きくかけ離れているため、業務時間外にご厚意でやるということで、時間はかけたくありません。そこで、AIの力を借りて爆速で完成させました。その時の体験談です。

タスクの内容

エクセルファイルの説明

  1. ○○病院からもらったエクセルの表 (*データは全て適当です)
a_id a_disease a_medicine
123 肺がん シスプラチン
456 アルツハイマー型認知症 ドネペジル
2002 糖尿病 (2型) SGLT2阻害剤
  1. データベースのエクセルファイル (*データは全て適当です)
a_id a_disease a_medine b_id b_disease b_medicine
123 肺がん シスプラチン 201 肺がん カルボプラチン
301 2型糖尿病 SGLT2阻害薬
2505 花粉症 抗ヒスタミン薬 402 季節性アレルギー性鼻炎 第2世代抗ヒスタミン薬

行いたいタスク

  1. "a_id" 列をキーとして病院からもらったエクセルファイルに "b_id", "b_disease", "b_medicine" 列を結合
  2. "a_id" で結合できなかった場合、病院ファイルの "a_disease" 列とデータベースファイルの "b_disease" 列の文字列の50%以上が一致かつ 病院ファイルの "a_medicine" 列とデータベースファイルの "b_medicine" 列の文字列の50%以上が一致したら結合する
  3. 新しい列としてFlag列を用意する ("a_id" で結合できたらFlag=0, "a_id"で結合できず、文字列の条件で結合できたらFlag=1, 結合できなかったらFlagは空欄)
    要するに上のファイルを例にすると、完成品はこんな感じになります (分かりづらかったら読まずに飛ばしてください)。
a_id a_disease a_medicine b_id b_disease b_medicine Flag
123 肺がん シスプラチン 201 肺がん カルボプラチン 0
456 アルツハイマー型認知症 ドネペジル
2002 糖尿病 (2型) SGLT2阻害剤 301 2型糖尿病 SGLT2阻害薬 1

制約

Pandasが使用不可能 (セキュリティが原因?で友人の社用PCに入れることができなかった) なため、Pythonにデフォルトで入っているモジュールを使って行います。

生成AIを使用したプログラミング (本題)

利用した生成AIツール | Perplexity

前置きが長くてすみません。ここから本題です。
今回は生成AIのツールとしては、私が愛用している Perplexity を使用しました。
以下、Perplexityについての説明です (Perplexityに生成してもらいました)。

Perplexity AIは、AIを活用した検索エンジンであり、ユーザーに対して正確で信頼性のある情報を提供します。以下に、指定されたトピックに基づいてPerplexity AIの機能を詳しく説明します。

Pro Searchについて
Perplexity AIの「Pro Search」は、複雑な質問に対する多段階推論を可能にする高度な検索機能です。この機能は、Wolfram Alphaとの統合により、数学的な問題やプログラミングの計算を迅速かつ正確に処理します。Pro Searchは、通常のクイック検索とは異なり、より深い分析と詳細な情報を提供するために、複数の検索ステップを組み合わせて結果を導き出します。有料プランでは、無制限のPro Searchが利用可能で、毎月20ドルで提供されています。

モデル選択について
Perplexity AIは、複数のAIモデルをサポートしており、ユーザーは自身のニーズに応じて最適なモデルを選択できます。有料プランでは、GPT-4o、Claude 3、Sonar Large(LLaMa 3)などの高度なAIモデルを利用可能です。これにより、ユーザーはより高度な自然言語処理能力を持つモデルを選び、専門的で精度の高い回答を得ることができます。

フォーカス機能
Perplexity AIのフォーカス機能は、検索範囲を特定のカテゴリーに絞り込むことができる便利な機能です。これにより、ユーザーは必要な情報を効率的に取得できます。例えば、「All」モードではインターネット全体を対象に検索し、「Academic」モードでは学術論文に特化した情報を提供します。また、「YouTube」モードでは動画に関連する情報を検索することができます。
これらの機能により、Perplexity AIはユーザーに対して迅速かつ正確な情報を提供し、特に研究やビジネスにおける情報収集において非常に有用です。

プロンプト (1回目)

現在、手元には"input.csv"と"database.csv"という2つのcsvファイルがある。

--- 処理の内容 ---
input.csvとdatabase.csvを左外部結合をしたい (左は"input.csv"とする)。

  1. "a_id" 列をキーとして "input.csv" に "b_id", "b_disease", "b_medicine" 列を結合する
  2. "a_id" で結合できなかった場合、"input.csv" の "a_disease" 列と "database.csv" の "b_disease" 列の文字列比較を行って50%以上が一致する、かつ "input.csv" の "a_medicine" 列と "database.csv" の "b_medicine" 列の文字列比較を行って50%以上が一致したら結合する
  3. 新しい列としてFlag列を用意する ("a_id" で結合できたらFlag=0, "a_id"で結合できず、文字列の条件で結合できたらFlag=1, いずれの条件でも結合できなかったらFlagは空欄)
  4. 出力は "output.csv" とする。

--- 使用するプログラミング言語・モジュール ---
プログラミング言語: Python
モジュール: Pythonにデフォルトで入っているモジュール。Pandasは使用することができません。

--- ファイルの列構成 ---

  1. input.csv
    列構成: [a_id, a_disease, a_medicine]
  2. database.csv
    列構成: [a_id, a_disease, a_medicine, b_id, b_disease, b_medicine]
  3. output.csv
    列構成: [a_id, a_disease, a_medicine, b_id, b_disease, b_medicine, Flag]

Perplexity の回答 (1回目)

import csv

def string_similarity(str1, str2):
    """Calculate the percentage of similarity between two strings."""
    matches = sum(1 for a, b in zip(str1, str2) if a == b)
    total_chars = max(len(str1), len(str2))
    return matches / total_chars

# input.csvを読み込む
with open('input.csv', mode='r', encoding='utf-8') as input_file:
    input_reader = csv.DictReader(input_file)
    input_data = [row for row in input_reader]

# database.csvを読み込む
with open('database.csv', mode='r', encoding='utf-8') as database_file:
    database_reader = csv.DictReader(database_file)
    database_data = [row for row in database_reader]

# output.csvに書き込む
with open('output.csv', mode='w', newline='', encoding='utf-8') as output_file:
    fieldnames = [
        'a_id', 'a_disease', 'a_medicine', 'b_id', 'b_disease', 'b_medicine', 
        'Flag'
    ]
    writer = csv.DictWriter(output_file, fieldnames=fieldnames)
    writer.writeheader()
    
    # 左外部結合の実行
    for input_row in input_data:
        key1 = input_row['a_id']
        matched_row = next((db_row for db_row in database_data if db_row['a_id'] == key1), None)
        
        if matched_row:
            flag = 0
        else:
            # 文字列の5割一致条件を確認
            potential_matches = [
                db_row for db_row in database_data
                if string_similarity(input_row['a_disease'], db_row['b_disease']) >= 0.5 and
                   string_similarity(input_row['a_medicine'], db_row['b_medicine']) >= 0.5
            ]
            matched_row = potential_matches[0] if potential_matches else None
            flag = 1 if matched_row else ''
        
        output_row = {
            'a_id': input_row['a_id'],
            'a_disease': input_row['a_disease'],
            'a_medicine': input_row['a_medicine'],
            'b_id': matched_row['b_id'] if matched_row else '',
            'b_disease': matched_row['b_disease'] if matched_row else '',
            'b_medicine': matched_row['b_medicine'] if matched_row else '',
            'Flag': flag
        }
        
        writer.writerow(output_row)

問題点

ほぼ完ぺきなコードを提示してくれましたが、上から2行目にある "string_similarity" 関数の所で問題点が2点見つかりました。

  1. matches = sum(1 for a, b in zip(str1, str2) if a == b) は文字の順番を考慮するようになっています。これだと、'a_disease': 糖尿病 (2型), 'b_disease': 2型糖尿病の場合は、結合することができず、意図した処理はできません。
  2. プログラムを動かしてみると、return matches / total_charsでZeroDivisionErrorが出ました。これは、"input.csv", "database.csv" の "disease" 列や "medicine" 列に欠損値があったことが原因です。

プロンプト (2回目)

Perplexityは前回の回答の続きに、更なるプロンプトを入力することができます。問題点を解決してもらえるようにお願いしましょう ↓

次の2か所の部分について改善してください。

  1. string_similarty関数の "matches = sum(1 for a, b in zip(str1, str2) if a == b)"
    こちらは文字列の順番も考慮した処理になっています。文字列の順番を考慮せずに、"同じ文字が5割以上含まれている"という条件に変更してください。具体例として、str1 = "糖尿病 (2型)", str2 = "2型糖尿病" の場合を考えます。現在のプログラムだと、一致しない判定になると思います。"同じ文字が5割以上含まれる"という条件にすれば、一致として判定できます。
  1. return matches / max(len(str1), len(str2))でZeroDivisionErrorが出ました。これは、"input.csv", "database.csv"に欠損値があることが原因だと思います。ZeroDivisionErrorを回避してください

Perplexityの回答 (2回目)

+ from collections import Counter

def string_similarity(str1, str2):
    """Calculate the percentage of similarity between two strings."""
-   matches = sum(1 for a, b in zip(str1, str2) if a == b)
+   matches = sum((Counter(str1) & Counter(str2)).values())
    total_chars = max(len(str1), len(str2))
-   return matches / total_chars
+   return matches / total_chars if total_chars > 0 else 0

コピペして終了

さいごに

以上、AIの力を借りてコーディングを行った体験談でした。かかった時間は30分ぐらいです。自分の実力を鑑みると、自力でやっていたら数時間はかかっていたと思います。皆さんもAIを駆使して良いコーディングライフを!

おまけ | Perplexityの紹介リンク

Perplexity使ってみたいなって方は無料版でも使うことができます (制限はありますが...)。
課金してみたいなって思った方は、以下のリンクから登録すると通常20ドルが10ドルになりますので、よかったらどうぞ
https://perplexity.ai/pro?referral_code=AIFC1LAK

Discussion