Spaces:
Running
Running
R14-KK-G2-R1 Per-Claim Repair Entitlement + Late-Detected QA Stabilization
#59
by GuXiaopeng - opened
- core/generation_runner.py +1 -1
- core/pipeline_agent.py +39 -22
core/generation_runner.py
CHANGED
|
@@ -43,7 +43,7 @@ CITATION_ROLE_RULES = {
|
|
| 43 |
"methods": (2, 280),
|
| 44 |
"discussion": (2, 220),
|
| 45 |
}
|
| 46 |
-
TRANSLATION_CONTRACT_VERSION = 'hierarchical-multilingual-
|
| 47 |
|
| 48 |
|
| 49 |
def _clean_trailing_references(text, keywords=("reference", "references", "reference list", "参考文献")):
|
|
|
|
| 43 |
"methods": (2, 280),
|
| 44 |
"discussion": (2, 220),
|
| 45 |
}
|
| 46 |
+
TRANSLATION_CONTRACT_VERSION = 'hierarchical-multilingual-v7'
|
| 47 |
|
| 48 |
|
| 49 |
def _clean_trailing_references(text, keywords=("reference", "references", "reference list", "参考文献")):
|
core/pipeline_agent.py
CHANGED
|
@@ -62,7 +62,8 @@ class CitationAuditError(DeepSeekRequestError):
|
|
| 62 |
|
| 63 |
|
| 64 |
class SSciPipelineAgent:
|
| 65 |
-
TRANSLATION_CONTRACT_VERSION = 'hierarchical-multilingual-
|
|
|
|
| 66 |
|
| 67 |
def __init__(self, ds_key, s2_key=""):
|
| 68 |
self.ds_key = str(ds_key or "").strip()
|
|
@@ -6330,9 +6331,11 @@ Decision must be CONFIRMED_BLOCKING or NOT_CONFIRMED. evidence_code must be one
|
|
| 6330 |
source_blocks, translations, quality_issues, self._translation_claim_qa_evidence,
|
| 6331 |
self._translation_claim_repair_meta,
|
| 6332 |
)
|
| 6333 |
-
|
| 6334 |
-
|
| 6335 |
-
|
|
|
|
|
|
|
| 6336 |
failed_pairs = [
|
| 6337 |
(block_id, claim_id, codes)
|
| 6338 |
for block_id, claim_map in sorted(quality_issues.items())
|
|
@@ -6340,7 +6343,7 @@ Decision must be CONFIRMED_BLOCKING or NOT_CONFIRMED. evidence_code must be one
|
|
| 6340 |
]
|
| 6341 |
logging.warning(
|
| 6342 |
'Translation claim-local QA recovery: section=%s round=%s failed=%s',
|
| 6343 |
-
section_name or 'section',
|
| 6344 |
[
|
| 6345 |
{'id': f'SP-P{block_id}-{claim_id}', 'codes': list(codes)}
|
| 6346 |
for block_id, claim_id, codes in failed_pairs
|
|
@@ -6363,6 +6366,36 @@ Decision must be CONFIRMED_BLOCKING or NOT_CONFIRMED. evidence_code must be one
|
|
| 6363 |
evidence_key = (block_id, claim_id)
|
| 6364 |
repair_evidence = dict(self._translation_claim_qa_evidence.get(evidence_key) or {})
|
| 6365 |
code_set = {str(code or '').strip().upper() for code in (codes or [])}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6366 |
|
| 6367 |
semantic_deltas = [
|
| 6368 |
str(code or '').strip().upper() for code in (repair_evidence.get('semantic_delta_codes') or [])
|
|
@@ -6441,27 +6474,10 @@ Decision must be CONFIRMED_BLOCKING or NOT_CONFIRMED. evidence_code must be one
|
|
| 6441 |
)
|
| 6442 |
self._translation_claim_qa_evidence[evidence_key] = dict(repair_evidence)
|
| 6443 |
signature = self._translation_repair_evidence_signature(codes, repair_evidence)
|
| 6444 |
-
meta = self._translation_claim_repair_meta.setdefault(evidence_key, {
|
| 6445 |
-
'repair_attempt_count': 0, 'last_issue_codes': [], 'last_evidence_signature': '',
|
| 6446 |
-
'last_strategy': '', 'nonconvergent_state': '',
|
| 6447 |
-
})
|
| 6448 |
-
prior_codes = set(meta.get('last_issue_codes') or [])
|
| 6449 |
same_defect = (
|
| 6450 |
str(meta.get('last_evidence_signature') or '') == signature
|
| 6451 |
and bool(prior_codes & code_set)
|
| 6452 |
)
|
| 6453 |
-
if (
|
| 6454 |
-
str(meta.get('nonconvergent_state') or '').startswith('exhausted')
|
| 6455 |
-
and bool(prior_codes & code_set)
|
| 6456 |
-
) or (same_defect and str(meta.get('last_strategy') or '').upper() == 'SOURCE_REGENERATE'):
|
| 6457 |
-
meta['nonconvergent_state'] = 'exhausted_after_source_regenerate'
|
| 6458 |
-
carried_exhausted.setdefault(block_id, {})[claim_id] = list(codes)
|
| 6459 |
-
self._record_translation_assurance(
|
| 6460 |
-
'CLAIM_REPAIR_EXHAUSTED', target_lang=target_lang,
|
| 6461 |
-
block_id=f'SP-P{block_id}-{claim_id}', severity='critical', decision='ADJUDICATE',
|
| 6462 |
-
detail={'attempts': int(meta.get('repair_attempt_count') or 0), 'strategy': 'SOURCE_REGENERATE'},
|
| 6463 |
-
)
|
| 6464 |
-
continue
|
| 6465 |
|
| 6466 |
force_source_regenerate = (
|
| 6467 |
'UNRESOLVED_SEMANTIC_DELTA' in set(repair_evidence.get('semantic_delta_codes') or [])
|
|
@@ -6469,6 +6485,7 @@ Decision must be CONFIRMED_BLOCKING or NOT_CONFIRMED. evidence_code must be one
|
|
| 6469 |
)
|
| 6470 |
strategy = 'SOURCE_REGENERATE' if (
|
| 6471 |
force_source_regenerate
|
|
|
|
| 6472 |
or (same_defect and str(meta.get('last_strategy') or '').upper() == 'LOCAL_EDIT')
|
| 6473 |
) else 'LOCAL_EDIT'
|
| 6474 |
if strategy == 'SOURCE_REGENERATE':
|
|
|
|
| 62 |
|
| 63 |
|
| 64 |
class SSciPipelineAgent:
|
| 65 |
+
TRANSLATION_CONTRACT_VERSION = 'hierarchical-multilingual-v7'
|
| 66 |
+
MAX_TRANSLATION_CLAIM_REPAIR_ATTEMPTS = 2
|
| 67 |
|
| 68 |
def __init__(self, ds_key, s2_key=""):
|
| 69 |
self.ds_key = str(ds_key or "").strip()
|
|
|
|
| 6331 |
source_blocks, translations, quality_issues, self._translation_claim_qa_evidence,
|
| 6332 |
self._translation_claim_repair_meta,
|
| 6333 |
)
|
| 6334 |
+
repair_cycle = 0
|
| 6335 |
+
total_claims = sum(len(self._translation_claim_units(source)) for source in source_blocks.values())
|
| 6336 |
+
max_repair_cycles = max(1, total_claims * self.MAX_TRANSLATION_CLAIM_REPAIR_ATTEMPTS)
|
| 6337 |
+
while quality_issues and repair_cycle < max_repair_cycles:
|
| 6338 |
+
repair_cycle += 1
|
| 6339 |
failed_pairs = [
|
| 6340 |
(block_id, claim_id, codes)
|
| 6341 |
for block_id, claim_map in sorted(quality_issues.items())
|
|
|
|
| 6343 |
]
|
| 6344 |
logging.warning(
|
| 6345 |
'Translation claim-local QA recovery: section=%s round=%s failed=%s',
|
| 6346 |
+
section_name or 'section', repair_cycle,
|
| 6347 |
[
|
| 6348 |
{'id': f'SP-P{block_id}-{claim_id}', 'codes': list(codes)}
|
| 6349 |
for block_id, claim_id, codes in failed_pairs
|
|
|
|
| 6366 |
evidence_key = (block_id, claim_id)
|
| 6367 |
repair_evidence = dict(self._translation_claim_qa_evidence.get(evidence_key) or {})
|
| 6368 |
code_set = {str(code or '').strip().upper() for code in (codes or [])}
|
| 6369 |
+
meta = self._translation_claim_repair_meta.setdefault(evidence_key, {
|
| 6370 |
+
'repair_attempt_count': 0, 'last_issue_codes': [], 'last_evidence_signature': '',
|
| 6371 |
+
'last_strategy': '', 'nonconvergent_state': '',
|
| 6372 |
+
})
|
| 6373 |
+
prior_attempts = int(meta.get('repair_attempt_count') or 0)
|
| 6374 |
+
prior_codes = set(meta.get('last_issue_codes') or [])
|
| 6375 |
+
already_source_regenerated = str(meta.get('last_strategy') or '').upper() == 'SOURCE_REGENERATE'
|
| 6376 |
+
already_exhausted = str(meta.get('nonconvergent_state') or '').startswith('exhausted')
|
| 6377 |
+
if (
|
| 6378 |
+
prior_attempts >= self.MAX_TRANSLATION_CLAIM_REPAIR_ATTEMPTS
|
| 6379 |
+
or already_exhausted
|
| 6380 |
+
or (already_source_regenerated and bool(prior_codes & code_set))
|
| 6381 |
+
):
|
| 6382 |
+
meta['nonconvergent_state'] = 'exhausted_after_source_regenerate' if already_source_regenerated else 'exhausted_after_claim_budget'
|
| 6383 |
+
carried_exhausted.setdefault(block_id, {})[claim_id] = list(codes)
|
| 6384 |
+
logging.info(
|
| 6385 |
+
'Translation claim repair entitlement exhausted: section=%s id=SP-P%s-%s attempts=%s strategy=%s',
|
| 6386 |
+
section_name or 'section', block_id, claim_id, prior_attempts, meta.get('last_strategy') or '',
|
| 6387 |
+
)
|
| 6388 |
+
self._record_translation_assurance(
|
| 6389 |
+
'CLAIM_REPAIR_EXHAUSTED', target_lang=target_lang,
|
| 6390 |
+
block_id=f'SP-P{block_id}-{claim_id}', severity='critical', decision='ADJUDICATE',
|
| 6391 |
+
detail={'attempts': prior_attempts, 'strategy': str(meta.get('last_strategy') or '')},
|
| 6392 |
+
)
|
| 6393 |
+
continue
|
| 6394 |
+
if prior_attempts == 0 and repair_cycle > 1:
|
| 6395 |
+
logging.info(
|
| 6396 |
+
'Translation late-detected claim receives own repair entitlement: section=%s id=SP-P%s-%s cycle=%s',
|
| 6397 |
+
section_name or 'section', block_id, claim_id, repair_cycle,
|
| 6398 |
+
)
|
| 6399 |
|
| 6400 |
semantic_deltas = [
|
| 6401 |
str(code or '').strip().upper() for code in (repair_evidence.get('semantic_delta_codes') or [])
|
|
|
|
| 6474 |
)
|
| 6475 |
self._translation_claim_qa_evidence[evidence_key] = dict(repair_evidence)
|
| 6476 |
signature = self._translation_repair_evidence_signature(codes, repair_evidence)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6477 |
same_defect = (
|
| 6478 |
str(meta.get('last_evidence_signature') or '') == signature
|
| 6479 |
and bool(prior_codes & code_set)
|
| 6480 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6481 |
|
| 6482 |
force_source_regenerate = (
|
| 6483 |
'UNRESOLVED_SEMANTIC_DELTA' in set(repair_evidence.get('semantic_delta_codes') or [])
|
|
|
|
| 6485 |
)
|
| 6486 |
strategy = 'SOURCE_REGENERATE' if (
|
| 6487 |
force_source_regenerate
|
| 6488 |
+
or prior_attempts >= 1
|
| 6489 |
or (same_defect and str(meta.get('last_strategy') or '').upper() == 'LOCAL_EDIT')
|
| 6490 |
) else 'LOCAL_EDIT'
|
| 6491 |
if strategy == 'SOURCE_REGENERATE':
|