誰も話さない問題
弱いポイントを与えたときに、ほとんどのAI履歴書リライトツールが実際にするのはこれです
元の文: "毎日のスタンディングアップに参加しました"
AIがリライトした文: "ReactとTypeScriptを使用してレスポンシブWebアプリケーションを開発し、アジャイルな毎日のスタンディングアップで協力して高品質なフロントエンドソリューションを提供しました"
もっと良く見えます。キーワードがあります。構造があります。プロフェッショナルに聞こえます.
それはまた嘘です.
その候補者は決してReactアプリケーションを開発したことはありません。彼らは会議に出席しました。AIは求人票を見て、ReactとTypeScriptを見つけ、静かに候補者が持っていない経験を作り上げました。もし面接を得たら、最初の技術的な質問でそれが露見するでしょう。
これは想定のことではなく、私の履歴書リライトツール—Resume AI Tailor—が修正する前のものです。測定したからわかっています.
Resume AI Tailorとは
Resume AI TailorはNanoCraftsで開発しているSaaS製品です。履歴書をアップロードし、求人情報を貼り付けると、数秒でカスタマイズされたバージョンを取得できます。スタックはNext.js、gpt-4o-mini、Clerk、Neon/Drizzle、Vercelです。
中心の約束はシンプルです:履歴書が向上すれば、マッチングスコアが向上し、面接のチャンスも向上します。問題は、AIが候補者が持っていないスキルを発明し始める瞬間に、その約束が崩れることです.
WordPress開発者に対してReactの経験を捏造する履歴書リライトツールは、その開発者を助けていません。むしろ、彼らを面接の場で失敗させる準備をしています.
私が目指したこと
私は2週間、高度なプロンプトエンジニアリング技術を適用しました。これは、Few-shot prompting、Role prompting、そしてLLM-as-judge evalループを特にResume AI Tailorのリライトと分析ルートに適用することに焦点を当てました。
目標は出力をより良く見せることが 아니었다。それは、各プロンプトの変更を追跡できる数値で、出力を測定可能にすることだった。
評価ループを作成しました:再構築された各項目を5つの基準(行動動詞、キーワードの適合性、結果、正確性、簡潔性)で評価するための2回目のモデル呼び出し。その後、10件の履歴書をパイプラインを通し、ベースラインを確立しました.
第1週のベースライン:38項目中7.37/10。
その後、私は繰り返し試しました。2週間、複数のプロンプトの変更、5つの履歴書プロファイルにおけるエッジケースのテスト。各変更はそのベースラインと比較されました。
最終スコア:8.37/10。改善:+1.0ポイント。
この投稿では、何が変わったか、なぜそれが効果的だったか、そしてどのような学びがプロンプトエンジニアリングのチュートリアルにないかを記録しています。
少数ショットプロンプティング:示すなきゃ言うな
元のリライトプロンプトはこんな感じでした:
const prompt = `You are an expert resume writer. Rewrite the following
bullet point to be stronger, specific, and results-oriented.
Original bullet: "${bullet}"
Rewritten bullet:`;
これはゼロショットプロンプティングです。一つの指示、例はありません。モデルは「より強い」という抽象的な意味を理解していますが、ソフトウェアエンジニアがシニア役職に応募する履歴書のバリューポイントにおいて「より強い」と具体的にどう見えるかは分かりません。
出力は自信に満ちた響きで構造的に一貫性がありませんでした。時には段落。時には箇条書き。時にはモデルがメトリクスを追加しました。時には追加しませんでした。そして時には全く技能を妄想しました。
Few-shot promptingは、出力を説明するのではなく、望む出力を示すことでフォーマットの問題を解決します。
const REWRITE_SYSTEM_PROMPT = `You are a senior ATS engineer and resume
specialist with 10 years of experience configuring applicant tracking
systems at Fortune 500 companies.
Study the examples below carefully. Your output must match this format
exactly — return only the rewritten bullet, no explanation.
EXAMPLE 1:
Original: "Worked on the backend of the company's main product"
Target keywords: Node.js, REST APIs, microservices
Job title: Senior Software Engineer
Candidate skills: Node.js, PostgreSQL, Docker, REST APIs
Rewritten: Engineered Node.js REST APIs for core product, improving
system performance across microservices architecture
EXAMPLE 2:
Original: "Attended daily standups"
Target keywords: React, TypeScript, agile, frontend
Job title: Frontend Developer
Candidate skills: HTML, CSS, JavaScript, WordPress
Rewritten: Participated in agile daily standups supporting [React]
and [TypeScript] frontend delivery
Return ONLY the rewritten bullet. No explanation. Maximum 20 words.`;
そのプロンプトで同時に三つのことが起こっています:
役割は注意を引きます。「上級ATSエンジニア」というのは、モデルがどの部分の訓練を参照するかを教えています——キーワードの準拠、フォーマットの厳守、パース可能性。汎用的な文章の品質ではありません。
例はフォーマットを定めます。 現在、各実行は指定された正確な構造の単一行出力を生成します。段落はなし、番号付きリストはなし、説明的なプレアムブルもなしです。
例2は正直さを示しています。 候補者はHTML、CSS、JavaScript、WordPress——ReactやTypeScriptではありません——を持ちます。例は、不足しているスキルに対してモデルに正確に何をするかを示しています:[React]のようなブラケットプレースホルダーを使用する代わりに、スキルを直接主張するのではなく。
最後の点が最も重要です。指示だけでは幻覚の問題を解決できませんでした。モデルに正しいプレースホルダーの振る舞いの実例を示すことで.
鍵となる洞察は:少数のサンプル例は、衝突する場合に書かれた指示を上書きします。 もしあなたの例が、そのスキルを持っていると考えられる候補者たちが自信を持ってキーワードを統合していることを示しているなら、モデルは例に従う——"正直である"という指示とは反対に——。あなたが望むものを示す。表示するものには注意する.
ロールプロンプティング:モデルにレンズを与える
ロールプロンプティングとは、ユーザーコンテンツが処理される前にシステムプロンプトを通じてモデルに人格を割り当てることです。モデルはその人になりますわけではありません。それがどの部分のトレーニングデータに最も重く依存するかを変えます。
その違いは重要です。「あなたは採用マネージャーです」というのは注意喚起であり、機能のアップグレードではありません。モデルはすでに採用マネージャーが何に気を付けるかを知っています。そのロールは、それを他のすべてよりも重視するように伝えます。(Role prompting is assigning a persona to the model via the system prompt before any user content is processed. The model doesn't become that person. It shifts which part of its training data it draws on most heavily. The difference matters. "You are a hiring manager" is an attention directive, not a capability upgrade. The model already knows what hiring managers care about. The role tells it to weight that knowledge above everything else.)
私たちはDay 2に同じ履歴書に対して三人のペルソナをテストしました
ATSエンジニア
`You are a senior ATS engineer with 10 years of experience configuring
applicant tracking systems at Fortune 500 companies like Greenhouse,
Workday, and Lever.
When analysing a resume, evaluate it exactly as an ATS would before
a human ever sees it. Your priorities are:
1. Keyword match — does the resume contain exact terms a recruiter
would search for?
2. Formatting compliance — tables, columns, and text boxes cause
parsing failures. Flag them.
3. Date formatting — inconsistent dates confuse parsers.`
出力:臨床的、狭義的、信頼性のある。マシンレベルの問題に気づきました——不統一の日付形式、キーワードの欠落、標準でないセクション名。人間が気にかけるすべてのことを無視しました
FAANGの採用マネージャ
`You are a senior engineering hiring manager at a FAANG company.
You have conducted over 500 hiring committee reviews across multiple
product and infrastructure teams.
When analysing a resume, evaluate it as you would in a 30-second
hiring committee pre-screen. Your priorities are:
1. Impact framing — does each bullet describe an outcome, not a task?
2. Scope signals — team size, user base, revenue influenced.
3. Levelling language — "Helped" signals junior. "Led" signals senior.`
「30秒のプレスクリーン」の枠組みが最も効果的な追加でした。それはモデルの評価姿勢を徹底的からフィルタリングへと変えました——完全性よりも信号密度を優先しました。
出力は直接的で具体的で高信号。レベルの言語のギャップ、範囲の文脈の欠如、採用委員会に評価できるものを与えない曖昧な項目をフラグ付けしました。三者中最も実行可能です.
キャリアコーチ
`You are a senior career coach with 12 years of experience helping
engineers at all levels land roles they care about.
When analysing a resume, evaluate it as you would in a first coaching
session: with honesty, warmth, and a focus on what the candidate can
improve before their next application.`
出力:温かく、物語に焦点を当てており、時折あまり励ましすぎる。技術的な役割の人々が無視するような、低く見積もった言葉や一般的な表現に気づいた。オープナーとして「履歴書を共有していただきありがとうございます!」を使用したが、明示的に追加しなければならなかったガイドラインである:「挨拶で始めるな」
私が配信したもの
FAANGの採用マネージャーが主要な分析プロンプトになりました。明らかな差をつけて最も実行可能なフィードバックを生み出しました.
ATSエンジニアは軽量な並列パスとして実行されます——安価な出力、焦点を当てた範囲、採用マネージャーが無視する機械レベルを捉えます.
キャリアコーチは将来のProレベル機能のために保留されています。直感は正しいですが、本番投入前に緊密化が必要です.
/api/analyse
├── hiring manager prompt (always — primary analysis)
└── ATS engineer prompt (always — parallel pass)
└── career coach prompt (Pro tier — future)
重要な教訓:役割の説明にある語彙は、職種名と同じくらい重要です「あなたは採用マネージャーです」は「30秒の事前スクリーンで候補者を評価し、レベルの言語に気を配る採用マネージャーです」という表現よりも弱いです。後者のバージョンはモデルに特定の視点を与えますが、単なるラベルではありません
評価ループ:作成したものを測定
一週間の迅速なイテレーションを経て、出力がより良く見えた。実際に良くなったかどうかを知る方法はなかった。
5つの履歴書に対する手動評価は45分かかり、信頼できるスコアを生成できなかった——十分な書き換えを読んだ後、判断が曖昧になる。一貫性があり、速く、繰り返し可能なものが必要だった。
LLMを審判者としてのパターンは、元のものと書き直された項目の両方を受け取り、構造化された評価基準に基づいて評価し、品質スコアと推論を返す2回目のモデル呼び出しです.
export async function evalBullet(
original: string,
rewritten: string,
targetKeywords: string[],
candidateSkills: string[]
): Promise<EvalResult> {
const response = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [
{ role: 'system', content: JUDGE_SYSTEM_PROMPT },
{ role: 'user', content: `
Original bullet: "${original}"
Rewritten bullet: "${rewritten}"
Target keywords: ${targetKeywords.join(', ')}
Candidate skills: ${candidateSkills.join(', ')}
`}
],
temperature: 0 // always 0 for judges
});
// parse and return structured score
}
温度は0でなければなりません。あなたのリライトは0.3を使用していますが、語彙の変化は望ましいです。あなたのジャッジは同じ項目を同じ方法で常に評価する必要があります—温度が0を上回ると、評価のずれが生じ、基準比較が無意味になります.
評価基準
評価基準は最も重要です。曖昧な評価基準は、どのモデルを使用するかに関わらず曖昧な評価を生み出します.
Score this rewritten bullet on 5 criteria, 2 points each (total 10):
1. Action verb (0-2)
2 = strong past-tense ownership verb: Led, Built, Architected
1 = weak or passive: Helped, Worked on, Assisted
0 = no clear action verb
2. Keyword fit (0-2)
2 = target keywords integrated naturally — reads well without them
1 = keywords present but sentence feels constructed around them
0 = no target keywords present
3. Outcome present (0-2)
2 = clear measurable outcome, or placeholder [X%] used correctly
1 = outcome implied but not quantified
0 = task description only, no outcome signal
4. Truthfulness (0-2)
2 = all claims supported by original or candidate skills,
OR missing keywords correctly wrapped in [brackets]
1 = minor extrapolation, defensible
0 = claims skill not in original or skills list, not bracketed
5. Brevity (0-2)
2 = one sentence, 20 words or under, no filler phrases
1 = slightly long or contains padding
0 = multiple sentences or significantly over 20 words
加法構造 — 5つの基準、各2点ずつ — は審査員に各次元を独立して評価させる。総合評価(「1~10で評価してください」)はすべてを直感に依存し、揺らぎを生む。明確なレベル記述を含む機械的基準は、集計・傾向分析可能な一貫したスコアを生み出す.
評価基準の設計は審査員モデルよりも重要
gpt-4o-miniからgpt-4oへのアップグレードが、あなたのジャッジで得られる改善よりも、ルールを一つの基準で締めくくる方が効果的です。LLMをジャッジとして使用するシステムにおけるボトルネックはほとんどモデルの能力ではなく、指示の明確さです.
比較:
// Vague — produces drift
"Rate keyword integration 0-2"
// Precise — produces consistent scores
"Keyword fit (0-2):
2 = target keywords integrated naturally — the sentence reads
well without them
1 = keywords present but the sentence feels constructed around them
0 = no target keywords present"
正確なバージョンは裁判官に機械的に適用できるテストを与えます。「キーワードなしでこの文が読みやすいか?」ははい/いいえの質問です。「キーワードの統合は良いか?」は判断の問題です。判断は曖昧になります。機械的なテストはしません.
スコアは絶対的なのではなく相対的なものです
スコアが7/10であるからといって、それが客観的に7/10の履歴書のポイントであるわけではありません。それは、あなたの評価基準に対して、あなたのジャッジによる、あなたのプロンプトのこのバージョンで7/10をスコア付けされたということです。
それが持っているのは比較的な価値です。リライトプロンプトを変更し、同じ10つのポイントが6.8/10ではなく8.2/10で平均した場合——他のすべてのものが一定のままで——プロンプトが改善しました。それがシステム的なプロンプトエンジニアリングの見た目です:直感ではなく、証拠です。
そのため、私は実行ごとに結果をJSONファイルに記録する:
export function logResults(results: EvalResult[], outputPath: string): void {
const dir = path.dirname(outputPath);
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
const existing = fs.existsSync(outputPath)
? JSON.parse(fs.readFileSync(outputPath, 'utf-8'))
: [];
fs.writeFileSync(outputPath, JSON.stringify(
[...existing, ...results], null, 2
));
}
各実行はファイルに追記される。ファイルはあなたの基準となるものだ。それなしでは、目盲に反復する。
実際に動いた修正策:構造的な制約を指示に優先
Few-shot examplesと役割プロンプティングを追加した後も、リライトエンジンは未適格な候補に対して幻覚を起こし続けていました。
サラ・ジョンソンにはHTML、CSS、JavaScript、WordPressのスキルがあります。彼女はReactとTypeScriptの役割に応募しました。リライトエンジンはこのようなものを生成していました:
Original: "Attended daily standups"
Rewritten: "Developed responsive web applications using React and TypeScript,
collaborating in agile daily standups to deliver frontend solutions"
ReactとTypeScript。作られたもの。毎回。
システムプロンプトで正直性の指示を受け取りました:
Truthfulness — never invent numbers or metrics not present in the original.
If a target keyword represents a skill the candidate has not explicitly used,
do NOT claim they used it.
それはうまくいきませんでした。プロンプトの3回の反復で同じ結果でした。指示は少数のショット例によって上書きされていました——すべての例は、そのスキルを持っている可能性のある候補者が自信を持ってキーワードを統合しています。モデルは例に従い、書かれたルールには従いませんでした。
修正はより良い指示ではなかった。構造的な変更だった
以前 — 指示のみ
export async function rewriteBullet(
bullet: string,
targetKeywords: string[],
jobTitle: string
): Promise<string>
モデルにはキーワードを確認するための参照リストがなかった。仕事にはReactが必要であることを知っていた。候補者がそれを持っていないことを知らなかった。それで彼はReactを統合した — 自信を持って、流暢に、誤って。
候補スキルとしてパラメータとして指定
export async function rewriteBullet(
bullet: string,
targetKeywords: string[],
jobTitle: string,
candidateSkills: string[] // added
): Promise<string> {
const userMessage = `Original: "${bullet}"
Target keywords: ${targetKeywords.join(', ')}
Job title: ${jobTitle}
Candidate skills: ${candidateSkills.join(', ')} // in every call
Rewritten:`;
今やモデルは各呼び出しで方程式の両側を持っています。一方にはターゲットキーワードがあり、もう一方には候補者の実際のスキルがあります。キーワードにReactが見つかるがスキルリストにない場合、それはスキルを主張するのではなくプレースホルダーを使用します:
Original: "Attended daily standups"
Rewritten: "Participated in agile daily standups supporting [React]
and [TypeScript] frontend delivery"
[React] と [TypeScript] は正直です。彼らは候補者に伝えます:これらは仕事が求めるスキルであり、あなたが現在持っていないものです。履歴書は捏造ではなく、ギャップ分析になります。
なぜ指示がうまくいかなかったのにこの方法が成功したのか
合格candidateSkills はパラメータとして構造的な制約です。データは各呼び出しでコンテキストウィンドウに存在します。モデルはそれを明示的に扱わなければなりません。
「正直であること」を指示するプロンプトは、モデルがそのコンテキスト内で他のすべての要素と比較して重みを付けるときの提案です——自信を持って統合を示す少数のサンプル例を含みます。例と指示が矛盾する場合、例が優先されます。
しかしコンテキストウィンドウ内のスキルリストは例と競合しません。それはデータです。モデルは指示を優先度を低くする方法でデータを無視することはできません.
教訓:構造的な制約は、真実の強制において指導的な制約を打ち負かします.モデルが行動する前に何かを確認したい場合は、確認するものを与えるのではなく、ただ確認するように指示するだけではありません。
2週間のプロンプト反復から得られた最も移行可能な洞察です。履歴書の書き換えを超えて、トレーニングデータが押し寄せる境界をモデルが尊重する必要があるどんな状況にも適用されます。
結果:前と後
幻覚問題、解決
同じ候補者—Sarah Johnson、HTML/CSS/JavaScript/WordPress開発者、ReactとTypeScriptの役割に応募—を、プロンプトの三つのバージョンを通して実行しました.
ゼロショット(第1週—例なし、候補者スキルなし):
Original: "Worked on client websites"
Rewritten: "Developed responsive client websites using React and TypeScript,
implementing modern CSS frameworks in an agile environment"
Original: "Helped with bug fixes"
Rewritten: "Resolved bugs in React and TypeScript, enhancing frontend
performance and responsiveness within agile development cycles"
Original: "Attended daily standups"
Rewritten: "Developed responsive web applications using React and TypeScript,
collaborating in agile daily standups to deliver frontend solutions"
ReactとTypeScriptが各項目に現れる。サラはどちらも持っていない。リライターは職務記述に最適化して候補者を完全に無視した。
第2週(役割プロンプティング+フィッシュショット+候補者スキル):
Original: "Worked on client websites"
Rewritten: "Developed client websites using HTML, CSS, and JavaScript,
ensuring responsive design and supporting [React] and
[TypeScript] frameworks"
Original: "Helped with bug fixes"
Rewritten: "Assisted in bug fixes for frontend components using HTML,
CSS, and JavaScript while supporting agile development
and [React] integration, improving [metric] by [X%]"
Original: "Attended daily standups"
Rewritten: "Participated in agile daily standups supporting [React]
and [TypeScript] frontend delivery"
構造的な違いがある。HTML、CSS、JavaScript — サラが実際に持っているスキル — は直接統合されています。[React] と [TypeScript] は括弧付きプレースホルダーとして表示され、主張ではありません。履歴書は今や正直な物語を伝えています:私が持っているものはここ、役割が求めているものはまだ持っていないものはここです。
それは候補者にとって捏造よりも有用です。また、実際に部屋で議論できるものでもあります。
強いポイントは正しく保存されています。
パイプラインはすべてを再書き出しません。scoreBulletは再書き出しの前に各項目を評価し、実際に作業が必要なものをマークします。
ここにPriya Patelの履歴書——スタッフエンジニアとしてプリンシパルエンジニアの役職に応募——が同じパイプラインを通過したものがあります:
Original: "Architected event-driven microservices platform handling
50M daily events, reducing infrastructure cost by 40%"
Rewritten: [unchanged — scoreBullet returned needs_rewrite: false]
Original: "Led team of 8 engineers across 3 time zones to deliver
platform re-architecture 2 weeks ahead of schedule"
Rewritten: [unchanged]
Original: "Defined engineering standards adopted across 4 product
teams, reducing incident rate by 35%"
Rewritten: [unchanged]
プライヤの3つの発言が保存されました。実績、所有形態詞、範囲文脈を備えた強力な発言は再書き換えを必要とせず——パイプラインはそれを正しく識別します。再書き換え器は良い入力を強化します。存在しない信号を作り出すことはできません.
スコアの下限
評価ループで6/10未満にスコアされた発言は、行動形態詞がなく、スキルがなく、結果がない元の発言に遡ることができました:
5/10 — original: "Helped with bug fixes"
no tool, no scale, no outcome — nothing to amplify
5/10 — original: "Attended daily standups"
describes presence, not contribution
プロンプトエンジニアリングの修正では解決されません。強いバルレットを書くのに必要な情報は元のものに存在しません。これは製品の問題ではなく、プロンプトの問題ではありません。正しい修正は、ユーザーにコーチングメッセージを表示することです:「このバルレットでは、私たちが取り組むのに十分な情報がありません。あなたが作成したもの、使用したツール、またはあなたの仕事によって変わったことを追加してみてください。」
コンテンツのない箇条書きに対するリライトの上限は、プロンプトの質に関わらず約6/10です。その上限の存在を知り、ユーザーに対して正直であることは、AIが何でも修正できるかと装うよりもずっと価値があります.
数値
スコアの進行
| 実行 | スコア | 主要な変更 |
|---|---|---|
| 第1週の基準 | 7.37/10 | 組み合わせられた役割+few-shotプロンプト |
| 第2週目第6日 | 8.26/10 | 結果プレースホルダー指示 |
| 第2週目第7日 | 8.18/10 | エッジケース修正 — ノイズ内 |
| 第2週目第8日最終 | 8.37/10 | 安定確認スコア |
2週間で+1.0ポイントの改善
8.37で2回の走行が同じ最低スコアの弾丸で、これは運が良かった走行ではなく安定した測定であることを確認しました。温度0での走行間の±0.15のばらつきは期待されるノイズフロアであり——その範囲内の変化は意味がありません
次元の分解
| 基準 | 第1週 | 第2週 | 変更 |
|---|---|---|---|
| 動詞 | 1.82/2 | 1.89/2 | +0.07 |
| キーワードの適合度 | 1.45/2 | 1.37/2 | -0.08 |
| 結果 | 1.08/2 | 1.97/2 | +0.89 |
| 正確性 | 1.68/2 | 1.66/2 | -0.02 |
| 簡潔 | 1.26/2 | 1.47/2 | +0.21 |
結果のストーリー
結果は目立つ改善で、単一の指示変更で2点スケールから+0.89です。
第1週:リライトは動詞とキーワードには長けていたが、ほとんど結果信号を追加しなかった。元の箇条書きに結果がない場合、モデルもリライトの結果を残さなかった。結果がないタスクを説明する箇条書きは、採用委員会に評価の対象を与えない。
対処法はシステムプロンプトに追加の優先度が1つあった:
7. Outcome placeholder — if no outcome exists in the original bullet,
add a placeholder rather than leaving the bullet outcome-free:
"improving [metric] by [X%]", "resulting in [outcome]",
"reducing [problem] by [X%]", or "enabling [result]".
Never leave a rewritten bullet without any outcome signal.
その指示により結果は1.08/2から1.97/2に移動しました。2点スケールで全点分の変化です。2週間で最高のROIプロンプト変更でした。
キーワードのフィットレジレーション
キーワードのフィットはわずかに1.45/2から1.37/2に低下しました。これは意図的なものです。
リライトは「配信記録」「強力なポートフォリオ」「5年以上の経験」といった汎用的なATSフレーズを、関連性に関わらず弱い箇所のリストに挿入していた。ルートハンドラにフィルタが追加された:
const GENERIC_KEYWORD_FILTER = [
'delivery record',
'strong delivery record',
'5+ years experience',
'strong portfolio',
'fast learner',
'team player',
];
const targetKeywords = [
...new Set([...(missingSkills || []), ...(atsKeywords || [])])
].filter(k => !GENERIC_KEYWORD_FILTER.some(
g => k.toLowerCase().includes(g.toLowerCase())
));
汎用的フレーズのフィルタリングによりキーワードのカバレッジはわずかに低下した。長い履歴書におけるキーワードの過剰配置は完全に削除された。このトレードオフは正しい——すべての項目が「配信記録の向上とビジネス要件の達成」で終わる履歴書は、経験豊富な採用担当者に機械生成であると示唆する。
8.37/10の実際の意味
評価ではない。基準である。
将来のプロンプトの変更はすべて8.37と比較されます。同じ10の履歴書と同じ評価基準、同じ審査員で変更が8.6を生み出す場合、プロンプトは改善されました。8.1を生み出す場合、それは後退しました。この数値は比較の中でのみ意味があります——孤立しています。
これは設計通りに機能している評価ループです。これがないと、すべてのプロンプトの変更は推測です。これがあると、すべてのプロンプトの変更は実験です。
評価統計
Bullets evaluated: 38
Average score: 8.37 / 10
Improved over orig: 30 / 38 (79%)
Unchanged (strong): 8 / 38
Average breakdown:
Action verb: 1.89 / 2
Keyword fit: 1.37 / 2
Outcome: 1.97 / 2
Truthfulness: 1.66 / 2
Brevity: 1.47 / 2
文書に記載されていないことを見つけた
1. 少しのサンプル例は衝突する場合、書かれた指示を上書きします
「候補者が持っていないスキルを主張しない」という一文をシステムプロンプトに書いた。数少ないサンプル例は、そのスキルを持っている可能性のある候補者が自信を持ってキーワードを統合していた。モデルはその例に従った。
これはバグではない——これはコンテキスト学習が機能する方法だ。モデルは示された行動にパターンマッチングするよりも、書かれたルールをフォローすることよりもより確実に機能する。つまり、あなたが選択する例は、あなたが書く指示よりも重要だということだ。
実際の意味合い:あなたの指示と同じように、あなたの少数のサンプル例を慎重に検査してください。もしあなたのサンプル例が、エッジケースであなたが望まない振る舞いを示すならば、指示が何であれ、モデルはそれをエッジケースで複製します。
行動を示すな、話すな。しかし、あなたが何を示すか注意してください。
2. 安全と品質は同じ測定基準ではありません
私はvalidateRewrite 任意書き換えられた弾を提供する前にゲートとして機能する関数:
// Returns: "use_rewrite" | "use_original" | "rewrite_again"
export async function validateRewrite(
original: string,
rewritten: string,
targetKeywords: string[],
candidateSkills: string[]
)
それは質問に答えた:これを提供するのは安全か?作られたスキルやキーワードはなく、元のものと異なる—それを使う。
評価ループは別の質問に答えた:これはどれくらい良いか?
弾丸は最初の質問を通過して二つ目に失敗することがある:
validateRewrite: recommendation = use_rewrite
truthfulness_risk = low ← passed the gate
eval loop: total_score = 5/10
action_verb = 1 ← weak verb
outcome = 0 ← no outcome signal
brevity = 1 ← slightly long
弾丸は安全だった。それは良くなかった。両方の評価は正しかった——彼らは異なることを測っていた。
AI機能を構築している開発者の多くは安全性レベルで終わる。彼らは幻覚を防ぐために検証を追加して完了とする。『安全に提供できる』と『十分に役立つにふさわしい』の間のギャップで、ユーザーの信頼が静かに蝕む。評価ループはそのギャップを明らかにする.
本番環境の修正は配線evalBullet は最低限の閾値を持つ二番目のゲートとして機能します — 安全性を満たすが品質を満たさない弾は、中途半端な書き直しではなくコーチングメッセージを得ます。これは3週目のタスクです。
3. プロンプトエンジニアリングが達成できることはある最低限の限界があります
評価ループで6/10未満のスコアを得たすべての弾は同じプロファイルを持っていました:元のものに動作動詞がなく、スキルがなく、結果もありません
"Attended daily standups" → no tool, no contribution, no result
"Helped with bug fixes" → passive, no scope, no outcome
"Worked on improving things" → no specificity whatsoever
これらのポイントに対するリライトの上限は、プロンプトがどれほど良くても約6/10です。強いポイントを書くのに必要な情報は、元のテキストに存在しません
これはプロンプトの問題ではありません。入力の問題です
指示や、少ないサンプル例、あるいは役割のプロンプティングで、存在しないシグナルを作り出すことはありません。コンテンツのないバルレットに対する正しい対応は、より良い書き直しではありません—候補者にさらに情報を尋ねることです.
"This bullet doesn't give us enough to work with.
Try adding: what you built, what tool you used,
or what changed because of your work.
Example: 'Attended daily standups' →
'Attended daily standups for a 6-person React team
shipping features weekly'"
そのコーチングメッセージは、候補者にとってより有用であり、モデルが元のものから生成できるどんな書き直しよりもそう。それはまた、自信に満ちたAIの出力がほとんどしないような、率直な方法で正直である。
二週間でプロンプトエンジニアリングが教えてくれた最も重要なことは、その限界がある場所だ。制限を知ること——そしてユーザーに対してそれを明確にすること——は、AIがあなたが与えるものを何でも修正できるかのように装うことよりも価値がある。
第3週で何が変わるか
評価ループでは、単独での変更だけでは修正できない4つの特定のギャップが浮かび上がった。これらは第3週の開始タスクである:
コードレベルのキーワード分布の追跡。 システムプロンプトにおけるキーワード分布指令は、状態のないAPI呼び出しに対して効果がない——各項目は別々の呼び出しであり、前の項目でどのキーワードが表示されたかを覚えていない。修正策は、ルートハンドラにおける後処理パスであり、完全に書き換えられたセット全体でキーワードの頻度を追跡し、過剰に繰り返されたフレーズを削除する。部分的なバージョンはすでに本番環境に導入されている。適切な実装には、項目間の状態が必要である。
技術スキルが求められる職種と一致しない候補者におけるソフトスキルの一致 候補者が職種の技術スキルと一致しない場合、モデルはトップレベルの「一致なし」評価を行い、ソフトスキルの重複を評価するスキル配列の評価を停止します。データアナリストの役割に応募する教師は、コミュニケーションとリーダーシップをスキル配列に持っていますが、これらは職種で求められていますが、分析器はmatched_skills: [] はコードレベルのポストプロセスで、TypeScript でスキル配列を直接 JD キーワードと比較し、このフィールドのモデルをバイパスします。
プロダクション評価ゲート。 現在の評価ループは測定ツールとしてオフラインで実行されています。週3目に evalBullet はプロダクションルートに async 質量ゲートとして接続され、矢印が通過します。validateRewrite しかし評価基準で6/10以下のスコアを得た場合は、中途半端な書き直しではなくコーチングメッセージを取得します。ゲートはバックグラウンドで実行されるため、クリティカルパスに遅延を追加しません.
制御された比較:組み合わせ vs 少しのみ。 第1週と第2週では、組み合わせられたプロンプト(役割 + フェイストショット)のみがテストされました。役割プロンプティングの孤立した寄与は決して測定されませんでした。第3週では、同じ10件の履歴書をフェイストショットのみのバリアント(役割宣言なし)を通じて実行し、それもスコア付けしました。これら二つのスコアの差が、実際に測定された役割プロンプティングの寄与です。それが、ブログ記事を事実に基づいたものから伝聞に基づいたものにするような証拠です。
ターゲット:同じ10件の履歴書に対して平均8.8/10です.
公開部分
この投稿は、10週間のカリキュラムの2週目を記録しており、プロンプトエンジニアリング技術を実際にユーザーが支払うリアルなSaaS製品—Resume AI Tailor—に適用しています.
評価のベースラインは7.37/10で始まり、8.37/10で終わりました。3週目の目標は8.8/10です.
来週3の結果——制御された比較、生産評価ゲート、そして新たに現れるどんな新しいエッジケースも——を次の投稿で公開します。スコアが8.8に達しなければ、それも言います.
評価ループのコード、プロンプトのバリエーション、そして完全なパイプラインはGitHubにあります:github.com/Azeez1314/resume-ai
製品はこちらで公開されています:resumetailor.cv
あなたに一つ質問があります
AIで動作する機能を構築し、「私には良く見える」というよりは出力の品質を測定している場合、本当に使っているものを知りたいです.
LLMを審判とするパターンは研究でよく文書化されていますが、プロダクションSaaSではあまり使われていません。技術が存在することを知っていると実際に決定に基づく評価された基準を持っている間のギャップは大きいです。そのギャップを埋めたら、どうやったか聞きたいです。
コメントを残すか、X(Twitter)とLinkedInでNanoCraftsとして私を探してください。
Resume AI TailorはNanoCraftsポートフォリオの一部で、公開して構築・提供された焦点を当てたSaaSツールのコレクションです。
resumetailor.cv · nanocrafts.xyz · azeezroheem.hashnode.dev











