簡易的なヒューリスティックパーサの自作方法
Table of Contents
背景・動機
クローリング結果や業務で使ってるデータベースの値など世の中にはDirtyな値が山のようにある。 一定のルールで正規化した値を取得したい場合にヒューリスティックパーサが便利。
業務で大量に作ったので作り方についてメモしておく。
試したこと・やったこと
0. ヒューリスティックパーサが適切か見極める
目の前の問題の性質がヒューリスティックパーサが適してるか確認する。
- メリット
- 不完全・壊れた入力への耐性が高い
- 実装の簡単さ
- パフォーマンス
- 依存関係の排除
- デメリット
- エッジケースに対応しきれない
- 偽陽性や偽陰性
- 正当性の証明が困難
1. テストデータのパターンを用意する
AIにテストケースをyamlで生成させる。 たとえば次のyamlは文字列から月給の下限と上限を取得するparserを実装する例。
# 年収(年俸)の文字列があるパターン
- input: "300万円~350万円 ※この限りではありません。"
expected:
form: "年収"
min: 3000000
max: 3500000
# 年収の単純な範囲指定パターン
- input: "年俸400万円~500万円"
expected:
form: "年俸"
min: 4000000
max: 5000000
# 月給のパターン
- input: "月給20万円~25万円"
expected:
form: "月給"
min: 200000
max: 250000
- input: "月給25万3000円"
expected:
form: "月給"
min: 253000
max: 253000
# 時給のパターン
- input: "時給1,500円~2,000円"
expected:
form: "時給"
min: 1500
max: 2000
- input: "時給1,800円"
expected:
form: "時給"
min: 1800
max: 1800
# 日給のパターン
- input: "日給12,000円~15,000円"
expected:
form: "日給"
min: 12000
max: 15000
- input: "日給10,000円"
expected:
form: "日給"
min: 10000
max: 10000
2. パーサをAIに作らせる
「yamlのinputとexpectedに合うparserを自作して、vitestで実装して」とAIに命令すればよい。
import { describe, it, expect } from "vitest";
import fs from "node:fs";
import yaml from "js-yaml";
import path from "node:path";
import { parseSalary } from "./salary";
interface TestData {
input: string;
expected: {
form: string | null;
min: number | null;
max: number | null;
};
}
describe("parseSalary", () => {
const yamlPath = path.join(__dirname, "salary.yaml");
const yamlFile = fs.readFileSync(yamlPath, "utf8");
const testCases = yaml.load(yamlFile) as TestData[];
testCases.forEach(({ input, expected }) => {
it(`should parse "${input}" correctly`, () => {
const result = parseSalary(input);
expect(result).toEqual(expected);
});
});
});
得られた結果・所感
Claude Codeに大量にヒューリスティックパーサを大量に錬成できた。 昔の人は手でパーサを書いてたと思うとAIさまざま。
今後の展開・検討事項
ヒューリスティックパーサよりも厳密性が求められる時にフォーマルなパーサを実装できるようにしておきたい。