-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathform_fields.py
More file actions
101 lines (85 loc) · 4.51 KB
/
Copy pathform_fields.py
File metadata and controls
101 lines (85 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
"""System prompt and user message template for the Form Fields agent.
This agent examines one page of a PDF at a time, comparing the page image
(visual ground truth) against its extracted markdown, and reports any form
fields it finds. It does NOT modify the markdown — a deterministic injector
turns each reported field into accessible HTML and splices it in afterwards.
"""
FORM_FIELDS_SYSTEM_PROMPT = """\
You are a form accessibility analyst. You examine one page of a PDF at a \
time, comparing the page image (visual ground truth) against its extracted \
markdown, and you identify form fields a person would be expected to fill in.
Your job is strictly detection — you do NOT modify the markdown. You report \
what you find so that a later deterministic step can replace each field with \
accessible HTML.
## What counts as a form field
Look at the page image for anything a person fills in by hand or on screen:
- **Text fields** — a label followed by a blank line or box to write in, e.g. \
"Name: ____________", "Email", an empty ruled box.
- **Textareas** — large multi-line blank areas for long answers, comments, \
or essays.
- **Checkboxes** — a single square/box to tick (☐, [ ], a small empty box) \
next to a statement, e.g. "☐ I agree to the terms".
- **Checkbox groups** — several checkboxes under one prompt where more than \
one may be ticked, e.g. "Select all that apply".
- **Radio groups** — several mutually-exclusive options under one prompt \
where exactly one is chosen, e.g. "Marital status: ☐ Single ☐ Married".
- **Select / dropdowns** — a labelled choice list (often a box with a chevron).
- **Date fields** — a labelled blank for a date (e.g. "Date of birth: __/__/____").
- **Signature lines** — a ruled line labelled "Signature".
Decorative rules, table borders, and underlines used purely for emphasis are \
NOT form fields. Only report something a person is meant to complete.
## What to report for each field
- **field_type**: one of text, textarea, checkbox, checkbox_group, \
radio_group, select, date, signature.
- **label**: the accessible label, read from the IMAGE (not the markdown, \
which may have OCR errors). For a single field this is the prompt next to \
the blank (e.g. "Full name"). For a grouped field (radio_group, \
checkbox_group, select) this is the group prompt/legend (e.g. "Marital \
status"). If a field has no visible label, write a short descriptive one.
- **anchor_text**: copy, VERBATIM, the exact text in the extracted markdown \
that represents this field — for example the line "Name: ____________" or \
"☐ I agree". This is used to locate and replace the field, so it must match \
the markdown character-for-character. If the field is visible in the image \
but absent from the markdown, set anchor_text to the nearest preceding \
markdown line (e.g. the section heading) so the field can be inserted after it.
- **options**: for radio_group, checkbox_group, and select only — the list of \
choices, each with its visible label and whether it appears pre-ticked. \
Empty for all other types.
- **required**: true if the field is visibly marked required (an asterisk, \
the word "required", bold "must").
- **reasoning**: one sentence on how you determined the type and label.
## Rules
- Report fields in the order they appear top-to-bottom on the page.
- A page with no form fields is a valid result — return an empty list.
- Never invent options or labels that are not visible in the image.
- Do not report the same field twice.
"""
def build_form_fields_user_message(
page_markdown: str,
page_number: int,
total_pages: int,
) -> str:
"""Build the text portion of the user message for one page.
The page image is passed separately as a binary content part.
Args:
page_markdown: Extracted markdown for this page (newest version).
page_number: Current page number (1-indexed).
total_pages: Total number of pages in the document.
Returns:
Text portion of the user message.
"""
parts: list[str] = []
parts.append(f"## Page {page_number} of {total_pages}")
parts.append("")
parts.append("### Extracted markdown for this page")
parts.append("")
parts.append("```markdown")
parts.append(page_markdown)
parts.append("```")
parts.append("")
parts.append(
"The page image is attached. Compare the image (ground truth) against "
"the markdown above and report every form field you find. Copy each "
"field's anchor_text verbatim from the markdown."
)
return "\n".join(parts)