OpenSource-Hub

hiring-agent

CLI ツール

interviewstreet/hiring-agent

AI履歴書評価・採点ツール。

概要

Hiring Agent は履歴書の PDF を解析し、大規模言語モデルを活用して構造化データを抽出し、GitHub のシグナルと組み合わせて、公平で説明可能なスコアを出力します。完全なローカル実行(Ollama)にも、Google Gemini の利用にも対応しています。

README プレビュー

# Hiring Agent\n\nResume-to-Score pipeline that extracts structured data from PDFs, enriches with GitHub signals, and outputs a fair, explainable evaluation.\n\n\n  \n    \n  \n  \n    \n  \n  \n    \n  \n\n\n---\n\n## Contents\n\n- [Overview](#overview)\n- [Architecture](#architecture)\n- [Installation and Setup](#installation-and-setup)\n  - [Prerequisites](#prerequisites)\n  - [Quick setup with pip](#quick-setup-with-pip)\n  - [Ollama models](#ollama-models)\n- [Configuration](#configuration)\n- [How it works](#how-it-works)\n- [CLI usage](#cli-usage)\n- [Directory layout](#directory-layout)\n- [Provider details](#provider-details)\n- [Contributing](#contributing)\n- [License](#license)\n\n---\n\n## Overview\n\nHiring Agent parses a resume PDF to Markdown, extracts sectioned JSON using a local or hosted LLM, augments the data with GitHub profile and repository signals, then produces an objective evaluation with category scores, evidence, bonus points, and deductions. You can run fully local with Ollama or use Google Gemini.\n\n---\n\n## Architecture\n\n\n\n\n\n**Flow**\n\n1. `pymupdf_rag.py` converts PDF pages to Markdown-like text.\n2. `pdf.py` calls the LLM per section using Jinja templates under `prompts/templates`.\n3. `github.py` fetches profile and repos, classifies projects, and asks the LLM to select the top 7.\n4. `evaluator.py` runs a strict-scored evaluation with fairness constraints.\n5. `score.py` orchestrates everything end to end and writes CSV when development mode is on.\n\n\n\n\n**Key modules**\n\n- `models.py`\n  Pydantic schemas and LLM provider interfaces.\n\n- `llm_utils.py`\n  Provider initialization and response cleanup.\n\n- `transform.py`\n  Normalization from loose LLM JSON to JSON Resume style.\n\n- `prompts/`\n  All Jinja templates for extraction and scoring.\n\n\n\n\n\n---\n\n## Installation and Setup\n\n### Prerequisites\n\n- **Python 3.11+**\n\n  The repository pins `.python-version` to 3.11.13.\n\n- **One LLM backend** (either of 

FAQ (5)

トラブル対応
GitHub APIのエラーハンドリングで「NameError: name 'response' is not defined」を修正するにはどうすればよいですか?

github.py の fetch_all_github_repos では、_fetch_github_api() が (status_code, data) を返すため、response.status_code や response.text にアクセスしないでください。エラーハンドリングブロックを次のように置き換えてください:

elif status_code == 404:
    print(f"GitHub user not found: {username}")
    return []
else:
    print(f"GitHub API error: {status_code} - {repos_data}")
    return []

これにより、GitHub が 404、レート制限、ネットワーク、その他の API エラーを返した場合に、アプリケーションが NameError でクラッシュするのを防ぎます。

参照 Issue #106
トラブル対応
Pythonで複数のPDFファイルを処理する際のPyMuPDFのメモリリークを修正するにはどうすればよいですか?

各 PyMuPDF Document を明示的に閉じてください。pdf.py で、extract_text_from_pdf() をコンテキストマネージャーを使用するように更新します:

import fitz

def extract_text_from_pdf(path):
    with fitz.open(path) as doc:
        return "".join(page.get_text() for page in doc)

with 文は抽出後に PDF を自動的に閉じ、メモリを解放します。コンテキストマネージャーを使用できない場合は、finally ブロック内で doc.close() を呼び出してください。これにより、Python 3.11 上で PyMuPDF 1.24.x を使って 50 件以上の PDF のバッチを処理する際に、メモリが継続的に増大するのを防げます。

参照 Issue #132
トラブル対応
WindowsでPythonを使用してJSONキャッシュファイルを書き込む際に「UnicodeEncodeError: 'charmap' codec can't encode」エラーが発生する場合、どのように修正すればよいですか?

キャッシュファイルを書き込むすべての Path.write_text() 呼び出しで、UTF-8 エンコーディングを明示的に設定してください。Windows では、デフォルトのエンコーディングが cp1252 になる場合があり、絵文字、アクセント付きの名前、その他の Unicode 文字をエンコードできません。

変更前:

Path(github_cache_filename).write_text(
    json.dumps(github_data, indent=2, ensure_ascii=False)
)

変更後:

Path(github_cache_filename).write_text(
    json.dumps(github_data, indent=2, ensure_ascii=False),
    encoding="utf-8"
)

同じ encoding="utf-8" 引数を、github.py および score.py 内のすべてのキャッシュ書き込み呼び出しに適用してください。これには github.py の49行目付近にある GitHub API キャッシュも含まれます。さらなる堅牢性を高めるために、キャッシュの読み込みでは、キャッシュを再構築することで空の JSON や破損した JSON を処理できます。この修正は Windows 11 上の Python 3.11 で検証されました。

参照 Issue #128
トラブル対応
score.py を実行したときに発生する Windows コンソールの UnicodeEncodeError と Python 3.14 の Protobuf TypeError を修正するにはどうすればよいですか?

Protobuf または LLM ライブラリをインポートする前に、以下を追加してください:

import os
import sys

# Windows コンソール出力に UTF-8 を使用する
if hasattr(sys.stdout, "reconfigure"):
    sys.stdout.reconfigure(encoding="utf-8", errors="replace")
if hasattr(sys.stderr, "reconfigure"):
    sys.stderr.reconfigure(encoding="utf-8", errors="replace")

# pure-Python の Protobuf 実装を強制する
os.environ.setdefault("PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION", "python")

この環境変数は protobuf がインポートされる前に設定する必要があります。または、以下を実行してください:

$env:PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION="python"
python score.py

また、set PYTHONUTF8=1 で UTF-8 モードを有効にするか、スクリプトを開始する前に chcp 65001 を実行することもできます。修正は PR #340 で提供されています。

参照 Issue #339
トラブル対応
Geminiの429エラーやOllamaのタイムアウトの後に、レジュメスコアリングが「List should have at least 1 item」というエラーで失敗するのはなぜですか?

LLMの抽出処理が失敗すると、空のリストや null フィールドなどの不完全なデータが cache/resumecache_<resume>.json に書き込まれることがあります。その後の実行では、PDFが再処理されずに破損したキャッシュが読み込まれ、Pydantic の ValidationError が発生します。

暫定的な回避策:

rm cache/resumecache_resume.json
python score.py data/resume.pdf

ファイル名が異なる場合は、影響を受けるPDFに対応するキャッシュファイルを削除してください。また、DEVELOPMENT_MODE = False を一時的に設定して、キャッシュの読み込みを回避することもできます。

恒久対策:抽出された JSONResume オブジェクトをディスクに書き込む前に検証し、失敗した抽出結果は決してキャッシュせず、読み込み時にキャッシュデータを検証します。キャッシュの検証に失敗した場合は、そのファイルを削除または無視し、PDFの抽出を新たに実行してください。この動作は PR #198 で対処されています。利用可能な場合は、そのPRを含むリリースに更新してください。

参照 Issue #192