Ian Chou's Blog

履歷素材的追蹤與去重:用 JD ID 建立關聯

履歷素材的追蹤與去重:用 JD ID 建立關聯

當你為多個職位投遞履歷時,如何避免重複使用相同素材?如何追蹤哪些素材來自哪次生成?本文分享三個關鍵功能的設計與實作。

問題場景

投遞 10 家公司時,你可能會遇到:

  1. 素材重複使用 - 同一個案例被用在 5 份履歷,面試時容易露餡
  2. 不知道素材來源 - 這個優化好的素材是從哪個 JD 生成的?
  3. 無法追蹤歷史 - 哪些素材已經給過 Google?

我們需要一個關聯系統來追蹤素材的使用歷史。

Schema 設計

resume_chunks 表添加兩個欄位:

class ResumeChunk(BaseModel):
    id: str
    text: str
    skills: list[str]
    # ... 其他欄位
    
    # 🆕 JD 關聯欄位
    used_in_jobs: list[str] = []      # 已用於哪些 JD
    created_from_jd: Optional[str]    # 來源 JD ID

三大功能

1. --created-from-jd:標記素材來源

當你從 AI 生成的履歷中提取優質素材回寫時,記錄它的來源:

uv run career-kb ingest \
  --text "Designed GraphQL schema supporting 10K TPS..." \
  --type project \
  --skills "GraphQL,API Design" \
  --role Lead \
  --impact 4 \
  --created-from-jd "abc123"  # 👈 標記來源

用途

2. --exclude-used-in:排除已用素材

搜尋時排除已經用過的素材,確保每份履歷獨特:

uv run career-kb search \
  --focus "distributed systems" \
  --exclude-used-in "abc123,def456"  # 👈 排除這兩個 JD 用過的

過濾邏輯

# 搜尋結果後過濾
if exclude_jd_ids:
    results = [
        r for r in results 
        if not any(jd_id in exclude_jd_ids 
                   for jd_id in (r.get("used_in_jobs") or []))
    ]

用途

3. --mark-used:自動標記使用

生成履歷時,自動標記哪些素材被使用了:

uv run career-kb generate \
  --jd-id "abc123" \
  --mark-used  # 👈 自動標記
  --output resume.md

更新邏輯

def mark_materials_as_used(material_ids: list[str], jd_id: str):
    for material_id in material_ids:
        record = get_record(material_id)
        used_in = record.get("used_in_jobs", [])
        if jd_id not in used_in:
            used_in.append(jd_id)
            update_record(material_id, {"used_in_jobs": used_in})

用途

完整工作流程

┌─────────────────────────────────────────────────────────────────┐
│                        JD 分析流程                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  save-jd ─────────→ jd_id: "abc123"                            │
│      │                    │                                     │
│      │                    ▼                                     │
│      │              verify ─→ 技能落差分析                      │
│      │                    │                                     │
│      │                    ▼                                     │
│      │   search --exclude-used-in "other-jd-ids"               │
│      │                    │                                     │
│      │                    ▼                                     │
│      │   generate --mark-used ─→ resume.md                     │
│      │                    │                                     │
│      │                    ▼ 標記 used_in_jobs: ["abc123"]       │
│      │                                                          │
│      │              優質素材提取                                │
│      │                    │                                     │
│      │                    ▼                                     │
│      └──────→ ingest --created-from-jd "abc123"                │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

實際效果

場景:投遞 3 家公司

# 第一家:Google
save-jd -c Google -p "AI PM" -f google.txt  # → jd_id: "goog1"
generate --jd-id "goog1" --mark-used

# 第二家:Meta(排除 Google 用過的素材)
save-jd -c Meta -p "PM" -f meta.txt  # → jd_id: "meta1"
search --focus "product management" --exclude-used-in "goog1"
generate --jd-id "meta1" --mark-used

# 第三家:Apple(排除 Google + Meta 用過的)
save-jd -c Apple -p "TPM" -f apple.txt  # → jd_id: "appl1"
search --focus "technical PM" --exclude-used-in "goog1,meta1"
generate --jd-id "appl1" --mark-used

每份履歷都有獨特的素材組合!

LanceDB 更新的挑戰

LanceDB 不支援原地更新(in-place update),需要 delete + add

def update_record(table, material_id, updates):
    # 1. 讀取現有記錄
    records = table.search().where(f"id = '{material_id}'").to_list()
    record = records[0]
    
    # 2. 合併更新
    record.update(updates)
    record.pop("_distance", None)  # 移除搜尋結果的額外欄位
    
    # 3. 刪除舊記錄
    table.delete(f"id = '{material_id}'")
    
    # 4. 新增更新後的記錄
    table.add([record])

這是 LanceDB 基於 Arrow 的限制,未來版本可能會支援更優雅的 update() 方法。

進階應用

統計熱門素材

# 找出被使用最多次的素材
SELECT id, text, array_length(used_in_jobs) as usage_count
ORDER BY usage_count DESC
LIMIT 10

找出閒置素材

# 從未被使用的高影響力素材
SELECT * 
WHERE impact_level >= 4 
  AND array_length(used_in_jobs) = 0

清理過期關聯

# 移除超過 6 個月的 JD 關聯
# (那些公司應該已經不會再聯繫了)

總結

功能 參數 解決的問題
標記來源 --created-from-jd 追蹤素材從哪來
排除已用 --exclude-used-in 避免重複使用
標記使用 --mark-used 記錄使用歷史

這三個功能組合起來,讓你的履歷系統從「一次性工具」升級為「可追蹤的知識庫」。


Career Knowledge Base 是一個本地優先的履歷知識庫系統,使用 Python + LanceDB + Voyage AI 建構。