#!/usr/bin/env python3 """ compress.py — Compress English reasoning text into the telegraphic CJK register using tessera-compressor behind any OpenAI-compatible endpoint (vLLM, llama.cpp server, etc.). No API keys or HF token required; the endpoint is yours. This is the same harness the compressor was accepted under: segment the block, group sentences into step-sized passages, classify each passage, compress it against the chain built so far, then run the deterministic fidelity gate. A passage that fails the gate falls back to a rules-only compression, so a bad model output costs savings, never content. Serve the model first, e.g.: vllm serve ZelligeAI/tessera-compressor --port 8001 or with the GGUF: llama-server -m gguf/compressor-v31-q8_0.gguf --port 8001 # from the repo root Then: # one block from a text file python compress.py --in think.txt --endpoint http://localhost:8001/v1 # a JSONL corpus: {"id": ..., "text": ...} per line python compress.py --in blocks.jsonl --out compressed.jsonl \ --endpoint http://localhost:8001/v1 Token counting: the fidelity gate compares token counts under a target tokenizer. For results matching the accepted harness, point --tokenizer at the model you are producing training data FOR (default: the compressor's own tokenizer, which is close but not identical to the Qwen3.5 target used in the acceptance run). """ import argparse import json import sys from openai import OpenAI from tokenizers import Tokenizer from segmenting import segment, group_steps, classify_passage, facts, gate from tokenmax import _apply_subs PASSAGE_SYSTEM = ( "你是推理压缩器。Re-notate the NEXT PASSAGE of a reasoning chain into telegraphic " "CJK/symbol notation. Every NEW logical step, fact, number and identifier must " "survive — unless already stated in the chain. Never restate chain content. " "[passage=load]: step-lossless telegraphic. [passage=narr]: minimal stubs " "(试X→否). Output only the re-notated continuation." ) MAX_NEW_TOKENS = 512 def compress_block(text, client, model, ntok): """Compress one reasoning block. Returns (compressed_text, stats).""" segs = group_steps(segment(text)) chain, seen = [], set() stats = {"segments": len(segs), "model_ok": 0, "fallback": 0, "narr_skipped": 0, "code": 0, "calls": 0} for kind, s in segs: if kind == "code": chain.append(s) seen |= facts(s) stats["code"] += 1 continue cls = classify_passage(s, seen, ntok) novel = facts(s) - seen rules_s, _ = _apply_subs(s) if not rules_s.strip(): continue tail = "\n".join(chain)[-500:] or "(start)" stats["calls"] += 1 r = client.chat.completions.create( model=model, temperature=0.0, max_tokens=MAX_NEW_TOKENS, messages=[ {"role": "system", "content": PASSAGE_SYSTEM}, {"role": "user", "content": f"[passage={cls}]\n链:\n{tail}\n\n段:\n{s[:2000]}"}, ], extra_body={"repetition_penalty": 1.15}, ) out = (r.choices[0].message.content or "").strip() if out == "∅" and cls == "narr" and not novel: stats["narr_skipped"] += 1 seen |= facts(s) continue if gate(s, rules_s, out, ntok, novel=novel) is None: chain.append(out) stats["model_ok"] += 1 else: chain.append(rules_s) stats["fallback"] += 1 seen |= facts(s) return "\n".join(chain), stats def main(): ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) ap.add_argument("--in", dest="inp", required=True, help=".txt (one block) or .jsonl ({'id','text'} per line)") ap.add_argument("--out", default=None, help="output JSONL (default: stdout)") ap.add_argument("--endpoint", default="http://localhost:8001/v1") ap.add_argument("--model", default="ZelligeAI/tessera-compressor", help="served model name at the endpoint") ap.add_argument("--tokenizer", default="ZelligeAI/tessera-compressor", help="HF repo id or local tokenizer.json for gate token counts") args = ap.parse_args() if args.tokenizer.endswith(".json"): tok = Tokenizer.from_file(args.tokenizer) else: tok = Tokenizer.from_pretrained(args.tokenizer) def ntok(s): return len(tok.encode(s).ids) if s else 0 client = OpenAI(base_url=args.endpoint, api_key="none") if args.inp.endswith(".jsonl"): rows = [json.loads(l) for l in open(args.inp) if l.strip()] else: rows = [{"id": args.inp, "text": open(args.inp).read()}] sink = open(args.out, "w") if args.out else sys.stdout for row in rows: compressed, stats = compress_block(row["text"], client, args.model, ntok) rec = {"id": row.get("id"), "compressed": compressed, "src_tokens": ntok(row["text"]), "out_tokens": ntok(compressed), "harness": stats} sink.write(json.dumps(rec, ensure_ascii=False) + "\n") sink.flush() print(f"[{row.get('id')}] {rec['src_tokens']} -> {rec['out_tokens']} tokens " f"(model_ok={stats['model_ok']} fallback={stats['fallback']})", file=sys.stderr) if args.out: sink.close() if __name__ == "__main__": main()