|
1 | 1 | import numpy |
2 | | -from typing import cast, Dict, List, Tuple, Callable, Set |
3 | | -import tokenizations |
| 2 | +from typing import cast, Dict, List, Tuple, Callable, Set, Optional |
| 3 | +from spacy_alignments.tokenizations import get_alignments |
4 | 4 | from spacy.tokens import Span, Token |
5 | 5 | from thinc.api import Ops |
6 | 6 | from thinc.types import Ragged, Floats2d, Ints1d |
@@ -100,7 +100,7 @@ def get_alignment_via_offset_mapping(spans: List[Span], token_data) -> Ragged: |
100 | 100 | return align |
101 | 101 |
|
102 | 102 |
|
103 | | -def get_alignment(spans: List[Span], wordpieces: List[List[str]]) -> Ragged: |
| 103 | +def get_alignment(spans: List[Span], wordpieces: List[List[str]], special_tokens: Optional[List[str]] = None) -> Ragged: |
104 | 104 | """Compute a ragged alignment array that records, for each unique token in |
105 | 105 | `spans`, the corresponding indices in the flattened `wordpieces` array. |
106 | 106 | For instance, imagine you have two overlapping spans: |
@@ -135,14 +135,24 @@ def get_alignment(spans: List[Span], wordpieces: List[List[str]]) -> Ragged: |
135 | 135 | """ |
136 | 136 | if len(spans) != len(wordpieces): |
137 | 137 | raise ValueError("Cannot align batches of different sizes.") |
| 138 | + if special_tokens is None: |
| 139 | + special_tokens = [] |
138 | 140 | # Tokens can occur more than once, and we need the alignment of each token |
139 | 141 | # to its place in the concatenated wordpieces array. |
140 | 142 | token_positions = get_token_positions(spans) |
141 | 143 | alignment: List[Set[int]] = [set() for _ in range(len(token_positions))] |
142 | 144 | wp_start = 0 |
143 | 145 | for i, (span, wp_toks) in enumerate(zip(spans, wordpieces)): |
144 | 146 | sp_toks = [token.text for token in span] |
145 | | - span2wp, wp2span = tokenizations.get_alignments(sp_toks, wp_toks) |
| 147 | + wp_toks_filtered = wp_toks |
| 148 | + # In the case that the special tokens do not appear in the text, filter |
| 149 | + # them out for alignment purposes so that special tokens like "<s>" are |
| 150 | + # not aligned to the character "s" in the text. (If the special tokens |
| 151 | + # appear in the text, it's not possible to distinguish them from the |
| 152 | + # added special tokens, so they may be aligned incorrectly.) |
| 153 | + if not any([special in span.text for special in special_tokens]): |
| 154 | + wp_toks_filtered = [tok if tok not in special_tokens else "" for tok in wp_toks] |
| 155 | + span2wp, wp2span = get_alignments(sp_toks, wp_toks_filtered) |
146 | 156 | for token, wp_js in zip(span, span2wp): |
147 | 157 | position = token_positions[token] |
148 | 158 | alignment[position].update(wp_start + j for j in wp_js) |
|
0 commit comments