Miscs
This commit is contained in:
@@ -76,6 +76,8 @@ be missing.
|
||||
|
||||
##wrong_labels##
|
||||
|
||||
##wrong_label_text_context##
|
||||
|
||||
Here's a list of the names of the students, pick the one that matches
|
||||
the best or `\"Unknown\"` if you cannot read the name
|
||||
|
||||
@@ -133,6 +135,8 @@ be missing.
|
||||
|
||||
##wrong_labels##
|
||||
|
||||
##wrong_label_text_context##
|
||||
|
||||
Since this copy isn't the first part of a sequence, simply set the
|
||||
name to `\"Continued\"`."""
|
||||
|
||||
@@ -147,7 +151,66 @@ class AnnotationData(BaseModel):
|
||||
)
|
||||
|
||||
|
||||
def generate_request(file, labels, names, context_labels, wrong_labels):
|
||||
TEXT_CONTEXT_MAX_CHARS = 4000
|
||||
|
||||
|
||||
def _label_filename(path: Path) -> str:
|
||||
return path.stem if path.suffix.casefold() in {".tex", ".txt"} else path.name
|
||||
|
||||
|
||||
def _common_prefix_length(left: str, right: str) -> int:
|
||||
left_folded = left.casefold()
|
||||
right_folded = right.casefold()
|
||||
limit = min(len(left_folded), len(right_folded))
|
||||
for index in range(limit):
|
||||
if left_folded[index] != right_folded[index]:
|
||||
return index
|
||||
return limit
|
||||
|
||||
|
||||
def closest_text_context(
|
||||
workspace: EvaluationWorkspace, wrong_labels: list[str]
|
||||
) -> tuple[Path | None, str]:
|
||||
"""Return a bounded excerpt from the Text file closest to an invalid label."""
|
||||
text_dir = workspace.root / "Text"
|
||||
if not wrong_labels or not text_dir.is_dir():
|
||||
return None, ""
|
||||
|
||||
ranked: list[tuple[int, str, Path]] = []
|
||||
for path in text_dir.iterdir():
|
||||
if not path.is_file() or path.suffix.casefold() == ".pdf":
|
||||
continue
|
||||
filename = _label_filename(path)
|
||||
prefix_length = max(
|
||||
_common_prefix_length(filename, wrong_label)
|
||||
for wrong_label in wrong_labels
|
||||
)
|
||||
if prefix_length:
|
||||
ranked.append((prefix_length, filename.casefold(), path))
|
||||
|
||||
for _prefix_length, _filename, path in sorted(
|
||||
ranked, key=lambda item: (-item[0], item[1])
|
||||
):
|
||||
try:
|
||||
content = path.read_text(encoding="utf-8")
|
||||
except (OSError, UnicodeError):
|
||||
continue
|
||||
if len(content) > TEXT_CONTEXT_MAX_CHARS:
|
||||
content = content[:TEXT_CONTEXT_MAX_CHARS] + "\n[excerpt truncated]"
|
||||
return path, content
|
||||
return None, ""
|
||||
|
||||
|
||||
def generate_request(
|
||||
file,
|
||||
labels,
|
||||
names,
|
||||
context_labels,
|
||||
wrong_labels,
|
||||
wrong_label_text_context="",
|
||||
wrong_label_text_file: Path | None = None,
|
||||
seed: int = 0,
|
||||
):
|
||||
"""Generates request for Gemini with context."""
|
||||
|
||||
image_path = Path(file)
|
||||
@@ -162,9 +225,36 @@ def generate_request(file, labels, names, context_labels, wrong_labels):
|
||||
text = my_prompt2.replace("##labels##", labels)\
|
||||
.replace("##prev_context##", context_str)
|
||||
if wrong_labels:
|
||||
text= text.replace("##wrong_labels##\n\n", f"On a previous request, you answered with the following wrong labels : {wrong_labels}. These are wrong, since they do not exactly match any of the labels in the previous list.")
|
||||
formatted_wrong_labels = "\n".join(f'- "{label}"' for label in wrong_labels)
|
||||
text = text.replace(
|
||||
"##wrong_labels##",
|
||||
"On the previous request for this image, you answered with these "
|
||||
"invalid labels:\n"
|
||||
f"{formatted_wrong_labels}\n"
|
||||
"They are wrong because they do not exactly match any label in the "
|
||||
"valid list above.\n\n"
|
||||
"CRITICAL RETRY CONSTRAINT: NEVER return any of the invalid labels "
|
||||
"listed above again. Your answer must use only exact labels copied "
|
||||
"verbatim from the valid list. If the handwriting resembles an "
|
||||
"invalid label, choose the closest exact valid label instead.",
|
||||
)
|
||||
else:
|
||||
text = text.replace("##wrong_labels##\n\n", "")
|
||||
text = text.replace("##wrong_labels##", "")
|
||||
|
||||
if wrong_label_text_context and wrong_label_text_file:
|
||||
text = text.replace(
|
||||
"##wrong_label_text_context##",
|
||||
"Here is an excerpt from the exam text file whose name has the "
|
||||
"longest prefix in common with the invalid label(s), "
|
||||
f"`{wrong_label_text_file.name}`:\n\n"
|
||||
"<exam_text_excerpt>\n"
|
||||
f"{wrong_label_text_context}\n"
|
||||
"</exam_text_excerpt>\n\n"
|
||||
"Use this excerpt as extra context for identifying the handwritten "
|
||||
"label, but return only an exact label from the valid list above.",
|
||||
)
|
||||
else:
|
||||
text = text.replace("##wrong_label_text_context##", "")
|
||||
|
||||
|
||||
contents = [
|
||||
@@ -181,9 +271,10 @@ def generate_request(file, labels, names, context_labels, wrong_labels):
|
||||
]
|
||||
|
||||
generate_content_config = types.GenerateContentConfig(
|
||||
automatic_function_calling=types.AutomaticFunctionCallingConfig(disable=True),
|
||||
temperature=1.0,
|
||||
top_p=0.95,
|
||||
seed=0,
|
||||
seed=seed,
|
||||
max_output_tokens=65535,
|
||||
response_mime_type= "application/json",
|
||||
response_json_schema= AnnotationData.model_json_schema(),
|
||||
@@ -293,17 +384,30 @@ def process_copy_group(
|
||||
f"{len(accumulated_labels)} accumulated labels..."
|
||||
)
|
||||
attempt = 0
|
||||
label_retry_count = 0
|
||||
wrong_labels: list[str] = []
|
||||
while True:
|
||||
if attempt > 0:
|
||||
sleep(10 * attempt)
|
||||
try:
|
||||
text_context_file, text_context = closest_text_context(
|
||||
workspace, wrong_labels
|
||||
)
|
||||
if text_context_file:
|
||||
print(
|
||||
f"[{group_key}] Retry context for {image_file.name}: "
|
||||
f"{text_context_file.relative_to(workspace.root)}"
|
||||
)
|
||||
request_seed = max(0, label_retry_count - 1)
|
||||
contents, request_config = generate_request(
|
||||
image_file,
|
||||
labels_text,
|
||||
names_text,
|
||||
accumulated_labels,
|
||||
wrong_labels,
|
||||
text_context,
|
||||
text_context_file,
|
||||
seed=request_seed,
|
||||
)
|
||||
response = client.models.generate_content(
|
||||
model=MODEL_ID,
|
||||
@@ -321,9 +425,23 @@ def process_copy_group(
|
||||
f"Error: {image_file.name} contained unknown labels: "
|
||||
f"{unknown}"
|
||||
)
|
||||
wrong_labels.extend(unknown)
|
||||
attempt += 1
|
||||
continue
|
||||
unique_unknown = list(dict.fromkeys(unknown))
|
||||
if (
|
||||
label_retry_count >= 2
|
||||
and set(unique_unknown) == set(wrong_labels)
|
||||
):
|
||||
for item in annotation.list:
|
||||
if item.label in unique_unknown:
|
||||
item.label = f"??{item.label}"
|
||||
print(
|
||||
f"Warning: {image_file.name} repeated the same unknown "
|
||||
"label(s) on the third try; keeping them with a ?? prefix."
|
||||
)
|
||||
else:
|
||||
wrong_labels = unique_unknown
|
||||
label_retry_count += 1
|
||||
attempt += 1
|
||||
continue
|
||||
if annotation.name not in valid_names:
|
||||
print(
|
||||
f"Error: {image_file.name} returned unknown name: "
|
||||
|
||||
Reference in New Issue
Block a user