はじめに
不動産データの名寄せは、表記揺れや欠損情報の補完が必要な場面が多く、手作業で行うには非常に手間がかかります。今回は、機械的な名寄せ処理とAIおよび翻訳APIを組み合わせた補完処理を組み込んだツールを作成しました。
このツールは以下の課題を解決します:
- 表記揺れの正規化とデータの重複排除
- 備考欄の英語を翻訳して日本語データに統一
- 欠損情報をAIで補完し、データの品質を向上
使用した技術スタック
以下の技術を使用しました:
- 言語: TypeScript
- フレームワーク: Next.js
- 翻訳サービス: DeepL API
- AIモデル: Google Generative AI (Gemini Pro)
-
データ操作:
- Node.js の
fs
モジュールでファイル操作 -
csv-parser
ライブラリでCSVデータ解析 -
csv-writer
ライブラリでCSV出力
- Node.js の
機能要件
主な機能
-
表記揺れの正規化
- 物件名、住所、電話番号の表記揺れを統一し、データの重複を検出しやすくする。
-
備考欄の翻訳
- 備考欄の英語をDeepL APIで高品質な日本語に翻訳。
- 日本語の備考は翻訳せずそのまま保持。
-
フェーズ1:機械的な名寄せ
- 正規化されたフィールドをもとに、同一データを識別。
- 備考欄の情報を重複なく統合。
-
フェーズ2:AIによる補完と仕上げ
- Google Generative AIを使用し、欠損データの補完や備考欄の整理を実施。
苦労した不具合と解決方法
1. 表記揺れの統一
問題: 名寄せキー作成時、住所や電話番号の表記揺れが原因でデータが正しく統合されない。
解決:
-
normalizeField
関数を作成し、全角・半角やハイフン、スペースなどを正規化。
2. 英語翻訳の品質問題
問題: 備考欄をAIで翻訳した場合、翻訳品質が低く、誤訳や不自然な表現が多発。
解決:
- DeepL APIを使用し、英語の備考のみを高品質な日本語に翻訳。
- 日本語の備考はそのまま保持するように
containsJapanese
関数を実装。
3. AIによる名寄せの品質不足
問題: AIを単独で名寄せに使用すると、備考欄の情報が欠損したり、順序が乱れるケースが発生。
解決:
- 機械的な名寄せ処理(フェーズ1)で同一データを事前に統合。
- AIには欠損補完や備考欄の調整のみを依頼。
工夫したロジック
1. 機械的な名寄せ処理の採用
AI任せにすると品質が低下するため、以下の手順を追加:
- 正規化されたフィールドを用いて名寄せキーを生成。
- 機械的にデータを統合し、備考欄を一意にまとめる。
2. DeepLとAIの役割分担
- 英語の備考翻訳をDeepL APIに任せることで、翻訳品質を確保。
- AIには欠損補完や最終的な統合処理を依頼。
3. プロンプト設計
Google Generative AIに渡すプロンプトを以下のように改善:
- 欠損や順序乱れを防ぐため、具体的な指示を記載。
- 出力フォーマットをJSONで固定し、解析エラーを防止。
以下は、AIによる名寄せの部分を含めたコードのポイントです。
コードのポイント
1. 備考欄をDeepL APIで翻訳するロジック
英語の備考を高品質な日本語に翻訳し、日本語の備考はそのまま保持します。
const translateNotes = async (records: Array<{ [key: string]: string }>) => {
const translatedRecords = [];
for (const record of records) {
if (record.備考) {
try {
if (containsJapanese(record.備考)) {
// 日本語の場合はそのまま
translatedRecords.push(record);
} else {
// DeepLで英語を日本語に翻訳
const result = await translator.translateText(record.備考, null, 'ja');
translatedRecords.push({ ...record, 備考: result.text });
}
} catch (err) {
console.error('Failed to translate note:', record.備考, err);
translatedRecords.push(record); // 翻訳失敗時は元データを保持
}
} else {
translatedRecords.push(record);
}
}
return translatedRecords;
};
2. AIによる名寄せのロジック
Google Generative AIを使用して、欠損データの補完と備考欄の整理を行います。
const finalizeDeduplicationWithAI = async (records: Array<{ [key: string]: string }>) => {
const prompt = `
以下の不動産データについて、重複を名寄せして整理してください。一意のレコードのみを保持し、すべての情報を欠損なく統合してください。
- 備考欄の情報は重要であるため、欠損や省略がないように統合してください。
- 既存の備考を削除せず、すべての内容を含めてください。
- 備考欄の情報が重複する場合は、順序を保持して統一してください。
入力データ:
${JSON.stringify(records)}
出力フォーマット:
[
{
"物件名": "正規化済みの物件名",
"住所": "正規化済みの住所",
"電話番号": "正規化済みの電話番号",
"備考": "統合された備考情報(, 区切り)"
},
...
]
`;
const model = googleClient.getGenerativeModel({ model: 'gemini-pro' });
const response = await model.generateContent(prompt);
const generatedText = typeof response.response?.text === 'function'
? response.response.text()
: response.response?.text;
if (!generatedText) {
throw new Error('No response text from Google Generative AI.');
}
const cleanedText = generatedText.trim().replace(/```\n/g, '').replace(/```/g, ''); // 不要な囲み文字を削除
console.log('Generated JSON:', cleanedText);
return JSON.parse(cleanedText);
};
ポイント
- AIのプロンプトに具体的な指示(欠損防止や備考欄の統合ルール)を記載し、出力品質を確保。
- プロンプト設計を工夫することで、データの欠損や乱れを最小化。
このように、DeepL APIとGoogle Generative AIを適材適所で組み合わせることで、データ品質を大幅に向上させることができました。
実行結果
以下のデータを処理した結果:
入力データ(サンプル)
物件名,住所,電話番号,備考
サンプルマンション,東京都新宿区西新宿1-1-1,0120-123-456,新築物件
サンプルマンション,東京都新宿区西新宿1-1-1,0120-123-456,築2年
さんぷるマンション,東京都新宿区西新宿1-1-1,0120123456,リフォーム済み
SAMPLE MANSION,Tokyo Shinjuku-ku Nishi-Shinjuku 1-1-1,0120123456,Free Wi-Fi
SAMPLE MANSION,Tokyo Shinjuku-ku Nishi-Shinjuku 1-1-1,0120123456,駐車場完備
出力データ
物件名,住所,電話番号,備考
サンプルマンション,東京都新宿区西新宿1-1-1,0120-123-456,"新築物件, 築2年, リフォーム済み, Free Wi-Fi , 駐車場完備"
まとめ
今回作成した不動産名寄せツールでは、DeepL APIとGoogle Generative AIを役割分担させることで、データの品質を大幅に向上させることができました。特に、以下の工夫が有効でした:
- 機械的な処理で表記揺れを正規化
- DeepL APIで高品質な英語翻訳を実現
- AIをデータ補完と調整のみに使用することで効率化
このツールは、不動産データ以外の名寄せ処理やデータ統合にも応用可能です。