Download code/minijev/text_task.py from markuz89/minijev-general: direct link, hf CLI and curl.
- Browser
- Download file 2.61 kB
-
https://huggingface.co/markuz89/minijev-general/resolve/main/code/minijev/text_task.py
- Command line
-
hf download hf://markuz89/minijev-general/code/minijev/text_task.py
-
curl -L -o text_task.py https://huggingface.co/markuz89/minijev-general/resolve/main/code/minijev/text_task.py
2.61 kB
| """Generic text decision task: the state is a string (document, entity, log, ...) | |
| or empty. Used by general QA, sentiment and any JSONL decision dataset. | |
| States are stored as ragged UTF-8 bytes and tokenised at batch time with the | |
| model's tokenizer (`task.tokenizer`: byte-level or the pretrained encoder's), so | |
| one stored dataset works for every text backend. | |
| """ | |
| from __future__ import annotations | |
| from typing import Sequence | |
| import numpy as np | |
| from minijev.text_task_utils import normalise_log | |
| from minijev.tokenizers import ByteTokenizer | |
| from minijev.tasks import Task, ragged_pack, ragged_take | |
| class TextDecisionTask(Task): | |
| name = "text" | |
| state_encoder = "text" | |
| default_question = "" | |
| default_choices: tuple[str, ...] = () | |
| def __init__(self, cfg: dict | None = None): | |
| super().__init__(cfg) | |
| self.tokenizer = ByteTokenizer() | |
| def max_len(self) -> int: | |
| return int(self.cfg.get("max_len", 256)) | |
| def preprocess(self, text: str) -> str: | |
| return normalise_log(text, int(self.cfg.get("max_lines", 20))) if self.state_encoder == "log" else text | |
| def states_to_arrays(self, states: Sequence[str | None]) -> dict[str, np.ndarray]: | |
| flat, offsets = ragged_pack([np.frombuffer(self.preprocess(s or "").encode("utf-8"), np.uint8) | |
| for s in states], np.uint8) | |
| return {"text": flat, "text_offsets": offsets} | |
| def texts(self, arrays, idx) -> list[str]: | |
| flat, lengths = ragged_take(arrays["text"], arrays["text_offsets"], np.asarray(idx)) | |
| out, pos = [], 0 | |
| for n in lengths.tolist(): | |
| out.append(bytes(flat[pos:pos + n]).decode("utf-8", "replace")) | |
| pos += n | |
| return out | |
| def encode_arrays(self, arrays, idx): | |
| texts = self.texts(arrays, idx) | |
| ids = self.tokenizer.encode_batch(texts, self.max_len, dynamic=True) | |
| return {"state_ids": ids} | |
| def example_states(self, n=4, seed=0): | |
| base = ["hotdog", "whale", "Python", "", "The support was terrible and nobody answered me.", | |
| "Great update, everything works now!", "Redis", "balena"] | |
| rng = np.random.default_rng(seed) | |
| return [base[i] for i in rng.integers(0, len(base), n)] | |
| class LogDecisionTask(TextDecisionTask): | |
| name = "log" | |
| state_encoder = "log" | |
| def encode_arrays(self, arrays, idx): | |
| return {"state_log_ids": super().encode_arrays(arrays, idx)["state_ids"]} | |
| def make_task(cfg: dict) -> TextDecisionTask: | |
| return LogDecisionTask(cfg) if cfg.get("name") == "log" else TextDecisionTask(cfg) | |