Skip to content

Commit c70da63

Browse files
Remove unused normalize_phrase and required_phrases field from dataset output
1 parent 2541b32 commit c70da63

2 files changed

Lines changed: 13 additions & 70 deletions

File tree

etc/scripts/dataset_pipeline/build_dataset.py

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
# outputs a JSONL dataset for NER model training
33
import hashlib
44
import json
5-
import re
65
import unicodedata
76
from collections import Counter
87
from pathlib import Path
@@ -14,25 +13,8 @@
1413
from licensedcode.tokenize import required_phrase_splitter
1514

1615

17-
def normalize_phrase(phrase):
18-
"""Clean raw marker phrase for training"""
19-
result = phrase
20-
# replace html entities
21-
result = result.replace('"', '"').replace('&', '&')
22-
result = result.replace('&lt;', '<').replace('&gt;', '>')
23-
# strip xml tags like <name>,</license> but keep urls in angle brackets
24-
result = re.sub(r'<(?![a-zA-Z]+://)[^>]+>', '', result)
25-
# remove markdown backticks
26-
result = result.replace('`', '')
27-
# collapse whitespace and trim
28-
result = re.sub(r'\s+', ' ', result).strip()
29-
# strip trailing/leading punct thats not meaningful
30-
result = result.strip('.,;:<>')
31-
return result
32-
33-
3416
def get_rule_type(rule):
35-
"""is_* flag set on the rule"""
17+
"""Return the is_* flag set on the rule"""
3618
for flag in ('is_license_text', 'is_license_notice', 'is_license_reference',
3719
'is_license_tag', 'is_license_intro', 'is_license_clue',
3820
'is_false_positive'):
@@ -42,11 +24,11 @@ def get_rule_type(rule):
4224

4325

4426
def tag_tokens(text):
45-
"""Tag each word token with a BIOES label"""
27+
"""Tag each word token with a BIOES label based on {{ }} markers"""
4628
tokens = []
4729
labels = []
4830
in_phrase = False
49-
count = 0 # word tokens seen since the last {{
31+
count = 0
5032

5133
for tok in required_phrase_splitter(text):
5234
if tok == '{{':
@@ -65,16 +47,18 @@ def tag_tokens(text):
6547
count += 1
6648
else:
6749
labels.append('O')
50+
51+
assert len(tokens) == len(labels), f'token/label mismatch: {len(tokens)} vs {len(labels)}'
6852
return tokens, labels
6953

7054

7155
def assign_splits(results, threshold=50):
72-
"""80/10/10 split. common expressions (>= threshold rules) get split per-rule,
56+
"""80/10/10 split by license expression to prevent data leakage.
57+
Expressions with >= threshold rules get split per-rule via hash,
7358
rare ones stay together in one split"""
7459
expr_counts = Counter(e['license_expression'] for e in results)
7560
heavy = {e for e, c in expr_counts.items() if c >= threshold}
7661

77-
# rare expressions: assign each to the split that needs more rules
7862
light_exprs = sorted((e for e in expr_counts if e not in heavy),
7963
key=lambda x: (-expr_counts[x], x))
8064
total = sum(expr_counts[e] for e in light_exprs)
@@ -106,18 +90,17 @@ def main(rules_dir, output_dir):
10690

10791
total_rules = 0
10892
annotated = 0
109-
total_phrases = 0
11093
results = []
11194

11295
click.echo(f'scanning rules from: {rules_path}')
11396
for rf in sorted(rules_path.glob('*.RULE')):
11497
try:
11598
rule = Rule.from_file(rule_file=str(rf))
116-
except Exception:
99+
except Exception as e:
100+
click.echo(f' skipping {rf.name}: {e}', err=True)
117101
continue
118102
total_rules += 1
119103

120-
# is_required_phrase rules don't need {{ }}.the flag covers them
121104
if getattr(rule, 'is_required_phrase', False):
122105
continue
123106

@@ -133,27 +116,19 @@ def main(rules_dir, output_dir):
133116
if not phrases:
134117
continue
135118

136-
# word tokens + BIOES labels (computed before stripping markers)
137119
tokens, bioes_labels = tag_tokens(text)
138120

139-
# strip out the {{ }} markers
140-
text = text.replace('{{', '').replace('}}', '')
141-
142-
valid_phrases = [
143-
{'phrase': p, 'phrase_normalized': normalize_phrase(p)}
144-
for p in phrases
145-
]
121+
# strip markers for the clean text field
122+
clean_text = text.replace('{{', '').replace('}}', '')
146123

147124
annotated += 1
148-
total_phrases += len(valid_phrases)
149125
results.append({
150126
'identifier': rule.identifier,
151127
'license_expression': rule.license_expression or '',
152128
'rule_type': get_rule_type(rule),
153-
'text': text,
129+
'text': clean_text,
154130
'tokens': tokens,
155131
'bioes_labels': bioes_labels,
156-
'required_phrases': valid_phrases,
157132
})
158133

159134
# split by license expression and write
@@ -162,7 +137,6 @@ def main(rules_dir, output_dir):
162137
for entry in results:
163138
expr = entry['license_expression']
164139
if expr in heavy:
165-
# common expressions: hash rule name for 80/10/10
166140
bucket = int(hashlib.md5(entry['identifier'].encode('utf-8')).hexdigest(), 16) % 100
167141
if bucket < 80:
168142
splits['train'].append(entry)
@@ -182,7 +156,6 @@ def main(rules_dir, output_dir):
182156
click.echo('\ndone')
183157
click.echo(f' rules scanned: {total_rules}')
184158
click.echo(f' annotated: {annotated}')
185-
click.echo(f' phrases extracted: {total_phrases}')
186159
click.echo(f' train: {len(splits["train"])} val: {len(splits["val"])} test: {len(splits["test"])}')
187160
click.echo(f' output: {out_dir}')
188161

etc/scripts/dataset_pipeline/test_build_dataset.py

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,7 @@
33
from pathlib import Path
44

55
sys.path.insert(0, str(Path(__file__).parent))
6-
from build_dataset import normalize_phrase, tag_tokens, assign_splits
7-
8-
9-
class TestNormalizePhrase:
10-
11-
def test_html_entities(self):
12-
assert normalize_phrase('&lt;b&gt;MIT&lt;/b&gt;') == 'MIT'
13-
assert normalize_phrase('the &quot;License&quot;') == 'the "License"'
14-
assert normalize_phrase('foo &amp; bar') == 'foo & bar'
15-
16-
def test_preserves_urls_in_angle_brackets(self):
17-
result = normalize_phrase('<http://example.com/LICENSE>')
18-
assert result == 'http://example.com/LICENSE'
19-
20-
def test_strips_xml_tags(self):
21-
assert normalize_phrase('<name>Apache 2.0</name>') == 'Apache 2.0'
22-
assert normalize_phrase('<license>MIT</license>') == 'MIT'
23-
24-
def test_strips_backticks(self):
25-
assert normalize_phrase('`MIT License`') == 'MIT License'
26-
27-
def test_collapses_whitespace(self):
28-
assert normalize_phrase('GNU General\n Public License') == 'GNU General Public License'
29-
30-
def test_strips_trailing_punct(self):
31-
assert normalize_phrase('Apache 2.0.') == 'Apache 2.0'
32-
assert normalize_phrase(',MIT,') == 'MIT'
33-
34-
def test_empty_after_strip(self):
35-
assert normalize_phrase('<foo>') == ''
36-
assert normalize_phrase('...') == ''
6+
from build_dataset import tag_tokens, assign_splits
377

388

399
class TestTagTokens:

0 commit comments

Comments
 (0)