採用におけるAI

AI履歴書解析:正規表現、NLP、LLMの精度トレードオフ

ClarityHire Team(Editorial)11 min read

履歴書解析の進化(とその課題)

かつて履歴書解析は本当に難しい問題でした。数十年間、最良の選択肢はSovrenのような企業に依頼して、PDFに対して正規表現パターンを実行し、nameemailphoneexperienceを抽出することでした。このパターンはケースの60%で機能しました。つまり、フォーマットが整った標準的な構造の履歴書です。一方、非標準的なレイアウト、国際的な名前形式、絵文字、表、異なるヘッダーなどの異常値は処理できませんでした。

このトレードオフは当時としては受け入れやすいものでした。代替案がなかったからです。そのため採用チームは独自の対策を講じました:解析結果の手動確認、バックエンド品質チェック、電話番号の検証、そして15%の候補者データが不正確になることを甘受するという状況です。

その後、NLP(spaCy、StanfordNLP)がより良い解決策を約束しました。固有表現認識により、生のテキストから正規表現なしに情報を抽出できます。確かに、固有表現抽出のタスクとしてはうまく機能しました。しかし履歴書解析は単なる固有表現抽出ではありません。履歴書は意味構造を持つドキュメントです。例えば「2020~2022」というテキストがヘッダーの下に書かれているのは、単なる日付ではなく、ある職務の「開始日と終了日」を表しています。ニュース記事で学習したNLPモデルには、このような文脈的な意味を捉えることはできません。

今ではLLM(Claude、GPT)が意味的文脈を理解できるようになりました。しかしLLMは確率的なモデルです。構造化された指示がなければ、存在しないフィールドを生成し、仮想の職務を作り出し、時には経歴セクション全体を省略することがあります。では、どうすればLLMに確実に履歴書を解析させることができるのでしょうか?

各手法の限界

正規表現(Sovren時代):

  • 失敗する場合: 非標準的なフォーマット(箇条書きではなく横方向のタイムライン)、異なるフォントのセクションヘッダー、国際的な名前形式、PDF抽出の副産物(余分な空白、破綻した改行)。
  • 機能する場合: フォーマットが整った単一列、英語の履歴書(新卒者や企業出身者の標準的なもの)。
  • 主な問題: 脆弱性。Canvaから出力された1つのPDFがパターンを壊すことがあります。

NLP(spaCy、StanfordNLP):

  • 失敗する場合: 意味的な理解の欠如。「2020~2022」は確かに日付に見えますが、なぜこの履歴書に書かれているのか?どの職務の下にあるのか?開始/終了日なのか、それとも単独の資格なのか?このような文脈を理解できません。
  • 機能する場合: ドキュメントが整理されていて、ラベルが明確な場合の固有表現抽出。
  • 主な問題: 意味的文脈の欠如。NLPモデルは「スキル」の下の「Python」と「Pythonコンサルティング企業」の「Python」(ツール vs. 企業名)の違いを理解できません。

構造化されていないLLM:

  • 失敗する場合: 幻覚(存在しないデータの生成)。「候補者の職務経歴を抽出してください」というリクエストに対して、[{ title: "Senior Software Engineer", company: "Google", start: "2018", end: "2022" }, { title: "Principal Engineer", company: "Apple", start: "2015", end: "2018" }]と返答するが、実際には履歴書に記載されているのはそのうち1つだけ。または、モデルのコンテキストウィンドウが埋まってセクション全体が省略される場合もあります。
  • 機能する場合: 要約や自由形式の解釈。
  • 主な問題: ガードレールがない。モデルは信じられそうなデータを勝手に生成する可能性があります。

構造化プロンプティング付きLLM(Zod/JSONスキーマ):

  • 失敗する場合: 複雑なエッジケース(15職務を経験した候補者、英語と非英語が混在する履歴書、非標準的な資格形式)。ただし、幻覚はほぼ発生しません。
  • 機能する場合: 対抗的でない約95%の履歴書。
  • 主な問題: 事前にスキーマ定義とプロンプトの調整が必要です。

構造化プロンプティングが実現すること

構造化プロンプティング+バリデーション(Zod、JSONスキーマ)は、LLMをガードレール内に留めることを強制します:

履歴書データを以下のスキーマに従って抽出してください:
{
  name: string,
  email: string,
  phone: string,
  experience: [{ title, company, start, end, summary }],
  skills: [string],
  education: [{ degree, field, school, graduationYear }]
}

ルール:
- フィールドが欠落している場合は、作り出した値ではなくnullを返してください。
- 日付はYYYYまたはYYYY-MM形式にしてください。曖昧な文字列は不可です。
- スキルは言及されたツール/言語であるべきで、抽象的な形容詞は含めないでください。

スキーマ+バリデーションは幻覚を捕捉します。例えば、モデルが履歴書に記載されている4職務に対して6職務を作り出した場合、バリデータがこれにフラグを立てることができます。start: "early 2020"(有効でない形式)を返した場合、スキーマはこれを拒否し、モデルに準拠するよう求め直します。

これがエラーを完全に排除するわけではありません。LLMが「2020~2022」を「2020~2023」と誤読することはあります。ただし、正規表現やNLPでは対応できない「種類」のエラー、つまり意味的な並べ替え、文脈的な抽出、複数ドキュメント解析を防ぐことができます。

精度トレードオフ

手法精度*レイテンシーコストロバスト性
正規表現60~70%<100ms$0.01/履歴書(オンサイト)脆弱
NLP70~80%200~500ms$0.02/履歴書中程度
LLM(非構造化)80~90%1~3s$0.10~0.50/履歴書幻覚の傾向あり
LLM+構造化+バリデーション92~98%1~3s$0.10~0.50/履歴書ロバスト

*精度 = 抽出されたフィールドがグラウンドトゥルース履歴書と一致する度合い(名前、メール、職務日付、スキル)。履歴書のフォーマットと複雑さによって変動します。

各手法をいつ使うか

  • 月50件の履歴書を処理するスタートアップ企業: LLM+構造化が最適。API呼び出しのコストは無視できる程度で、精度が候補者体験に大きく影響します。
  • 月10,000件の履歴書を処理するエンタープライズATS: ハイブリッドアプローチ。新規の履歴書入力にはLLMを使い、既存の従業員データベースに対して検証します。LLMが失敗した場合は人間による確認にフォールバックします。
  • 大量だが低接触のソーシング: 自社のPDF解析スタックで正規表現を使用。20%のエラーを許容し、下流のフィルターで問題を捕捉します。
  • コンプライアンス・法務対応: 自動抽出だけに依存しないでください。アーカイブの前に必ず人間による検証を行ってください。

ClarityHireが履歴書解析を実装している方法

候補者が履歴書をアップロードまたは貼り付けると、ClarityHireはClaudeを使用してZodバリデーション付きで構造化データを抽出します。抽出される情報は、名前、連絡先、職務経歴、教育、スキルです。候補者はその後、抽出されたデータを確認・修正してからパイプラインに進めます。LLMの出力をリスク低減するための人間が介在するループです。

このアプローチは、コスト(APIコール)と精度・候補者体験とのバランスを取ります。候補者は評価を受ける前に、自分の解析データを確認し、正確性を確認することができます。また、後になって「私たちのシステムに不正確なデータが保存されていた」という状況を防ぎます。例えば、オファーレターで名前が誤字になったり、HRシステムに実際と異なる職務経歴が記録されたりすることがなくなります。

ClarityHireで履歴書解析を試す

履歴書解析NLPLLMAI精度構造化抽出

関連記事