diff --git a/packages/ai/src/prompts.ts b/packages/ai/src/prompts.ts index ac45857bd..52b84558d 100644 --- a/packages/ai/src/prompts.ts +++ b/packages/ai/src/prompts.ts @@ -4,11 +4,46 @@ const readPrompt = (filename: string) => { return readFileSync(new URL(`./prompts/${filename}`, import.meta.url), "utf-8"); }; +// ponytail: single template with per-source substitutions; produced text is identical per source type +const parserTemplate = readPrompt("parser-system.md"); + +type ParserVars = { + FORMAT_HEADER: string; + FORMAT_NOUN: string; + ALLOWED_INPUT: string; + URL_CLAUSE: string; + EXTRA_RULES: string; + FALLBACK_CLAUSE: string; +}; + +function makeParserPrompt(vars: ParserVars): string { + return Object.entries(vars).reduce((acc, [k, v]) => acc.replaceAll(`{{${k}}}`, v), parserTemplate); +} + +const pdfParserSystemPrompt = makeParserPrompt({ + FORMAT_HEADER: "PDF files", + FORMAT_NOUN: "PDF", + ALLOWED_INPUT: + "- Use only the visible content from the attached PDF document.\n- Ignore OCR noise, watermarks, repeated headers/footers, and broken line wraps.", + URL_CLAUSE: "full URLs that are explicitly present", + EXTRA_RULES: "", + FALLBACK_CLAUSE: "PDF is low quality or partially unreadable", +}); + +const docxParserSystemPrompt = makeParserPrompt({ + FORMAT_HEADER: "Microsoft Word files (DOC/DOCX)", + FORMAT_NOUN: "document", + ALLOWED_INPUT: + "- Use only visible, intended content from the attached document.\n- Ignore hidden text, comments, track changes, revision history, document metadata, and layout artifacts.", + URL_CLAUSE: "URLs explicitly visible in document content", + EXTRA_RULES: + "- Lists and tables: extract visible text faithfully; preserve relationships in section fields.\n- Headers/footers: include only if they contain real resume data.\n", + FALLBACK_CLAUSE: "document is malformed or partially unreadable", +}); + const analyzeResumeSystemPrompt = readPrompt("analyze-resume-system.md"); const chatSystemPromptTemplate = readPrompt("chat-system.md"); -const docxParserSystemPrompt = readPrompt("docx-parser-system.md"); const docxParserUserPrompt = readPrompt("docx-parser-user.md"); -const pdfParserSystemPrompt = readPrompt("pdf-parser-system.md"); const pdfParserUserPrompt = readPrompt("pdf-parser-user.md"); export { diff --git a/packages/ai/src/prompts/docx-parser-system.md b/packages/ai/src/prompts/docx-parser-system.md deleted file mode 100644 index 5f2a91fc2..000000000 --- a/packages/ai/src/prompts/docx-parser-system.md +++ /dev/null @@ -1,54 +0,0 @@ -You are a strict resume extraction engine for Microsoft Word files (DOC/DOCX). Convert the attached document into a Reactive Resume JSON object. - -## Objective - -- Extract resume content accurately and map it into the provided JSON template. -- Prioritize source fidelity and schema correctness over completeness. - -## Allowed Input - -- Use only visible, intended content from the attached document. -- Ignore hidden text, comments, track changes, revision history, document metadata, and layout artifacts. - -## Hard Constraints - -1. Extract only explicitly stated information. -2. Never fabricate, infer, or normalize missing data. -3. Keep original wording and original language. -4. When uncertain, omit content and leave template defaults. -5. Do not use external knowledge. - -## Conflict Resolution Order - -1. Schema validity (must return valid JSON matching template shape) -2. Source fidelity (exactly what the document states) -3. Omit uncertain values (never guess) - -## Extraction Rules - -- Dates: preserve exactly as written. -- URLs: include only URLs explicitly visible in document content. -- Contact data: copy as-is; do not reformat. -- Skills: include only explicit skill mentions. -- Descriptions: output HTML using `

`, `