feat(regulatory): 按实际处理数量更新节点进度
This commit is contained in:
@@ -1,13 +1,25 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
|
||||
from review_agent.models import FileSummaryBatch
|
||||
from review_agent.regulatory_review.schemas import Finding
|
||||
|
||||
|
||||
def run_completeness_check(batch: FileSummaryBatch, rule_set: dict) -> list[Finding]:
|
||||
def run_completeness_check(
|
||||
batch: FileSummaryBatch,
|
||||
rule_set: dict,
|
||||
progress_callback: Callable[[dict[str, object]], None] | None = None,
|
||||
) -> list[Finding]:
|
||||
items = list(batch.items.order_by("file_index"))
|
||||
findings: list[Finding] = []
|
||||
for requirement in rule_set.get("requirements", []):
|
||||
requirements = [
|
||||
requirement
|
||||
for requirement in rule_set.get("requirements", [])
|
||||
if requirement.get("type") in {"required", "conditional", "recommended", "chapter", "directory"}
|
||||
]
|
||||
total = len(requirements)
|
||||
for index, requirement in enumerate(requirements, start=1):
|
||||
if requirement.get("type") not in {"required", "conditional", "recommended", "chapter", "directory"}:
|
||||
continue
|
||||
matched = [
|
||||
@@ -20,24 +32,32 @@ def run_completeness_check(batch: FileSummaryBatch, rule_set: dict) -> list[Find
|
||||
[*requirement.get("file_keywords", []), *requirement.get("aliases", [])],
|
||||
)
|
||||
]
|
||||
if matched:
|
||||
continue
|
||||
findings.append(
|
||||
Finding(
|
||||
rule_code=requirement["code"],
|
||||
category=requirement.get("category", "completeness"),
|
||||
severity=requirement.get("severity", "medium"),
|
||||
title=f"缺少{_numbered_title(requirement)}",
|
||||
detail=f"当前文件汇总批次未发现{_numbered_title(requirement)}。",
|
||||
suggestion=requirement.get("suggestion", ""),
|
||||
evidence={
|
||||
"requirement_type": requirement.get("type"),
|
||||
"matched_files": [],
|
||||
"searched_keywords": requirement.get("file_keywords", []),
|
||||
"searched_fields": ["file_name", "relative_path", "directory_level"],
|
||||
},
|
||||
if not matched:
|
||||
findings.append(
|
||||
Finding(
|
||||
rule_code=requirement["code"],
|
||||
category=requirement.get("category", "completeness"),
|
||||
severity=requirement.get("severity", "medium"),
|
||||
title=f"缺少{_numbered_title(requirement)}",
|
||||
detail=f"当前文件汇总批次未发现{_numbered_title(requirement)}。",
|
||||
suggestion=requirement.get("suggestion", ""),
|
||||
evidence={
|
||||
"requirement_type": requirement.get("type"),
|
||||
"matched_files": [],
|
||||
"searched_keywords": requirement.get("file_keywords", []),
|
||||
"searched_fields": ["file_name", "relative_path", "directory_level"],
|
||||
},
|
||||
)
|
||||
)
|
||||
if progress_callback:
|
||||
progress_callback(
|
||||
{
|
||||
"processed": index,
|
||||
"total": total,
|
||||
"label": _numbered_title(requirement),
|
||||
"finding_count": len(findings),
|
||||
}
|
||||
)
|
||||
)
|
||||
return findings
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import re
|
||||
from collections import defaultdict
|
||||
from collections.abc import Callable
|
||||
|
||||
from review_agent.regulatory_review.schemas import Finding
|
||||
|
||||
@@ -17,27 +18,40 @@ FIELDS = {
|
||||
}
|
||||
|
||||
|
||||
def run_consistency_check(document_texts: dict[str, str]) -> list[Finding]:
|
||||
def run_consistency_check(
|
||||
document_texts: dict[str, str],
|
||||
progress_callback: Callable[[dict[str, object]], None] | None = None,
|
||||
) -> list[Finding]:
|
||||
findings: list[Finding] = []
|
||||
for label, pattern in FIELDS.items():
|
||||
fields = list(FIELDS.items())
|
||||
total = len(fields)
|
||||
for index, (label, pattern) in enumerate(fields, start=1):
|
||||
values: dict[str, list[str]] = defaultdict(list)
|
||||
for file_name, text in document_texts.items():
|
||||
match = re.search(pattern, text)
|
||||
if match:
|
||||
values[_normalize(match.group(1))].append(file_name)
|
||||
if len(values) <= 1:
|
||||
continue
|
||||
findings.append(
|
||||
Finding(
|
||||
rule_code=f"consistency:{label}",
|
||||
category="consistency",
|
||||
severity="high",
|
||||
title=f"{label}在不同文件中不一致",
|
||||
detail=f"发现 {len(values)} 个不同的{label}取值。",
|
||||
suggestion=f"请统一各注册资料中的{label}。",
|
||||
evidence={"field": label, "values": dict(values)},
|
||||
if len(values) > 1:
|
||||
findings.append(
|
||||
Finding(
|
||||
rule_code=f"consistency:{label}",
|
||||
category="consistency",
|
||||
severity="high",
|
||||
title=f"{label}在不同文件中不一致",
|
||||
detail=f"发现 {len(values)} 个不同的{label}取值。",
|
||||
suggestion=f"请统一各注册资料中的{label}。",
|
||||
evidence={"field": label, "values": dict(values)},
|
||||
)
|
||||
)
|
||||
if progress_callback:
|
||||
progress_callback(
|
||||
{
|
||||
"processed": index,
|
||||
"total": total,
|
||||
"label": label,
|
||||
"finding_count": len(findings),
|
||||
}
|
||||
)
|
||||
)
|
||||
return findings
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
|
||||
from review_agent.regulatory_review.schemas import Finding
|
||||
|
||||
|
||||
def run_structure_check(document_texts: dict[str, str], rule_set: dict) -> list[Finding]:
|
||||
def run_structure_check(
|
||||
document_texts: dict[str, str],
|
||||
rule_set: dict,
|
||||
progress_callback: Callable[[dict[str, object]], None] | None = None,
|
||||
) -> list[Finding]:
|
||||
findings: list[Finding] = []
|
||||
combined_all_text = "\n".join(document_texts.values())
|
||||
for requirement in rule_set.get("requirements", []):
|
||||
requirements = list(rule_set.get("requirements", []))
|
||||
total = len(requirements)
|
||||
for index, requirement in enumerate(requirements, start=1):
|
||||
if requirement.get("structure_required") and not _contains_any(
|
||||
combined_all_text,
|
||||
[requirement.get("title", ""), *requirement.get("aliases", [])],
|
||||
@@ -27,25 +35,32 @@ def run_structure_check(document_texts: dict[str, str], rule_set: dict) -> list[
|
||||
)
|
||||
)
|
||||
required_sections = requirement.get("required_sections") or []
|
||||
if not required_sections:
|
||||
continue
|
||||
matching_docs = _matching_documents(document_texts, requirement.get("file_keywords", []))
|
||||
if not matching_docs:
|
||||
continue
|
||||
combined_text = "\n".join(matching_docs.values())
|
||||
for section in required_sections:
|
||||
if _contains_any(combined_text, [section]):
|
||||
continue
|
||||
findings.append(
|
||||
Finding(
|
||||
rule_code=f"{requirement['code']}:{section}",
|
||||
category="structure",
|
||||
severity=requirement.get("severity", "medium"),
|
||||
title=f"{requirement['title']}缺少{section}章节",
|
||||
detail=f"已匹配{requirement['title']}文件,但未发现{section}相关内容。",
|
||||
suggestion=requirement.get("suggestion", ""),
|
||||
evidence={"section": section, "files": list(matching_docs)},
|
||||
)
|
||||
if required_sections:
|
||||
matching_docs = _matching_documents(document_texts, requirement.get("file_keywords", []))
|
||||
if matching_docs:
|
||||
combined_text = "\n".join(matching_docs.values())
|
||||
for section in required_sections:
|
||||
if _contains_any(combined_text, [section]):
|
||||
continue
|
||||
findings.append(
|
||||
Finding(
|
||||
rule_code=f"{requirement['code']}:{section}",
|
||||
category="structure",
|
||||
severity=requirement.get("severity", "medium"),
|
||||
title=f"{requirement['title']}缺少{section}章节",
|
||||
detail=f"已匹配{requirement['title']}文件,但未发现{section}相关内容。",
|
||||
suggestion=requirement.get("suggestion", ""),
|
||||
evidence={"section": section, "files": list(matching_docs)},
|
||||
)
|
||||
)
|
||||
if progress_callback:
|
||||
progress_callback(
|
||||
{
|
||||
"processed": index,
|
||||
"total": total,
|
||||
"label": _numbered_title(requirement),
|
||||
"finding_count": len(findings),
|
||||
}
|
||||
)
|
||||
return findings
|
||||
|
||||
|
||||
Reference in New Issue
Block a user