Download serializer.py from aialchemist-dev/compressor-reflex: direct link, hf CLI and curl.
- Browser
- Download file 5 kB
-
https://huggingface.co/aialchemist-dev/compressor-reflex/resolve/main/serializer.py
- Command line
-
hf download hf://aialchemist-dev/compressor-reflex/serializer.py
-
curl -L -o serializer.py https://huggingface.co/aialchemist-dev/compressor-reflex/resolve/main/serializer.py
5 kB
| import os | |
| from typing import List, Tuple, Dict, Any | |
| class CompressorSerializer: | |
| """ | |
| Serializes tool outputs and step intents into tokenized chunks with line spans. | |
| - Intent capped at 128 tokens | |
| - Chunk capped at 512 tokens | |
| - Sliding window with line preservation | |
| """ | |
| def __init__(self, tokenizer, max_intent_tokens: int = 128, max_chunk_tokens: int = 512): | |
| self.tokenizer = tokenizer | |
| self.max_intent_tokens = max_intent_tokens | |
| self.max_chunk_tokens = max_chunk_tokens | |
| def chunk_tool_output(self, intent: str, raw_output: str) -> List[Dict[str, Any]]: | |
| """ | |
| Splits raw_output into chunks <= max_chunk_tokens, preserving whole lines. | |
| Returns a list of chunks, each with: | |
| - chunk_text | |
| - lines (list of str) | |
| - input_ids, attention_mask | |
| - line_token_spans: list of (start_token, end_token) | |
| """ | |
| raw_lines = raw_output.splitlines() | |
| if not raw_lines: | |
| return [] | |
| # Tokenize intent with truncation | |
| intent_enc = self.tokenizer( | |
| f"INTENT: {intent.strip()}\n---\n", | |
| add_special_tokens=False, | |
| truncation=True, | |
| max_length=self.max_intent_tokens | |
| ) | |
| intent_prefix = self.tokenizer.decode(intent_enc["input_ids"]) | |
| intent_token_len = len(intent_enc["input_ids"]) | |
| avail_chunk_tokens = self.max_chunk_tokens - intent_token_len - 4 # room for CLS/SEP | |
| chunks = [] | |
| curr_lines = [] | |
| curr_tokens_est = 0 | |
| for line in raw_lines: | |
| line_str = line if line.strip() else " " | |
| # Fast token estimation: ~3.5 chars per token | |
| line_tok_est = max(1, len(line_str) // 3 + 1) | |
| if curr_lines and (curr_tokens_est + line_tok_est > avail_chunk_tokens): | |
| # Finalize current chunk | |
| chunk_obj = self._build_chunk(intent_prefix, curr_lines) | |
| chunks.append(chunk_obj) | |
| curr_lines = [line_str] | |
| curr_tokens_est = line_tok_est | |
| else: | |
| curr_lines.append(line_str) | |
| curr_tokens_est += line_tok_est | |
| if curr_lines: | |
| chunk_obj = self._build_chunk(intent_prefix, curr_lines) | |
| chunks.append(chunk_obj) | |
| return chunks | |
| def _build_chunk(self, intent_prefix: str, lines: List[str]) -> Dict[str, Any]: | |
| """ | |
| Formats chunk text and computes line token spans via offset mapping. | |
| """ | |
| prefix = intent_prefix | |
| chunk_body = "\n".join(lines) | |
| full_text = prefix + chunk_body | |
| enc = self.tokenizer( | |
| full_text, | |
| return_offsets_mapping=True, | |
| truncation=True, | |
| max_length=self.max_chunk_tokens, | |
| return_tensors="pt" | |
| ) | |
| offsets = enc["offset_mapping"][0].tolist() | |
| line_spans = [] | |
| curr_char = len(prefix) | |
| for line in lines: | |
| start_char = curr_char | |
| end_char = curr_char + len(line) | |
| curr_char = end_char + 1 # newline | |
| t_start = None | |
| t_end = None | |
| for idx, (os_char, oe_char) in enumerate(offsets): | |
| if os_char == oe_char: | |
| continue | |
| if os_char >= start_char and t_start is None: | |
| t_start = idx | |
| if oe_char <= end_char and t_start is not None: | |
| t_end = idx + 1 | |
| if t_start is not None and t_end is not None and t_end > t_start: | |
| line_spans.append((t_start, t_end)) | |
| elif t_start is not None: | |
| line_spans.append((t_start, min(t_start + 1, len(offsets) - 1))) | |
| else: | |
| # Truncated or zero-token line fallback | |
| last_idx = max(0, len(offsets) - 2) | |
| line_spans.append((last_idx, last_idx + 1)) | |
| return { | |
| "full_text": full_text, | |
| "lines": lines, | |
| "input_ids": enc["input_ids"][0], | |
| "attention_mask": enc["attention_mask"][0], | |
| "line_spans": line_spans, | |
| "num_lines": len(lines) | |
| } | |
| if __name__ == "__main__": | |
| from transformers import AutoTokenizer | |
| tok = AutoTokenizer.from_pretrained(r"C:\Users\EricM\Dev\jev-research\compressor-reflex\base_model") | |
| serializer = CompressorSerializer(tok) | |
| intent = "Inspect pytest output for failure in auth" | |
| output = "running pytest...\n==== test session starts ====\nFAILED test_auth.py:23 - Token expired\n==== 1 failed ====" | |
| chunks = serializer.chunk_tool_output(intent, output) | |
| print(f"Generated {len(chunks)} chunk(s)") | |
| for i, c in enumerate(chunks): | |
| print(f"Chunk {i}: {c['num_lines']} lines, {len(c['input_ids'])} tokens") | |
| for l_idx, (s, e) in enumerate(c["line_spans"]): | |
| line_text = c["lines"][l_idx] | |
| print(f" Line {l_idx} [{s}:{e}]: {line_text}") | |