Практычныя прыемы: Чыстка дадзейнаў і падготовка да выкарыстанняя ў RAG для працы: стварэнне
Практычныя прыказкі: чыстка дадзейнаў і падготовка ўсіх неабходных элементаў для выкорыстання ў модэлі RAG у працоўнай супервізіі: структура, контракты, перакананні, а таксама шаблоны коду для команд, якія викорыстоўваюць гэты патэрн.
Існавайце гэта як перапрацоўаны варыянт ідэй з кніги «Чыстка дадзеных і прадаўнае обробкі для прымення RAG: стварэнне дакументаў, гатовых да выкарыстоўвання для пошуку», адпаведны для працавікаў: чыстыя этапы, аранжаваныя блакі коду і прыметкі з восстанавлення, якія застаюцца пасля перадачы задання. Этап агульнага апісу працюе найэфектывней, калі яго розглядаць як мерыябельную структуру. Запісаце адну ідеальную версію, адзін прыклад неудачы і прыметкі з вярнення да пачатковага стану прычаму, перш чым расширваць масштаб задання. Валідзіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісьця крока не выходзіце, прычына неудачы павінна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцюг задання.
CONFIDENTIAL - INTERNAL USE ONLY
Group Financial Crime Compliance
Page 47 of 132
Як чыстка дадзеных пасляўляецца ў ланцюгу RAG
Для стадіі «Дзея прыменяецца чыстка дадзейн» неабходна прадзеява вводных дадзейн, адказальніка за гэты крок і крэтарыя выходу пры змены коду. Аператары должны магчымаць перзапуск крока з вядомай точкі контролю, не падозрываючы схованы стан. Спрыяйце гэтай стадіі як даговору межа вводнымі дадзейнамі і перакананымі выходнымі рэзультатамі. Даўце назвы артыфактам, прадзеяваце перакананні на успех і адмовіцеся ад тыхоўскага частковага завершэння. Указывайце тыя часткі, якія фактычна лежалі в основе адпаведнай адказы. Без цых цітатаў аператары не зможуць разлічыць галюцинацію ад прасоўкі ў індэксаванні.
Нормалізацыя кодавання: Вылечыце тэкст прытым, як будзеце яго аналізаваць
Для выправлення проблемы нормалізації кодування неабяжна пазлікаваць вхідныя даны, абонента крока та крэтыры завершэння пры змяне коду. Аперацыйныя працавнікі павінны магчыма ўвайсці крок з вядомага пункта контролю, не спрабоўваючы здагадвацца пра схованы стан. Запісвайце час выконання та кост токенаў або запытаў праза функцыйнае рэзультат. Відкрытыя даны пра косцы запобегаюць неспадзеваным рачункам, калі парадокс пераходзіць з дэмавайнага режыма ў спадзеленыя среды. Указвайце часткі тексту, якія фактычна служылі падставай для адпаведзення. Без цых цитатаў аперацыйныя працавнікі не зможуць адразніць галюцинацыю ад прасоўкі ў індэксаванні.
Customer’s identity must be verified before account opening.
The customer must provide proof of address.
Enhanced Due Diligence â€" High Risk Customers
Лячэнне зламанага Unicode за дапамогою ftfy
Для процеса адміністрування зламанага Unicode паветку неабяжна ўзначыць вхідныя даны, адпаведальнага за крок і крэтыры завершэння пры змяне коду. Аператары должны магчымаць перзапуск кроку з вядомай точкі контролю без адгадвання захаванага стану. Конфігурацыю трэба знаходзіць за межамі коду прыкладнення. Файлы сераўнавання, хранільнікі секрэтных дадзеных і флагі функцый належыць у аднам месца, якое аператары можаць пераглядаць без чытання всіх элементаў структуры. Паказваць трэба тыя часткі тексту, якія фактычна лежаць у падставе адпаведнай адказы. Без ціх цитатаў аператары не можаць разлічыць галюцинацію ад працягу індэксавання. Для процеса адміністрування зламанага Unicode паветку неабяжна ўзначыць вхідныя даны, адпаведальнага за крок і крэтыры завершэння пры змяне коду. Аператары должны магчымаць перзапуск кроку з вядомай точкі контролю без адгадвання захаванага стану. Лепш выбіраць маленькія, тэставаныя елементы замест большых скрыптов. Калі крок не выйшаў, прычына нехаспекі должна вказываць на адну конкрэтную адпаведальнасць, а не на канвал.
заплутаныя трубопрацэсы.import re
import unicodedata
from dataclasses import dataclass, field
import ftfy
@dataclass
class TextCleaningResult:
original_text: str
cleaned_text: str
transformations: list[str] = field(default_factory=list)
quality_flags: list[str] = field(default_factory=list)
def normalize_encoding(text: str) -> TextCleaningResult:
"""
Repair common encoding problems while preserving meaningful Unicode.
Suitable for policy, AML/KYC, payment, and regulatory documents where
accented names, currency symbols, and multilingual text must survive.
"""
transformations: list[str] = []
quality_flags: list[str] = []
if not text:
return TextCleaningResult(original_text=text, cleaned_text=text)
cleaned = text
# Repair mojibake and common Unicode encoding mistakes.
repaired = ftfy.fix_text(cleaned)
if repaired != cleaned:
transformations.append("ftfy_encoding_repair")
cleaned = repaired
# NFC preserves characters while producing a consistent Unicode
# representation. Safer than aggressively stripping accents.
normalized = unicodedata.normalize("NFC", cleaned)
if normalized != cleaned:
transformations.append("unicode_nfc_normalization")
cleaned = normalized
# Replace non-breaking spaces with normal spaces.
if "\u00a0" in cleaned:
cleaned = cleaned.replace("\u00a0", " ")
transformations.append("non_breaking_space_normalization")
# Remove zero-width characters that frequently leak from PDFs,
# web pages, and copied Office content.
zero_width_chars = {"\u200b", "\u200c", "\u200d", "\ufeff"}
if any(char in cleaned for char in zero_width_chars):
cleaned = "".join(char for char in cleaned if char not in zero_width_chars)
transformations.append("zero_width_character_removal")
# Remove control characters; preserve newline and tab because
# they may still carry document structure needed downstream.
cleaned_without_controls = "".join(
char for char in cleaned
if char in "\n\t" or unicodedata.category(char) != "Cc"
)
if cleaned_without_controls != cleaned:
transformations.append("control_character_removal")
cleaned = cleaned_without_controls
# Normalize horizontal whitespace without flattening paragraphs.
whitespace_normalized = re.sub(r"[ \t]+", " ", cleaned)
whitespace_normalized = re.sub(r"\n{3,}", "\n\n", whitespace_normalized)
if whitespace_normalized != cleaned:
transformations.append("whitespace_normalization")
cleaned = whitespace_normalized
cleaned = cleaned.strip()
# Keep suspicious replacement characters observable rather than silently deleting them.
if "\ufffd" in cleaned:
quality_flags.append("unicode_replacement_character_detected")
return TextCleaningResult(
original_text=text,
cleaned_text=cleaned,
transformations=transformations,
quality_flags=quality_flags,
)
Чаму агрэсыўнае чысткаванне текста шкодзіць RAG
Калі працуеце над этапам «Чаму агрэсыўнае чысткаванне текста», спачатку запісайце угоду: неабходныя вхідныя даны, сигнал успеху і тое, што выходзіць у разы ў частковай невялікай неудачы. Такі список перакладае пазнейшыя змены ў кодзе на более працэсабельныя. Спрытавайцеся да гэтага этапу як да угоды між вхіднымі данымі і перакананымі выходнымі рэзультатамі. Дайце назвы артыфактам, задацьте критэрыя успеху і не падтрымайце тых, хто выкананяе задачу часткова без паведамлення. Змяркуйце рэкалі на фіксаваным наборе запытанняў прычым перэналаштаваць прапты. Частая зміна праптова рэдка калі-небудзь выправляе слабую систему адналёгчэння інформацыі.
Customer must NOT be classified as low risk.
Адзьёмка стандартных фрагментаў: з урахоўванням структуры, а не ключавых слоў
Калі працюеце над стадіяй «Boilerplate Removal Structure-Aware Not», спачатку запісайце шаблон: неабяжныя вхідныя даны, сигнал успеху і тое, што выходзіць у разе частковага абякання. Такій чарт дапамагае залічваць змяны ў кодзе адкрыта і чэстна. Запісвайце час выканання і кост токена або запыту праза функцыйнальнымі рэзултатамі. Відразы коста з самага пачатку запобегае неспакоўным рахункам, калі працэс пераходзіць з дэмаверыяна ў спакульнаныя сераўысы. Замерьце рэкалі на фіксаванай сэтке запытаў прычым регулюванні прамптав. Частае змена прамптав рэдка калі-небудзь вылечвае слабую систему аднаходжэння інфармацыі.
KYC Policy | Version 7.2 | Page 41 of 132
KYC Policy | Version 7.2 | Page 42 of 132
import re
from collections import Counter
from dataclasses import dataclass
@dataclass
class BoilerplatePattern:
normalized_text: str
occurrences: int
page_ratio: float
position: str
def normalize_boilerplate_candidate(line: str) -> str:
"""
Normalize variable fields so structurally identical headers and
footers can be compared across pages.
"""
normalized = line.strip()
normalized = re.sub(
r"\bpage\s+\d+\s+of\s+\d+\b", "page <n> of <n>",
normalized, flags=re.IGNORECASE,
)
normalized = re.sub(r"\bpage\s+\d+\b", "page <n>", normalized, flags=re.IGNORECASE)
normalized = re.sub(r"\s+", " ", normalized)
return normalized.casefold()
def detect_repeated_marginal_text(
pages: list[dict],
margin_lines: int = 3,
min_page_ratio: float = 0.6,
) -> list[BoilerplatePattern]:
"""
Detect repeated text in page-header or page-footer regions.
A candidate is considered boilerplate only when it appears in the same
marginal position across a substantial fraction of the document.
"""
if not pages:
return []
header_counts: Counter = Counter()
footer_counts: Counter = Counter()
for page in pages:
lines = [line.strip() for line in page["text"].splitlines() if line.strip()]
if not lines:
continue
header_counts.update(normalize_boilerplate_candidate(l) for l in lines[:margin_lines])
footer_counts.update(normalize_boilerplate_candidate(l) for l in lines[-margin_lines:])
total_pages = len(pages)
patterns: list[BoilerplatePattern] = []
for position, counts in (("header", header_counts), ("footer", footer_counts)):
for normalized_text, occurrences in counts.items():
page_ratio = occurrences / total_pages
if page_ratio >= min_page_ratio:
patterns.append(BoilerplatePattern(
normalized_text=normalized_text,
occurrences=occurrences,
page_ratio=page_ratio,
position=position,
))
return patterns
Усуненне дуплікацый: Точныя падабенства — гэта простая частка
Калі працуеце над стадзіяй «Deduplication Exact Matches Are», спачатку запісайце умовы вярбунка: неабяжлівыя данні, сігнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список контроля дапамагае заліцьварыць пазнейшыя змены ў кодзе. Храніце настройкі парадульна ад коду прыемліка. Файлы сераўіснага сэрвісу, хранальнікі секретных данных і флагі функцыйяў должны знаходзіцца ў аднам месцы, куды аператары можаюць адбавіць аудыт без неабяжлівага чытання всей структуры. Перад налаштаваннем запитоў пераканайцеся ў рэкалі на фіксаваным наборе запытанняў. Частае змена запытоў рэдка калі вярнуе слабую эфектыўнасць пошуку. Калі працуеце над стадзіяй «Deduplication Exact Matches Are», спачатку запісайце умовы вярбунка: неабяжлівыя данні, сігнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список контроля дапамагае заліцьварыць пазнейшыя змены ў кодзе. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшаў, прычына нявыпання должна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцюг задач.
AML_Policy_v8_Final.docx
AML_Policy_v8_Final_Approved.docx
AML_Policy_v8_Final_Copy.docx
AML_Policy_v8_Approved_2026.docx
Точная адыяктуляцыя за дапамою хэшавання кантэнту
Этап точной адыяктуляцыі за дапамою кантэнту работае наяўней, калі яго спрыяваць як меравальную плошчу. Зберыце адну ідеальную версію транскрыпцыі, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштабы. Спрыяйце этапу як кантракту между вхіднымі дадзеннямі і паўнастацэннымі выходнымі рэзультатамі. Дайце назвы артыфактам, задаце критэрыя успеху і не прымайце часткова завершаныя рэзультаты без паведамлення. Раздзеліце правілы часткавага разбівання дадзеных і правілы ўтрымання ўхідных дадзеных. Змена аднаго з іх не павінна вымагаць перапісвання другога, калі зменяюцыся паказнікі якосці.
import hashlib
from dataclasses import dataclass
@dataclass
class DeduplicationRecord:
document_id: str
source: str
content_hash: str
duplicate_of: str | None = None
def canonicalize_for_hashing(text: str) -> str:
"""
Deterministic normalization before hashing.
Does not lowercase or remove punctuation because those transformations
could collapse documents that are not actually identical.
"""
lines = [" ".join(line.split()) for line in text.splitlines()]
return "\n".join(lines).strip()
def calculate_content_hash(text: str) -> str:
canonical_text = canonicalize_for_hashing(text)
return hashlib.sha256(canonical_text.encode("utf-8")).hexdigest()
def find_exact_duplicates(
documents: list[dict],
) -> tuple[list[dict], list[DeduplicationRecord]]:
"""
Keep one canonical copy of each identical document while preserving
duplicate lineage for auditability.
"""
seen_hashes: dict[str, str] = {}
unique_documents: list[dict] = []
records: list[DeduplicationRecord] = []
for document in documents:
content_hash = calculate_content_hash(document["clean_text"])
if content_hash in seen_hashes:
records.append(DeduplicationRecord(
document_id=document["document_id"],
source=document["source"],
content_hash=content_hash,
duplicate_of=seen_hashes[content_hash],
))
continue
seen_hashes[content_hash] = document["document_id"]
unique_documents.append(document)
records.append(DeduplicationRecord(
document_id=document["document_id"],
source=document["source"],
content_hash=content_hash,
))
return unique_documents, records
Адкрытыя адыяктуляцыі за дапамою MinHash LSH
Адзінаковасць няблізкіх копій, выяўленая за дапамогою MinHash, працуе наякша, калі яе розглядаць як мерыябельную велічыну. Перш чым расширваць сферу прыемлівання, зафіксавайце адну ідеальную транскрыпцыю, адзін прыклад неудачы і запіску па поверненню да пачатковага стану. Запісвайце часы виконання аперацый, а таксу токенавання чы роезпытваў па боку ад функцыйнаых рэзультатаў. Візуальная адразлівасць костов у раннім перыядзе запобегае неспакою з боку расчыткаў, калі працэс пераходзіць з дамовай среды ў спакульную. Раздзеліце правілы часткавання дадзеных ад правілаў ўзяць іх з памяці. Змена аднаго з яных не должна вымагаць перапісвання другога, калі зменяюцца паказнікі якосці.
import re
from datasketch import MinHash, MinHashLSH
def create_word_shingles(text: str, shingle_size: int = 5) -> set[str]:
"""
Five-word shingles work well for long policy and regulatory documents
because they capture local textual structure without being overly
sensitive to isolated formatting changes.
"""
tokens = re.findall(r"\b\w+\b", text.casefold())
if len(tokens) < shingle_size:
return {" ".join(tokens)} if tokens else set()
return {
" ".join(tokens[i:i + shingle_size])
for i in range(len(tokens) - shingle_size + 1)
}
def create_minhash(text: str, num_perm: int = 128) -> MinHash:
shingles = create_word_shingles(text)
minhash = MinHash(num_perm=num_perm)
for shingle in shingles:
minhash.update(shingle.encode("utf-8"))
return minhash
def build_duplicate_index(
documents: list[dict],
threshold: float = 0.85,
num_perm: int = 128,
) -> tuple[MinHashLSH, dict[str, MinHash]]:
"""
Build an LSH index for candidate near-duplicate discovery.
The threshold identifies candidates. It does not automatically
determine whether a document is deleted.
"""
lsh = MinHashLSH(threshold=threshold, num_perm=num_perm)
signatures: dict[str, MinHash] = {}
for document in documents:
document_id = document["document_id"]
signature = create_minhash(document["clean_text"], num_perm=num_perm)
signatures[document_id] = signature
lsh.insert(document_id, signature)
return lsh, signatures
Корэкцыя памылак OCR: Калі тэкст выглядае правільна, але ўсё ж неправільны
Этап карэкцыі паклопчанняў OCR працуе наякша, калі яго спрыяваць як мерыемую паверхню. Зберагачыце адна ідеальная транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перад расшырэнням масштаба. Храніце настройкі пазырочна ад коду прыемліка. Файлы сяродавішча, хранальнікі секрэтных дадзеных і флагі функцыйяў должны знаходзіцца ў аднам месцы, куды аператары можаць адбавляць аудыт без неабяжнага чытання всіх элементаў. Раздзеляйце правілы часткавання дадзеных ад правілаў ўзяць іх. Змена аднаго з яных не должна вымагаць перапісву другога, калі зменяюцыся паказнікі якосці. Этап карэкцыі паклопчанняў OCR працуе наякша, калі яго спрыяваць як мерыемую паверхню. Зберагачыце адна ідеальная транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перад расшырэнням масштаба. Валіце маленькія, тэставаныя елементы працы над вялікімі, складнымі скрыптамі. Калі які-небудзь крок не выйшаў, прычына неудачы должна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцужок задач.
import re
from dataclasses import dataclass
@dataclass
class OCRIssue:
token: str
issue_type: str
risk_level: str
suggested_value: str | None
requires_review: bool
CURRENCY_PATTERN = re.compile(r"\b(EUR|USD|GBP|INR)\s+([A-Za-z0-9.,]+)\b")
PERCENTAGE_PATTERN = re.compile(r"\b([A-Za-z0-9.,]+)\s*%")
def detect_numeric_ocr_issues(text: str) -> list[OCRIssue]:
"""
Detect suspicious OCR substitutions inside financial values.
This function identifies candidates. It does not silently rewrite
high-risk values in the source text.
"""
issues: list[OCRIssue] = []
substitutions = {"O": "0", "o": "0", "I": "1", "l": "1"}
def inspect_numeric_token(token: str, issue_type: str) -> None:
if token.replace(",", "").replace(".", "").isdigit():
return
corrected = "".join(substitutions.get(char, char) for char in token)
numeric_candidate = corrected.replace(",", "").replace(".", "")
if numeric_candidate.isdigit() and corrected != token:
issues.append(OCRIssue(
token=token,
issue_type=issue_type,
risk_level="high",
suggested_value=corrected,
requires_review=True,
))
for match in CURRENCY_PATTERN.finditer(text):
inspect_numeric_token(match.group(2), issue_type="currency_value")
for match in PERCENTAGE_PATTERN.finditer(text):
inspect_numeric_token(match.group(1), issue_type="percentage")
return issues
Багатыязычная прадаўнае обробка: адна дакумент, калькі языкаў
У стадзіі багатыязычнай прадаўнае обробкі адной дакумента неабходна прадзефінаваць вхідныя даны, адпаведальную за ўзел і крэтыніяты выходу пры перадзеўранні коду. Аператары должны магчымае перзапускіць гэты узел з вядомага пункту контролю, не спрабоўваючы здагадвацца пра схованы стан. Спрыяйце гэтай стадзіі як даговору межа вхіднымі данымі і пасвярджанымі выходамі. Дайце назву рэзультатам, прадзефінаваць перакананняя пра успех і адмовіцеся ад тыхнай частковай завершэння без паведамлення. Указацьы фрагменты, якія насправдзе сталі падставай для адпаведнай адказу. Без ціх указаў, аператары не зможуць разлічыць галюцинацыю ад прасоўкі ў індэксаванні.
from dataclasses import dataclass
from langdetect import DetectorFactory, LangDetectException, detect_langs
DetectorFactory.seed = 0 # Makes pipeline output reproducible.
@dataclass
class LanguagePrediction:
language: str
confidence: float
alternatives: list[tuple[str, float]]
needs_review: bool
def detect_document_language(
text: str,
confidence_threshold: float = 0.85,
) -> LanguagePrediction:
sample = text.strip()
if not sample:
return LanguagePrediction(language="unknown", confidence=0.0, alternatives=[], needs_review=True)
try:
predictions = detect_langs(sample)
except LangDetectException:
return LanguagePrediction(language="unknown", confidence=0.0, alternatives=[], needs_review=True)
best = predictions[0]
alternatives = [(p.lang, round(p.prob, 4)) for p in predictions]
return LanguagePrediction(
language=best.lang,
confidence=best.prob,
alternatives=alternatives,
needs_review=best.prob < confidence_threshold,
)
metadata = {
"primary_language": "en",
"languages": ["en", "de", "fr"],
"language_distribution": {"en": 0.72, "de": 0.21, "fr": 0.07},
"is_multilingual": True,
}
Персональныя даны і чутлівыя даны: адкрыцце пры ўбудоўванні
Для стадіі перакантролю Персональных данных і Чутлівых дадзей неабяжна ўскладніць вхідныя даны, абярону крока і крэтыры завершэння пры перадзеіснаванні коду. Аператары должны магчымаць перапрацаваць крок з вядомага пункта контролю, не спрабоўваючы здагадвацца пра схованы стан. Запісвайце час выконання і кост токена або запыту праза функцыйнальныя рэзултаты. Відразлівасць костаў з самага пачатку запобегае неспакою, калі процес пераходзіць з дэмовай среды ў спакульную. Указвайце тыя часткі тексту, якія фактычна лежалі в основе адпаведнай адказу. Без цых цітатаў аператары не можаць разлічыць галюцинацію ад прасоўкі ў індэксаванні.
from dataclasses import dataclass, field
from presidio_analyzer import AnalyzerEngine
@dataclass
class SensitiveEntity:
entity_type: str
start: int
end: int
score: float
original_value: str
@dataclass
class PIIScanResult:
entities: list[SensitiveEntity] = field(default_factory=list)
needs_review: bool = False
class BankingPIIDetector:
def __init__(self) -> None:
self.analyzer = AnalyzerEngine()
def detect(
self,
text: str,
language: str = "en",
score_threshold: float = 0.70,
) -> PIIScanResult:
"""
Detect sensitive entities without modifying the source text.
Detection is deliberately separated from anonymization because
different entity types require different handling policies.
"""
results = self.analyzer.analyze(
text=text, language=language, score_threshold=score_threshold
)
entities = [
SensitiveEntity(
entity_type=r.entity_type,
start=r.start,
end=r.end,
score=r.score,
original_value=text[r.start:r.end],
)
for r in results
]
high_risk_types = {"CREDIT_CARD", "IBAN_CODE", "US_SSN", "IP_ADDRESS"}
return PIIScanResult(
entities=entities,
needs_review=any(e.entity_type in high_risk_types for e in entities),
)
Customer IBAN: <IBAN>
Customer Email: <EMAIL_ADDRESS>
Аб’еднанне элементаў: Працэс чысткі дадзей высокага стандарта
У стадії «Адаптаванне» неабяжна практычна вказаць інпуты, адміністратара крока та крэтэрыявання завершэння пры зміне коду. Аперацыйныя працавнікі павінны магчымаць перзапуск крока з вядомай точкі контролю, не спрабоўваючы здагадвацца пра схованы стан. Конфігурацыю трэба знаходзіць за межамі коду прыемленае. Файлы сераўіса, хранальнікі секрэтных дадзеных та флагі функцыйяў павінны быць у адном месца, якое аперацыйныя працавнікі могу пераглядаць, не чытаючы весь ланцуг задач. Прыкладзіце часткі тексту, якія фактычна лежаць у падставе адпаведнай адказы. Без ціх прамянаў аперацыйныя працавнікі не зможуць адразніць галюцинацыю ад працягу індэксавання. У стадії «Адаптаванне» неабяжна практычна вказаць інпуты, адміністратара крока та крэтэрыявання завершэння пры зміне коду. Аперацыйныя працавнікі павінны магчымаць перзапуск крока з вядомай точкі контролю, не спрабоўваючы здагадвацца пра схованы стан. Валідзіце маленькія, тэставаныя елементы замест большых скрыптов. Калі крок не выканаецца, прычына нехваткі павінна вказываць на адную адпаведальнасць, а не на заплутаны ланцуг задач.
e.from dataclasses import dataclass, field
from enum import Enum
from typing import Any
class QualityStatus(str, Enum):
PASS = "pass"
REVIEW = "review"
REJECT = "reject"
@dataclass
class Transformation:
stage: str
operation: str
details: dict[str, Any] = field(default_factory=dict)
@dataclass
class QualityFlag:
code: str
severity: str
details: dict[str, Any] = field(default_factory=dict)
@dataclass
class RetrievalReadyDocument:
document_id: str
source: str
raw_text: str
clean_text: str
language: str | None = None
language_confidence: float | None = None
content_hash: str | None = None
duplicate_of: str | None = None
transformations: list[Transformation] = field(default_factory=list)
quality_flags: list[QualityFlag] = field(default_factory=list)
metadata: dict[str, Any] = field(default_factory=dict)
status: QualityStatus = QualityStatus.PASS
import logging
logger = logging.getLogger(__name__)
class ProductionDocumentCleaner:
def __init__(
self,
pii_detector: BankingPIIDetector,
pii_anonymizer,
redact_pii_for_embeddings: bool = True,
) -> None:
self.pii_detector = pii_detector
self.pii_anonymizer = pii_anonymizer
self.redact_pii_for_embeddings = redact_pii_for_embeddings
def clean(self, document: dict) -> RetrievalReadyDocument:
result = RetrievalReadyDocument(
document_id=document["document_id"],
source=document["source"],
raw_text=document["text"],
clean_text=document["text"],
metadata=document.get("metadata", {}).copy(),
)
try:
self._normalize_text(result)
self._detect_language(result)
self._validate_ocr(result)
self._handle_sensitive_data(result)
self._calculate_hash(result)
self._apply_quality_gate(result)
except Exception as exc:
logger.exception("Preprocessing failed for document %s", result.document_id)
result.quality_flags.append(QualityFlag(
code="PREPROCESSING_EXCEPTION",
severity="critical",
details={"error": str(exc)},
))
result.status = QualityStatus.REJECT
return result
def _apply_quality_gate(self, document: RetrievalReadyDocument) -> None:
severities = {flag.severity for flag in document.quality_flags}
if "critical" in severities:
document.status = QualityStatus.REJECT
elif "high" in severities:
document.status = QualityStatus.REVIEW
else:
document.status = QualityStatus.PASS
Адаптация працы пад час вырабаткі
Калі працуеце над стадзіяй адаптации працы пад час вырабаткі, спачатку запісайце угоду: неабяжлівыя вхідныя даны, сигнал успеху і тое, што выканаецца у разы ўзельнага нявярнага рэзультата. Такі чартак дапамагае заліцвачыць пазнейшыя змены ў кодзе. Спрэцьвачайце гэтую стадзію як угоду межаў вхідных дадзеных і перакананыя выходныя даны. Дайце назвы артыфактам, задаць тэсты на успех і не падзеўляйцеся мовчаным частковым завершэнням. Перад налаштаваннем запитоў пераканайцеся ў рэгулярнасці адпаведзенняў на фіксованы набор запитаў. Рэдкаколі змены запитоў можу выправіць слабую эфектывнасць адзысквання інформаціі.
Што гэта значыць на практыцы
Калі працюеце над этапам «Што гэта значыць», спачатку запісайце умовы контракту: неабяжлівыя даны, сігнал успеху і тое, што выходзіць пад частыя неудачы. Такі список пераканае застаўляцца чыстасцю пазнейшых змян у кодзе. Запісвайце час выканання і кост токенаў або запытаў пад функцыйнальнымі рэзултатамі. Відразлівасць костаў з самага пачатку запобегае неспакойным рахункам, калі працэс пераходзіць з дэмаверсіі ў спяльныя среды. Замерьце рэткість аднаходжання адпаведных дадзеных на фіксованыя наборы запытаў прычым перад налаштаваннем підказак. Частае змяненне підказак рэдка калі-небудзь выправляе слабыя аспекты пошуку дадзеных.
Спіс пераканаў пры роботе ў працоўнай средзе перад пачаткам фрагментавання
Калі працюеце над стадіяй «A Production Checklist Before», спачатку запісайце умовы кантракту: неабяжлівыя даны, сігнал успеху і тое, што выходзіць у разе частковага абякання. Такі чэк-ліст дапамагае заставаць пазнейшыя змены коду чыстымі. Зберагаеце настройкі за межамі коду прыемлі. Файлы сераўіснага сэрвісу, храненні секретных дадзенаў і флагі функцыйяй должны знаходзіцца ў аднам месцы, куды аператары можаюць адбавіць аудыт без неабяжлівага чытання всей структуры. Перад налаштаваннем запытаў пераканайцеся ў рэкале на фіксаваным наборы запытаў. Частае змена запытаў рэдка калі вярнайць слабкую ступеню адналічэння дадзенаў. Калі працюеце над стадіяй «A Production Checklist Before», спачатку запісайце умовы кантракту: неабяжлівыя даны, сігнал успеху і тое, што выходзіць у разе частковага абякання. Такі чэк-ліст дапамагае заставаць пазнейшыя змены коду чыстымі. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок абякае, абяканне должна паказваць на адну адпаведальнасць, а не на заплутаны процес.
Чэк-ліст для аператыўнай роботы
Калі працюеце над стадзіяй аператыўнага чэк-лісту, спачатку запісайце контракт: неабходныя даны, сігнал успеху і тое, што выходзіць пад час частковага абякання. Такі чэк-ліст дапамагае заставаць пазнейшыя змены коду чыстымі.
Документавайце як шлях успеху, так і шлях вярнення. Перапрыбуткі, людзкія контралі і обработка некоректных паведамленняў ёсць часткай продукту, а не пазнейшым дапрацоўкам.
Змяроўвайце эфектыўнасць адзыскання інформаціі на фіксаванай сэтке запытаў прычым регулювання прапаноў. Змена прапаноў рэдка калі вярнайць слабую систему адзыскання дакументаў.
Заморозьце «золаты» набір параметраў прычым змены прапаноў або модэляў. Змена як самай системы, так і критэрыяў ацэнкі магчымая сховаць регрэсіі.
Калі бюджет дазволяе, дадзіце тэст на пераверканне критычнага шляху ў процесе CI з викорыстаннем фіксатараў, а не рэальных платных API.
Запісвайце часы выканання аперацый і косць токена чыста запитоў праза функцыйнальныя рэзултаты. Відразлівая візуабільнасць косца ў раннім перыядзе запобегае неспакоўным рахункам, калі маршрут пераходзіць з дэмовай среды ў спадзеленыя среды.
Перш чым пераводзіць стэк у болей серйозны режым, заморожвайце версіі, зафіксавайце «золаты» транскрыпты для критычных маршрутаў і паказвайце шагі для атрыбуцыі. Спадзеленыя среды выклекваюць патрэбу ў лімітах частоты выканання, пераказах прыналежнасці і чысткай адпаведальнасці за змяну секрэтных даных. Лепш выбіраць простую надзею на надзейнасць, чым хітрыя експерыментальныя дэманстрацыі.
Прыметка для af00655fb2bc: не кладзіце ключы прадастаўцаў у репазітарый, задаце верхні ліміт токена на кожную сесыю і зберагайце транскрыпты праза фіксаты для ацэнкі, каб пазнейшыя замены моделяў заставаліся пораўнанымі.
Этап 0 пры практыкаванні заходаў з абароны працюе наякша, калі яго расследжваць як мерыемую паверхню. Запісаце адна «золатая» версія, адзін прыклад неудачы і запісы парадоксу перад расшырэнням масштаба. Запісвайце часы выканання, а таксу токенаў чы запытак праза рэзультаты функцыйнасці. Відчутнасць костоў з самага пачатку запобегае неспакойным рахункам, калі процес пераходзіць з дэмаверсіі ў спяльныя среды.
Дакладнасць пры практыкаванні заходаў 0/902: змерьце час выканання, класію памылак і выкарыстаныя токены для гэтага пункту, а потым выберце, чы застаўляць змены на адной пазнакованай базе пытанняў, а не на адной лічбе прыкладаў.
Для этапу 1 пры практыкаванні заходаў з абароны перад змянай коду неабходна праказаць вхідныя даны, адпаведальнага за крок і критэрыя завершэння. Аперацыёныя працавнікі должны магчымае перадзеяць крок з вядомай точкі контролю, не спадзяючыся на скрыты стан. Дакументавайце як успешны, так і варыянт вяснавання. Перапрыбуткі, людзкія контралі і обработка неканальных паведамленняў є часткай продукту, а не чымсь, што дадаецца пазней.
Дзеянне паўжасткі 1/902: звярніце увагу на час выканання, клас памылакі і колькасць токенаў, якія былі выкарыстаны для гэтага зазначэння, а пасля, на аднойчыне з фіксаваным наборам пытанняў, а не на асобістых спазыраннях, выявіце, чы хачаце застаўіць гэтыя змены.
Калі працуеце над 2-й стадзіяю паўжасткі, спачатку запісайце умовы кантракту: неабходныя данні, сігнал успеху і тое, што выканаецца у разе частковай памылки. Такі список дапамагае заставіць пасляэтапныя змены ў кодзе чыстымі. Спрыймайце гэтую стадзію як кантракт межаў між вхіднымі даннымі і перакананымі выходнымі рэзультатамі. Дайце назвы аб’ектам, задаць правілы пераканання успеху і адмовіцеся ад мовчкай частковай рэалізацыі.
Дзеянне паўжасткі 2/902: звярніце увагу на час выканання, клас памылакі і колькасць токенаў, якія былі выкарыстаны для гэтага зазначэння, а пасля, на аднойчыне з фіксаваным наборам пытанняў, а не на асобістых спазыраннях, выявіце, чы хачаце застаўіць гэтыя змены.
Этап 3 прыцелкі змяцнення работае наяўна, калі яго спрыяваць як вимерную паверхню. Запісаўце адна «золатая» транскрыпцыя, адин прыклад неудачы і запіс перадвороту рэшэнняя пры расшырэнні масштаба. Зберагачце канфігурацыю праза код аплікацыі. Файлы сяродавішча, хранільнікі секрэтных дадзеных і флагі функций павінны знаходзіцца ў адном месцы, куды аператары можаць адбавляць без неабяжнага чытання всіх дадзеных.
Дакладнасць прыцелкі змяцнення 3/902: вимеравайце час выканання, класію памылак і витрату токенаў для гэтай прыцелкі, а пасля, на аднойчынку з фіксаваным наборам пытанняў, а не на аднойчынку з пераказамі, вырашайце, чы робіць змяну.
Для 4-го этапа практыкы зміцнення неабяжна ўзначыць вхідныя даны, адпаведальнага за крок і критэрыя завершэння пры зміне коду. Аператары должны магчыма ўвайсці крок з вядомай точкі контролю, не спрабоўваючы здогадвацца пра схованы стан. Лепш выбіраць маленькія, тэставаныя елементы замест большых скрыптов. Калі крок не выйшоў, прычына неудачы павінна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны процес.
Дзеянне зміцнення 4/902: вымерыце час виконання, класію памылак і колькасць викорыстоўваных токенав для гэтай практыкы, а потым выявіце, чы рэшацься застаўляць зміны на адной пазычанай сэткі пытанняў, а не на асобістых спазыраннях.
Калі працуеце над 5-м падземам прыемкі з ударожэння, спачатку запісайце контракт: неабяжлівыя даны, сігнал успеху і тое, што выходзіць пад частковыя неудачы. Такі список пераканае ў тым, што пазнейшыя змены коду будуць чыстымі. Запісвайце час выканання і вартасьць токена або запытку пад функцыйнальнымі рэзултатамі. Відразы вартасці з самага пачатку запобегае неспакоўным рахункам, калі процес пераходзіць з дэмаверсіі ў спяльныя среды.
Дзеянне 5/902 па прыемкі з ударожэння: вымерайце час выканання, класію памылак і витрату токена для гэтай прыемкі, а потым выберайце, чы робіць змену на адной фіксаванай сэтке пытанняў, а не на адной лепты.
5-й падзем прыемкі з ударожэння работае лепш, калі яго спрыямаць як вимерную паверхню. Запісайце адна ідеальная транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану, перш чым расширваць масштаб. Дакументавайце і ўспешны шлях, і шлях вярнэння разам. Перапрыбуткі, людзкія контралі і обработка некоректных паведамленняў є часткай продукту, а не чымсь, што дадаецца пазней.
Дзеянне паўжасткі 6/902: звярніце увагу на час выканання, класы паказчыкаў і колькасць токенаў, якія былі выкарыстаны для гэтага зазначэння, а пасля, на аднойчынай базе фіксаванага набору пытанняў, а не на індывідуальных прыкладах, выявіце, чы рэшацься застаўляць змяну.
Для 7-й стадзіі паўжасткі неабходна перад змянай коду адзначыць вхідныя даны, адпаведальнага за выкананне крока і критэрыяы завершэння. Аперацыйныя працавнікі павінны магчымае перадзванаць крок з вядомай точкі контролю, не прабуючы спадарацца прыватны стан системы. Штуючы гэту стадзію як кантракт межа вхіднымі данымі і перакананымі выходнымі рэзультатамі, неабходна даць назвы всім элементам, апрацаваць критэрыяы успеху і не прымножваць частковае завершэння без падтверджэння.
Дзеянне паўжасткі 7/902: звярніце увагу на час выканання, класы паказчыкаў і колькасць токенаў, якія былі выкарыстаны для гэтага зазначэння, а пасля, на аднойчынай базе фіксаванага набору пытанняў, а не на індывідуальных прыкладах, выявіце, чы рэшацься застаўляць змяну.
Калі працюеце над 8-м пунктам правіл забезпечэння безпекі, спачатку запісайце умовы кантракта: неабяжлівыя даны, сігнал успеху і тое, што выходзіць у разе частковага невыпання. Такі список дапамагае залічваць будучыя змены ў кодзе чыста і адкрыта. Зберагайце настройкі пазырочна ад коду прыемліка. Файлы сераўнавання, храненні секрэтных данных і флагі функцыйяў должны знаходзіцца ў аднам месцы, куды аператары можаць адбавіць аудыт без неабяжлівага чытання всей структуры.
Дзялёўка 8/902 з правіл забезпечэння безпекі: вымерайце час выканання, класы каштоўкаў і витрату токенаў для гэтага пункта, а потым выберайце, чы хацяце застаўіць змену, стварыўшы фіксаваны набор пытанняў, а не на базе індывідуальных спазыроў.