Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

HR 入社書類処理パイプライン:Dify Workflow による PDF 解析から人事システム連携までの実装ガイド

はじめに

新入社員の入社手続きにおいて、人事部門は大量の書類を処理する必要がある。履歴書、住民票、マイナンバー通知カード、銀行口座届出書、年金手帳のコピー、各種誓約書――これらの書類から必要な情報を正確に抽出し、人事システムに登録する作業は、1 名あたり数十分から 1 時間を要する。4 月の一括入社時期には、この作業が集中的に発生し、人事部門のボトルネックとなる。

本稿では、Dify の Workflow を活用して、PDF / 画像形式の入社書類から情報を自動抽出し、検証・人間確認を経て人事システムに登録するエンドツーエンドのパイプラインを設計・実装する方法を解説する。


背景と課題

入社書類処理の現実

課題詳細
書類の多様性テキスト PDF、スキャン PDF、写真撮影の画像が混在
手書き情報の存在住所変更届や銀行口座届出書には手書き項目がある
転記ミスのリスク手動転記では氏名の漢字、口座番号、住所の誤りが発生しやすい
個人情報の機密性マイナンバー、口座情報等の取扱いにセキュリティ制約がある
繁忙期の集中4 月入社の新卒採用では数十名分が同時に発生
書類の不備・不足提出された書類に不備があると、差戻しと再提出のやり取りが発生

パイプライン化のメリット

項目手動処理Dify パイプライン
1 名あたりの処理時間30-60 分5-10 分(人間確認含む)
転記ミス率2-5%0.5% 未満(人間確認後)
書類不備の検出タイミング入力時に発見アップロード直後に自動検出
処理のトレーサビリティ紙ベース全ステップがログに記録

全体アーキテクチャ

flowchart TD
    A[書類アップロード<br>PDF / 画像] --> B[ファイル振分けノード]
    B --> C{ファイル形式判定}
    C -->|テキスト PDF| D[テキスト抽出]
    C -->|スキャン PDF / 画像| E[VLM / OCR 処理]
    D --> F[パラメータ抽出ノード<br>構造化 JSON 出力]
    E --> F
    F --> G[フィールド検証ノード]
    G --> H{検証結果}
    H -->|全項目 OK| I[Human-in-the-Loop<br>最終確認]
    H -->|不備あり| J[不備通知<br>再提出依頼]
    I --> K{承認?}
    K -->|Yes| L[人事システム連携<br>HTTP Request]
    K -->|修正| M[修正入力]
    M --> G
    L --> N[処理完了・ログ記録]

ノード設計の詳細

ノード 1: ファイル受信(開始ノード)

Dify Workflow の開始ノードで、以下の入力を受け付ける。

変数名必須説明
employee_nametextYes入社予定者の氏名
employee_idtextYes社員番号(仮番号可)
entry_datedateYes入社予定日
documentsfile[]Yes入社書類(複数ファイル)
document_typestextNo各ファイルの書類種別(カンマ区切り)

ノード 2: ファイル形式判定・振分け

アップロードされた各ファイルについて、処理方法を振り分ける。

判定ロジック:
- 拡張子が .pdf でテキスト抽出可能 → テキスト PDF ルート
- 拡張子が .pdf でテキスト抽出不可 → スキャン PDF ルート(VLM)
- 拡張子が .jpg / .png / .heic → 画像ルート(VLM)

ノード 3: テキスト抽出

テキスト PDF の場合

PDF パーサーを使用して直接テキストを抽出する。最もコストが低く、精度も高い。

スキャン PDF / 画像の場合

Dify の Vision 対応モデル(GPT-4o、Claude 等)を使用し、画像から直接構造化データを抽出する。従来の OCR パイプライン(画像 → 文字認識 → 後処理)よりも、VLM による直接抽出の方が以下の点で優れている。

項目従来 OCRVLM 直接抽出
表形式への対応構造解析が別途必要テーブル構造を理解して抽出
手書き文字精度が大きく低下文脈を踏まえた推定が可能
複合レイアウトレイアウト解析が必要視覚的に理解して処理
印影・証明写真の存在認識エラーの原因に無視すべき要素を判断可能

ノード 4: パラメータ抽出(LLM ノード)

抽出したテキストまたは画像から、構造化された JSON を出力する。

System Prompt:
あなたは HR 書類処理の専門アシスタントです。
以下の入社書類から、指定されたフィールドを正確に抽出してください。

【抽出フィールド】
{
  "personal_info": {
    "full_name_kanji": "氏名(漢字)",
    "full_name_kana": "氏名(カタカナ)",
    "date_of_birth": "生年月日(YYYY-MM-DD)",
    "gender": "性別",
    "nationality": "国籍"
  },
  "address": {
    "postal_code": "郵便番号(XXX-XXXX)",
    "prefecture": "都道府県",
    "city": "市区町村",
    "street": "番地以降",
    "building": "建物名・部屋番号"
  },
  "contact": {
    "phone": "電話番号",
    "email": "メールアドレス",
    "emergency_contact_name": "緊急連絡先氏名",
    "emergency_contact_phone": "緊急連絡先電話番号",
    "emergency_contact_relationship": "続柄"
  },
  "bank_account": {
    "bank_name": "銀行名",
    "branch_name": "支店名",
    "account_type": "口座種別(普通/当座)",
    "account_number": "口座番号",
    "account_holder": "口座名義(カタカナ)"
  },
  "tax_social": {
    "my_number": "マイナンバー(12桁)",
    "pension_number": "基礎年金番号",
    "health_insurance_number": "健康保険証番号"
  }
}

【重要ルール】
1. 書類に記載がないフィールドは null を設定すること
2. 読み取りに自信がないフィールドは
   {"value": "読み取り値", "confidence": "low", "note": "理由"}
   の形式で出力すること
3. マイナンバーは12桁の数字であること。桁数が合わない場合は
   confidence を "low" に設定すること
4. 絶対に推測や補完を行わないこと

各フィールドには valueconfidence(high / medium / low)、source_file を付与する。confidence が low のフィールドは後続の Human-in-the-Loop で必ず人間確認に回す設計とする。

ノード 5: フィールド検証

抽出されたデータに対して、ルールベースの検証を行う。

検証ルール:
1. 郵便番号: XXX-XXXX 形式であること
2. 電話番号: 0X-XXXX-XXXX または 0XX-XXX-XXXX 形式
3. メールアドレス: 有効な形式であること
4. マイナンバー: 12桁の数字であること
5. 口座番号: 7桁の数字であること
6. 生年月日: 入社日時点で18歳以上であること
7. 必須フィールド: 氏名、住所、銀行口座が全て入力済みであること

Dify Workflow では、コードノード(Python / JavaScript)を使用してこれらの検証を実装できる。

# コードノードでの検証例
import re
import json

def validate_fields(data):
    errors = []
    warnings = []
    
    # 郵便番号チェック
    postal = data.get("address", {}).get("postal_code", "")
    if postal and not re.match(r"^\d{3}-\d{4}$", postal):
        errors.append({
            "field": "address.postal_code",
            "value": postal,
            "message": "郵便番号の形式が不正です(XXX-XXXX)"
        })
    
    # マイナンバーチェック
    my_number = data.get("tax_social", {}).get("my_number", "")
    if isinstance(my_number, dict):
        # confidence が low の場合
        warnings.append({
            "field": "tax_social.my_number",
            "value": my_number.get("value"),
            "message": my_number.get("note"),
            "requires_human_review": True
        })
    elif my_number and not re.match(r"^\d{12}$", str(my_number)):
        errors.append({
            "field": "tax_social.my_number",
            "value": my_number,
            "message": "マイナンバーは12桁の数字である必要があります"
        })
    
    # 口座番号チェック
    account = data.get("bank_account", {}).get("account_number", "")
    if account and not re.match(r"^\d{7}$", str(account)):
        errors.append({
            "field": "bank_account.account_number",
            "value": account,
            "message": "口座番号は7桁の数字である必要があります"
        })
    
    return {
        "is_valid": len(errors) == 0,
        "errors": errors,
        "warnings": warnings,
        "requires_human_review": len(warnings) > 0
    }

ノード 6: Human-in-the-Loop(人間確認)

以下の条件で、人事担当者による確認を求める。

トリガー条件重要度対応
confidence: low のフィールドが存在該当フィールドをハイライトして確認依頼
検証エラーが存在エラー内容を表示し修正を依頼
必須フィールドが null不足書類の再提出を依頼
マイナンバー・口座番号の抽出必須機密情報は必ず人間が最終確認
氏名の漢字・カナの不一致正しい表記を確認
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
入社書類処理: 確認が必要です
━━━━━━━━━━━━━━━━━━━━━━━━━━━━

■ 対象者: 山田 太郎(社員番号: EMP-2026-0501)
■ 入社予定日: 2026-05-01

■ 要確認項目:

  ⚠ マイナンバー: 123456789012
    → スキャン品質が低く、3桁目が不明確です。
       原本を確認してください。

  ⚠ 基礎年金番号: 未検出
    → 年金手帳のコピーが提出されていない可能性があります。

■ 抽出結果(全項目):
  [構造化データを表示]

■ アクション:
  [承認] [修正して承認] [書類再提出依頼]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━

ノード 7: 人事システム連携(HTTP Request ノード)

確認済みのデータを、Dify Workflow の HTTP Request ノードから人事システムの API に送信する。構造化 JSON をそのまま POST するため、フィールドマッピングの設計が重要である。

連携先のシステム例:

システム連携方法登録内容
人事マスタ(COMPANY 等)REST API基本情報・住所・家族情報
給与システム(freee 人事労務等)REST API銀行口座・社会保険情報
勤怠システム(KING OF TIME 等)REST API社員番号・所属部門
Active Directory / IdPLDAP / SCIMアカウント自動作成
Google Workspace / Microsoft 365Admin APIメールアドレス・グループ割当

セキュリティ設計

個人情報の取扱い

入社書類にはマイナンバー、銀行口座情報など、特に厳格な管理が求められる個人情報が含まれる。

対策実装方法
通信の暗号化Dify と各システム間は HTTPS / TLS 1.3
データの一時保存制限Workflow 実行完了後、一時ファイルを自動削除
アクセス制御Dify のワークスペース権限で処理担当者を限定
監査ログ全操作(アップロード・抽出・確認・登録)をログに記録
オンプレミスデプロイ機密性が高い場合、Dify セルフホスト版を閉域網で運用
マイナンバーの特別管理抽出後はマスキングして表示、人間確認時のみ全桁表示

個人情報保護の観点から、マイナンバーや口座情報を外部クラウドに送信できない場合は、Dify セルフホスト版(Docker Compose)を閉域網で運用し、ローカル VLM と組み合わせることでデータ外部送信を完全に回避できる。


エラーハンドリング

想定されるエラーと対処

エラー検出方法対処
PDF が暗号化されているファイル解析時のエラー暗号化解除を依頼
画像の解像度が低いVLM の confidence が全般的に低い再撮影・再スキャンを依頼
書類の種類が想定外書類タイプ判定で「不明」人事担当者にエスカレーション
人事システム API エラーHTTP レスポンスコードで検出3 回リトライ後、保留キューに格納
抽出データの矛盾検証ノードで不整合を検出人間確認に回す

導入ステップ

Phase期間内容
Phase 12 週間履歴書のみを対象に PoC。テキスト抽出 → JSON 変換の精度を検証。
Phase 22-4 週間書類種別を拡大(口座届出書、住民票等)。VLM によるスキャン対応を追加。
Phase 31-2 ヶ月検証ノード・Human-in-the-Loop を実装。人事システムとの API 連携。
Phase 4継続バッチ処理の整備。抽出精度のモニタリングと改善。

まとめ

HR 入社書類処理パイプラインの核心は、「AI が PDF を読めるか」ではなく、解析・抽出・検証・人間確認・システム登録という一連のプロセスを、追跡可能かつ再現可能な形で自動化することにある。

Dify Workflow は、ファイル入力の受付、VLM / OCR による情報抽出、コードノードによるバリデーション、Human-in-the-Loop による人間確認、HTTP Request ノードによる外部システム連携――これらすべてをビジュアルに設計・運用できる基盤を提供する。

特に重要な設計原則は以下の三点である。

  1. 構造化出力: 自然文ではなく、フィールド単位の JSON で出力し、confidencesource を付与する
  2. 人間確認の必須化: 機密性の高いフィールド(マイナンバー、口座番号)は必ず人間が最終確認する
  3. セキュリティ設計: 個人情報の取扱いに応じて、セルフホスト版の採用やデータの一時保存制限を検討する

これらの原則を守ることで、人事部門の繁忙期における書類処理の負荷を大幅に軽減しつつ、正確性と安全性を担保するパイプラインを実現できる。